2142 lines
54 KiB
C
2142 lines
54 KiB
C
#ifndef lint
|
|
static char sccsid[] = "@(#)pr_texvec.c 1.1 94/10/31 SMI";
|
|
#endif
|
|
|
|
/*
|
|
* Copyright 1986, 1990 Sun Microsystems, Inc.
|
|
*/
|
|
|
|
|
|
#include <sys/types.h>
|
|
#include <pixrect/pixrect.h>
|
|
#include <pixrect/pr_line.h>
|
|
#include "pr_texmacs.h"
|
|
|
|
/* largest delta we can handle without overflow in clip code */
|
|
#define MAXDELTA (32767)
|
|
|
|
#define swap(a,b,t) do { (t) = (a); (a) = (b); (b) = (t); } while (0)
|
|
#define abs(i) ((i) < 0 ? -(i) : (i))
|
|
|
|
/* XXX mallocated segment array, never freed */
|
|
#define MaxSegs 256
|
|
static short *segarray;
|
|
|
|
pr_texvec(dst, x0, y0, x1, y1, tex, op)
|
|
Pixrect *dst;
|
|
int x0, y0, x1, y1;
|
|
Pr_texture *tex;
|
|
int op;
|
|
{
|
|
register dx, dy, count, initerror;
|
|
int clip, tempos, start_x, start_y, vert, npts;
|
|
int reflect = 0, clip_off = 0;
|
|
static unsigned ptlist_size;
|
|
struct pr_size size;
|
|
static struct pr_pos *ptlist;
|
|
|
|
if (!segarray &&
|
|
!(segarray = (short *) malloc(MaxSegs * sizeof (short))))
|
|
return PIX_ERR;
|
|
|
|
size = dst->pr_size;
|
|
|
|
tex->options.res_right = 1;
|
|
tex->options.res_cliprt = 0;
|
|
dx = x1 - x0;
|
|
dy = y1 - y0;
|
|
vert = ((dx > 0)^(dy > 0)) ? -1 : 1;
|
|
|
|
/*
|
|
* Need to normalize the vector so that the following
|
|
* algorithm can limit the number of cases to be considered.
|
|
* We can always interchange the points in x, so that
|
|
* pos0 is to the left of pos1.
|
|
*/
|
|
if (dx < 0) {
|
|
/* force vector to scan to right */
|
|
dx = -dx;
|
|
dy = -dy;
|
|
swap(x0, x1, tempos);
|
|
swap(y0, y1, tempos);
|
|
tex->options.res_right = 0;
|
|
}
|
|
|
|
/*
|
|
* The clipping routine needs to work with a vector which
|
|
* increases in y from y0 to y1. We want to change
|
|
* y0 and y1 so that there is an increase in y
|
|
* from y0 to y1 without affecting the clipping
|
|
* and bounds checking that we will do. We accomplish
|
|
* this by reflecting the vector around the horizontal
|
|
* centerline of dst, and remember that we did this by
|
|
* incrementing reflect by 2. The reflection will be undone
|
|
* before the vector is drawn.
|
|
*/
|
|
if (dy < 0) {
|
|
dy = -dy;
|
|
y0 = (size.y-1) - y0;
|
|
y1 = (size.y-1) - y1;
|
|
if (!dx)
|
|
tex->options.res_right = 0;
|
|
reflect += 2;
|
|
}
|
|
/*
|
|
* Can now do bounds check, since the vector increasing in
|
|
* x and y can check easily if it has no chance of intersecting
|
|
* the destination rectangle: if the vector ends before the
|
|
* beginning of the target or begins after the end!
|
|
*/
|
|
if (op & PIX_DONTCLIP)
|
|
clip = 0;
|
|
else {
|
|
if (y1 < 0 || y0 >= size.y || x1 < 0 || x0 >= size.x) {
|
|
if (dx < dy)
|
|
swap(dx, dy, count);
|
|
|
|
clip_offset(dx, dy, tex);
|
|
|
|
return 0;
|
|
}
|
|
clip = 1;
|
|
op |= PIX_DONTCLIP;
|
|
}
|
|
|
|
/*
|
|
* If vector is horizontal, use fast algorithm.
|
|
*/
|
|
if (dy == 0) {
|
|
if (clip) {
|
|
if (x0 < 0) {
|
|
clip_off = -x0;
|
|
x0 = 0;
|
|
}
|
|
if (x1 >= size.x) {
|
|
x1 = size.x - 1;
|
|
tex->options.res_cliprt = 1;
|
|
}
|
|
}
|
|
count = x1 - x0 + 1;
|
|
|
|
MALLOC_PTLIST(ptlist, ptlist_size, count);
|
|
|
|
npts = bres_horizontal(count, dx, x0, y0,
|
|
clip_off, tex, ptlist);
|
|
return pr_polypoint(dst, 0, 0, npts, ptlist, op);
|
|
}
|
|
|
|
/*
|
|
* If vector is vertical, use fast algorithm.
|
|
*/
|
|
if (dx == 0) {
|
|
if (clip) {
|
|
if (y0 < 0) {
|
|
if (tex->options.res_right)
|
|
clip_off = -y0;
|
|
else
|
|
tex->options.res_cliprt = 1;
|
|
y0 = 0;
|
|
}
|
|
if (y1 >= size.y) {
|
|
if (!(tex->options.res_right))
|
|
clip_off += y1 - size.y + 1;
|
|
else
|
|
tex->options.res_cliprt = 1;
|
|
y1 = size.y - 1;
|
|
}
|
|
}
|
|
count = y1 - y0 + 1;
|
|
|
|
MALLOC_PTLIST(ptlist, ptlist_size, count);
|
|
|
|
if (reflect & 2) /* undo reflection, startpoint only */
|
|
y0 = size.y - 1 - y1;
|
|
npts = bres_vert(count, dy, 1, x0, y0,
|
|
clip_off, tex, ptlist);
|
|
return pr_polypoint(dst, 0, 0, npts, ptlist, op);
|
|
}
|
|
|
|
/*
|
|
* One more reflection: we want to assume that dx >= dy.
|
|
* So if this is not true, we reflect the vector around
|
|
* the diagonal line x = y and remember that we did
|
|
* this by adding 1 to reflect.
|
|
*/
|
|
if (dx < dy) {
|
|
swap(x0, y0, count);
|
|
swap(x1, y1, count);
|
|
swap(dx, dy, count);
|
|
swap(size.x, size.y, count);
|
|
reflect += 1;
|
|
}
|
|
initerror = -(dx>>1); /* error at pos0 */
|
|
start_x = x0;
|
|
start_y = y0;
|
|
if (!clip)
|
|
goto clipdone;
|
|
|
|
/*
|
|
* Begin hard part of clipping.
|
|
*
|
|
* We have insured that we are clipping on a vector
|
|
* which has dx > 0, dy > 0 and dx >= dy. The error is
|
|
* the vertical distance from the true line to the approximation
|
|
* in units where each pixel is dx by dx. Moving one
|
|
* to the right (increasing x by 1) subtracts dy from
|
|
* the error. Moving one pixel down (increasing y by 1)
|
|
* adds dx to the error.
|
|
*
|
|
* Bresenham functions by restoring the error to the
|
|
* range (-dx,0] whenever the error leaves it. The
|
|
* algorithm increases x and increases y when
|
|
* it needs to constrain the error.
|
|
*/
|
|
|
|
|
|
/*
|
|
* If dx or dy are too large, scale to avoid overflow in
|
|
* multiplications below.
|
|
*/
|
|
while (dx > MAXDELTA || dy > MAXDELTA) {
|
|
dx >>= 1;
|
|
dy >>= 1;
|
|
}
|
|
|
|
/*
|
|
* Clip left end to yield start of visible vector.
|
|
* If the starting x coordinate is negative, we
|
|
* must advance to the first x coordinate which will
|
|
* be drawn (x=0). As we advance (-start_x) units in the
|
|
* x direction, the error increases by (-start_x)*dy.
|
|
* This means that the error when x=0 will be
|
|
* -(dx/2)+(-start_x)*dy
|
|
* For each y advance in this range, the error is reduced
|
|
* by dx, and should be in the range (-dx,0] at the y
|
|
* value at x=0. Thus to compute the increment in y we
|
|
* should take
|
|
* (-(dx/2)+(-start_x)*dy+(dx-1))/dx
|
|
* where the numerator represents the length of the interval
|
|
* [-dx+1,-(dx/2)+(-start_x)*dy]
|
|
* The number of dx steps by which the error can be reduced
|
|
* and stay in this interval is the y increment which would
|
|
* result if the vector were drawn over this interval.
|
|
*/
|
|
if (start_x < 0) {
|
|
initerror += (-start_x * dy);
|
|
clip_off = -start_x;
|
|
start_x = 0;
|
|
count = (initerror + (dx-1)) / dx;
|
|
start_y += count;
|
|
initerror -= (count * dx);
|
|
}
|
|
|
|
/*
|
|
* After having advanced x to be at least 0, advance
|
|
* y to be in range. If y is already too large (and can
|
|
* only get larger!), just give up. Otherwise, if start_y < 0,
|
|
* we need to compute the value of x at which y is first 0.
|
|
* In advancing y to be zero, the error decreases by (-start_y)*dx,
|
|
* in the y steps.
|
|
*
|
|
* Immediately after an advance in y the error is in the range
|
|
* (-dx,-dx+dy]. This can be seen by noting that what last
|
|
* happened was that the error was in the range (-dy,0],
|
|
* the error became positive by adding dy, to be in the range (0,dy],
|
|
* and we subtracted dx to get into the range (-dx,-dx+dy].
|
|
*
|
|
* Thus we need to advance x to cause the error to change
|
|
* to be at most (-dx+dy), or, in steps of dy, at most:
|
|
* ((-dx+dy)-error)/dy
|
|
* which is the number of dy steps in the interval [error,-dx+dy].
|
|
*/
|
|
if (start_y >= size.y) {
|
|
clip_offset(dx, dy, tex);
|
|
return (0);
|
|
}
|
|
if (start_y < 0) {
|
|
/* skip to dst top edge */
|
|
initerror += (start_y * dx);
|
|
start_y = 0;
|
|
count = ((-dx+dy)-initerror)/dy;
|
|
start_x += count;
|
|
clip_off += count;
|
|
initerror += (count * dy);
|
|
if (start_x >= size.x) {
|
|
clip_offset(dx, dy, tex);
|
|
return (0);
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Now clip right end.
|
|
*
|
|
* If the last x position is outside the rectangle,
|
|
* then clip the vector back to within the rectangle
|
|
* at x=size.x-1. The corresponding y value has initerror
|
|
* -(dx/2)+((size.x-1)-x0)*dy
|
|
* We need an error in the range (-dx,0], so compute
|
|
* the corresponding number of steps in y from the number
|
|
* of dy's in the interval:
|
|
* (-dx,-(dx/2)+((size.x-1)-x0)*dy]
|
|
* which is:
|
|
* [-dx+1,-(dx/2)+((size.x-1)-x0)*dy]
|
|
* or:
|
|
* (-(dx/2)+((size.x-1)-x0)*dy+dx-1)/dx
|
|
* Note that:
|
|
* dx - (dx/2) != (dx/2)
|
|
* (consider dx odd), so we can't simplify much further.
|
|
*/
|
|
if (x1 >= size.x) {
|
|
x1 = size.x - 1;
|
|
y1 = y0+ (-(dx>>1)+ (((size.x-1)-x0) * dy)+ dx-1)/dx;
|
|
tex->options.res_cliprt = 1;
|
|
}
|
|
/*
|
|
* If the last y position is outside the rectangle, then
|
|
* clip it back at y=size.y-1. The corresponding x value
|
|
* has error
|
|
* -(dx/2)-((size.y-1)-y0)*dx
|
|
* We want the last x value with this y value, which
|
|
* will have an error in the range (-dy,0] (so that increasing
|
|
* x one more time will make the error > 0.) Thus
|
|
* the amount of error allocatable to dy steps is from
|
|
* the length of the interval:
|
|
* [-(dx/2)-((size.y-1)-y0)*dx,0]
|
|
* that is,
|
|
* (0-(-(dx/2)-((size.y-1)-y0)*dx))/dy
|
|
* or:
|
|
* ((dx/2)+((size.y-1)-y0)*dx)/dy
|
|
*/
|
|
if (y1 >= size.y) {
|
|
y1 = size.y - 1;
|
|
x1 = x0 + ((dx>>1) + (((size.y-1)-y0) * dx))/dy;
|
|
tex->options.res_cliprt = 1;
|
|
}
|
|
|
|
clipdone:
|
|
/*
|
|
* Now have to set up for the Bresenham routines.
|
|
*/
|
|
|
|
count = x1 - start_x + 1;
|
|
|
|
MALLOC_PTLIST(ptlist, ptlist_size, count);
|
|
|
|
if (reflect & 1) {
|
|
/* major axis is y */
|
|
if (reflect & 2) {
|
|
/* unreflect major axis (misnamed x) */
|
|
start_x = ((size.x-1) - start_x);
|
|
}
|
|
npts = bres_majy(dx, dy, count, initerror, vert,
|
|
start_y, start_x, clip_off, tex, ptlist);
|
|
} else {
|
|
/* major axis is x */
|
|
if (reflect & 2) {
|
|
/* unreflect minor axis */
|
|
start_y = ((size.y-1) - start_y);
|
|
}
|
|
npts = bres_majx(dx, dy, count, initerror, vert,
|
|
start_x, start_y, clip_off, tex, ptlist);
|
|
}
|
|
|
|
return pr_polypoint(dst, 0, 0, npts, ptlist, op);
|
|
}
|
|
|
|
|
|
/*
|
|
* This routine calculates and sets up the offset for vectors. If the
|
|
* vectors were meant to be drawn left to right, or if the computed offset
|
|
* is equal to the pattern length, we set the offset to the length of
|
|
* the first segment of the pattern and return. If the vector was meant
|
|
* to be drawn from left to right, we calculate an offset into the pattern
|
|
* so that we would get concentric circles when drawing multiple vectors
|
|
* from the origin. Seg holds the number of the segment that we are in,
|
|
* and offset contains an offset into that segment.
|
|
*/
|
|
|
|
static
|
|
pattern_offset (segment,numsegs,seg,offset,majax,pat_length,start_off,
|
|
clip_off,tex)
|
|
int clip_off;
|
|
register short *segment;
|
|
int numsegs;
|
|
register majax, pat_length, start_off;
|
|
register int *offset, *seg;
|
|
Pr_texture *tex;
|
|
{
|
|
int i, mod, init_off;
|
|
/*
|
|
* First we handle the code for balanced lines, and the different starting
|
|
* offsets for the left and right sides. For line balancing, we take
|
|
* the modulus of the count and pattern length and divide this by 2 so
|
|
* that the offset is the same from either end. But, since the pattern is
|
|
* even (has an even number of segments) we cannot truly center it, so we
|
|
* add in the length of the first segment divided by 2.
|
|
*/
|
|
init_off = start_off;
|
|
mod = ((majax + 1) % pat_length) + start_off;
|
|
if (!(tex->options.res_right)) { /* for left side */
|
|
tex->res_polyoff = mod + 1;
|
|
start_off = clip_off + pat_length - mod;
|
|
if (tex->options.balanced)
|
|
start_off += ((mod-init_off)>>1) - (segment[numsegs-1] >> 1);
|
|
while (start_off < 0)
|
|
start_off += pat_length;
|
|
} else {
|
|
tex->res_polyoff = mod - 1;
|
|
start_off += clip_off; /* for right side */
|
|
if (tex->options.balanced)
|
|
start_off += pat_length - ((mod-init_off)>>1) + (*segment>>1);
|
|
}
|
|
while (tex->res_polyoff >= pat_length)
|
|
tex->res_polyoff -= pat_length;
|
|
while (start_off >= pat_length)
|
|
start_off -= pat_length;
|
|
if (start_off == 0) { /* no offset necessary */
|
|
*offset = *segment;
|
|
*seg = 0;
|
|
return;
|
|
}
|
|
/*
|
|
* When we reach here we know that the starting offset is less than the total
|
|
* pattern length, so we want to figure out where in the patttern we should
|
|
* start. Offset holds the count into a segment, and seg holds the segment
|
|
* number.
|
|
*/
|
|
for (i = 0; (*offset = *segment++); i++) {
|
|
if (start_off <= *offset) {
|
|
*offset -= start_off;
|
|
break;
|
|
} else
|
|
start_off -= *offset;
|
|
}
|
|
if (*offset) /* offset is not zero */
|
|
*seg = i;
|
|
else { /* offset is zero */
|
|
*offset = *segment;
|
|
*seg = ++i;
|
|
}
|
|
} /* pattern_offset */
|
|
|
|
|
|
static
|
|
IncSetPattern(majax,minax,segment,pat_length,numsegs,start_off,tex)
|
|
register majax, minax;
|
|
register int *pat_length, *start_off;
|
|
register short *segment;
|
|
register Pr_texture *tex;
|
|
int numsegs;
|
|
/*
|
|
* This routine computes the actual pattern length for non-horizontal
|
|
* and non-vertical vectors, using pythagoreans theorem. When the error
|
|
* for the current point is greater than the error for the last point, the
|
|
* routine falls out of its loop. For the case when the major axis is
|
|
* the x axis, then x squared begins as 1, and after that, the
|
|
* algorithm follows the formula (x + 1)**2 = x**2 + 2x + 1.
|
|
*/
|
|
{
|
|
int diag_sq, maj_sq = 1, min_sq = 1, maj_count = 0, min_count = 0;
|
|
int not_begin = 0, maj_count_old = 0, i, seg_count = 0;
|
|
register error, seg_error = 0, old_error;
|
|
|
|
error = -(majax >> 1); /* done for clipping reasons */
|
|
for (i = 0; i < numsegs; i++) {
|
|
seg_count += *segment;
|
|
diag_sq = pr_product(seg_count, seg_count);
|
|
old_error = diag_sq - (maj_sq + min_sq);
|
|
while ((abs(seg_error)) <= (abs(old_error))) {
|
|
maj_count++;
|
|
maj_sq += maj_count + maj_count + 1;
|
|
error += minax;
|
|
if (error > 0) {
|
|
min_count++;
|
|
min_sq += min_count + min_count + 1;
|
|
error -= majax;
|
|
}
|
|
if (not_begin)
|
|
old_error = seg_error;
|
|
seg_error = diag_sq - (maj_sq + min_sq);
|
|
not_begin = 1;
|
|
}
|
|
*segment++ = maj_count - maj_count_old;
|
|
maj_count_old = maj_count;
|
|
not_begin = seg_error = 0;
|
|
}
|
|
*pat_length = maj_count;
|
|
*start_off = tex->res_fatoff = ((*start_off) * (*pat_length) +
|
|
(tex->res_oldpatln>>1)) / tex->res_oldpatln;
|
|
} /* IncSetPattern */
|
|
|
|
|
|
static
|
|
clip_offset(majax, minax, tex)
|
|
register majax, minax;
|
|
register Pr_texture *tex;
|
|
{
|
|
int start_off, mod, pat_length, i, j;
|
|
int numsegs;
|
|
/*
|
|
* Fill in the segment array and compute the pattern_length for vectors
|
|
* on both the left and right halves, since it could be used for balancing
|
|
* or for offsets into the pattern for vectors on the left half. It isn't
|
|
* worth the time to do the tests that would be needed to determine if
|
|
* absolutely necessary.
|
|
*/
|
|
if (!tex->options.res_fat) { /* is NOT fat vector */
|
|
{
|
|
register short *s, *p;
|
|
|
|
pat_length = numsegs = 0;
|
|
for (s = segarray, p = tex->pattern; (*p); numsegs++) {
|
|
*s++ = *p;
|
|
pat_length += *p++;
|
|
}
|
|
} /* end block */
|
|
if (tex->options.res_poly) {
|
|
start_off = tex->res_fatoff = tex->res_polyoff;
|
|
} else {
|
|
start_off = tex->res_fatoff = tex->offset;
|
|
tex->res_oldpatln = pat_length;
|
|
}
|
|
/*
|
|
* Angle correct if not horizontal or vertical & givenpattern bit is clear.
|
|
*/
|
|
if ((!tex->options.givenpattern) && (majax && minax)) {
|
|
IncSetPattern(majax, minax, segarray, &pat_length, numsegs,
|
|
&start_off, tex);
|
|
}
|
|
if (!tex->options.res_right) { /* reverse pattern in array */
|
|
REVERSE_PATTERN(segarray, ptlist, numsegs, i, j);
|
|
}
|
|
/*
|
|
* For fat vectors who are initially totally outside the clipping region,
|
|
* and then enter the drawing window, we store a pointer to the angle
|
|
* corrected pattern, in addition to storing the number of segments in
|
|
* the pattern.
|
|
*/
|
|
tex->res_patfat = segarray;
|
|
tex->res_numsegs = numsegs;
|
|
} else { /* is fat vector */
|
|
start_off = tex->res_fatoff;
|
|
pat_length = tex->res_oldpatln;
|
|
}
|
|
/*
|
|
* Now we compute the necessary offset parameters, with code lifted from the
|
|
* pattern_offset routine
|
|
*/
|
|
mod = ((majax + 1) % pat_length) + start_off;
|
|
if (tex->options.res_right) /* for right side */
|
|
tex->res_polyoff = mod - 1;
|
|
else /* for left side */
|
|
tex->res_polyoff = mod + 1;
|
|
while (tex->res_polyoff >= pat_length)
|
|
tex->res_polyoff -= pat_length;
|
|
tex->res_oldpatln = pat_length;
|
|
} /* clip_offset */
|
|
|
|
#define nxt(k,np) ((k+1)%np)
|
|
#define prev(k,np) ((k-1+np)%np)
|
|
#define even(n) (!(n & 1))
|
|
#define isgap(n) (n & 1)
|
|
#define min(m,n) ((m)<(n)? (m): (n))
|
|
|
|
static int hl, hr, hrsave;
|
|
static int maxdash, mindash, maxgap, mingap;
|
|
|
|
extern void bal_dash();
|
|
extern void fil_dash();
|
|
extern void clip_offset1();
|
|
|
|
static int
|
|
bres_horizontal(count,majax,x,y,clip_off,tex,ptlist)
|
|
register count, majax;
|
|
register Pr_texture *tex;
|
|
register struct pr_pos *ptlist;
|
|
int clip_off, x, y;
|
|
{
|
|
int i, j, start_off, offset, seg, npts = 0, pat_length;
|
|
int numsegs;
|
|
register short *segment, *segptr;
|
|
short auxp[20];
|
|
short lauxp[20];
|
|
int auxnp;
|
|
int lauxnp;
|
|
int bestc;
|
|
int lcount, mcount, rcount;
|
|
|
|
/*
|
|
* Fill in the p array and compute the pattern_length for vectors
|
|
* on both the left and right halves, since it could be used for balancing
|
|
* or for offsets into the pattern for vectors on the left half. It isn't
|
|
* worth the time to do the tests that would be needed to determine if
|
|
* absolutely necessary.
|
|
*/
|
|
|
|
if (!tex->options.res_fat) { /* is NOT fat vector */
|
|
{
|
|
register short *_s, *_p;
|
|
|
|
pat_length = numsegs = 0;
|
|
for (_s = segarray, _p = tex->pattern; (*_p); numsegs++) {
|
|
*_s++ = *_p;
|
|
pat_length += *_p++;
|
|
}
|
|
} /* end block */
|
|
|
|
/* reverse pattern in array */
|
|
if (!tex->options.res_right && !tex->options.balanced) {
|
|
REVERSE_PATTERN(segarray, ptlist, numsegs, i, j);
|
|
}
|
|
if (tex->options.res_poly)
|
|
start_off = tex->res_fatoff = tex->res_polyoff;
|
|
else {
|
|
start_off = tex->res_fatoff = tex->offset;
|
|
tex->res_oldpatln = pat_length;
|
|
}
|
|
segment = tex->res_patfat = segarray;
|
|
tex->res_numsegs = numsegs;
|
|
}
|
|
else { /* is fat vector */
|
|
start_off = tex->res_fatoff;
|
|
pat_length = tex->res_oldpatln;
|
|
numsegs = tex->res_numsegs;
|
|
segment = tex->res_patfat;
|
|
}
|
|
/*
|
|
* Account for the case when you have a single segment in your pattern.
|
|
* Line will appear solid.
|
|
*/
|
|
if (numsegs == 1)
|
|
tex->options.res_right = 1;
|
|
|
|
if (tex->options.balanced) {
|
|
bal_dash(majax+1,numsegs,segment,&bestc,&auxnp,auxp,
|
|
&seg,&offset,&lcount,&rcount);
|
|
mcount = majax+1-lcount-rcount;
|
|
}
|
|
else {
|
|
pattern_offset(segment,numsegs,&seg,&offset,majax,pat_length,
|
|
start_off,clip_off,tex);
|
|
bestc = -1;
|
|
}
|
|
segptr = &segment[seg+1];
|
|
tex->res_oldpatln = pat_length;
|
|
|
|
|
|
/*
|
|
* Modified bresenham for horizontals.
|
|
*/
|
|
if (tex->options.balanced) {
|
|
short* lsegptr;
|
|
int loffset;
|
|
int lseg;
|
|
int rseg;
|
|
short* rsegptr;
|
|
int roffset;
|
|
|
|
for (i=0; i<auxnp; i++) {
|
|
lauxp[i] = auxp[i];
|
|
}
|
|
lauxnp = auxnp;
|
|
|
|
if (rcount > 0 && lcount > rcount) {
|
|
(lauxp[0])++;
|
|
if (lauxp[0] > 1.6 * maxdash && lauxp[0] < 4) { /* ugly */
|
|
if (lauxnp == 1) {
|
|
if (seg & 1) { /* first regular portion is gap */
|
|
lauxp[0]--;
|
|
lauxnp = 2;
|
|
lauxp[1] = 1;
|
|
}
|
|
}
|
|
else {
|
|
lauxp[0]--;
|
|
lauxp[1]++;
|
|
}
|
|
}
|
|
}
|
|
|
|
/* determine clip_off */
|
|
lseg = 0;
|
|
loffset = lauxp[lseg];
|
|
lsegptr = &lauxp[(lseg+1)%lauxnp];
|
|
rseg = auxnp-1;
|
|
roffset = auxp[rseg];
|
|
rsegptr = &auxp[(rseg-1+auxnp)%auxnp];
|
|
|
|
(void) clip_offset1(clip_off,majax,count,numsegs,segment,
|
|
lauxnp,lauxp,auxnp,auxp,&lcount,&mcount,&rcount,
|
|
&lseg,&loffset,&seg,&offset,&rseg,&roffset);
|
|
|
|
lsegptr = &lauxp[(lseg+1)%lauxnp];
|
|
segptr = &segment[(seg+1)%numsegs];
|
|
rsegptr = &auxp[(rseg-1+auxnp)%auxnp];
|
|
|
|
/* test point */
|
|
|
|
while (lcount > 0) {
|
|
for ( ; ((lcount > 0) && (loffset > 0)); --lcount, --loffset) {
|
|
if (!(lseg & 1))
|
|
FILL_PR_POS(npts, ptlist, x, y);
|
|
x++;
|
|
}
|
|
if (lcount == 0) break;
|
|
lseg++;
|
|
if (lseg >= lauxnp) {
|
|
lseg = 0;
|
|
lsegptr = lauxp;
|
|
}
|
|
loffset = *lsegptr++;
|
|
}
|
|
|
|
while (mcount > 0) {
|
|
for ( ; ((mcount > 0) && (offset > 0)); --mcount, --offset) {
|
|
if (!(seg & 1))
|
|
FILL_PR_POS(npts, ptlist, x, y);
|
|
x++;
|
|
}
|
|
seg++;
|
|
if (seg >= numsegs) {
|
|
seg = 0;
|
|
segptr = segment;
|
|
}
|
|
offset = *segptr++;
|
|
}
|
|
|
|
while (rcount > 0) {
|
|
for ( ; ((rcount > 0) && (roffset > 0)); --rcount, --roffset) {
|
|
if (!(rseg & 1))
|
|
FILL_PR_POS(npts, ptlist, x, y);
|
|
x++;
|
|
}
|
|
if (rcount == 0) break;
|
|
rseg--;
|
|
if (rseg < 0) {
|
|
rseg = auxnp-1;
|
|
rsegptr = &auxp[auxnp-1];
|
|
}
|
|
roffset = *rsegptr--;
|
|
}
|
|
return npts;
|
|
}
|
|
if (tex->options.res_right) { /* right half */
|
|
if ((tex->options.startpoint) && (!clip_off)) {
|
|
FILL_PR_POS(npts, ptlist, x, y);
|
|
DRAW_HORZ();
|
|
}
|
|
if (count == 0)
|
|
return npts;
|
|
if ((tex->options.endpoint) && (!tex->options.res_cliprt))
|
|
--count;
|
|
while (count > 0) {
|
|
for ( ; ((count > 0) && (offset > 0)); --count, --offset) {
|
|
if (!(seg & 1))
|
|
FILL_PR_POS(npts, ptlist, x, y);
|
|
x++;
|
|
}
|
|
seg++;
|
|
if (seg >= numsegs) {
|
|
seg= 0;
|
|
segptr = segment;
|
|
}
|
|
offset = *segptr++;
|
|
}
|
|
if ((tex->options.endpoint) && (!tex->options.res_cliprt))
|
|
FILL_PR_POS(npts, ptlist, x, y);
|
|
}
|
|
else { /* left half */
|
|
if ((tex->options.endpoint) && (!clip_off)) {
|
|
FILL_PR_POS(npts, ptlist, x, y);
|
|
DRAW_HORZ();
|
|
}
|
|
if ((tex->options.startpoint) && (!tex->options.res_cliprt))
|
|
--count;
|
|
while (count > 0) {
|
|
for ( ; ((count > 0) && (offset > 0)); --count, --offset) {
|
|
if (seg & 1)
|
|
FILL_PR_POS(npts, ptlist, x, y);
|
|
x++;
|
|
}
|
|
seg++;
|
|
if (seg >= numsegs) {
|
|
seg= 0;
|
|
segptr = segment;
|
|
}
|
|
offset = *segptr++;
|
|
}
|
|
if ((tex->options.startpoint) && (!tex->options.res_cliprt))
|
|
FILL_PR_POS(npts, ptlist, x, y);
|
|
}
|
|
return(npts);
|
|
} /* bres_horizontal */
|
|
|
|
|
|
static int
|
|
bres_vert (count,majax,vert,x,y,clip_off,tex,ptlist)
|
|
register count, majax, vert;
|
|
register Pr_texture *tex;
|
|
register struct pr_pos *ptlist;
|
|
int clip_off, x, y;
|
|
{
|
|
int i, j, start_off, offset, seg, npts = 0, pat_length;
|
|
int numsegs;
|
|
register short *segment, *segptr;
|
|
short auxp[20];
|
|
short lauxp[20];
|
|
int auxnp;
|
|
int lauxnp;
|
|
int bestc;
|
|
int lcount, mcount, rcount;
|
|
|
|
/*
|
|
* Fill in the segment array and compute the pattern_length for vectors
|
|
* on both the left and right halves, since it could be used for balancing
|
|
* or for offsets into the pattern for vectors on the left half. It isn't
|
|
* worth the time to do the tests that would be needed to determine if
|
|
* absolutely necessary.
|
|
*/
|
|
if (!tex->options.res_fat) { /* is NOT fat vector */
|
|
{
|
|
register short *s, *p;
|
|
|
|
pat_length = numsegs = 0;
|
|
for (s = segarray, p = tex->pattern; (*p); numsegs++) {
|
|
*s++ = *p;
|
|
pat_length += *p++;
|
|
}
|
|
} /* end block */
|
|
if (tex->options.res_poly)
|
|
start_off = tex->res_fatoff = tex->res_polyoff;
|
|
else {
|
|
start_off = tex->res_fatoff = tex->offset;
|
|
tex->res_oldpatln = pat_length;
|
|
}
|
|
|
|
/* reverse pattern in array */
|
|
if (!tex->options.res_right && !tex->options.balanced) {
|
|
REVERSE_PATTERN(segarray, ptlist, numsegs, i, j);
|
|
}
|
|
segment = tex->res_patfat = segarray;
|
|
tex->res_numsegs = numsegs;
|
|
}
|
|
else { /* is fat vector */
|
|
start_off = tex->res_fatoff;
|
|
pat_length = tex->res_oldpatln;
|
|
numsegs = tex->res_numsegs;
|
|
segment = tex->res_patfat;
|
|
}
|
|
/*
|
|
* Account for the case when you have a single segment in your pattern.
|
|
* Line will appear solid.
|
|
*/
|
|
if (numsegs == 1)
|
|
tex->options.res_right = 1;
|
|
|
|
if (tex->options.balanced) {
|
|
bal_dash(majax+1,numsegs,segment,&bestc,&auxnp,auxp,
|
|
&seg,&offset,&lcount,&rcount);
|
|
mcount = majax+1-lcount-rcount;
|
|
}
|
|
else {
|
|
pattern_offset(segment,numsegs,&seg,&offset,majax,pat_length,
|
|
start_off, clip_off, tex);
|
|
bestc = -1;
|
|
}
|
|
segptr = &segment[seg+1];
|
|
tex->res_oldpatln = pat_length;
|
|
/*
|
|
* Modified bresenham for verticals.
|
|
*/
|
|
|
|
if (tex->options.balanced) {
|
|
short* lsegptr;
|
|
int loffset;
|
|
int lseg;
|
|
int rseg;
|
|
short* rsegptr;
|
|
int roffset;
|
|
|
|
for (i=0; i<auxnp; i++) {
|
|
lauxp[i] = auxp[i];
|
|
}
|
|
lauxnp = auxnp;
|
|
loffset = lauxp[0];
|
|
|
|
if (rcount > 0 && lcount > rcount) {
|
|
(lauxp[0])++;
|
|
|
|
if (lauxp[0] > 1.6 * maxdash && lauxp[0] < 4) {
|
|
if (lauxnp == 1) {
|
|
if (seg & 1) { /* first reg is gap */
|
|
lauxp[0]--;
|
|
lauxnp = 2;
|
|
lauxp[1] = 1;
|
|
}
|
|
}
|
|
else {
|
|
lauxp[0]--;
|
|
lauxp[1]++;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
/* determine clip_off */
|
|
lseg = 0;
|
|
loffset = lauxp[lseg];
|
|
lsegptr = &lauxp[(lseg+1)%lauxnp];
|
|
rseg = auxnp-1;
|
|
roffset = auxp[rseg];
|
|
rsegptr = &auxp[(rseg-1+auxnp)%auxnp];
|
|
|
|
(void) clip_offset1(clip_off,majax,count,numsegs,segment,
|
|
lauxnp,lauxp,auxnp,auxp,&lcount,&mcount,&rcount,
|
|
&lseg,&loffset,&seg,&offset,&rseg,&roffset);
|
|
|
|
lsegptr = &lauxp[(lseg+1)%lauxnp];
|
|
segptr = &segment[(seg+1)%numsegs];
|
|
rsegptr = &auxp[(rseg-1+auxnp)%auxnp];
|
|
|
|
|
|
while (lcount > 0) {
|
|
for ( ; ((lcount > 0) && (loffset > 0)); --lcount, --loffset) {
|
|
if (!(lseg & 1))
|
|
FILL_PR_POS(npts, ptlist, x, y);
|
|
y += vert;
|
|
}
|
|
if (lcount == 0) break;
|
|
lseg++;
|
|
if (lseg >= lauxnp) {
|
|
lseg = 0;
|
|
lsegptr = lauxp;
|
|
}
|
|
loffset = *lsegptr++;
|
|
}
|
|
|
|
while (mcount > 0) {
|
|
for ( ; ((mcount > 0) && (offset > 0)); --mcount, --offset) {
|
|
if (!(seg & 1))
|
|
FILL_PR_POS(npts, ptlist, x, y);
|
|
y += vert;
|
|
}
|
|
seg++;
|
|
if (seg >= numsegs) {
|
|
seg = 0;
|
|
segptr = segment;
|
|
}
|
|
offset = *segptr++;
|
|
}
|
|
|
|
while (rcount > 0) {
|
|
for ( ; ((rcount > 0) && (roffset > 0)); --rcount, --roffset) {
|
|
if (!(rseg & 1))
|
|
FILL_PR_POS(npts, ptlist, x, y);
|
|
y += vert;
|
|
}
|
|
if (rcount == 0) break;
|
|
rseg--;
|
|
if (rseg < 0) {
|
|
rseg = auxnp-1;
|
|
rsegptr = &auxp[auxnp-1];
|
|
}
|
|
roffset = *rsegptr--;
|
|
}
|
|
return npts;
|
|
}
|
|
|
|
if (tex->options.res_right) {
|
|
if ((tex->options.startpoint) && (!clip_off)) {
|
|
FILL_PR_POS(npts, ptlist, x, y);
|
|
DRAW_VERT();
|
|
}
|
|
if ((tex->options.endpoint) && (!tex->options.res_cliprt))
|
|
--count;
|
|
while (count > 0) {
|
|
for ( ; ((count > 0) && (offset > 0)); --count, --offset) {
|
|
if (!(seg & 1))
|
|
FILL_PR_POS(npts, ptlist, x, y);
|
|
y += vert;
|
|
}
|
|
seg++;
|
|
if (seg >= numsegs) {
|
|
seg = 0;
|
|
segptr = segment;
|
|
}
|
|
offset = *segptr++;
|
|
} /* end bresenham */
|
|
if ((tex->options.endpoint) && (!tex->options.res_cliprt))
|
|
FILL_PR_POS(npts, ptlist, x, y);
|
|
}
|
|
else {
|
|
if ((tex->options.endpoint) && (!clip_off)) {
|
|
FILL_PR_POS(npts, ptlist, x, y);
|
|
DRAW_VERT();
|
|
}
|
|
if ((tex->options.startpoint) && (!tex->options.res_cliprt))
|
|
--count;
|
|
while (count > 0) {
|
|
for ( ; ((count > 0) && (offset > 0)); --count, --offset) {
|
|
if (seg & 1)
|
|
FILL_PR_POS(npts, ptlist, x, y);
|
|
y += vert;
|
|
}
|
|
seg++;
|
|
if (seg >= numsegs) {
|
|
seg = 0;
|
|
segptr = segment;
|
|
}
|
|
offset = *segptr++;
|
|
} /* end bresenham */
|
|
if ((tex->options.startpoint) && (!tex->options.res_cliprt))
|
|
FILL_PR_POS(npts, ptlist, x, y);
|
|
}
|
|
return(npts);
|
|
} /* bres_vert */
|
|
|
|
|
|
static int
|
|
bres_majx(majax,minax,count,error,vert,x,y,clip_off,tex,ptlist)
|
|
register majax, minax, count, error, vert;
|
|
register Pr_texture *tex;
|
|
register struct pr_pos *ptlist;
|
|
int clip_off, x, y;
|
|
{
|
|
int i, j, start_off, offset, seg, npts = 0, pat_length;
|
|
int numsegs;
|
|
register short *segment, *segptr;
|
|
short auxp[20];
|
|
short lauxp[20];
|
|
int auxnp;
|
|
int lauxnp;
|
|
int bestc;
|
|
int lcount, mcount, rcount;
|
|
|
|
|
|
if (!tex->options.res_fat) { /* is NOT fat vector */
|
|
{
|
|
register short *s, *p;
|
|
|
|
numsegs = pat_length = 0;
|
|
for (s = segarray, p = tex->pattern; (*p); numsegs++) {
|
|
*s++ = *p;
|
|
pat_length += *p++;
|
|
}
|
|
} /* end block */
|
|
|
|
if (tex->options.res_poly)
|
|
start_off = tex->res_fatoff = tex->res_polyoff;
|
|
else {
|
|
start_off = tex->res_fatoff = tex->offset;
|
|
tex->res_oldpatln = pat_length;
|
|
}
|
|
if (!tex->options.givenpattern) {
|
|
IncSetPattern(majax, minax, segarray, &pat_length, numsegs,
|
|
&start_off, tex);
|
|
}
|
|
/*
|
|
* Now we reverse the pattern if we were supposed to draw from right to
|
|
* left.
|
|
*/
|
|
if (!tex->options.res_right && !tex->options.balanced) {
|
|
REVERSE_PATTERN(segarray, ptlist, numsegs, i, j);
|
|
}
|
|
segment = tex->res_patfat = segarray;
|
|
tex->res_numsegs = numsegs;
|
|
}
|
|
else { /* is fat vector */
|
|
/*
|
|
* Restore angle-corrected offset, since don't need to continually angle
|
|
* correct for a fat vector & restore patln in case this is the first
|
|
* visible vector of the fat vector.
|
|
*/
|
|
start_off = tex->res_fatoff;
|
|
pat_length = tex->res_oldpatln;
|
|
numsegs = tex->res_numsegs;
|
|
segment = tex->res_patfat;
|
|
}
|
|
|
|
/*
|
|
* Account for the case when you have a single segment in your pattern.
|
|
* Line will appear solid.
|
|
*/
|
|
if (numsegs == 1)
|
|
tex->options.res_right = 1;
|
|
|
|
if (tex->options.balanced) {
|
|
bal_dash(majax+1,numsegs,segment,&bestc,&auxnp,auxp,
|
|
&seg,&offset,&lcount,&rcount);
|
|
mcount = majax+1-lcount-rcount;
|
|
}
|
|
else {
|
|
pattern_offset(segment, numsegs, &seg, &offset, majax, pat_length,
|
|
start_off, clip_off, tex);
|
|
bestc = -1;
|
|
}
|
|
segptr = &segment[seg+1];
|
|
tex->res_oldpatln = pat_length;
|
|
/*
|
|
* Modified bresenham loop, where we account for the fact that if we were
|
|
* meant to go right to left, we are drawing the pattern backwards,
|
|
* therefore we draw the even segments for the right half, and the odd
|
|
* segments for the left half.
|
|
*/
|
|
if (tex->options.balanced) {
|
|
short* lsegptr;
|
|
int loffset;
|
|
int lseg;
|
|
int rseg;
|
|
short* rsegptr;
|
|
int roffset;
|
|
|
|
for (i=0; i<auxnp; i++) {
|
|
lauxp[i] = auxp[i];
|
|
}
|
|
lauxnp = auxnp;
|
|
loffset = lauxp[0];
|
|
|
|
if (rcount > 0 && lcount > rcount) {
|
|
(lauxp[0])++;
|
|
|
|
if (lauxp[0] > 1.6 * maxdash && lauxp[0] < 4) {
|
|
if (lauxnp == 1) {
|
|
if (seg & 1) { /* first reg is gap */
|
|
lauxp[0]--;
|
|
lauxnp = 2;
|
|
lauxp[1] = 1;
|
|
}
|
|
}
|
|
else {
|
|
lauxp[0]--;
|
|
lauxp[1]++;
|
|
}
|
|
}
|
|
}
|
|
|
|
/* determine clip_off */
|
|
lseg = 0;
|
|
loffset = lauxp[lseg];
|
|
lsegptr = &lauxp[(lseg+1)%lauxnp];
|
|
rseg = auxnp-1;
|
|
roffset = auxp[rseg];
|
|
rsegptr = &auxp[(rseg-1+auxnp)%auxnp];
|
|
|
|
(void) clip_offset1(clip_off,majax,count,numsegs,segment,
|
|
lauxnp,lauxp,auxnp,auxp,&lcount,&mcount,&rcount,
|
|
&lseg,&loffset,&seg,&offset,&rseg,&roffset);
|
|
|
|
lsegptr = &lauxp[(lseg+1)%lauxnp];
|
|
segptr = &segment[(seg+1)%numsegs];
|
|
rsegptr = &auxp[(rseg-1+auxnp)%auxnp];
|
|
|
|
|
|
while (lcount > 0) {
|
|
for ( ; ((lcount > 0) && (loffset > 0)); --lcount, --loffset) {
|
|
if (!(lseg & 1))
|
|
FILL_PR_POS(npts, ptlist, x, y);
|
|
x++;
|
|
error += minax;
|
|
if (error > 0) {
|
|
error -= majax;
|
|
y += vert;
|
|
}
|
|
}
|
|
if (lcount == 0) break;
|
|
lseg++;
|
|
if (lseg >= lauxnp) {
|
|
lseg = 0;
|
|
lsegptr = lauxp;
|
|
}
|
|
loffset = *lsegptr++;
|
|
}
|
|
|
|
while (mcount > 0) {
|
|
for ( ; ((mcount > 0) && (offset > 0)); --mcount, --offset) {
|
|
if (!(seg & 1))
|
|
FILL_PR_POS(npts, ptlist, x, y);
|
|
x++;
|
|
error += minax;
|
|
if (error > 0) {
|
|
error -= majax;
|
|
y += vert;
|
|
}
|
|
}
|
|
seg++;
|
|
if (seg >= numsegs) {
|
|
seg = 0;
|
|
segptr = segment;
|
|
}
|
|
offset = *segptr++;
|
|
}
|
|
|
|
while (rcount > 0) {
|
|
for ( ; ((rcount > 0) && (roffset > 0)); --rcount, --roffset) {
|
|
if (!(rseg & 1))
|
|
FILL_PR_POS(npts, ptlist, x, y);
|
|
x++;
|
|
error += minax;
|
|
if (error > 0) {
|
|
error -= majax;
|
|
y += vert;
|
|
}
|
|
}
|
|
if (rcount == 0) break;
|
|
rseg--;
|
|
if (rseg < 0) {
|
|
rseg = auxnp-1;
|
|
rsegptr = &auxp[auxnp-1];
|
|
}
|
|
roffset = *rsegptr--;
|
|
}
|
|
return npts;
|
|
}
|
|
|
|
if (tex->options.res_right) { /* right half */
|
|
if ((tex->options.startpoint) && (!clip_off)) {
|
|
FILL_PR_POS(npts, ptlist, x, y);
|
|
DRAW_MAJ_X();
|
|
}
|
|
if ((tex->options.endpoint) && (!tex->options.res_cliprt))
|
|
--count;
|
|
while (count > 0) { /* for each segment. */
|
|
for (; ((offset > 0) && (count > 0)); count--, offset--) {
|
|
if (!(seg & 1))
|
|
FILL_PR_POS(npts, ptlist, x, y);
|
|
x++;
|
|
error += minax;
|
|
if (error > 0) {
|
|
error -= majax;
|
|
y += vert;
|
|
}
|
|
} /* for each pixel in segment. */
|
|
seg++;
|
|
if (seg >= numsegs) {
|
|
seg = 0;
|
|
segptr = segment;
|
|
}
|
|
offset = *segptr++;
|
|
}
|
|
if ((tex->options.endpoint) && (!tex->options.res_cliprt))
|
|
FILL_PR_POS(npts, ptlist, x, y);
|
|
}
|
|
else { /* left half */
|
|
if ((tex->options.endpoint) && (!clip_off)) {
|
|
FILL_PR_POS(npts, ptlist, x, y);
|
|
DRAW_MAJ_X();
|
|
}
|
|
if ((tex->options.startpoint) && (!tex->options.res_cliprt))
|
|
--count;
|
|
while (count > 0) { /* for each segment. */
|
|
for (; ((offset > 0) && (count > 0)); count--, offset--) {
|
|
if (seg & 1)
|
|
FILL_PR_POS(npts, ptlist, x, y);
|
|
x++;
|
|
error += minax;
|
|
if (error > 0) {
|
|
error -= majax;
|
|
y += vert;
|
|
}
|
|
}
|
|
seg++;
|
|
if (seg >= numsegs) {
|
|
seg = 0;
|
|
segptr = segment;
|
|
}
|
|
offset = *segptr++;
|
|
}
|
|
if ((tex->options.startpoint) && (!tex->options.res_cliprt))
|
|
FILL_PR_POS(npts, ptlist, x, y);
|
|
} /* end bresenham loop */
|
|
return(npts);
|
|
} /* bres_majx */
|
|
|
|
|
|
static int
|
|
bres_majy (majax,minax,count,error,vert,x,y,clip_off,tex,ptlist)
|
|
register majax, minax, count, error, vert;
|
|
register Pr_texture *tex;
|
|
register struct pr_pos *ptlist;
|
|
int clip_off, x, y;
|
|
{
|
|
int i, j, start_off, offset, seg, npts = 0, pat_length;
|
|
int numsegs;
|
|
register short *segment, *segptr;
|
|
short auxp[20];
|
|
short lauxp[20];
|
|
int auxnp;
|
|
int lauxnp;
|
|
int bestc;
|
|
int lcount, mcount, rcount;
|
|
|
|
if (!tex->options.res_fat) { /* is NOT fat vector */
|
|
{
|
|
register short *s, *p;
|
|
|
|
pat_length = numsegs = 0;
|
|
for (s = segarray, p = tex->pattern; (*p); numsegs++) {
|
|
*s++ = *p;
|
|
pat_length += *p++;
|
|
}
|
|
} /* end block */
|
|
|
|
if (tex->options.res_poly)
|
|
start_off = tex->res_fatoff = tex->res_polyoff;
|
|
else {
|
|
start_off = tex->res_fatoff = tex->offset;
|
|
tex->res_oldpatln = pat_length;
|
|
}
|
|
|
|
if (!tex->options.givenpattern) {
|
|
IncSetPattern(majax, minax, segarray, &pat_length, numsegs,
|
|
&start_off, tex);
|
|
}
|
|
|
|
/* reverse pattern in array */
|
|
if (!tex->options.res_right && !tex->options.balanced) {
|
|
REVERSE_PATTERN(segarray, ptlist, numsegs, i, j);
|
|
}
|
|
segment = tex->res_patfat = segarray;
|
|
tex->res_numsegs = numsegs;
|
|
}
|
|
else { /* is fat vector */
|
|
/*
|
|
* Restore angle-corrected offset, since don't need to continually angle
|
|
* correct for a fat vector & restore patln in case this is the first
|
|
* visible vector of the fat vector.
|
|
*/
|
|
start_off = tex->res_fatoff;
|
|
pat_length = tex->res_oldpatln;
|
|
numsegs = tex->res_numsegs;
|
|
segment = tex->res_patfat;
|
|
}
|
|
/*
|
|
* Account for the case when you have a single segment in your pattern.
|
|
* Line will appear solid.
|
|
*/
|
|
if (numsegs == 1)
|
|
tex->options.res_right = 1;
|
|
|
|
if (tex->options.balanced) {
|
|
bal_dash(majax+1,numsegs,segment,&bestc,&auxnp,auxp,
|
|
&seg,&offset,&lcount,&rcount);
|
|
mcount = majax+1-lcount-rcount;
|
|
}
|
|
else {
|
|
pattern_offset(segment, numsegs, &seg, &offset, majax, pat_length,
|
|
start_off, clip_off, tex);
|
|
bestc = -1;
|
|
}
|
|
segptr = &segment[seg+1];
|
|
tex->res_oldpatln = pat_length;
|
|
/*
|
|
* Modified bresenham loop, where we account for the fact that if we were
|
|
* meant to go right to left, we are drawing the pattern backwards,
|
|
* therefore we draw the even segments for the right half, and the odd
|
|
* segments for the left half.
|
|
*/
|
|
if (tex->options.balanced) {
|
|
short* lsegptr;
|
|
int loffset;
|
|
int lseg;
|
|
int rseg;
|
|
short* rsegptr;
|
|
int roffset;
|
|
|
|
for (i=0; i<auxnp; i++) {
|
|
lauxp[i] = auxp[i];
|
|
}
|
|
lauxnp = auxnp;
|
|
loffset = lauxp[0];
|
|
|
|
if (rcount > 0 && lcount > rcount) {
|
|
(lauxp[0])++;
|
|
|
|
if (lauxp[0] > 1.6 * maxdash && lauxp[0] < 4) {
|
|
if (lauxnp == 1) {
|
|
if (seg & 1) { /* first reg is gap */
|
|
lauxp[0]--;
|
|
lauxnp = 2;
|
|
lauxp[1] = 1;
|
|
}
|
|
}
|
|
else {
|
|
lauxp[0]--;
|
|
lauxp[1]++;
|
|
}
|
|
}
|
|
}
|
|
|
|
/* determine clip_off */
|
|
lseg = 0;
|
|
loffset = lauxp[lseg];
|
|
lsegptr = &lauxp[(lseg+1)%lauxnp];
|
|
rseg = auxnp-1;
|
|
roffset = auxp[rseg];
|
|
rsegptr = &auxp[(rseg-1+auxnp)%auxnp];
|
|
|
|
(void) clip_offset1(clip_off,majax,count,numsegs,segment,
|
|
lauxnp,lauxp,auxnp,auxp,&lcount,&mcount,&rcount,
|
|
&lseg,&loffset,&seg,&offset,&rseg,&roffset);
|
|
|
|
lsegptr = &lauxp[(lseg+1)%lauxnp];
|
|
segptr = &segment[(seg+1)%numsegs];
|
|
rsegptr = &auxp[(rseg-1+auxnp)%auxnp];
|
|
|
|
|
|
while (lcount > 0) {
|
|
for ( ; ((lcount > 0) && (loffset > 0)); --lcount, --loffset) {
|
|
if (!(lseg & 1))
|
|
FILL_PR_POS(npts, ptlist, x, y);
|
|
|
|
y += vert;
|
|
error += minax;
|
|
if (error > 0) {
|
|
error -= majax;
|
|
x++;
|
|
}
|
|
|
|
}
|
|
if (lcount == 0) break;
|
|
lseg++;
|
|
if (lseg >= lauxnp) {
|
|
lseg = 0;
|
|
lsegptr = lauxp;
|
|
}
|
|
loffset = *lsegptr++;
|
|
}
|
|
|
|
while (mcount > 0) {
|
|
for ( ; ((mcount > 0) && (offset > 0)); --mcount, --offset) {
|
|
if (!(seg & 1))
|
|
FILL_PR_POS(npts, ptlist, x, y);
|
|
y += vert;
|
|
error += minax;
|
|
if (error > 0) {
|
|
error -= majax;
|
|
x++;
|
|
}
|
|
}
|
|
seg++;
|
|
if (seg >= numsegs) {
|
|
seg = 0;
|
|
segptr = segment;
|
|
}
|
|
offset = *segptr++;
|
|
}
|
|
|
|
while (rcount > 0) {
|
|
for ( ; ((rcount > 0) && (roffset > 0)); --rcount, --roffset) {
|
|
if (!(rseg & 1))
|
|
FILL_PR_POS(npts, ptlist, x, y);
|
|
y += vert;
|
|
error += minax;
|
|
if (error > 0) {
|
|
error -= majax;
|
|
x++;
|
|
}
|
|
}
|
|
if (rcount == 0) break;
|
|
rseg--;
|
|
if (rseg < 0) {
|
|
rseg = auxnp-1;
|
|
rsegptr = &auxp[auxnp-1];
|
|
}
|
|
roffset = *rsegptr--;
|
|
}
|
|
return npts;
|
|
}
|
|
|
|
if (tex->options.res_right) { /* right half */
|
|
if ((tex->options.startpoint) && (!clip_off)) {
|
|
FILL_PR_POS(npts, ptlist, x, y);
|
|
DRAW_MAJ_Y();
|
|
}
|
|
if ((tex->options.endpoint) && (!tex->options.res_cliprt))
|
|
--count;
|
|
while (count > 0) { /* for each segment. */
|
|
for (; ((offset > 0) && (count > 0)); --count, --offset) {
|
|
if (!(seg & 1))
|
|
FILL_PR_POS(npts, ptlist, x, y);
|
|
y += vert;
|
|
error += minax;
|
|
if (error > 0) {
|
|
error -= majax;
|
|
x++;
|
|
}
|
|
} /* for each pixel in segment. */
|
|
seg++;
|
|
if (seg >= numsegs) {
|
|
seg = 0;
|
|
segptr = segment;
|
|
}
|
|
offset = *segptr++;
|
|
}
|
|
if ((tex->options.endpoint) && (!tex->options.res_cliprt))
|
|
FILL_PR_POS(npts, ptlist, x, y);
|
|
}
|
|
else { /* left half */
|
|
if ((tex->options.endpoint) && (!clip_off)) {
|
|
FILL_PR_POS(npts, ptlist, x, y);
|
|
DRAW_MAJ_Y();
|
|
}
|
|
if ((tex->options.startpoint) && (!tex->options.res_cliprt))
|
|
--count;
|
|
while (count > 0) { /* for each segment. */
|
|
for (; ((offset > 0) && (count > 0)); --count, --offset) {
|
|
if (seg & 1)
|
|
FILL_PR_POS(npts, ptlist, x, y);
|
|
y += vert;
|
|
error += minax;
|
|
if (error > 0) {
|
|
error -= majax;
|
|
x++;
|
|
}
|
|
}
|
|
seg++;
|
|
if (seg >= numsegs) {
|
|
seg = 0;
|
|
segptr = segment;
|
|
}
|
|
offset = *segptr++;
|
|
}
|
|
if ((tex->options.startpoint) && (!tex->options.res_cliprt))
|
|
FILL_PR_POS(npts, ptlist, x, y);
|
|
} /* end bresenham loop */
|
|
return(npts);
|
|
} /* bres_majy */
|
|
|
|
|
|
void
|
|
bal_dash(len,np,p,bestc,auxnp,auxp,seg,offset,lcount,rcount)
|
|
int len, np;
|
|
short *p;
|
|
int* bestc;
|
|
int* auxnp;
|
|
short* auxp;
|
|
int* seg;
|
|
int* offset;
|
|
int* lcount;
|
|
int* rcount;
|
|
{
|
|
int i, j;
|
|
int maxi, mini;
|
|
int maxc, minc;
|
|
int alen, blen, clen, dlen, elen, flen;
|
|
int c;
|
|
int bal;
|
|
int center[20];
|
|
int nport;
|
|
int nfold;
|
|
int nc; /* number of centers */
|
|
int rem;
|
|
int score[20];
|
|
int scoremax;
|
|
int flg[20];
|
|
int unit;
|
|
int h;
|
|
int flag;
|
|
int fflag;
|
|
|
|
maxgap = 0;
|
|
maxdash = 0;
|
|
mingap = 999;
|
|
mindash = 999;
|
|
for (i=0; i<np; i += 2) {
|
|
if (maxdash < p[i]) { /* find max dash */
|
|
maxdash = p[i];
|
|
maxi = i;
|
|
}
|
|
if (mindash > p[i]) { /*find min dash */
|
|
mindash = p[i];
|
|
mini = i;
|
|
}
|
|
if (maxgap < p[i+1]) { /* find max dash */
|
|
maxgap = p[i+1];
|
|
maxc = i+1;
|
|
}
|
|
if (mingap > p[i+1]) { /* find min gap */
|
|
mingap = p[i+1];
|
|
minc = i+1;
|
|
}
|
|
}
|
|
|
|
/* decide minimum *.....* length */
|
|
alen = mingap + 2*min(mindash,2);
|
|
blen = mingap + 2*min(maxdash,2);
|
|
clen = mingap + 2*min(p[prev(minc,np)],p[nxt(minc,np)]);
|
|
dlen = maxgap + 2*min(mindash,2);
|
|
elen = maxgap + 2*min(maxdash,2);
|
|
flen = maxgap + 2*min(p[prev(maxc,np)],p[nxt(maxc,np)]);
|
|
|
|
/* 1.3 is a magic number */
|
|
/* 8 <7 7> => [********] */
|
|
/* 3 <1 5> => [* *] */
|
|
if (len <= alen) {
|
|
if (len <= 1.3*maxdash) { /* draw a solid line */
|
|
*lcount = len;
|
|
*rcount = 0;
|
|
auxp[0] = len;
|
|
*auxnp = 1;
|
|
*bestc = -1;
|
|
return;
|
|
}
|
|
else { /* draw a *....* line w/ adaptive gap */
|
|
*lcount = len;
|
|
*rcount = 0;
|
|
auxp[0] = auxp[2] = min(2,maxdash);
|
|
auxp[1] = len -2*auxp[0];
|
|
*auxnp = 3;
|
|
*bestc = -1;
|
|
return;
|
|
}
|
|
}
|
|
|
|
if (len >= blen && len <= clen) { /* draw *..* line w/ fixed gap */
|
|
*lcount = len;
|
|
*rcount = 0;
|
|
auxp[2] = (len-mingap)/2;
|
|
if (!((len-mingap) & 1)) /* even */
|
|
auxp[0] = auxp[2];
|
|
else
|
|
auxp[0] = auxp[2] + 1;
|
|
auxp[1] = mingap;
|
|
*auxnp = 3;
|
|
*bestc = -1;
|
|
return;
|
|
}
|
|
|
|
if (len < dlen) {
|
|
*lcount = len;
|
|
*rcount = 0;
|
|
if (len <= 1.3*maxdash) { /* draw a solid line */
|
|
auxp[0] = len;
|
|
*auxnp = 1;
|
|
*bestc = -1;
|
|
return;
|
|
}
|
|
else { /* draw a *..* line w/ adaptive gap */
|
|
auxp[0] = auxp[2] = min(2,maxdash);
|
|
auxp[1] = len - 2*auxp[0];
|
|
*auxnp = 3;
|
|
*bestc = -1;
|
|
return;
|
|
}
|
|
}
|
|
|
|
if (len >= elen && len <= flen) { /* draw *..* line w/ fixed gap */
|
|
*lcount = len;
|
|
*rcount = 0;
|
|
auxp[2] = (len-maxgap)/2;
|
|
if (even(len-maxgap)) /* even */
|
|
auxp[0] = auxp[2];
|
|
else
|
|
auxp[0] = auxp[2] + 1;
|
|
auxp[1] = maxgap;
|
|
*auxnp = 2;
|
|
*bestc = -1;
|
|
return;
|
|
}
|
|
|
|
c = 0;
|
|
for (i=0; i<np; i++) {
|
|
bal = 1;
|
|
for (j=1; j<np/2+1; j++) {
|
|
if (p[(i+j)%np] != p[(i-j+np)%np]) {
|
|
bal = 0;
|
|
break;
|
|
}
|
|
}
|
|
if (bal == 1) {
|
|
center[c++] = i;
|
|
}
|
|
}
|
|
|
|
nc = c; /* no of portion can be used as center */
|
|
if (nc == 0) { /* impossible to balance */
|
|
nc = 1;
|
|
center[0] = maxi;
|
|
}
|
|
|
|
/* get the remainder */
|
|
unit = 0;
|
|
for (i=0; i<np; i++) unit += p[i];
|
|
scoremax = -9999;
|
|
for (c=0; c<nc; c++) {
|
|
if (len <= p[center[c]]) {
|
|
if (center[c] & 1) { /* gap */
|
|
score[c] = -9999;
|
|
}
|
|
else { /* dash */
|
|
score[c] = 0;
|
|
flg[c] = 0;
|
|
}
|
|
}
|
|
else {
|
|
h = (len-p[center[c]])/2 + p[center[c]];
|
|
rem = h % unit;
|
|
nfold = h / unit; /* no of fold */
|
|
nport = 0;
|
|
for (i=center[c]; rem>0; i=(i+1)%np) {
|
|
rem -= p[i];
|
|
nport += 1;
|
|
}
|
|
nport += nfold * np;
|
|
|
|
if (nport == 1) { /* special case */
|
|
flg[c] = 0;
|
|
score[c] = 0;
|
|
}
|
|
else { /* more than 1 portion */
|
|
flag = 0;
|
|
score[c] = heur(rem,(i-1+np)%np,nport,np,p,&flag);
|
|
flg[c] = flag;
|
|
}
|
|
}
|
|
if (score[c] > scoremax) {
|
|
scoremax = score[c];
|
|
*bestc = center[c];
|
|
fflag = flg[c];
|
|
}
|
|
} /* end for (c) loop */
|
|
|
|
if ((len <= p[*bestc]) || (len - p[*bestc] <= 1)) {
|
|
*lcount = len;
|
|
*rcount = 0;
|
|
auxp[0] = len;
|
|
*auxnp = 1;
|
|
*bestc = -1;
|
|
return;
|
|
}
|
|
|
|
do_bal(len,*bestc,fflag,np,p,auxnp,auxp,seg,offset,lcount,rcount);
|
|
}
|
|
|
|
|
|
static int
|
|
heur(rem,i,nport,np,p,flag)
|
|
int rem;
|
|
int i;
|
|
int nport;
|
|
int np;
|
|
short* p;
|
|
int* flag;
|
|
{
|
|
int sc, shksc, strsc, mersc;
|
|
int endp;
|
|
int strchlen, strratio;
|
|
int xtra;
|
|
|
|
sc = -999;
|
|
shksc = -999;
|
|
strsc = -999;
|
|
mersc = -999;
|
|
|
|
/* exactly match */
|
|
if (rem == 0) {
|
|
if (isgap(i)) { /* match gap */
|
|
/* get the score for shrinking gap */
|
|
|
|
if (p[i] > (0.5*mingap+min(2,maxdash))) { /* shrink gap */
|
|
endp = i;
|
|
shksc = -40*mingap/(p[i]-2);
|
|
}
|
|
|
|
/* get the score for stretching segment */
|
|
strchlen = p[i];
|
|
endp = prev(i,np);
|
|
|
|
if (p[endp]+strchlen > 1.3*maxdash) { /* serious stretch */
|
|
strsc = -60*strchlen/p[endp];
|
|
}
|
|
else { /* minor stretch */
|
|
strsc = -20*strchlen/p[endp];
|
|
}
|
|
|
|
if (shksc > strsc) { /* shrink gap */
|
|
sc = shksc;
|
|
*flag = 2;
|
|
}
|
|
else { /* stretch segment */
|
|
sc = strsc;
|
|
*flag = 1;
|
|
}
|
|
|
|
return sc;
|
|
}
|
|
else { /* match segment */
|
|
|
|
endp = i;
|
|
|
|
if (p[endp] == 1) { /* end segment == 1 */
|
|
if (maxdash == 1) { /* since the max dash is 1, O.K. */
|
|
sc = 999;
|
|
*flag = 0;
|
|
}
|
|
else { /* evaluate shrink and stretch */
|
|
/* get the score for shrinking gap */
|
|
if (p[prev(i,np)] > (0.5*mingap+2)) { /* shrink gap */
|
|
shksc = -40*mingap/(p[i]);
|
|
}
|
|
strratio = (p[prev(endp,np)]+p[endp])/p[(endp-2+np)%np];
|
|
if (nport>2 && strratio < 0.3) { /* can be stretched */
|
|
strsc = -40*strratio; /* penalty for stretch */
|
|
}
|
|
else { /* serious penalty */
|
|
strsc = -60*strratio; /* avoid short end dash */
|
|
}
|
|
if (shksc > strsc) { /* shrink gap */
|
|
sc = shksc;
|
|
*flag = 2;
|
|
}
|
|
else { /* stretch segment */
|
|
sc = strsc;
|
|
*flag = 1;
|
|
}
|
|
}
|
|
}
|
|
else { /* match segment and segment > 1 */
|
|
sc = 999;
|
|
*flag = 0;
|
|
}
|
|
}
|
|
return sc;
|
|
}
|
|
else if (rem < 0) { /* not exactly match */
|
|
if (isgap(i)) { /* end is gap */
|
|
xtra = rem+p[i]; /* extra portion */
|
|
if (xtra > (0.5*mingap+min(2,maxdash))) { /* */
|
|
shksc = -40*mingap/xtra;
|
|
}
|
|
strchlen = xtra; /* stretch length */
|
|
endp = prev(i,np);
|
|
if (p[endp]+strchlen > 1.3*maxdash) { /* serious penalty */
|
|
strsc = -20*strchlen/p[endp]-60*strchlen/maxdash;
|
|
}
|
|
else { /* minor penalty */
|
|
strsc = -20*strchlen/p[endp];
|
|
}
|
|
if (p[(i-2+np)%np]+p[prev(i,np)]+xtra < 1.6*maxgap && nport > 2) {
|
|
/* merge two gaps together */
|
|
mersc = -80*(p[endp]+xtra)/p[prev(endp,np)];
|
|
}
|
|
if (shksc > strsc) {
|
|
if (shksc > mersc) {
|
|
sc = shksc;
|
|
*flag = 2;
|
|
}
|
|
else {
|
|
sc = mersc;
|
|
*flag = 3;
|
|
}
|
|
}
|
|
else {
|
|
if (strsc > mersc) {
|
|
sc = strsc;
|
|
*flag = 1;
|
|
}
|
|
else {
|
|
sc = mersc;
|
|
*flag = 3;
|
|
}
|
|
}
|
|
|
|
return sc;
|
|
}
|
|
else { /* end is segment */
|
|
/* can be stay, stretch, shrink, but not merge */
|
|
endp = i;
|
|
xtra = p[endp] + rem;
|
|
|
|
if (xtra == 1) {
|
|
strratio = (p[prev(endp,np)]+1)/p[(endp-2+np)%np];
|
|
if (nport>1 && strratio < 0.3) { /* minor penalty */
|
|
strsc = -30*(p[prev(endp,np)]+1)/p[(endp-2+np)%np];
|
|
}
|
|
else { /* severe penalty */
|
|
strsc = -200*strratio; /* avoid end segment == 1 */
|
|
}
|
|
/* try shrink gap */
|
|
if (p[prev(i,np)]+1 > 0.5*mingap+min(2,maxdash)) {
|
|
shksc = -40*mingap/(p[prev(i,np)]+1);
|
|
}
|
|
}
|
|
else { /* xtra > 1 */
|
|
sc = (5*xtra/p[prev(endp,np)]);
|
|
*flag = 0;
|
|
}
|
|
if (sc > 0) {
|
|
*flag = 0;
|
|
}
|
|
else {
|
|
if (shksc > strsc) {
|
|
sc = shksc;
|
|
*flag = 2;
|
|
}
|
|
else {
|
|
sc = strsc;
|
|
*flag = 1;
|
|
}
|
|
}
|
|
}
|
|
return sc;
|
|
}
|
|
return sc;
|
|
}
|
|
|
|
|
|
static int
|
|
do_bal(len,bestc,fillflg,np,p,auxnp,auxp,seg,offset,lcount,rcount)
|
|
int len, bestc, fillflg;
|
|
int np;
|
|
short* p;
|
|
short* auxp;
|
|
int* auxnp;
|
|
int* seg;
|
|
int* offset;
|
|
int* lcount;
|
|
int* rcount;
|
|
{
|
|
int k, kl;
|
|
int endlen;
|
|
int i;
|
|
int symmetry;
|
|
int noseg;
|
|
|
|
*auxnp = 0; /* always initialize it */
|
|
hrsave = hr = (len-p[bestc])/2 + p[bestc]; /* right half */
|
|
hl = len - hr; /* left half */
|
|
if (even(len) ^ even(p[bestc]))
|
|
symmetry = 0;
|
|
else
|
|
symmetry = 1;
|
|
|
|
noseg = 0;
|
|
kl = k = bestc; /* kl is left side starting segment */
|
|
for (i=0; hr > 0; i++) {
|
|
if (hr < p[k])
|
|
break;
|
|
else {
|
|
hr -= p[k];
|
|
k = (k+1)%np;
|
|
kl = (kl-1+np)%np;
|
|
noseg++;
|
|
}
|
|
}
|
|
if (hr == 0) {
|
|
k = (k-1+np)%np;
|
|
kl = (kl+1)%np;
|
|
noseg--;
|
|
}
|
|
|
|
/* decide no of segment (ns) */
|
|
|
|
if (hr == 0) { /* exactly match */
|
|
if (isgap(k)) { /* match gap, need to stretch */
|
|
/* .......*******....... */
|
|
/* (i-3) (i-2) (i-1) */
|
|
/* k */
|
|
/* hr == 0 */
|
|
*rcount = p[k];
|
|
*lcount = (symmetry)? (*rcount): (*rcount+1);
|
|
if (fillflg == 1) { /* stretch */
|
|
auxp[0] = p[k];
|
|
*auxnp = 1;
|
|
*seg = (kl+1)%np;
|
|
*offset = p[*seg];
|
|
}
|
|
else if (fillflg == 2) { /* don't stretch, use mindash as end instead */
|
|
auxp[0] = mindash;
|
|
auxp[1] = p[k] - mindash;
|
|
*auxnp = 2;
|
|
*seg = (kl+1)%np;
|
|
*offset = p[*seg];
|
|
}
|
|
}
|
|
else { /* match segment */
|
|
if (fillflg == 0) {
|
|
*rcount = p[k];
|
|
*lcount = (symmetry)? (*rcount): (*rcount+1);
|
|
auxp[0] = p[k];
|
|
*auxnp = 1;
|
|
*seg = (kl+1)%np;
|
|
*offset = p[*seg];
|
|
}
|
|
else if (fillflg == 1) { /* stretch for special end treatment */
|
|
auxp[0] = p[k] + p[prev(k,np)];
|
|
*auxnp = 1;
|
|
*rcount = auxp[0];
|
|
*lcount = (symmetry)? (*rcount): (*rcount+1);
|
|
*seg = (kl+2)%np;
|
|
*offset = p[*seg];
|
|
}
|
|
else if (fillflg == 2) { /* shrink for special end treatment */
|
|
int trim;
|
|
|
|
trim = 2-p[k];
|
|
auxp[0] = 2;
|
|
auxp[1] = p[prev(k,np)] - trim;
|
|
*rcount = auxp[0]+auxp[1];
|
|
*lcount = (symmetry)? (*rcount): (*rcount+1);
|
|
*auxnp = 2;
|
|
*seg = (kl+2)%np;
|
|
*offset = p[*seg];
|
|
}
|
|
}
|
|
}
|
|
else { /* nomatch, */
|
|
if (isgap(k)) { /* gap cut off */
|
|
/* ......*****...... */
|
|
/* (i-2) (i-1) i */
|
|
/* k */
|
|
/* hr > 0 */
|
|
if (fillflg == 1) { /* allow stretch */
|
|
*rcount = hr;
|
|
*lcount = (symmetry)? (*rcount): (*rcount+1);
|
|
auxp[0] = hr;
|
|
*auxnp = 1;
|
|
*seg = (kl+1)%np;
|
|
*offset = p[*seg];
|
|
}
|
|
else if (fillflg == 2) { /* shrink */
|
|
*rcount = hr;
|
|
*lcount = (symmetry)? (*rcount): (*rcount+1);
|
|
endlen = min(2,maxdash);
|
|
auxp[1] = hr - endlen;
|
|
auxp[0] = endlen;
|
|
*auxnp = 2;
|
|
*seg = (kl+1)%np;
|
|
*offset = p[*seg];
|
|
}
|
|
else if (fillflg == 3) { /* merge two gaps together */
|
|
if (noseg > 2) {
|
|
auxp[1] = p[(k-2+np)%np] + p[(k-1+np)%np] + hr - mindash;
|
|
auxp[0] = mindash;
|
|
*auxnp = 2;
|
|
*rcount = auxp[0] + auxp[1];
|
|
*lcount = (symmetry)? (*rcount): (*rcount+1);
|
|
*seg = (kl+3)%np;
|
|
*offset = p[*seg];
|
|
}
|
|
else {
|
|
auxp[0] = mindash; /*(symmetry)? (mindash): (mindash+1);*/
|
|
auxp[2] = mindash;
|
|
auxp[1] = len - auxp[0] - auxp[2];
|
|
*auxnp = 3;
|
|
*rcount = 0;
|
|
*lcount = len;
|
|
}
|
|
}
|
|
}
|
|
else { /* nomatch, end dash */
|
|
if (fillflg == 0) { /* regular cut */
|
|
auxp[0] = hr;
|
|
*rcount = hr;
|
|
*lcount = (symmetry)? (*rcount): (*rcount+1);
|
|
*auxnp = 1;
|
|
*seg = (kl+1)%np;
|
|
*offset = p[*seg];
|
|
}
|
|
else if (fillflg == 1) { /* special end treatment */
|
|
/* merge (i-1) and (i) into (i-2) segment */
|
|
auxp[0] = p[prev(k,np)] + hr;
|
|
*auxnp = 1;
|
|
*rcount = auxp[0];
|
|
*lcount = (symmetry)? (*rcount): (*rcount+1);
|
|
*seg = (kl+2)%np;
|
|
*offset = p[*seg];
|
|
}
|
|
else if (fillflg == 2) {
|
|
auxp[0] = mindash;
|
|
auxp[1] = p[(k-1+np)%np] - (mindash - hr);
|
|
*auxnp = 2;
|
|
*rcount = auxp[0]+auxp[1];
|
|
*lcount = (symmetry)? (*rcount): (*rcount+1);
|
|
*seg = (kl+2)%np;
|
|
*offset = p[*seg];
|
|
}
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
|
|
static void
|
|
clip_offset1(clip_off,majax,count,numsegs,segment,lauxnp,lauxp,auxnp,auxp,
|
|
lcount,mcount,rcount,lseg,loffset,seg,offset,rseg,roffset)
|
|
int clip_off;
|
|
int majax;
|
|
int count;
|
|
int numsegs;
|
|
short segment[];
|
|
int auxnp;
|
|
short auxp[];
|
|
int lauxnp;
|
|
short lauxp[];
|
|
int* lcount;
|
|
int* mcount;
|
|
int* rcount;
|
|
int* lseg;
|
|
int* loffset;
|
|
int* seg;
|
|
int* offset;
|
|
int* rseg;
|
|
int* roffset;
|
|
{
|
|
if (clip_off == 0 && count < majax+1) { /* right clipping */
|
|
if (count <= *lcount ) {
|
|
*lcount = count;
|
|
*mcount = *rcount = 0;
|
|
}
|
|
else if (count <= *lcount+*mcount) {
|
|
*mcount = count - *lcount;
|
|
*rcount = 0;
|
|
}
|
|
else {
|
|
*rcount = count - *lcount - *mcount;
|
|
}
|
|
}
|
|
else { /* left clipping */
|
|
if (clip_off <= *lcount) { /* within left */
|
|
*lcount -= clip_off;
|
|
if (*lcount) {
|
|
for (; clip_off>0; (*lseg)++, *loffset=lauxp[*lseg]) {
|
|
clip_off -= *loffset;
|
|
}
|
|
if (clip_off < 0) {
|
|
*loffset = -clip_off;
|
|
(*lseg)--;
|
|
}
|
|
}
|
|
}
|
|
else if (clip_off <= *lcount + *mcount) { /* within middle */
|
|
*mcount += *lcount-clip_off;
|
|
clip_off -= *lcount;
|
|
*lcount = 0;
|
|
if (*mcount) {
|
|
for (; clip_off>0; *seg=(*seg+1)%numsegs, *offset=segment[*seg]) {
|
|
clip_off -= *offset;
|
|
}
|
|
if (clip_off < 0) {
|
|
*offset = -clip_off;
|
|
(*seg)--;
|
|
}
|
|
}
|
|
}
|
|
else { /* within right */
|
|
*rcount += *lcount + *mcount-clip_off;
|
|
clip_off -= (*lcount + *mcount);
|
|
*lcount = *mcount = 0;
|
|
if (*rcount) {
|
|
for (; clip_off>0; (*rseg)--, *roffset=auxp[*rseg]) {
|
|
clip_off -= *roffset;
|
|
}
|
|
if (clip_off < 0) {
|
|
*roffset = -clip_off;
|
|
(*rseg)++;
|
|
}
|
|
}
|
|
} /* end if */
|
|
}
|
|
}
|
|
|