428261197a
Tested by ajacoutot@, krw@, shadchin@ and jasper@ on various configurations including multihead with both zaphod and xrandr.
922 lines
22 KiB
C
922 lines
22 KiB
C
/*
|
|
|
|
XAAPolylinesWideSolid does not maintain a span list and subsequently does
|
|
not follow the "touch-each-pixel-once" rules for wide lines and arcs.
|
|
This means it can only be used in the case where we have
|
|
miSpansEasyRop(pGC->alu). Since we clip spans on the fly, we
|
|
limited usage of this function to one rect situations. This
|
|
function is used only for solid lines.
|
|
|
|
Adapted from miWideLine by Mark Vojkovich (mvojkovi@ucsd.edu)
|
|
Original mi code written by Keith Packard.
|
|
|
|
*/
|
|
|
|
#ifdef HAVE_XORG_CONFIG_H
|
|
#include <xorg-config.h>
|
|
#endif
|
|
|
|
#include <math.h>
|
|
|
|
#include "misc.h"
|
|
#include "xf86.h"
|
|
#include "xf86_OSproc.h"
|
|
|
|
#include <X11/X.h>
|
|
#include "windowstr.h"
|
|
#include "gcstruct.h"
|
|
#include "regionstr.h"
|
|
#include "miwideline.h"
|
|
#include "mi.h"
|
|
#include "xf86str.h"
|
|
#include "xaa.h"
|
|
#include "xaalocal.h"
|
|
|
|
#define DRAW_POINT(pScrn, x, y) \
|
|
if(hardClip) (*infoRec->SubsequentSolidFillRect)(pScrn, x, y, 1, 1); \
|
|
else XAAPointHelper(pScrn, x, y)
|
|
|
|
#define FILL_RECT(pScrn, x, y, w, h) \
|
|
if(hardClip) (*infoRec->SubsequentSolidFillRect)(pScrn, x, y, w, h); \
|
|
else XAAFillRectHelper(pScrn, x, y, w, h)
|
|
|
|
#define FILL_SPAN(pScrn, x, y, w) \
|
|
if(hardClip) (*infoRec->SubsequentSolidFillRect)(pScrn, x, y, w, 1); \
|
|
else XAASpanHelper(pScrn, x, y, w)
|
|
|
|
|
|
#define CLIPSTEPEDGE(edgey,edge,edgeleft) \
|
|
if (ybase == edgey) { \
|
|
if (edgeleft) { \
|
|
if (edge->x > xcl) \
|
|
xcl = edge->x; \
|
|
} else { \
|
|
if (edge->x < xcr) \
|
|
xcr = edge->x; \
|
|
} \
|
|
edgey++; \
|
|
edge->x += edge->stepx; \
|
|
edge->e += edge->dx; \
|
|
if (edge->e > 0) { \
|
|
edge->x += edge->signdx; \
|
|
edge->e -= edge->dy; \
|
|
} \
|
|
}
|
|
|
|
static void
|
|
XAAPointHelper(ScrnInfoPtr pScrn, int x, int y)
|
|
{
|
|
XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_SCRNINFOPTR(pScrn);
|
|
BoxPtr extents = infoRec->ClipBox;
|
|
|
|
if((x >= extents->x1) && (x < extents->x2) &&
|
|
(y >= extents->y1) && (y < extents->y2))
|
|
(*infoRec->SubsequentSolidFillRect)(pScrn, x, y, 1, 1);
|
|
}
|
|
|
|
static void
|
|
XAAFillRectHelper(ScrnInfoPtr pScrn, int x1, int y1, int dx, int dy)
|
|
{
|
|
XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_SCRNINFOPTR(pScrn);
|
|
BoxPtr extents = infoRec->ClipBox;
|
|
int x2 = x1 + dx;
|
|
int y2 = y1 + dy;
|
|
|
|
if(x1 < extents->x1) x1 = extents->x1;
|
|
if(x2 >= extents->x2) x2 = extents->x2;
|
|
if((dx = x2 - x1)<1) return;
|
|
if(y1 < extents->y1) y1 = extents->y1;
|
|
if(y2 >= extents->y2) y2 = extents->y2;
|
|
if((dy = y2 - y1)<1) return;
|
|
|
|
(*infoRec->SubsequentSolidFillRect)(pScrn, x1, y1, dx, dy);
|
|
}
|
|
|
|
|
|
static void
|
|
XAASpanHelper(ScrnInfoPtr pScrn, int x1, int y, int width)
|
|
{
|
|
XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_SCRNINFOPTR(pScrn);
|
|
BoxPtr extents = infoRec->ClipBox;
|
|
int x2;
|
|
|
|
if((y < extents->y1) || (y >= extents->y2)) return;
|
|
|
|
x2 = x1 + width;
|
|
if(x1 < extents->x1) x1 = extents->x1;
|
|
if(x2 > extents->x2) x2 = extents->x2;
|
|
width = x2 - x1;
|
|
|
|
if(width > 0)
|
|
(*infoRec->SubsequentSolidFillRect)(pScrn, x1, y, width, 1);
|
|
|
|
}
|
|
|
|
#define FixError(x, dx, dy, e, sign, step, h) { \
|
|
e += (h) * dx; \
|
|
x += (h) * step; \
|
|
if(e > 0) { \
|
|
x += e * sign/dy; \
|
|
e %= dy; \
|
|
if(e) { \
|
|
x += sign; \
|
|
e -= dy; \
|
|
} \
|
|
} \
|
|
}
|
|
|
|
|
|
static void
|
|
XAAFillPolyHelper (
|
|
GCPtr pGC,
|
|
int y, /* start y coordinate */
|
|
int overall_height, /* height of entire segment */
|
|
PolyEdgePtr left, PolyEdgePtr right,
|
|
int left_count, int right_count )
|
|
{
|
|
XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_GC(pGC);
|
|
BoxPtr extents = infoRec->ClipBox;
|
|
int left_x, left_e, left_stepx, left_signdx, left_dy, left_dx;
|
|
int right_x, right_e, right_stepx, right_signdx, right_dy, right_dx;
|
|
int height, left_height, right_height;
|
|
int xorg;
|
|
Bool hardClip;
|
|
|
|
if((y >= extents->y2) || ((y + overall_height) <= extents->y1))
|
|
return;
|
|
|
|
/* Muffle compiler */
|
|
left_x = left_e = left_stepx = left_signdx = left_dy = left_dx = 0;
|
|
right_x = right_e = right_stepx = right_signdx = right_dy = right_dx = 0;
|
|
|
|
left_height = right_height = 0;
|
|
xorg = 0;
|
|
|
|
hardClip = (infoRec->ClippingFlags & HARDWARE_CLIP_SOLID_FILL);
|
|
|
|
while ((left_count || left_height) && (right_count || right_height)) {
|
|
if (!left_height && left_count) {
|
|
left_height = left->height;
|
|
left_x = left->x + xorg;
|
|
left_stepx = left->stepx;
|
|
left_signdx = left->signdx;
|
|
left_e = left->e;
|
|
left_dy = left->dy;
|
|
left_dx = left->dx;
|
|
left_count--;
|
|
left++;
|
|
}
|
|
if (!right_height && right_count) {
|
|
right_height = right->height;
|
|
right_x = right->x + xorg + 1;
|
|
right_stepx = right->stepx;
|
|
right_signdx = right->signdx;
|
|
right_e = right->e;
|
|
right_dy = right->dy;
|
|
right_dx = right->dx;
|
|
right_count--;
|
|
right++;
|
|
}
|
|
|
|
height = (left_height > right_height) ? right_height : left_height;
|
|
|
|
left_height -= height;
|
|
right_height -= height;
|
|
|
|
if(hardClip && infoRec->SubsequentSolidFillTrap && (height > 6)) {
|
|
int right_DX, left_DX;
|
|
|
|
right_DX = (right_dx * right_signdx) + (right_stepx * right_dy);
|
|
left_DX = (left_dx * left_signdx) + (left_stepx * left_dy);
|
|
|
|
(*infoRec->SubsequentSolidFillTrap)(infoRec->pScrn, y, height,
|
|
left_x, left_DX, left_dy, left_e,
|
|
right_x - 1, right_DX, right_dy, right_e);
|
|
|
|
FixError(left_x, left_dx, left_dy, left_e, left_signdx,
|
|
left_stepx, height);
|
|
FixError(right_x, right_dx, right_dy, right_e, right_signdx,
|
|
right_stepx, height);
|
|
y += height;
|
|
continue;
|
|
}
|
|
|
|
while (height--) {
|
|
if(right_x > left_x) {
|
|
FILL_SPAN(infoRec->pScrn, left_x, y, right_x - left_x);
|
|
}
|
|
y++;
|
|
|
|
left_x += left_stepx;
|
|
left_e += left_dx;
|
|
if (left_e > 0) {
|
|
left_x += left_signdx;
|
|
left_e -= left_dy;
|
|
}
|
|
right_x += right_stepx;
|
|
right_e += right_dx;
|
|
if (right_e > 0) {
|
|
right_x += right_signdx;
|
|
right_e -= right_dy;
|
|
}
|
|
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
XAAWideSegment (
|
|
GCPtr pGC,
|
|
int x1, int y1, int x2, int y2,
|
|
Bool projectLeft, Bool projectRight,
|
|
LineFacePtr leftFace, LineFacePtr rightFace )
|
|
{
|
|
XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_GC(pGC);
|
|
double l, L, r;
|
|
double xa, ya;
|
|
double projectXoff, projectYoff;
|
|
double k;
|
|
double maxy;
|
|
int x, y;
|
|
int dx, dy;
|
|
int finaly;
|
|
PolyEdgePtr left, right;
|
|
PolyEdgePtr top, bottom;
|
|
int lefty, righty, topy, bottomy;
|
|
int signdx;
|
|
PolyEdgeRec lefts[2], rights[2];
|
|
LineFacePtr tface;
|
|
int lw = pGC->lineWidth;
|
|
Bool hardClip = (infoRec->ClippingFlags & HARDWARE_CLIP_SOLID_FILL);
|
|
|
|
/* draw top-to-bottom always */
|
|
if ((y2 < y1) || ((y2 == y1) && (x2 < x1))) {
|
|
x = x1;
|
|
x1 = x2;
|
|
x2 = x;
|
|
|
|
y = y1;
|
|
y1 = y2;
|
|
y2 = y;
|
|
|
|
x = projectLeft;
|
|
projectLeft = projectRight;
|
|
projectRight = x;
|
|
|
|
tface = leftFace;
|
|
leftFace = rightFace;
|
|
rightFace = tface;
|
|
}
|
|
|
|
dy = y2 - y1;
|
|
signdx = 1;
|
|
dx = x2 - x1;
|
|
if (dx < 0)
|
|
signdx = -1;
|
|
|
|
leftFace->x = x1;
|
|
leftFace->y = y1;
|
|
leftFace->dx = dx;
|
|
leftFace->dy = dy;
|
|
|
|
rightFace->x = x2;
|
|
rightFace->y = y2;
|
|
rightFace->dx = -dx;
|
|
rightFace->dy = -dy;
|
|
|
|
if (!dy) {
|
|
rightFace->xa = 0;
|
|
rightFace->ya = (double) lw / 2.0;
|
|
rightFace->k = -(double) (lw * dx) / 2.0;
|
|
leftFace->xa = 0;
|
|
leftFace->ya = -rightFace->ya;
|
|
leftFace->k = rightFace->k;
|
|
x = x1;
|
|
if (projectLeft)
|
|
x -= (lw >> 1);
|
|
y = y1 - (lw >> 1);
|
|
dx = x2 - x;
|
|
if (projectRight)
|
|
dx += ((lw + 1) >> 1);
|
|
dy = lw;
|
|
FILL_RECT(infoRec->pScrn, x, y, dx, dy);
|
|
} else if (!dx) {
|
|
leftFace->xa = (double) lw / 2.0;
|
|
leftFace->ya = 0;
|
|
leftFace->k = (double) (lw * dy) / 2.0;
|
|
rightFace->xa = -leftFace->xa;
|
|
rightFace->ya = 0;
|
|
rightFace->k = leftFace->k;
|
|
y = y1;
|
|
if (projectLeft)
|
|
y -= lw >> 1;
|
|
x = x1 - (lw >> 1);
|
|
dy = y2 - y;
|
|
if (projectRight)
|
|
dy += ((lw + 1) >> 1);
|
|
dx = lw;
|
|
FILL_RECT(infoRec->pScrn, x, y, dx, dy);
|
|
} else {
|
|
l = ((double) lw) / 2.0;
|
|
L = sqrt((double)(dx*dx + dy*dy));
|
|
|
|
if (dx < 0) {
|
|
right = &rights[1];
|
|
left = &lefts[0];
|
|
top = &rights[0];
|
|
bottom = &lefts[1];
|
|
} else {
|
|
right = &rights[0];
|
|
left = &lefts[1];
|
|
top = &lefts[0];
|
|
bottom = &rights[1];
|
|
}
|
|
r = l / L;
|
|
|
|
/* coord of upper bound at integral y */
|
|
ya = -r * dx;
|
|
xa = r * dy;
|
|
|
|
projectXoff = -ya;
|
|
projectYoff = xa;
|
|
|
|
/* xa * dy - ya * dx */
|
|
k = l * L;
|
|
|
|
leftFace->xa = xa;
|
|
leftFace->ya = ya;
|
|
leftFace->k = k;
|
|
rightFace->xa = -xa;
|
|
rightFace->ya = -ya;
|
|
rightFace->k = k;
|
|
|
|
if (projectLeft)
|
|
righty = miPolyBuildEdge (xa - projectXoff, ya - projectYoff,
|
|
k, dx, dy, x1, y1, 0, right);
|
|
else
|
|
righty = miPolyBuildEdge (xa, ya,
|
|
k, dx, dy, x1, y1, 0, right);
|
|
|
|
/* coord of lower bound at integral y */
|
|
ya = -ya;
|
|
xa = -xa;
|
|
|
|
/* xa * dy - ya * dx */
|
|
k = - k;
|
|
|
|
if (projectLeft)
|
|
lefty = miPolyBuildEdge (xa - projectXoff, ya - projectYoff,
|
|
k, dx, dy, x1, y1, 1, left);
|
|
else
|
|
lefty = miPolyBuildEdge (xa, ya,
|
|
k, dx, dy, x1, y1, 1, left);
|
|
|
|
/* coord of top face at integral y */
|
|
|
|
if (signdx > 0) {
|
|
ya = -ya;
|
|
xa = -xa;
|
|
}
|
|
|
|
if (projectLeft) {
|
|
double xap = xa - projectXoff;
|
|
double yap = ya - projectYoff;
|
|
topy = miPolyBuildEdge (xap, yap, xap * dx + yap * dy,
|
|
-dy, dx, x1, y1, dx > 0, top);
|
|
}
|
|
else
|
|
topy = miPolyBuildEdge(xa, ya, 0.0,
|
|
-dy, dx, x1, y1, dx > 0, top);
|
|
|
|
/* coord of bottom face at integral y */
|
|
|
|
if (projectRight) {
|
|
double xap = xa + projectXoff;
|
|
double yap = ya + projectYoff;
|
|
bottomy = miPolyBuildEdge (xap, yap, xap * dx + yap * dy,
|
|
-dy, dx, x2, y2, dx < 0, bottom);
|
|
maxy = -ya + projectYoff;
|
|
} else {
|
|
bottomy = miPolyBuildEdge (xa, ya, 0.0,
|
|
-dy, dx, x2, y2, dx < 0, bottom);
|
|
maxy = -ya;
|
|
}
|
|
|
|
finaly = ICEIL (maxy) + y2;
|
|
|
|
if (dx < 0) {
|
|
left->height = bottomy - lefty;
|
|
right->height = finaly - righty;
|
|
top->height = righty - topy;
|
|
} else {
|
|
right->height = bottomy - righty;
|
|
left->height = finaly - lefty;
|
|
top->height = lefty - topy;
|
|
}
|
|
bottom->height = finaly - bottomy;
|
|
XAAFillPolyHelper (pGC, topy,
|
|
bottom->height + bottomy - topy, lefts, rights, 2, 2);
|
|
}
|
|
}
|
|
|
|
|
|
static void
|
|
XAALineArcI (GCPtr pGC, int xorg, int yorg)
|
|
{
|
|
XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_GC(pGC);
|
|
int x, y, e, ex;
|
|
int slw = pGC->lineWidth;
|
|
Bool hardClip = (infoRec->ClippingFlags & HARDWARE_CLIP_SOLID_FILL);
|
|
|
|
y = (slw >> 1) + 1;
|
|
if (slw & 1)
|
|
e = - ((y << 2) + 3);
|
|
else
|
|
e = - (y << 3);
|
|
ex = -4;
|
|
x = 0;
|
|
while (y) {
|
|
e += (y << 3) - 4;
|
|
while (e >= 0) {
|
|
x++;
|
|
e += (ex = -((x << 3) + 4));
|
|
}
|
|
y--;
|
|
slw = (x << 1) + 1;
|
|
if ((e == ex) && (slw > 1))
|
|
slw--;
|
|
|
|
FILL_SPAN(infoRec->pScrn, xorg - x, yorg - y, slw);
|
|
|
|
if ((y != 0) && ((slw > 1) || (e != ex))) {
|
|
FILL_SPAN(infoRec->pScrn, xorg - x, yorg + y, slw);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
static void
|
|
XAALineArcD (
|
|
GCPtr pGC,
|
|
double xorg,
|
|
double yorg,
|
|
PolyEdgePtr edge1,
|
|
int edgey1,
|
|
Bool edgeleft1,
|
|
PolyEdgePtr edge2,
|
|
int edgey2,
|
|
Bool edgeleft2 )
|
|
{
|
|
XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_GC(pGC);
|
|
double radius, x0, y0, el, er, yk, xlk, xrk, k;
|
|
int xbase, ybase, y, boty, xl, xr, xcl, xcr;
|
|
int ymin, ymax;
|
|
Bool edge1IsMin, edge2IsMin;
|
|
int ymin1, ymin2;
|
|
Bool hardClip = (infoRec->ClippingFlags & HARDWARE_CLIP_SOLID_FILL);
|
|
|
|
|
|
xbase = floor(xorg);
|
|
x0 = xorg - xbase;
|
|
ybase = ICEIL (yorg);
|
|
y0 = yorg - ybase;
|
|
|
|
xlk = x0 + x0 + 1.0;
|
|
xrk = x0 + x0 - 1.0;
|
|
yk = y0 + y0 - 1.0;
|
|
radius = ((double)pGC->lineWidth) / 2.0;
|
|
y = floor(radius - y0 + 1.0);
|
|
ybase -= y;
|
|
ymin = ybase;
|
|
ymax = 65536;
|
|
edge1IsMin = FALSE;
|
|
ymin1 = edgey1;
|
|
if (edge1->dy >= 0) {
|
|
if (!edge1->dy) {
|
|
if (edgeleft1)
|
|
edge1IsMin = TRUE;
|
|
else
|
|
ymax = edgey1;
|
|
edgey1 = 65536;
|
|
} else if ((edge1->signdx < 0) == edgeleft1)
|
|
edge1IsMin = TRUE;
|
|
}
|
|
edge2IsMin = FALSE;
|
|
ymin2 = edgey2;
|
|
if (edge2->dy >= 0) {
|
|
if (!edge2->dy) {
|
|
if (edgeleft2)
|
|
edge2IsMin = TRUE;
|
|
else
|
|
ymax = edgey2;
|
|
edgey2 = 65536;
|
|
} else if ((edge2->signdx < 0) == edgeleft2)
|
|
edge2IsMin = TRUE;
|
|
}
|
|
if (edge1IsMin) {
|
|
ymin = ymin1;
|
|
if (edge2IsMin && (ymin1 > ymin2))
|
|
ymin = ymin2;
|
|
} else if (edge2IsMin)
|
|
ymin = ymin2;
|
|
el = radius * radius - ((y + y0) * (y + y0)) - (x0 * x0);
|
|
er = el + xrk;
|
|
xl = 1;
|
|
xr = 0;
|
|
if (x0 < 0.5) {
|
|
xl = 0;
|
|
el -= xlk;
|
|
}
|
|
boty = (y0 < -0.5) ? 1 : 0;
|
|
if (ybase + y - boty > ymax)
|
|
boty = ymax - ybase - y;
|
|
while (y > boty) {
|
|
k = (y << 1) + yk;
|
|
er += k;
|
|
while (er > 0.0) {
|
|
xr++;
|
|
er += xrk - (xr << 1);
|
|
}
|
|
el += k;
|
|
while (el >= 0.0) {
|
|
xl--;
|
|
el += (xl << 1) - xlk;
|
|
}
|
|
y--;
|
|
ybase++;
|
|
if (ybase < ymin)
|
|
continue;
|
|
xcl = xl + xbase;
|
|
xcr = xr + xbase;
|
|
CLIPSTEPEDGE(edgey1, edge1, edgeleft1);
|
|
CLIPSTEPEDGE(edgey2, edge2, edgeleft2);
|
|
if(xcr >= xcl) {
|
|
FILL_SPAN(infoRec->pScrn, xcl, ybase, xcr - xcl + 1);
|
|
}
|
|
}
|
|
er = xrk - (xr << 1) - er;
|
|
el = (xl << 1) - xlk - el;
|
|
boty = floor(-y0 - radius + 1.0);
|
|
if (ybase + y - boty > ymax)
|
|
boty = ymax - ybase - y;
|
|
while (y > boty) {
|
|
k = (y << 1) + yk;
|
|
er -= k;
|
|
while ((er >= 0.0) && (xr >= 0)) {
|
|
xr--;
|
|
er += xrk - (xr << 1);
|
|
}
|
|
el -= k;
|
|
while ((el > 0.0) && (xl <= 0)) {
|
|
xl++;
|
|
el += (xl << 1) - xlk;
|
|
}
|
|
y--;
|
|
ybase++;
|
|
if (ybase < ymin)
|
|
continue;
|
|
xcl = xl + xbase;
|
|
xcr = xr + xbase;
|
|
CLIPSTEPEDGE(edgey1, edge1, edgeleft1);
|
|
CLIPSTEPEDGE(edgey2, edge2, edgeleft2);
|
|
if(xcr >= xcl) {
|
|
FILL_SPAN(infoRec->pScrn, xcl, ybase, xcr - xcl + 1);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
static void
|
|
XAALineArc (
|
|
GCPtr pGC,
|
|
LineFacePtr leftFace,
|
|
LineFacePtr rightFace,
|
|
double xorg,
|
|
double yorg,
|
|
Bool isInt )
|
|
{
|
|
int xorgi, yorgi;
|
|
PolyEdgeRec edge1, edge2;
|
|
int edgey1, edgey2;
|
|
Bool edgeleft1, edgeleft2;
|
|
|
|
if (isInt) {
|
|
xorgi = leftFace ? leftFace->x : rightFace->x;
|
|
yorgi = leftFace ? leftFace->y : rightFace->y;
|
|
} else { /* Muffle compiler */
|
|
xorgi = yorgi = 0;
|
|
}
|
|
edgey1 = 65536;
|
|
edgey2 = 65536;
|
|
edge1.x = 0; /* not used, keep memory checkers happy */
|
|
edge1.dy = -1;
|
|
edge2.x = 0; /* not used, keep memory checkers happy */
|
|
edge2.dy = -1;
|
|
edgeleft1 = FALSE;
|
|
edgeleft2 = FALSE;
|
|
|
|
if ((pGC->lineWidth > 2) &&
|
|
((pGC->capStyle == CapRound && pGC->joinStyle != JoinRound) ||
|
|
(pGC->joinStyle == JoinRound && pGC->capStyle == CapButt))) {
|
|
if (isInt) {
|
|
xorg = (double) xorgi;
|
|
yorg = (double) yorgi;
|
|
}
|
|
|
|
if (leftFace && rightFace)
|
|
miRoundJoinClip (leftFace, rightFace, &edge1, &edge2,
|
|
&edgey1, &edgey2, &edgeleft1, &edgeleft2);
|
|
else if (leftFace)
|
|
edgey1 = miRoundCapClip (leftFace, isInt, &edge1, &edgeleft1);
|
|
else if (rightFace)
|
|
edgey2 = miRoundCapClip (rightFace, isInt, &edge2, &edgeleft2);
|
|
|
|
isInt = FALSE;
|
|
}
|
|
|
|
if (isInt) {
|
|
if(pGC->lineWidth == 1) {
|
|
XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_GC(pGC);
|
|
Bool hardClip = (infoRec->ClippingFlags & HARDWARE_CLIP_SOLID_FILL);
|
|
DRAW_POINT(infoRec->pScrn, xorgi, yorgi);
|
|
} else
|
|
XAALineArcI(pGC, xorgi, yorgi);
|
|
} else
|
|
XAALineArcD(pGC, xorg, yorg, &edge1, edgey1, edgeleft1,
|
|
&edge2, edgey2, edgeleft2);
|
|
|
|
}
|
|
|
|
|
|
static void
|
|
XAALineJoin (
|
|
GCPtr pGC,
|
|
LineFacePtr pLeft,
|
|
LineFacePtr pRight )
|
|
{
|
|
double mx = 0, my = 0;
|
|
double denom = 0;
|
|
PolyVertexRec vertices[4];
|
|
PolySlopeRec slopes[4];
|
|
int edgecount;
|
|
PolyEdgeRec left[4], right[4];
|
|
int nleft, nright;
|
|
int y, height;
|
|
int swapslopes;
|
|
int joinStyle = pGC->joinStyle;
|
|
int lw = pGC->lineWidth;
|
|
|
|
if (lw == 1) {
|
|
/* Lines going in the same direction have no join */
|
|
if ((pLeft->dx >= 0) == (pRight->dx <= 0))
|
|
return;
|
|
if (joinStyle != JoinRound) {
|
|
denom = - pLeft->dx * (double)pRight->dy + pRight->dx *
|
|
(double)pLeft->dy;
|
|
if (denom == 0.0)
|
|
return; /* no join to draw */
|
|
}
|
|
if (joinStyle != JoinMiter) {
|
|
XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_GC(pGC);
|
|
Bool hardClip = (infoRec->ClippingFlags & HARDWARE_CLIP_SOLID_FILL);
|
|
DRAW_POINT(infoRec->pScrn, pLeft->x, pLeft->y);
|
|
return;
|
|
}
|
|
} else {
|
|
if (joinStyle == JoinRound) {
|
|
XAALineArc(pGC, pLeft, pRight,(double)0.0, (double)0.0, TRUE);
|
|
return;
|
|
}
|
|
denom = - pLeft->dx * (double)pRight->dy + pRight->dx *
|
|
(double)pLeft->dy;
|
|
if (denom == 0.0)
|
|
return; /* no join to draw */
|
|
}
|
|
|
|
swapslopes = 0;
|
|
if (denom > 0) {
|
|
pLeft->xa = -pLeft->xa;
|
|
pLeft->ya = -pLeft->ya;
|
|
pLeft->dx = -pLeft->dx;
|
|
pLeft->dy = -pLeft->dy;
|
|
} else {
|
|
swapslopes = 1;
|
|
pRight->xa = -pRight->xa;
|
|
pRight->ya = -pRight->ya;
|
|
pRight->dx = -pRight->dx;
|
|
pRight->dy = -pRight->dy;
|
|
}
|
|
|
|
vertices[0].x = pRight->xa;
|
|
vertices[0].y = pRight->ya;
|
|
slopes[0].dx = -pRight->dy;
|
|
slopes[0].dy = pRight->dx;
|
|
slopes[0].k = 0;
|
|
|
|
vertices[1].x = 0;
|
|
vertices[1].y = 0;
|
|
slopes[1].dx = pLeft->dy;
|
|
slopes[1].dy = -pLeft->dx;
|
|
slopes[1].k = 0;
|
|
|
|
vertices[2].x = pLeft->xa;
|
|
vertices[2].y = pLeft->ya;
|
|
|
|
if (joinStyle == JoinMiter) {
|
|
my = (pLeft->dy * (pRight->xa * pRight->dy - pRight->ya * pRight->dx) -
|
|
pRight->dy * (pLeft->xa * pLeft->dy - pLeft->ya * pLeft->dx ))/
|
|
denom;
|
|
if (pLeft->dy != 0)
|
|
mx = pLeft->xa + (my - pLeft->ya) *
|
|
(double) pLeft->dx / (double) pLeft->dy;
|
|
else
|
|
mx = pRight->xa + (my - pRight->ya) *
|
|
(double) pRight->dx / (double) pRight->dy;
|
|
|
|
/* check miter limit */
|
|
if ((mx * mx + my * my) * 4 > SQSECANT * lw * lw)
|
|
joinStyle = JoinBevel;
|
|
}
|
|
|
|
if (joinStyle == JoinMiter) {
|
|
slopes[2].dx = pLeft->dx;
|
|
slopes[2].dy = pLeft->dy;
|
|
slopes[2].k = pLeft->k;
|
|
if (swapslopes) {
|
|
slopes[2].dx = -slopes[2].dx;
|
|
slopes[2].dy = -slopes[2].dy;
|
|
slopes[2].k = -slopes[2].k;
|
|
}
|
|
vertices[3].x = mx;
|
|
vertices[3].y = my;
|
|
slopes[3].dx = pRight->dx;
|
|
slopes[3].dy = pRight->dy;
|
|
slopes[3].k = pRight->k;
|
|
if (swapslopes) {
|
|
slopes[3].dx = -slopes[3].dx;
|
|
slopes[3].dy = -slopes[3].dy;
|
|
slopes[3].k = -slopes[3].k;
|
|
}
|
|
edgecount = 4;
|
|
} else {
|
|
double scale, dx, dy, adx, ady;
|
|
|
|
adx = dx = pRight->xa - pLeft->xa;
|
|
ady = dy = pRight->ya - pLeft->ya;
|
|
if (adx < 0)
|
|
adx = -adx;
|
|
if (ady < 0)
|
|
ady = -ady;
|
|
scale = ady;
|
|
if (adx > ady)
|
|
scale = adx;
|
|
slopes[2].dx = (dx * 65536) / scale;
|
|
slopes[2].dy = (dy * 65536) / scale;
|
|
slopes[2].k = ((pLeft->xa + pRight->xa) * slopes[2].dy -
|
|
(pLeft->ya + pRight->ya) * slopes[2].dx) / 2.0;
|
|
edgecount = 3;
|
|
}
|
|
|
|
y = miPolyBuildPoly (vertices, slopes, edgecount, pLeft->x, pLeft->y,
|
|
left, right, &nleft, &nright, &height);
|
|
XAAFillPolyHelper(pGC, y, height, left, right, nleft, nright);
|
|
}
|
|
|
|
|
|
void
|
|
XAAPolylinesWideSolid (
|
|
DrawablePtr pDrawable,
|
|
GCPtr pGC,
|
|
int mode,
|
|
int npt,
|
|
DDXPointPtr pPts )
|
|
{
|
|
XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_GC(pGC);
|
|
int x1, y1, x2, y2;
|
|
Bool projectLeft, projectRight;
|
|
LineFaceRec leftFace, rightFace, prevRightFace, firstFace;
|
|
int first = TRUE;
|
|
Bool somethingDrawn = FALSE;
|
|
Bool selfJoin = FALSE;
|
|
int xorg = pDrawable->x;
|
|
int yorg = pDrawable->y;
|
|
Bool hardClip = FALSE;
|
|
|
|
if(!RegionNumRects(pGC->pCompositeClip))
|
|
return;
|
|
|
|
if(RegionNumRects(pGC->pCompositeClip) != 1) {
|
|
miWideLine(pDrawable, pGC, mode, npt, pPts);
|
|
return;
|
|
}
|
|
|
|
x2 = pPts->x;
|
|
y2 = pPts->y;
|
|
if (npt > 1) {
|
|
if (mode == CoordModePrevious) {
|
|
int nptTmp;
|
|
register DDXPointPtr pPtsTmp;
|
|
|
|
x1 = x2;
|
|
y1 = y2;
|
|
nptTmp = npt;
|
|
pPtsTmp = pPts + 1;
|
|
while (--nptTmp) {
|
|
x1 += pPtsTmp->x;
|
|
y1 += pPtsTmp->y;
|
|
++pPtsTmp;
|
|
}
|
|
if ((x2 == x1) && (y2 == y1))
|
|
selfJoin = TRUE;
|
|
} else if ((x2 == pPts[npt-1].x) && (y2 == pPts[npt-1].y))
|
|
selfJoin = TRUE;
|
|
}
|
|
|
|
projectLeft = ((pGC->capStyle == CapProjecting) && !selfJoin);
|
|
projectRight = FALSE;
|
|
|
|
(*infoRec->SetupForSolidFill)(infoRec->pScrn, pGC->fgPixel, pGC->alu,
|
|
pGC->planemask);
|
|
|
|
infoRec->ClipBox = &pGC->pCompositeClip->extents;
|
|
|
|
if(infoRec->ClippingFlags & HARDWARE_CLIP_SOLID_FILL) {
|
|
hardClip = TRUE;
|
|
(*infoRec->SetClippingRectangle)(infoRec->pScrn,
|
|
infoRec->ClipBox->x1, infoRec->ClipBox->y1,
|
|
infoRec->ClipBox->x2 - 1, infoRec->ClipBox->y2 - 1);
|
|
}
|
|
|
|
x2 += xorg;
|
|
y2 += yorg;
|
|
while (--npt) {
|
|
x1 = x2;
|
|
y1 = y2;
|
|
++pPts;
|
|
x2 = pPts->x;
|
|
y2 = pPts->y;
|
|
if (mode == CoordModePrevious) {
|
|
x2 += x1;
|
|
y2 += y1;
|
|
} else {
|
|
x2 += xorg;
|
|
y2 += yorg;
|
|
}
|
|
if ((x1 != x2) || (y1 != y2)) {
|
|
somethingDrawn = TRUE;
|
|
if ((npt == 1) && (pGC->capStyle == CapProjecting) && !selfJoin)
|
|
projectRight = TRUE;
|
|
XAAWideSegment(pGC, x1, y1, x2, y2,
|
|
projectLeft, projectRight, &leftFace, &rightFace);
|
|
if (first) {
|
|
if (selfJoin)
|
|
firstFace = leftFace;
|
|
else if (pGC->capStyle == CapRound) {
|
|
if (pGC->lineWidth == 1) {
|
|
DRAW_POINT(infoRec->pScrn, x1, y1);
|
|
} else
|
|
XAALineArc(pGC,&leftFace, (LineFacePtr) NULL,
|
|
(double)0.0, (double)0.0,TRUE);
|
|
}
|
|
} else
|
|
XAALineJoin (pGC, &leftFace, &prevRightFace);
|
|
|
|
prevRightFace = rightFace;
|
|
first = FALSE;
|
|
projectLeft = FALSE;
|
|
}
|
|
if (npt == 1 && somethingDrawn) {
|
|
if (selfJoin)
|
|
XAALineJoin (pGC, &firstFace, &rightFace);
|
|
else if (pGC->capStyle == CapRound) {
|
|
if (pGC->lineWidth == 1) {
|
|
DRAW_POINT(infoRec->pScrn, x2, y2);
|
|
} else
|
|
XAALineArc (pGC, (LineFacePtr) NULL, &rightFace,
|
|
(double)0.0, (double)0.0,TRUE);
|
|
}
|
|
}
|
|
}
|
|
/* handle crock where all points are coincedent */
|
|
if (!somethingDrawn) {
|
|
projectLeft = (pGC->capStyle == CapProjecting);
|
|
XAAWideSegment (pGC, x2, y2, x2, y2, projectLeft, projectLeft,
|
|
&leftFace, &rightFace);
|
|
if (pGC->capStyle == CapRound) {
|
|
XAALineArc (pGC, &leftFace, (LineFacePtr) NULL,
|
|
(double)0.0, (double)0.0, TRUE);
|
|
rightFace.dx = -1; /* sleezy hack to make it work */
|
|
XAALineArc (pGC, (LineFacePtr) NULL, &rightFace,
|
|
(double)0.0, (double)0.0, TRUE);
|
|
}
|
|
}
|
|
|
|
infoRec->ClipBox = NULL;
|
|
if(hardClip)
|
|
(*infoRec->DisableClipping)(infoRec->pScrn);
|
|
|
|
SET_SYNC_FLAG(infoRec);
|
|
}
|