#ifdef HAVE_DIX_CONFIG_H
#include <dix-config.h>
#endif
#include <X11/X.h>
#include "misc.h"
#include "scrnintstr.h"
#include "gcstruct.h"
#include "windowstr.h"
#include "pixmap.h"
#include "mi.h"
#include "miline.h"
#define MAX_COORDINATE ((1 << (((sizeof(DDXPointRec) >> 1) << 3) - 1)) - 1)
#define MI_OUTPUT_POINT(xx, yy)\
{\
if ( !new_span && yy == current_y)\
{\
if (xx < spans->x)\
spans->x = xx;\
++*widths;\
}\
else\
{\
++Nspans;\
++spans;\
++widths;\
spans->x = xx;\
spans->y = yy;\
*widths = 1;\
current_y = yy;\
new_span = FALSE;\
}\
}
_X_EXPORT void
miZeroLine(
DrawablePtr pDraw,
GCPtr pGC,
int mode,
int npt,
DDXPointPtr pptInit)
{
int Nspans, current_y = 0;
DDXPointPtr ppt;
DDXPointPtr pspanInit, spans;
int *pwidthInit, *widths, list_len;
int xleft, ytop, xright, ybottom;
int new_x1, new_y1, new_x2, new_y2;
int x = 0, y = 0, x1, y1, x2, y2, xstart, ystart;
int oc1, oc2;
int result;
int pt1_clipped, pt2_clipped = 0;
Bool new_span;
int signdx, signdy;
int clipdx, clipdy;
int width, height;
int adx, ady;
int octant;
unsigned int bias = miGetZeroLineBias(pDraw->pScreen);
int e, e1, e2, e3;
int length;
xleft = pDraw->x;
ytop = pDraw->y;
xright = pDraw->x + pDraw->width - 1;
ybottom = pDraw->y + pDraw->height - 1;
if (!pGC->miTranslate)
{
xleft = 0;
ytop = 0;
xright -= pDraw->x;
ybottom -= pDraw->y;
}
if (xright > MAX_COORDINATE)
xright = MAX_COORDINATE;
if (ybottom > MAX_COORDINATE)
ybottom = MAX_COORDINATE;
width = xright - xleft + 1;
height = ybottom - ytop + 1;
list_len = (height >= width) ? height : width;
pspanInit = (DDXPointPtr)xalloc(list_len * sizeof(DDXPointRec));
pwidthInit = (int *)xalloc(list_len * sizeof(int));
if (!pspanInit || !pwidthInit)
return;
Nspans = 0;
new_span = TRUE;
spans = pspanInit - 1;
widths = pwidthInit - 1;
ppt = pptInit;
xstart = ppt->x;
ystart = ppt->y;
if (pGC->miTranslate)
{
xstart += pDraw->x;
ystart += pDraw->y;
}
x2 = xstart;
y2 = ystart;
oc2 = 0;
MIOUTCODES(oc2, x2, y2, xleft, ytop, xright, ybottom);
while (--npt > 0)
{
if (Nspans > 0)
(*pGC->ops->FillSpans)(pDraw, pGC, Nspans, pspanInit,
pwidthInit, FALSE);
Nspans = 0;
new_span = TRUE;
spans = pspanInit - 1;
widths = pwidthInit - 1;
x1 = x2;
y1 = y2;
oc1 = oc2;
++ppt;
x2 = ppt->x;
y2 = ppt->y;
if (pGC->miTranslate && (mode != CoordModePrevious))
{
x2 += pDraw->x;
y2 += pDraw->y;
}
else if (mode == CoordModePrevious)
{
x2 += x1;
y2 += y1;
}
oc2 = 0;
MIOUTCODES(oc2, x2, y2, xleft, ytop, xright, ybottom);
CalcLineDeltas(x1, y1, x2, y2, adx, ady, signdx, signdy, 1, 1, octant);
if (adx > ady)
{
e1 = ady << 1;
e2 = e1 - (adx << 1);
e = e1 - adx;
length = adx;
FIXUP_ERROR(e, octant, bias);
new_x1 = x1;
new_y1 = y1;
new_x2 = x2;
new_y2 = y2;
pt1_clipped = 0;
pt2_clipped = 0;
if ((oc1 | oc2) != 0)
{
result = miZeroClipLine(xleft, ytop, xright, ybottom,
&new_x1, &new_y1, &new_x2, &new_y2,
adx, ady,
&pt1_clipped, &pt2_clipped,
octant, bias, oc1, oc2);
if (result == -1)
continue;
length = abs(new_x2 - new_x1);
if (pt2_clipped)
length++;
if (pt1_clipped)
{
clipdx = abs(new_x1 - x1);
clipdy = abs(new_y1 - y1);
e += (clipdy * e2) + ((clipdx - clipdy) * e1);
}
}
x = new_x1;
y = new_y1;
e3 = e2 - e1;
e = e - e1;
while (length--)
{
MI_OUTPUT_POINT(x, y);
e += e1;
if (e >= 0)
{
y += signdy;
e += e3;
}
x += signdx;
}
}
else
{
e1 = adx << 1;
e2 = e1 - (ady << 1);
e = e1 - ady;
length = ady;
SetYMajorOctant(octant);
FIXUP_ERROR(e, octant, bias);
new_x1 = x1;
new_y1 = y1;
new_x2 = x2;
new_y2 = y2;
pt1_clipped = 0;
pt2_clipped = 0;
if ((oc1 | oc2) != 0)
{
result = miZeroClipLine(xleft, ytop, xright, ybottom,
&new_x1, &new_y1, &new_x2, &new_y2,
adx, ady,
&pt1_clipped, &pt2_clipped,
octant, bias, oc1, oc2);
if (result == -1)
continue;
length = abs(new_y2 - new_y1);
if (pt2_clipped)
length++;
if (pt1_clipped)
{
clipdx = abs(new_x1 - x1);
clipdy = abs(new_y1 - y1);
e += (clipdx * e2) + ((clipdy - clipdx) * e1);
}
}
x = new_x1;
y = new_y1;
e3 = e2 - e1;
e = e - e1;
while (length--)
{
MI_OUTPUT_POINT(x, y);
e += e1;
if (e >= 0)
{
x += signdx;
e += e3;
}
y += signdy;
}
}
}
if ( (! pt2_clipped) && (pGC->capStyle != CapNotLast) &&
(((xstart != x2) || (ystart != y2)) || (ppt == pptInit + 1)))
{
MI_OUTPUT_POINT(x, y);
}
if (Nspans > 0)
(*pGC->ops->FillSpans)(pDraw, pGC, Nspans, pspanInit,
pwidthInit, FALSE);
xfree(pwidthInit);
xfree(pspanInit);
}
void
miZeroDashLine(
DrawablePtr dst,
GCPtr pgc,
int mode,
int nptInit,
DDXPointRec *pptInit
)
{
pgc->lineWidth = 1;
miWideDash (dst, pgc, mode, nptInit, pptInit);
pgc->lineWidth = 0;
}