2003-11-14 16:54:54 +01:00
|
|
|
/*
|
|
|
|
|
|
|
|
Copyright 1988, 1998 The Open Group
|
|
|
|
|
|
|
|
Permission to use, copy, modify, distribute, and sell this software and its
|
|
|
|
documentation for any purpose is hereby granted without fee, provided that
|
|
|
|
the above copyright notice appear in all copies and that both that
|
|
|
|
copyright notice and this permission notice appear in supporting
|
|
|
|
documentation.
|
|
|
|
|
|
|
|
The above copyright notice and this permission notice shall be included
|
|
|
|
in all copies or substantial portions of the Software.
|
|
|
|
|
|
|
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
|
|
|
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
|
|
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
|
|
|
IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
|
|
|
OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
|
|
|
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
|
|
|
OTHER DEALINGS IN THE SOFTWARE.
|
|
|
|
|
|
|
|
Except as contained in this notice, the name of The Open Group shall
|
|
|
|
not be used in advertising or otherwise to promote the sale, use or
|
|
|
|
other dealings in this Software without prior written authorization
|
|
|
|
from The Open Group.
|
|
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
/* Author: Keith Packard, MIT X Consortium */
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Mostly integer wideline code. Uses a technique similar to
|
|
|
|
* bresenham zero-width lines, except walks an X edge
|
|
|
|
*/
|
|
|
|
|
2005-07-03 09:02:09 +02:00
|
|
|
#ifdef HAVE_DIX_CONFIG_H
|
|
|
|
#include <dix-config.h>
|
|
|
|
#endif
|
|
|
|
|
2003-11-14 16:54:54 +01:00
|
|
|
#include <stdio.h>
|
|
|
|
#ifdef _XOPEN_SOURCE
|
|
|
|
#include <math.h>
|
|
|
|
#else
|
2012-03-21 20:55:09 +01:00
|
|
|
#define _XOPEN_SOURCE /* to get prototype for hypot on some systems */
|
2003-11-14 16:54:54 +01:00
|
|
|
#include <math.h>
|
|
|
|
#undef _XOPEN_SOURCE
|
|
|
|
#endif
|
2005-04-20 14:25:48 +02:00
|
|
|
#include <X11/X.h>
|
2003-11-14 16:54:54 +01:00
|
|
|
#include "windowstr.h"
|
|
|
|
#include "gcstruct.h"
|
2003-11-25 20:29:01 +01:00
|
|
|
#include "regionstr.h"
|
2003-11-14 16:54:54 +01:00
|
|
|
#include "miwideline.h"
|
|
|
|
#include "mi.h"
|
|
|
|
|
2010-05-08 22:38:00 +02:00
|
|
|
static Bool
|
2012-03-21 20:55:09 +01:00
|
|
|
InitSpans(Spans * spans, size_t nspans)
|
2010-05-08 22:38:00 +02:00
|
|
|
{
|
2012-03-21 20:55:09 +01:00
|
|
|
spans->points = malloc(nspans * sizeof(*spans->points));
|
2010-05-08 22:38:00 +02:00
|
|
|
if (!spans->points)
|
2012-03-21 20:55:09 +01:00
|
|
|
return FALSE;
|
|
|
|
spans->widths = malloc(nspans * sizeof(*spans->widths));
|
|
|
|
if (!spans->widths) {
|
|
|
|
free(spans->points);
|
|
|
|
return FALSE;
|
2010-05-08 22:38:00 +02:00
|
|
|
}
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
2010-05-08 21:26:47 +02:00
|
|
|
/*
|
|
|
|
* interface data to span-merging polygon filler
|
|
|
|
*/
|
|
|
|
|
|
|
|
typedef struct _SpanData {
|
2012-03-21 20:55:09 +01:00
|
|
|
SpanGroup fgGroup, bgGroup;
|
2010-05-08 21:26:47 +02:00
|
|
|
} SpanDataRec, *SpanDataPtr;
|
|
|
|
|
|
|
|
static void
|
2012-03-21 20:55:09 +01:00
|
|
|
AppendSpanGroup(GCPtr pGC, unsigned long pixel, Spans * spanPtr,
|
|
|
|
SpanDataPtr spanData)
|
2010-05-08 21:26:47 +02:00
|
|
|
{
|
|
|
|
SpanGroup *group, *othergroup = NULL;
|
2012-03-21 20:55:09 +01:00
|
|
|
|
|
|
|
if (pixel == pGC->fgPixel) {
|
|
|
|
group = &spanData->fgGroup;
|
|
|
|
if (pGC->lineStyle == LineDoubleDash)
|
|
|
|
othergroup = &spanData->bgGroup;
|
2010-05-08 21:26:47 +02:00
|
|
|
}
|
2012-03-21 20:55:09 +01:00
|
|
|
else {
|
|
|
|
group = &spanData->bgGroup;
|
|
|
|
othergroup = &spanData->fgGroup;
|
2010-05-08 21:26:47 +02:00
|
|
|
}
|
2012-03-21 20:55:09 +01:00
|
|
|
miAppendSpans(group, othergroup, spanPtr);
|
2010-05-08 21:26:47 +02:00
|
|
|
}
|
|
|
|
|
2007-03-09 04:46:23 +01:00
|
|
|
static void miLineArc(DrawablePtr pDraw, GCPtr pGC,
|
2012-03-21 20:55:09 +01:00
|
|
|
unsigned long pixel, SpanDataPtr spanData,
|
|
|
|
LineFacePtr leftFace,
|
|
|
|
LineFacePtr rightFace,
|
|
|
|
double xorg, double yorg, Bool isInt);
|
2003-11-14 16:54:54 +01:00
|
|
|
|
|
|
|
/*
|
|
|
|
* spans-based polygon filler
|
|
|
|
*/
|
|
|
|
|
2010-05-08 21:06:50 +02:00
|
|
|
static void
|
2012-03-21 20:55:09 +01:00
|
|
|
fillSpans(DrawablePtr pDrawable, GCPtr pGC, unsigned long pixel, Spans * spans,
|
|
|
|
SpanDataPtr spanData)
|
2010-05-08 21:06:50 +02:00
|
|
|
{
|
2012-03-21 20:55:09 +01:00
|
|
|
if (!spanData) {
|
|
|
|
ChangeGCVal oldPixel, tmpPixel;
|
|
|
|
|
|
|
|
oldPixel.val = pGC->fgPixel;
|
|
|
|
if (pixel != oldPixel.val) {
|
|
|
|
tmpPixel.val = (XID) pixel;
|
|
|
|
ChangeGC(NullClient, pGC, GCForeground, &tmpPixel);
|
|
|
|
ValidateGC(pDrawable, pGC);
|
|
|
|
}
|
|
|
|
(*pGC->ops->FillSpans) (pDrawable, pGC, spans->count, spans->points,
|
|
|
|
spans->widths, TRUE);
|
|
|
|
free(spans->widths);
|
|
|
|
free(spans->points);
|
|
|
|
if (pixel != oldPixel.val) {
|
|
|
|
ChangeGC(NullClient, pGC, GCForeground, &oldPixel);
|
|
|
|
ValidateGC(pDrawable, pGC);
|
|
|
|
}
|
2010-05-08 21:06:50 +02:00
|
|
|
}
|
|
|
|
else
|
2012-03-21 20:55:09 +01:00
|
|
|
AppendSpanGroup(pGC, pixel, spans, spanData);
|
2010-05-08 21:06:50 +02:00
|
|
|
}
|
|
|
|
|
2007-03-25 23:56:32 +02:00
|
|
|
static void
|
2012-03-21 20:55:09 +01:00
|
|
|
miFillPolyHelper(DrawablePtr pDrawable, GCPtr pGC, unsigned long pixel,
|
|
|
|
SpanDataPtr spanData, int y, int overall_height,
|
|
|
|
PolyEdgePtr left, PolyEdgePtr right,
|
|
|
|
int left_count, int right_count)
|
2003-11-14 16:54:54 +01:00
|
|
|
{
|
2007-03-09 04:46:23 +01:00
|
|
|
int left_x = 0, left_e = 0;
|
2012-03-21 20:55:09 +01:00
|
|
|
int left_stepx = 0;
|
|
|
|
int left_signdx = 0;
|
|
|
|
int left_dy = 0, left_dx = 0;
|
2003-11-14 16:54:54 +01:00
|
|
|
|
2007-03-09 04:46:23 +01:00
|
|
|
int right_x = 0, right_e = 0;
|
2012-03-21 20:55:09 +01:00
|
|
|
int right_stepx = 0;
|
|
|
|
int right_signdx = 0;
|
|
|
|
int right_dy = 0, right_dx = 0;
|
2003-11-14 16:54:54 +01:00
|
|
|
|
2012-03-21 20:55:09 +01:00
|
|
|
int height = 0;
|
|
|
|
int left_height = 0, right_height = 0;
|
2003-11-14 16:54:54 +01:00
|
|
|
|
2007-03-09 04:46:23 +01:00
|
|
|
DDXPointPtr ppt;
|
2012-03-21 20:55:09 +01:00
|
|
|
int *pwidth;
|
|
|
|
int xorg;
|
|
|
|
Spans spanRec;
|
2003-11-14 16:54:54 +01:00
|
|
|
|
2010-05-08 22:38:00 +02:00
|
|
|
if (!InitSpans(&spanRec, overall_height))
|
2012-03-21 20:55:09 +01:00
|
|
|
return;
|
2010-05-08 22:38:00 +02:00
|
|
|
ppt = spanRec.points;
|
|
|
|
pwidth = spanRec.widths;
|
2003-11-14 16:54:54 +01:00
|
|
|
|
|
|
|
xorg = 0;
|
2012-03-21 20:55:09 +01:00
|
|
|
if (pGC->miTranslate) {
|
|
|
|
y += pDrawable->y;
|
|
|
|
xorg = pDrawable->x;
|
|
|
|
}
|
|
|
|
while ((left_count || left_height) && (right_count || right_height)) {
|
|
|
|
if (!left_height && left_count) {
|
|
|
|
left_height = left->height;
|
|
|
|
left_x = left->x;
|
|
|
|
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;
|
|
|
|
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;
|
|
|
|
if (height > right_height)
|
|
|
|
height = right_height;
|
|
|
|
|
|
|
|
left_height -= height;
|
|
|
|
right_height -= height;
|
|
|
|
|
|
|
|
while (--height >= 0) {
|
|
|
|
if (right_x >= left_x) {
|
|
|
|
ppt->y = y;
|
|
|
|
ppt->x = left_x + xorg;
|
|
|
|
ppt++;
|
|
|
|
*pwidth++ = right_x - left_x + 1;
|
|
|
|
}
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
}
|
2003-11-14 16:54:54 +01:00
|
|
|
}
|
2010-05-08 22:38:00 +02:00
|
|
|
spanRec.count = ppt - spanRec.points;
|
2012-03-21 20:55:09 +01:00
|
|
|
fillSpans(pDrawable, pGC, pixel, &spanRec, spanData);
|
2003-11-14 16:54:54 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2012-03-21 20:55:09 +01:00
|
|
|
miFillRectPolyHelper(DrawablePtr pDrawable,
|
|
|
|
GCPtr pGC,
|
|
|
|
unsigned long pixel,
|
|
|
|
SpanDataPtr spanData, int x, int y, int w, int h)
|
2003-11-14 16:54:54 +01:00
|
|
|
{
|
2007-03-09 04:46:23 +01:00
|
|
|
DDXPointPtr ppt;
|
2012-03-21 20:55:09 +01:00
|
|
|
int *pwidth;
|
|
|
|
ChangeGCVal oldPixel, tmpPixel;
|
|
|
|
Spans spanRec;
|
|
|
|
xRectangle rect;
|
|
|
|
|
|
|
|
if (!spanData) {
|
|
|
|
rect.x = x;
|
|
|
|
rect.y = y;
|
|
|
|
rect.width = w;
|
|
|
|
rect.height = h;
|
|
|
|
oldPixel.val = pGC->fgPixel;
|
|
|
|
if (pixel != oldPixel.val) {
|
|
|
|
tmpPixel.val = (XID) pixel;
|
|
|
|
ChangeGC(NullClient, pGC, GCForeground, &tmpPixel);
|
|
|
|
ValidateGC(pDrawable, pGC);
|
|
|
|
}
|
|
|
|
(*pGC->ops->PolyFillRect) (pDrawable, pGC, 1, &rect);
|
|
|
|
if (pixel != oldPixel.val) {
|
|
|
|
ChangeGC(NullClient, pGC, GCForeground, &oldPixel);
|
|
|
|
ValidateGC(pDrawable, pGC);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
if (!InitSpans(&spanRec, h))
|
|
|
|
return;
|
|
|
|
ppt = spanRec.points;
|
|
|
|
pwidth = spanRec.widths;
|
|
|
|
|
|
|
|
if (pGC->miTranslate) {
|
|
|
|
y += pDrawable->y;
|
|
|
|
x += pDrawable->x;
|
|
|
|
}
|
|
|
|
while (h--) {
|
|
|
|
ppt->x = x;
|
|
|
|
ppt->y = y;
|
|
|
|
ppt++;
|
|
|
|
*pwidth++ = w;
|
|
|
|
y++;
|
|
|
|
}
|
|
|
|
spanRec.count = ppt - spanRec.points;
|
|
|
|
AppendSpanGroup(pGC, pixel, &spanRec, spanData);
|
2003-11-14 16:54:54 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
Rework symbol visibility for easier maintenance
Save in a few special cases, _X_EXPORT should not be used in C source
files. Instead, it should be used in headers, and the proper C source
include that header. Some special cases are symbols that need to be
shared between modules, but not expected to be used by external drivers,
and symbols that are accessible via LoaderSymbol/dlopen.
This patch also adds conditionally some new sdk header files, depending
on extensions enabled. These files were added to match pattern for
other extensions/modules, that is, have the headers "deciding" symbol
visibility in the sdk. These headers are:
o Xext/panoramiXsrv.h, Xext/panoramiX.h
o fbpict.h (unconditionally)
o vidmodeproc.h
o mioverlay.h (unconditionally, used only by xaa)
o xfixes.h (unconditionally, symbols required by dri2)
LoaderSymbol and similar functions now don't have different prototypes,
in loaderProcs.h and xf86Module.h, so that both headers can be included,
without the need of defining IN_LOADER.
xf86NewInputDevice() device prototype readded to xf86Xinput.h, but
not exported (and with a comment about it).
2008-12-03 08:43:34 +01:00
|
|
|
/* static */ int
|
2012-03-21 20:55:09 +01:00
|
|
|
miPolyBuildEdge(double x0, double y0, double k, /* x0 * dy - y0 * dx */
|
|
|
|
int dx, int dy, int xi, int yi, int left, PolyEdgePtr edge)
|
2003-11-14 16:54:54 +01:00
|
|
|
{
|
2012-03-21 20:55:09 +01:00
|
|
|
int x, y, e;
|
|
|
|
int xady;
|
2003-11-14 16:54:54 +01:00
|
|
|
|
2012-03-21 20:55:09 +01:00
|
|
|
if (dy < 0) {
|
|
|
|
dy = -dy;
|
|
|
|
dx = -dx;
|
|
|
|
k = -k;
|
2003-11-14 16:54:54 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
#ifdef NOTDEF
|
|
|
|
{
|
2012-03-21 20:55:09 +01:00
|
|
|
double realk, kerror;
|
|
|
|
|
|
|
|
realk = x0 * dy - y0 * dx;
|
|
|
|
kerror = fabs(realk - k);
|
|
|
|
if (kerror > .1)
|
|
|
|
printf("realk: %g k: %g\n", realk, k);
|
2003-11-14 16:54:54 +01:00
|
|
|
}
|
|
|
|
#endif
|
2012-03-21 20:55:09 +01:00
|
|
|
y = ICEIL(y0);
|
|
|
|
xady = ICEIL(k) + y * dx;
|
2003-11-14 16:54:54 +01:00
|
|
|
|
|
|
|
if (xady <= 0)
|
2012-03-21 20:55:09 +01:00
|
|
|
x = -(-xady / dy) - 1;
|
2003-11-14 16:54:54 +01:00
|
|
|
else
|
2012-03-21 20:55:09 +01:00
|
|
|
x = (xady - 1) / dy;
|
2003-11-14 16:54:54 +01:00
|
|
|
|
|
|
|
e = xady - x * dy;
|
|
|
|
|
2012-03-21 20:55:09 +01:00
|
|
|
if (dx >= 0) {
|
|
|
|
edge->signdx = 1;
|
|
|
|
edge->stepx = dx / dy;
|
|
|
|
edge->dx = dx % dy;
|
2003-11-14 16:54:54 +01:00
|
|
|
}
|
2012-03-21 20:55:09 +01:00
|
|
|
else {
|
|
|
|
edge->signdx = -1;
|
|
|
|
edge->stepx = -(-dx / dy);
|
|
|
|
edge->dx = -dx % dy;
|
|
|
|
e = dy - e + 1;
|
2003-11-14 16:54:54 +01:00
|
|
|
}
|
|
|
|
edge->dy = dy;
|
|
|
|
edge->x = x + left + xi;
|
2012-03-21 20:55:09 +01:00
|
|
|
edge->e = e - dy; /* bias to compare against 0 instead of dy */
|
2003-11-14 16:54:54 +01:00
|
|
|
return y + yi;
|
|
|
|
}
|
|
|
|
|
|
|
|
#define StepAround(v, incr, max) (((v) + (incr) < 0) ? (max - 1) : ((v) + (incr) == max) ? 0 : ((v) + (incr)))
|
|
|
|
|
Rework symbol visibility for easier maintenance
Save in a few special cases, _X_EXPORT should not be used in C source
files. Instead, it should be used in headers, and the proper C source
include that header. Some special cases are symbols that need to be
shared between modules, but not expected to be used by external drivers,
and symbols that are accessible via LoaderSymbol/dlopen.
This patch also adds conditionally some new sdk header files, depending
on extensions enabled. These files were added to match pattern for
other extensions/modules, that is, have the headers "deciding" symbol
visibility in the sdk. These headers are:
o Xext/panoramiXsrv.h, Xext/panoramiX.h
o fbpict.h (unconditionally)
o vidmodeproc.h
o mioverlay.h (unconditionally, used only by xaa)
o xfixes.h (unconditionally, symbols required by dri2)
LoaderSymbol and similar functions now don't have different prototypes,
in loaderProcs.h and xf86Module.h, so that both headers can be included,
without the need of defining IN_LOADER.
xf86NewInputDevice() device prototype readded to xf86Xinput.h, but
not exported (and with a comment about it).
2008-12-03 08:43:34 +01:00
|
|
|
/* static */ int
|
2012-03-21 20:55:09 +01:00
|
|
|
miPolyBuildPoly(PolyVertexPtr vertices,
|
|
|
|
PolySlopePtr slopes,
|
|
|
|
int count,
|
|
|
|
int xi,
|
|
|
|
int yi,
|
|
|
|
PolyEdgePtr left,
|
|
|
|
PolyEdgePtr right, int *pnleft, int *pnright, int *h)
|
2003-11-14 16:54:54 +01:00
|
|
|
{
|
2012-03-21 20:55:09 +01:00
|
|
|
int top, bottom;
|
|
|
|
double miny, maxy;
|
|
|
|
int i;
|
|
|
|
int j;
|
|
|
|
int clockwise;
|
|
|
|
int slopeoff;
|
|
|
|
int s;
|
|
|
|
int nright, nleft;
|
|
|
|
int y, lasty = 0, bottomy, topy = 0;
|
2003-11-14 16:54:54 +01:00
|
|
|
|
|
|
|
/* find the top of the polygon */
|
|
|
|
maxy = miny = vertices[0].y;
|
|
|
|
bottom = top = 0;
|
2012-03-21 20:55:09 +01:00
|
|
|
for (i = 1; i < count; i++) {
|
|
|
|
if (vertices[i].y < miny) {
|
|
|
|
top = i;
|
|
|
|
miny = vertices[i].y;
|
|
|
|
}
|
|
|
|
if (vertices[i].y >= maxy) {
|
|
|
|
bottom = i;
|
|
|
|
maxy = vertices[i].y;
|
|
|
|
}
|
2003-11-14 16:54:54 +01:00
|
|
|
}
|
|
|
|
clockwise = 1;
|
|
|
|
slopeoff = 0;
|
|
|
|
|
|
|
|
i = top;
|
2012-03-21 20:55:09 +01:00
|
|
|
j = StepAround(top, -1, count);
|
2003-11-14 16:54:54 +01:00
|
|
|
|
2012-03-21 20:55:09 +01:00
|
|
|
if ((int64_t) slopes[j].dy * slopes[i].dx >
|
|
|
|
(int64_t) slopes[i].dy * slopes[j].dx) {
|
|
|
|
clockwise = -1;
|
|
|
|
slopeoff = -1;
|
2003-11-14 16:54:54 +01:00
|
|
|
}
|
|
|
|
|
2012-03-21 20:55:09 +01:00
|
|
|
bottomy = ICEIL(maxy) + yi;
|
2003-11-14 16:54:54 +01:00
|
|
|
|
|
|
|
nright = 0;
|
|
|
|
|
2012-03-21 20:55:09 +01:00
|
|
|
s = StepAround(top, slopeoff, count);
|
2003-11-14 16:54:54 +01:00
|
|
|
i = top;
|
2012-03-21 20:55:09 +01:00
|
|
|
while (i != bottom) {
|
|
|
|
if (slopes[s].dy != 0) {
|
|
|
|
y = miPolyBuildEdge(vertices[i].x, vertices[i].y,
|
|
|
|
slopes[s].k,
|
|
|
|
slopes[s].dx, slopes[s].dy,
|
|
|
|
xi, yi, 0, &right[nright]);
|
|
|
|
if (nright != 0)
|
|
|
|
right[nright - 1].height = y - lasty;
|
|
|
|
else
|
|
|
|
topy = y;
|
|
|
|
nright++;
|
|
|
|
lasty = y;
|
|
|
|
}
|
|
|
|
|
|
|
|
i = StepAround(i, clockwise, count);
|
|
|
|
s = StepAround(s, clockwise, count);
|
2003-11-14 16:54:54 +01:00
|
|
|
}
|
|
|
|
if (nright != 0)
|
2012-03-21 20:55:09 +01:00
|
|
|
right[nright - 1].height = bottomy - lasty;
|
2003-11-14 16:54:54 +01:00
|
|
|
|
|
|
|
if (slopeoff == 0)
|
2012-03-21 20:55:09 +01:00
|
|
|
slopeoff = -1;
|
2003-11-14 16:54:54 +01:00
|
|
|
else
|
2012-03-21 20:55:09 +01:00
|
|
|
slopeoff = 0;
|
2003-11-14 16:54:54 +01:00
|
|
|
|
|
|
|
nleft = 0;
|
2012-03-21 20:55:09 +01:00
|
|
|
s = StepAround(top, slopeoff, count);
|
2003-11-14 16:54:54 +01:00
|
|
|
i = top;
|
2012-03-21 20:55:09 +01:00
|
|
|
while (i != bottom) {
|
|
|
|
if (slopes[s].dy != 0) {
|
|
|
|
y = miPolyBuildEdge(vertices[i].x, vertices[i].y,
|
|
|
|
slopes[s].k,
|
|
|
|
slopes[s].dx, slopes[s].dy, xi, yi, 1,
|
|
|
|
&left[nleft]);
|
|
|
|
|
|
|
|
if (nleft != 0)
|
|
|
|
left[nleft - 1].height = y - lasty;
|
|
|
|
nleft++;
|
|
|
|
lasty = y;
|
|
|
|
}
|
|
|
|
i = StepAround(i, -clockwise, count);
|
|
|
|
s = StepAround(s, -clockwise, count);
|
2003-11-14 16:54:54 +01:00
|
|
|
}
|
|
|
|
if (nleft != 0)
|
2012-03-21 20:55:09 +01:00
|
|
|
left[nleft - 1].height = bottomy - lasty;
|
2003-11-14 16:54:54 +01:00
|
|
|
*pnleft = nleft;
|
|
|
|
*pnright = nright;
|
|
|
|
*h = bottomy - topy;
|
|
|
|
return topy;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2012-03-21 20:55:09 +01:00
|
|
|
miLineOnePoint(DrawablePtr pDrawable,
|
|
|
|
GCPtr pGC,
|
|
|
|
unsigned long pixel, SpanDataPtr spanData, int x, int y)
|
2003-11-14 16:54:54 +01:00
|
|
|
{
|
|
|
|
DDXPointRec pt;
|
2012-03-21 20:55:09 +01:00
|
|
|
int wid;
|
|
|
|
unsigned long oldPixel;
|
|
|
|
|
|
|
|
MILINESETPIXEL(pDrawable, pGC, pixel, oldPixel);
|
|
|
|
if (pGC->fillStyle == FillSolid) {
|
|
|
|
pt.x = x;
|
|
|
|
pt.y = y;
|
|
|
|
(*pGC->ops->PolyPoint) (pDrawable, pGC, CoordModeOrigin, 1, &pt);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
wid = 1;
|
|
|
|
if (pGC->miTranslate) {
|
|
|
|
x += pDrawable->x;
|
|
|
|
y += pDrawable->y;
|
|
|
|
}
|
|
|
|
pt.x = x;
|
|
|
|
pt.y = y;
|
|
|
|
(*pGC->ops->FillSpans) (pDrawable, pGC, 1, &pt, &wid, TRUE);
|
|
|
|
}
|
|
|
|
MILINERESETPIXEL(pDrawable, pGC, pixel, oldPixel);
|
2003-11-14 16:54:54 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2012-03-21 20:55:09 +01:00
|
|
|
miLineJoin(DrawablePtr pDrawable,
|
|
|
|
GCPtr pGC,
|
|
|
|
unsigned long pixel,
|
|
|
|
SpanDataPtr spanData, LineFacePtr pLeft, LineFacePtr pRight)
|
2003-11-14 16:54:54 +01:00
|
|
|
{
|
2012-03-21 20:55:09 +01:00
|
|
|
double mx = 0, my = 0;
|
|
|
|
double denom = 0.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;
|
2003-11-14 16:54:54 +01:00
|
|
|
|
|
|
|
if (lw == 1 && !spanData) {
|
2012-03-21 20:55:09 +01:00
|
|
|
/* See if one of the lines will draw the joining pixel */
|
|
|
|
if (pLeft->dx > 0 || (pLeft->dx == 0 && pLeft->dy > 0))
|
|
|
|
return;
|
|
|
|
if (pRight->dx > 0 || (pRight->dx == 0 && pRight->dy > 0))
|
|
|
|
return;
|
|
|
|
if (joinStyle != JoinRound) {
|
|
|
|
denom =
|
|
|
|
-pLeft->dx * (double) pRight->dy +
|
|
|
|
pRight->dx * (double) pLeft->dy;
|
|
|
|
if (denom == 0)
|
|
|
|
return; /* no join to draw */
|
|
|
|
}
|
|
|
|
if (joinStyle != JoinMiter) {
|
|
|
|
miLineOnePoint(pDrawable, pGC, pixel, spanData, pLeft->x, pLeft->y);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
if (joinStyle == JoinRound) {
|
|
|
|
miLineArc(pDrawable, pGC, pixel, spanData,
|
|
|
|
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 */
|
2003-11-14 16:54:54 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
swapslopes = 0;
|
2012-03-21 20:55:09 +01:00
|
|
|
if (denom > 0) {
|
|
|
|
pLeft->xa = -pLeft->xa;
|
|
|
|
pLeft->ya = -pLeft->ya;
|
|
|
|
pLeft->dx = -pLeft->dx;
|
|
|
|
pLeft->dy = -pLeft->dy;
|
2003-11-14 16:54:54 +01:00
|
|
|
}
|
2012-03-21 20:55:09 +01:00
|
|
|
else {
|
|
|
|
swapslopes = 1;
|
|
|
|
pRight->xa = -pRight->xa;
|
|
|
|
pRight->ya = -pRight->ya;
|
|
|
|
pRight->dx = -pRight->dx;
|
|
|
|
pRight->dy = -pRight->dy;
|
2003-11-14 16:54:54 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
vertices[0].x = pRight->xa;
|
|
|
|
vertices[0].y = pRight->ya;
|
|
|
|
slopes[0].dx = -pRight->dy;
|
2012-03-21 20:55:09 +01:00
|
|
|
slopes[0].dy = pRight->dx;
|
2003-11-14 16:54:54 +01:00
|
|
|
slopes[0].k = 0;
|
|
|
|
|
|
|
|
vertices[1].x = 0;
|
|
|
|
vertices[1].y = 0;
|
2012-03-21 20:55:09 +01:00
|
|
|
slopes[1].dx = pLeft->dy;
|
2003-11-14 16:54:54 +01:00
|
|
|
slopes[1].dy = -pLeft->dx;
|
|
|
|
slopes[1].k = 0;
|
|
|
|
|
|
|
|
vertices[2].x = pLeft->xa;
|
|
|
|
vertices[2].y = pLeft->ya;
|
|
|
|
|
2012-03-21 20:55:09 +01:00
|
|
|
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);
|
|
|
|
miFillPolyHelper(pDrawable, pGC, pixel, spanData, y, height, left, right,
|
|
|
|
nleft, nright);
|
2003-11-14 16:54:54 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
2012-03-21 20:55:09 +01:00
|
|
|
miLineArcI(DrawablePtr pDraw,
|
|
|
|
GCPtr pGC, int xorg, int yorg, DDXPointPtr points, int *widths)
|
2003-11-14 16:54:54 +01:00
|
|
|
{
|
2007-03-09 04:46:23 +01:00
|
|
|
DDXPointPtr tpts, bpts;
|
|
|
|
int *twids, *bwids;
|
|
|
|
int x, y, e, ex, slw;
|
2003-11-14 16:54:54 +01:00
|
|
|
|
|
|
|
tpts = points;
|
|
|
|
twids = widths;
|
2012-03-21 20:55:09 +01:00
|
|
|
if (pGC->miTranslate) {
|
|
|
|
xorg += pDraw->x;
|
|
|
|
yorg += pDraw->y;
|
2003-11-14 16:54:54 +01:00
|
|
|
}
|
|
|
|
slw = pGC->lineWidth;
|
2012-03-21 20:55:09 +01:00
|
|
|
if (slw == 1) {
|
|
|
|
tpts->x = xorg;
|
|
|
|
tpts->y = yorg;
|
|
|
|
*twids = 1;
|
|
|
|
return 1;
|
2003-11-14 16:54:54 +01:00
|
|
|
}
|
|
|
|
bpts = tpts + slw;
|
|
|
|
bwids = twids + slw;
|
|
|
|
y = (slw >> 1) + 1;
|
|
|
|
if (slw & 1)
|
2012-03-21 20:55:09 +01:00
|
|
|
e = -((y << 2) + 3);
|
2003-11-14 16:54:54 +01:00
|
|
|
else
|
2012-03-21 20:55:09 +01:00
|
|
|
e = -(y << 3);
|
2003-11-14 16:54:54 +01:00
|
|
|
ex = -4;
|
|
|
|
x = 0;
|
2012-03-21 20:55:09 +01:00
|
|
|
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--;
|
|
|
|
tpts->x = xorg - x;
|
|
|
|
tpts->y = yorg - y;
|
|
|
|
tpts++;
|
|
|
|
*twids++ = slw;
|
|
|
|
if ((y != 0) && ((slw > 1) || (e != ex))) {
|
|
|
|
bpts--;
|
|
|
|
bpts->x = xorg - x;
|
|
|
|
bpts->y = yorg + y;
|
|
|
|
*--bwids = slw;
|
|
|
|
}
|
2003-11-14 16:54:54 +01:00
|
|
|
}
|
2010-06-06 16:18:40 +02:00
|
|
|
return pGC->lineWidth;
|
2003-11-14 16:54:54 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
#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 int
|
2012-03-21 20:55:09 +01:00
|
|
|
miLineArcD(DrawablePtr pDraw,
|
|
|
|
GCPtr pGC,
|
|
|
|
double xorg,
|
|
|
|
double yorg,
|
|
|
|
DDXPointPtr points,
|
|
|
|
int *widths,
|
|
|
|
PolyEdgePtr edge1,
|
|
|
|
int edgey1,
|
|
|
|
Bool edgeleft1, PolyEdgePtr edge2, int edgey2, Bool edgeleft2)
|
2003-11-14 16:54:54 +01:00
|
|
|
{
|
2007-03-09 04:46:23 +01:00
|
|
|
DDXPointPtr pts;
|
|
|
|
int *wids;
|
2003-11-14 16:54:54 +01:00
|
|
|
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;
|
|
|
|
|
|
|
|
pts = points;
|
|
|
|
wids = widths;
|
|
|
|
xbase = floor(xorg);
|
|
|
|
x0 = xorg - xbase;
|
2012-03-21 20:55:09 +01:00
|
|
|
ybase = ICEIL(yorg);
|
2003-11-14 16:54:54 +01:00
|
|
|
y0 = yorg - ybase;
|
2012-03-21 20:55:09 +01:00
|
|
|
if (pGC->miTranslate) {
|
|
|
|
xbase += pDraw->x;
|
|
|
|
ybase += pDraw->y;
|
|
|
|
edge1->x += pDraw->x;
|
|
|
|
edge2->x += pDraw->x;
|
|
|
|
edgey1 += pDraw->y;
|
|
|
|
edgey2 += pDraw->y;
|
2003-11-14 16:54:54 +01:00
|
|
|
}
|
|
|
|
xlk = x0 + x0 + 1.0;
|
|
|
|
xrk = x0 + x0 - 1.0;
|
|
|
|
yk = y0 + y0 - 1.0;
|
2012-03-21 20:55:09 +01:00
|
|
|
radius = ((double) pGC->lineWidth) / 2.0;
|
2003-11-14 16:54:54 +01:00
|
|
|
y = floor(radius - y0 + 1.0);
|
|
|
|
ybase -= y;
|
|
|
|
ymin = ybase;
|
|
|
|
ymax = 65536;
|
|
|
|
edge1IsMin = FALSE;
|
|
|
|
ymin1 = edgey1;
|
2012-03-21 20:55:09 +01:00
|
|
|
if (edge1->dy >= 0) {
|
|
|
|
if (!edge1->dy) {
|
|
|
|
if (edgeleft1)
|
|
|
|
edge1IsMin = TRUE;
|
|
|
|
else
|
|
|
|
ymax = edgey1;
|
|
|
|
edgey1 = 65536;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
if ((edge1->signdx < 0) == edgeleft1)
|
|
|
|
edge1IsMin = TRUE;
|
|
|
|
}
|
2003-11-14 16:54:54 +01:00
|
|
|
}
|
|
|
|
edge2IsMin = FALSE;
|
|
|
|
ymin2 = edgey2;
|
2012-03-21 20:55:09 +01:00
|
|
|
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;
|
2003-11-14 16:54:54 +01:00
|
|
|
el = radius * radius - ((y + y0) * (y + y0)) - (x0 * x0);
|
|
|
|
er = el + xrk;
|
|
|
|
xl = 1;
|
|
|
|
xr = 0;
|
2012-03-21 20:55:09 +01:00
|
|
|
if (x0 < 0.5) {
|
|
|
|
xl = 0;
|
|
|
|
el -= xlk;
|
2003-11-14 16:54:54 +01:00
|
|
|
}
|
|
|
|
boty = (y0 < -0.5) ? 1 : 0;
|
|
|
|
if (ybase + y - boty > ymax)
|
2012-03-21 20:55:09 +01:00
|
|
|
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) {
|
|
|
|
pts->x = xcl;
|
|
|
|
pts->y = ybase;
|
|
|
|
pts++;
|
|
|
|
*wids++ = xcr - xcl + 1;
|
|
|
|
}
|
2003-11-14 16:54:54 +01:00
|
|
|
}
|
|
|
|
er = xrk - (xr << 1) - er;
|
|
|
|
el = (xl << 1) - xlk - el;
|
|
|
|
boty = floor(-y0 - radius + 1.0);
|
|
|
|
if (ybase + y - boty > ymax)
|
2012-03-21 20:55:09 +01:00
|
|
|
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) {
|
|
|
|
pts->x = xcl;
|
|
|
|
pts->y = ybase;
|
|
|
|
pts++;
|
|
|
|
*wids++ = xcr - xcl + 1;
|
|
|
|
}
|
2003-11-14 16:54:54 +01:00
|
|
|
}
|
2010-06-06 16:18:40 +02:00
|
|
|
return pts - points;
|
2003-11-14 16:54:54 +01:00
|
|
|
}
|
|
|
|
|
2007-03-25 23:56:32 +02:00
|
|
|
static int
|
2012-03-21 20:55:09 +01:00
|
|
|
miRoundJoinFace(LineFacePtr face, PolyEdgePtr edge, Bool *leftEdge)
|
2003-11-14 16:54:54 +01:00
|
|
|
{
|
2012-03-21 20:55:09 +01:00
|
|
|
int y;
|
|
|
|
int dx, dy;
|
|
|
|
double xa, ya;
|
|
|
|
Bool left;
|
2003-11-14 16:54:54 +01:00
|
|
|
|
|
|
|
dx = -face->dy;
|
|
|
|
dy = face->dx;
|
|
|
|
xa = face->xa;
|
|
|
|
ya = face->ya;
|
|
|
|
left = 1;
|
2012-03-21 20:55:09 +01:00
|
|
|
if (ya > 0) {
|
|
|
|
ya = 0.0;
|
|
|
|
xa = 0.0;
|
2003-11-14 16:54:54 +01:00
|
|
|
}
|
2012-03-21 20:55:09 +01:00
|
|
|
if (dy < 0 || (dy == 0 && dx > 0)) {
|
|
|
|
dx = -dx;
|
|
|
|
dy = -dy;
|
|
|
|
left = !left;
|
2003-11-14 16:54:54 +01:00
|
|
|
}
|
|
|
|
if (dx == 0 && dy == 0)
|
2012-03-21 20:55:09 +01:00
|
|
|
dy = 1;
|
|
|
|
if (dy == 0) {
|
|
|
|
y = ICEIL(face->ya) + face->y;
|
|
|
|
edge->x = -32767;
|
|
|
|
edge->stepx = 0;
|
|
|
|
edge->signdx = 0;
|
|
|
|
edge->e = -1;
|
|
|
|
edge->dy = 0;
|
|
|
|
edge->dx = 0;
|
|
|
|
edge->height = 0;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
y = miPolyBuildEdge(xa, ya, 0.0, dx, dy, face->x, face->y, !left, edge);
|
|
|
|
edge->height = 32767;
|
2003-11-14 16:54:54 +01:00
|
|
|
}
|
|
|
|
*leftEdge = !left;
|
|
|
|
return y;
|
|
|
|
}
|
|
|
|
|
Rework symbol visibility for easier maintenance
Save in a few special cases, _X_EXPORT should not be used in C source
files. Instead, it should be used in headers, and the proper C source
include that header. Some special cases are symbols that need to be
shared between modules, but not expected to be used by external drivers,
and symbols that are accessible via LoaderSymbol/dlopen.
This patch also adds conditionally some new sdk header files, depending
on extensions enabled. These files were added to match pattern for
other extensions/modules, that is, have the headers "deciding" symbol
visibility in the sdk. These headers are:
o Xext/panoramiXsrv.h, Xext/panoramiX.h
o fbpict.h (unconditionally)
o vidmodeproc.h
o mioverlay.h (unconditionally, used only by xaa)
o xfixes.h (unconditionally, symbols required by dri2)
LoaderSymbol and similar functions now don't have different prototypes,
in loaderProcs.h and xf86Module.h, so that both headers can be included,
without the need of defining IN_LOADER.
xf86NewInputDevice() device prototype readded to xf86Xinput.h, but
not exported (and with a comment about it).
2008-12-03 08:43:34 +01:00
|
|
|
void
|
2012-03-21 20:55:09 +01:00
|
|
|
miRoundJoinClip(LineFacePtr pLeft, LineFacePtr pRight,
|
|
|
|
PolyEdgePtr edge1, PolyEdgePtr edge2,
|
|
|
|
int *y1, int *y2, Bool *left1, Bool *left2)
|
2003-11-14 16:54:54 +01:00
|
|
|
{
|
2012-03-21 20:55:09 +01:00
|
|
|
double denom;
|
2003-11-14 16:54:54 +01:00
|
|
|
|
2012-03-21 20:55:09 +01:00
|
|
|
denom = -pLeft->dx * (double) pRight->dy + pRight->dx * (double) pLeft->dy;
|
2003-11-14 16:54:54 +01:00
|
|
|
|
2012-03-21 20:55:09 +01:00
|
|
|
if (denom >= 0) {
|
|
|
|
pLeft->xa = -pLeft->xa;
|
|
|
|
pLeft->ya = -pLeft->ya;
|
2003-11-14 16:54:54 +01:00
|
|
|
}
|
2012-03-21 20:55:09 +01:00
|
|
|
else {
|
|
|
|
pRight->xa = -pRight->xa;
|
|
|
|
pRight->ya = -pRight->ya;
|
2003-11-14 16:54:54 +01:00
|
|
|
}
|
2012-03-21 20:55:09 +01:00
|
|
|
*y1 = miRoundJoinFace(pLeft, edge1, left1);
|
|
|
|
*y2 = miRoundJoinFace(pRight, edge2, left2);
|
2003-11-14 16:54:54 +01:00
|
|
|
}
|
|
|
|
|
Rework symbol visibility for easier maintenance
Save in a few special cases, _X_EXPORT should not be used in C source
files. Instead, it should be used in headers, and the proper C source
include that header. Some special cases are symbols that need to be
shared between modules, but not expected to be used by external drivers,
and symbols that are accessible via LoaderSymbol/dlopen.
This patch also adds conditionally some new sdk header files, depending
on extensions enabled. These files were added to match pattern for
other extensions/modules, that is, have the headers "deciding" symbol
visibility in the sdk. These headers are:
o Xext/panoramiXsrv.h, Xext/panoramiX.h
o fbpict.h (unconditionally)
o vidmodeproc.h
o mioverlay.h (unconditionally, used only by xaa)
o xfixes.h (unconditionally, symbols required by dri2)
LoaderSymbol and similar functions now don't have different prototypes,
in loaderProcs.h and xf86Module.h, so that both headers can be included,
without the need of defining IN_LOADER.
xf86NewInputDevice() device prototype readded to xf86Xinput.h, but
not exported (and with a comment about it).
2008-12-03 08:43:34 +01:00
|
|
|
int
|
2012-03-21 20:55:09 +01:00
|
|
|
miRoundCapClip(LineFacePtr face, Bool isInt, PolyEdgePtr edge, Bool *leftEdge)
|
2003-11-14 16:54:54 +01:00
|
|
|
{
|
2012-03-21 20:55:09 +01:00
|
|
|
int y;
|
|
|
|
int dx, dy;
|
|
|
|
double xa, ya, k;
|
|
|
|
Bool left;
|
2003-11-14 16:54:54 +01:00
|
|
|
|
|
|
|
dx = -face->dy;
|
|
|
|
dy = face->dx;
|
|
|
|
xa = face->xa;
|
|
|
|
ya = face->ya;
|
|
|
|
k = 0.0;
|
|
|
|
if (!isInt)
|
2012-03-21 20:55:09 +01:00
|
|
|
k = face->k;
|
2003-11-14 16:54:54 +01:00
|
|
|
left = 1;
|
2012-03-21 20:55:09 +01:00
|
|
|
if (dy < 0 || (dy == 0 && dx > 0)) {
|
|
|
|
dx = -dx;
|
|
|
|
dy = -dy;
|
|
|
|
xa = -xa;
|
|
|
|
ya = -ya;
|
|
|
|
left = !left;
|
2003-11-14 16:54:54 +01:00
|
|
|
}
|
|
|
|
if (dx == 0 && dy == 0)
|
2012-03-21 20:55:09 +01:00
|
|
|
dy = 1;
|
|
|
|
if (dy == 0) {
|
|
|
|
y = ICEIL(face->ya) + face->y;
|
|
|
|
edge->x = -32767;
|
|
|
|
edge->stepx = 0;
|
|
|
|
edge->signdx = 0;
|
|
|
|
edge->e = -1;
|
|
|
|
edge->dy = 0;
|
|
|
|
edge->dx = 0;
|
|
|
|
edge->height = 0;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
y = miPolyBuildEdge(xa, ya, k, dx, dy, face->x, face->y, !left, edge);
|
|
|
|
edge->height = 32767;
|
2003-11-14 16:54:54 +01:00
|
|
|
}
|
|
|
|
*leftEdge = !left;
|
|
|
|
return y;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2012-03-21 20:55:09 +01:00
|
|
|
miLineArc(DrawablePtr pDraw,
|
|
|
|
GCPtr pGC,
|
|
|
|
unsigned long pixel,
|
|
|
|
SpanDataPtr spanData,
|
|
|
|
LineFacePtr leftFace,
|
|
|
|
LineFacePtr rightFace, double xorg, double yorg, Bool isInt)
|
2003-11-14 16:54:54 +01:00
|
|
|
{
|
2003-11-14 17:49:22 +01:00
|
|
|
int xorgi = 0, yorgi = 0;
|
2003-11-14 16:54:54 +01:00
|
|
|
Spans spanRec;
|
|
|
|
int n;
|
2012-03-21 20:55:09 +01:00
|
|
|
PolyEdgeRec edge1, edge2;
|
|
|
|
int edgey1, edgey2;
|
|
|
|
Bool edgeleft1, edgeleft2;
|
2003-11-14 16:54:54 +01:00
|
|
|
|
2012-03-21 20:55:09 +01:00
|
|
|
if (isInt) {
|
|
|
|
xorgi = leftFace ? leftFace->x : rightFace->x;
|
|
|
|
yorgi = leftFace ? leftFace->y : rightFace->y;
|
2003-11-14 16:54:54 +01:00
|
|
|
}
|
|
|
|
edgey1 = 65536;
|
|
|
|
edgey2 = 65536;
|
2012-03-21 20:55:09 +01:00
|
|
|
edge1.x = 0; /* not used, keep memory checkers happy */
|
2003-11-14 16:54:54 +01:00
|
|
|
edge1.dy = -1;
|
2012-03-21 20:55:09 +01:00
|
|
|
edge2.x = 0; /* not used, keep memory checkers happy */
|
2003-11-14 16:54:54 +01:00
|
|
|
edge2.dy = -1;
|
|
|
|
edgeleft1 = FALSE;
|
|
|
|
edgeleft2 = FALSE;
|
|
|
|
if ((pGC->lineStyle != LineSolid || pGC->lineWidth > 2) &&
|
2012-03-21 20:55:09 +01:00
|
|
|
((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;
|
2003-11-14 16:54:54 +01:00
|
|
|
}
|
2010-05-08 22:38:00 +02:00
|
|
|
if (!InitSpans(&spanRec, pGC->lineWidth))
|
2012-03-21 20:55:09 +01:00
|
|
|
return;
|
2003-11-14 16:54:54 +01:00
|
|
|
if (isInt)
|
2012-03-21 20:55:09 +01:00
|
|
|
n = miLineArcI(pDraw, pGC, xorgi, yorgi, spanRec.points,
|
|
|
|
spanRec.widths);
|
2003-11-14 16:54:54 +01:00
|
|
|
else
|
2012-03-21 20:55:09 +01:00
|
|
|
n = miLineArcD(pDraw, pGC, xorg, yorg, spanRec.points, spanRec.widths,
|
|
|
|
&edge1, edgey1, edgeleft1, &edge2, edgey2, edgeleft2);
|
2010-05-08 22:38:00 +02:00
|
|
|
spanRec.count = n;
|
2012-03-21 20:55:09 +01:00
|
|
|
fillSpans(pDraw, pGC, pixel, &spanRec, spanData);
|
2003-11-14 16:54:54 +01:00
|
|
|
}
|
|
|
|
|
2007-03-25 23:56:32 +02:00
|
|
|
static void
|
2012-03-21 20:55:09 +01:00
|
|
|
miLineProjectingCap(DrawablePtr pDrawable, GCPtr pGC, unsigned long pixel,
|
|
|
|
SpanDataPtr spanData, LineFacePtr face, Bool isLeft,
|
|
|
|
double xorg, double yorg, Bool isInt)
|
2003-11-14 16:54:54 +01:00
|
|
|
{
|
2012-03-21 20:55:09 +01:00
|
|
|
int xorgi = 0, yorgi = 0;
|
|
|
|
int lw;
|
2013-07-16 01:44:29 +02:00
|
|
|
PolyEdgeRec lefts[4], rights[4];
|
2012-03-21 20:55:09 +01:00
|
|
|
int lefty, righty, topy, bottomy;
|
2003-11-14 16:54:54 +01:00
|
|
|
PolyEdgePtr left, right;
|
2012-03-21 20:55:09 +01:00
|
|
|
PolyEdgePtr top, bottom;
|
|
|
|
double xa, ya;
|
|
|
|
double k;
|
|
|
|
double xap, yap;
|
|
|
|
int dx, dy;
|
|
|
|
double projectXoff, projectYoff;
|
|
|
|
double maxy;
|
|
|
|
int finaly;
|
|
|
|
|
|
|
|
if (isInt) {
|
|
|
|
xorgi = face->x;
|
|
|
|
yorgi = face->y;
|
2003-11-14 16:54:54 +01:00
|
|
|
}
|
|
|
|
lw = pGC->lineWidth;
|
|
|
|
dx = face->dx;
|
|
|
|
dy = face->dy;
|
|
|
|
k = face->k;
|
2012-03-21 20:55:09 +01:00
|
|
|
if (dy == 0) {
|
|
|
|
lefts[0].height = lw;
|
|
|
|
lefts[0].x = xorgi;
|
|
|
|
if (isLeft)
|
|
|
|
lefts[0].x -= (lw >> 1);
|
|
|
|
lefts[0].stepx = 0;
|
|
|
|
lefts[0].signdx = 1;
|
|
|
|
lefts[0].e = -lw;
|
|
|
|
lefts[0].dx = 0;
|
|
|
|
lefts[0].dy = lw;
|
|
|
|
rights[0].height = lw;
|
|
|
|
rights[0].x = xorgi;
|
|
|
|
if (!isLeft)
|
|
|
|
rights[0].x += ((lw + 1) >> 1);
|
|
|
|
rights[0].stepx = 0;
|
|
|
|
rights[0].signdx = 1;
|
|
|
|
rights[0].e = -lw;
|
|
|
|
rights[0].dx = 0;
|
|
|
|
rights[0].dy = lw;
|
|
|
|
miFillPolyHelper(pDrawable, pGC, pixel, spanData, yorgi - (lw >> 1), lw,
|
|
|
|
lefts, rights, 1, 1);
|
|
|
|
}
|
|
|
|
else if (dx == 0) {
|
|
|
|
if (dy < 0) {
|
|
|
|
dy = -dy;
|
|
|
|
isLeft = !isLeft;
|
|
|
|
}
|
|
|
|
topy = yorgi;
|
|
|
|
bottomy = yorgi + dy;
|
|
|
|
if (isLeft)
|
|
|
|
topy -= (lw >> 1);
|
|
|
|
else
|
|
|
|
bottomy += (lw >> 1);
|
|
|
|
lefts[0].height = bottomy - topy;
|
|
|
|
lefts[0].x = xorgi - (lw >> 1);
|
|
|
|
lefts[0].stepx = 0;
|
|
|
|
lefts[0].signdx = 1;
|
|
|
|
lefts[0].e = -dy;
|
|
|
|
lefts[0].dx = dx;
|
|
|
|
lefts[0].dy = dy;
|
|
|
|
|
|
|
|
rights[0].height = bottomy - topy;
|
|
|
|
rights[0].x = lefts[0].x + (lw - 1);
|
|
|
|
rights[0].stepx = 0;
|
|
|
|
rights[0].signdx = 1;
|
|
|
|
rights[0].e = -dy;
|
|
|
|
rights[0].dx = dx;
|
|
|
|
rights[0].dy = dy;
|
|
|
|
miFillPolyHelper(pDrawable, pGC, pixel, spanData, topy, bottomy - topy,
|
|
|
|
lefts, rights, 1, 1);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
xa = face->xa;
|
|
|
|
ya = face->ya;
|
|
|
|
projectXoff = -ya;
|
|
|
|
projectYoff = xa;
|
|
|
|
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];
|
|
|
|
}
|
|
|
|
if (isLeft) {
|
|
|
|
righty = miPolyBuildEdge(xa, ya, k, dx, dy, xorgi, yorgi, 0, right);
|
|
|
|
|
|
|
|
xa = -xa;
|
|
|
|
ya = -ya;
|
|
|
|
k = -k;
|
|
|
|
lefty = miPolyBuildEdge(xa - projectXoff, ya - projectYoff,
|
|
|
|
k, dx, dy, xorgi, yorgi, 1, left);
|
|
|
|
if (dx > 0) {
|
|
|
|
ya = -ya;
|
|
|
|
xa = -xa;
|
|
|
|
}
|
|
|
|
xap = xa - projectXoff;
|
|
|
|
yap = ya - projectYoff;
|
|
|
|
topy = miPolyBuildEdge(xap, yap, xap * dx + yap * dy,
|
|
|
|
-dy, dx, xorgi, yorgi, dx > 0, top);
|
|
|
|
bottomy = miPolyBuildEdge(xa, ya,
|
|
|
|
0.0, -dy, dx, xorgi, yorgi, dx < 0,
|
|
|
|
bottom);
|
|
|
|
maxy = -ya;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
righty = miPolyBuildEdge(xa - projectXoff, ya - projectYoff,
|
|
|
|
k, dx, dy, xorgi, yorgi, 0, right);
|
|
|
|
|
|
|
|
xa = -xa;
|
|
|
|
ya = -ya;
|
|
|
|
k = -k;
|
|
|
|
lefty = miPolyBuildEdge(xa, ya, k, dx, dy, xorgi, yorgi, 1, left);
|
|
|
|
if (dx > 0) {
|
|
|
|
ya = -ya;
|
|
|
|
xa = -xa;
|
|
|
|
}
|
|
|
|
xap = xa - projectXoff;
|
|
|
|
yap = ya - projectYoff;
|
|
|
|
topy =
|
|
|
|
miPolyBuildEdge(xa, ya, 0.0, -dy, dx, xorgi, xorgi, dx > 0,
|
|
|
|
top);
|
|
|
|
bottomy =
|
|
|
|
miPolyBuildEdge(xap, yap, xap * dx + yap * dy, -dy, dx, xorgi,
|
|
|
|
xorgi, dx < 0, bottom);
|
|
|
|
maxy = -ya + projectYoff;
|
|
|
|
}
|
|
|
|
finaly = ICEIL(maxy) + yorgi;
|
|
|
|
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;
|
|
|
|
miFillPolyHelper(pDrawable, pGC, pixel, spanData, topy,
|
|
|
|
bottom->height + bottomy - topy, lefts, rights, 2, 2);
|
2003-11-14 16:54:54 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2012-03-21 20:55:09 +01:00
|
|
|
miWideSegment(DrawablePtr pDrawable,
|
|
|
|
GCPtr pGC,
|
|
|
|
unsigned long pixel,
|
|
|
|
SpanDataPtr spanData,
|
|
|
|
int x1,
|
|
|
|
int y1,
|
|
|
|
int x2,
|
|
|
|
int y2,
|
|
|
|
Bool projectLeft,
|
|
|
|
Bool projectRight, LineFacePtr leftFace, LineFacePtr rightFace)
|
2003-11-14 16:54:54 +01:00
|
|
|
{
|
2012-03-21 20:55:09 +01:00
|
|
|
double l, L, r;
|
|
|
|
double xa, ya;
|
|
|
|
double projectXoff = 0.0, projectYoff = 0.0;
|
|
|
|
double k;
|
|
|
|
double maxy;
|
|
|
|
int x, y;
|
|
|
|
int dx, dy;
|
|
|
|
int finaly;
|
2003-11-14 16:54:54 +01:00
|
|
|
PolyEdgePtr left, right;
|
2012-03-21 20:55:09 +01:00
|
|
|
PolyEdgePtr top, bottom;
|
|
|
|
int lefty, righty, topy, bottomy;
|
|
|
|
int signdx;
|
2013-07-16 01:44:29 +02:00
|
|
|
PolyEdgeRec lefts[4], rights[4];
|
2012-03-21 20:55:09 +01:00
|
|
|
LineFacePtr tface;
|
|
|
|
int lw = pGC->lineWidth;
|
2003-11-14 16:54:54 +01:00
|
|
|
|
|
|
|
/* draw top-to-bottom always */
|
2012-03-21 20:55:09 +01:00
|
|
|
if (y2 < y1 || (y2 == y1 && x2 < x1)) {
|
|
|
|
x = x1;
|
|
|
|
x1 = x2;
|
|
|
|
x2 = x;
|
2003-11-14 16:54:54 +01:00
|
|
|
|
2012-03-21 20:55:09 +01:00
|
|
|
y = y1;
|
|
|
|
y1 = y2;
|
|
|
|
y2 = y;
|
2003-11-14 16:54:54 +01:00
|
|
|
|
2012-03-21 20:55:09 +01:00
|
|
|
x = projectLeft;
|
|
|
|
projectLeft = projectRight;
|
|
|
|
projectRight = x;
|
2003-11-14 16:54:54 +01:00
|
|
|
|
2012-03-21 20:55:09 +01:00
|
|
|
tface = leftFace;
|
|
|
|
leftFace = rightFace;
|
|
|
|
rightFace = tface;
|
2003-11-14 16:54:54 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
dy = y2 - y1;
|
|
|
|
signdx = 1;
|
|
|
|
dx = x2 - x1;
|
|
|
|
if (dx < 0)
|
2012-03-21 20:55:09 +01:00
|
|
|
signdx = -1;
|
2003-11-14 16:54:54 +01:00
|
|
|
|
|
|
|
leftFace->x = x1;
|
|
|
|
leftFace->y = y1;
|
|
|
|
leftFace->dx = dx;
|
|
|
|
leftFace->dy = dy;
|
|
|
|
|
|
|
|
rightFace->x = x2;
|
|
|
|
rightFace->y = y2;
|
|
|
|
rightFace->dx = -dx;
|
|
|
|
rightFace->dy = -dy;
|
|
|
|
|
2012-03-21 20:55:09 +01:00
|
|
|
if (dy == 0) {
|
|
|
|
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;
|
|
|
|
miFillRectPolyHelper(pDrawable, pGC, pixel, spanData, x, y, dx, dy);
|
|
|
|
}
|
|
|
|
else if (dx == 0) {
|
|
|
|
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;
|
|
|
|
miFillRectPolyHelper(pDrawable, pGC, pixel, spanData, x, y, dx, dy);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
l = ((double) lw) / 2.0;
|
|
|
|
L = hypot((double) dx, (double) 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;
|
|
|
|
|
|
|
|
if (projectLeft | projectRight) {
|
|
|
|
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;
|
|
|
|
miFillPolyHelper(pDrawable, pGC, pixel, spanData, topy,
|
|
|
|
bottom->height + bottomy - topy, lefts, rights, 2, 2);
|
2003-11-14 16:54:54 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2007-03-25 23:56:32 +02:00
|
|
|
static SpanDataPtr
|
2012-03-21 20:55:09 +01:00
|
|
|
miSetupSpanData(GCPtr pGC, SpanDataPtr spanData, int npt)
|
2003-11-14 16:54:54 +01:00
|
|
|
{
|
2003-11-14 17:49:22 +01:00
|
|
|
if ((npt < 3 && pGC->capStyle != CapRound) || miSpansEasyRop(pGC->alu))
|
2012-03-21 20:55:09 +01:00
|
|
|
return (SpanDataPtr) NULL;
|
2003-11-14 16:54:54 +01:00
|
|
|
if (pGC->lineStyle == LineDoubleDash)
|
2012-03-21 20:55:09 +01:00
|
|
|
miInitSpanGroup(&spanData->bgGroup);
|
|
|
|
miInitSpanGroup(&spanData->fgGroup);
|
2003-11-14 16:54:54 +01:00
|
|
|
return spanData;
|
|
|
|
}
|
|
|
|
|
2007-03-25 23:56:32 +02:00
|
|
|
static void
|
2012-03-21 20:55:09 +01:00
|
|
|
miCleanupSpanData(DrawablePtr pDrawable, GCPtr pGC, SpanDataPtr spanData)
|
2003-11-14 16:54:54 +01:00
|
|
|
{
|
2012-03-21 20:55:09 +01:00
|
|
|
if (pGC->lineStyle == LineDoubleDash) {
|
|
|
|
ChangeGCVal oldPixel, pixel;
|
|
|
|
|
|
|
|
pixel.val = pGC->bgPixel;
|
|
|
|
oldPixel.val = pGC->fgPixel;
|
|
|
|
if (pixel.val != oldPixel.val) {
|
|
|
|
ChangeGC(NullClient, pGC, GCForeground, &pixel);
|
|
|
|
ValidateGC(pDrawable, pGC);
|
|
|
|
}
|
|
|
|
miFillUniqueSpanGroup(pDrawable, pGC, &spanData->bgGroup);
|
|
|
|
miFreeSpanGroup(&spanData->bgGroup);
|
|
|
|
if (pixel.val != oldPixel.val) {
|
|
|
|
ChangeGC(NullClient, pGC, GCForeground, &oldPixel);
|
|
|
|
ValidateGC(pDrawable, pGC);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
miFillUniqueSpanGroup(pDrawable, pGC, &spanData->fgGroup);
|
|
|
|
miFreeSpanGroup(&spanData->fgGroup);
|
2003-11-14 16:54:54 +01:00
|
|
|
}
|
|
|
|
|
Rework symbol visibility for easier maintenance
Save in a few special cases, _X_EXPORT should not be used in C source
files. Instead, it should be used in headers, and the proper C source
include that header. Some special cases are symbols that need to be
shared between modules, but not expected to be used by external drivers,
and symbols that are accessible via LoaderSymbol/dlopen.
This patch also adds conditionally some new sdk header files, depending
on extensions enabled. These files were added to match pattern for
other extensions/modules, that is, have the headers "deciding" symbol
visibility in the sdk. These headers are:
o Xext/panoramiXsrv.h, Xext/panoramiX.h
o fbpict.h (unconditionally)
o vidmodeproc.h
o mioverlay.h (unconditionally, used only by xaa)
o xfixes.h (unconditionally, symbols required by dri2)
LoaderSymbol and similar functions now don't have different prototypes,
in loaderProcs.h and xf86Module.h, so that both headers can be included,
without the need of defining IN_LOADER.
xf86NewInputDevice() device prototype readded to xf86Xinput.h, but
not exported (and with a comment about it).
2008-12-03 08:43:34 +01:00
|
|
|
void
|
2012-03-21 20:55:09 +01:00
|
|
|
miWideLine(DrawablePtr pDrawable, GCPtr pGC,
|
|
|
|
int mode, int npt, DDXPointPtr pPts)
|
2003-11-14 16:54:54 +01:00
|
|
|
{
|
2012-03-21 20:55:09 +01:00
|
|
|
int x1, y1, x2, y2;
|
|
|
|
SpanDataRec spanDataRec;
|
|
|
|
SpanDataPtr spanData;
|
|
|
|
long pixel;
|
|
|
|
Bool projectLeft, projectRight;
|
|
|
|
LineFaceRec leftFace, rightFace, prevRightFace;
|
|
|
|
LineFaceRec firstFace;
|
|
|
|
int first;
|
|
|
|
Bool somethingDrawn = FALSE;
|
|
|
|
Bool selfJoin;
|
|
|
|
|
|
|
|
spanData = miSetupSpanData(pGC, &spanDataRec, npt);
|
2003-11-14 16:54:54 +01:00
|
|
|
pixel = pGC->fgPixel;
|
|
|
|
x2 = pPts->x;
|
|
|
|
y2 = pPts->y;
|
|
|
|
first = TRUE;
|
|
|
|
selfJoin = FALSE;
|
2012-03-21 20:55:09 +01:00
|
|
|
if (npt > 1) {
|
|
|
|
if (mode == CoordModePrevious) {
|
|
|
|
int nptTmp;
|
|
|
|
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;
|
|
|
|
}
|
2003-11-14 16:54:54 +01:00
|
|
|
}
|
|
|
|
projectLeft = pGC->capStyle == CapProjecting && !selfJoin;
|
|
|
|
projectRight = FALSE;
|
2012-03-21 20:55:09 +01:00
|
|
|
while (--npt) {
|
|
|
|
x1 = x2;
|
|
|
|
y1 = y2;
|
|
|
|
++pPts;
|
|
|
|
x2 = pPts->x;
|
|
|
|
y2 = pPts->y;
|
|
|
|
if (mode == CoordModePrevious) {
|
|
|
|
x2 += x1;
|
|
|
|
y2 += y1;
|
|
|
|
}
|
|
|
|
if (x1 != x2 || y1 != y2) {
|
|
|
|
somethingDrawn = TRUE;
|
|
|
|
if (npt == 1 && pGC->capStyle == CapProjecting && !selfJoin)
|
|
|
|
projectRight = TRUE;
|
|
|
|
miWideSegment(pDrawable, pGC, pixel, spanData, x1, y1, x2, y2,
|
|
|
|
projectLeft, projectRight, &leftFace, &rightFace);
|
|
|
|
if (first) {
|
|
|
|
if (selfJoin)
|
|
|
|
firstFace = leftFace;
|
|
|
|
else if (pGC->capStyle == CapRound) {
|
|
|
|
if (pGC->lineWidth == 1 && !spanData)
|
|
|
|
miLineOnePoint(pDrawable, pGC, pixel, spanData, x1, y1);
|
|
|
|
else
|
|
|
|
miLineArc(pDrawable, pGC, pixel, spanData,
|
|
|
|
&leftFace, (LineFacePtr) NULL,
|
|
|
|
(double) 0.0, (double) 0.0, TRUE);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
miLineJoin(pDrawable, pGC, pixel, spanData, &leftFace,
|
|
|
|
&prevRightFace);
|
|
|
|
}
|
|
|
|
prevRightFace = rightFace;
|
|
|
|
first = FALSE;
|
|
|
|
projectLeft = FALSE;
|
|
|
|
}
|
|
|
|
if (npt == 1 && somethingDrawn) {
|
|
|
|
if (selfJoin)
|
|
|
|
miLineJoin(pDrawable, pGC, pixel, spanData, &firstFace,
|
|
|
|
&rightFace);
|
|
|
|
else if (pGC->capStyle == CapRound) {
|
|
|
|
if (pGC->lineWidth == 1 && !spanData)
|
|
|
|
miLineOnePoint(pDrawable, pGC, pixel, spanData, x2, y2);
|
|
|
|
else
|
|
|
|
miLineArc(pDrawable, pGC, pixel, spanData,
|
|
|
|
(LineFacePtr) NULL, &rightFace,
|
|
|
|
(double) 0.0, (double) 0.0, TRUE);
|
|
|
|
}
|
|
|
|
}
|
2003-11-14 16:54:54 +01:00
|
|
|
}
|
|
|
|
/* handle crock where all points are coincedent */
|
2012-03-21 20:55:09 +01:00
|
|
|
if (!somethingDrawn) {
|
|
|
|
projectLeft = pGC->capStyle == CapProjecting;
|
|
|
|
miWideSegment(pDrawable, pGC, pixel, spanData,
|
|
|
|
x2, y2, x2, y2, projectLeft, projectLeft,
|
|
|
|
&leftFace, &rightFace);
|
|
|
|
if (pGC->capStyle == CapRound) {
|
|
|
|
miLineArc(pDrawable, pGC, pixel, spanData,
|
|
|
|
&leftFace, (LineFacePtr) NULL,
|
|
|
|
(double) 0.0, (double) 0.0, TRUE);
|
|
|
|
rightFace.dx = -1; /* sleezy hack to make it work */
|
|
|
|
miLineArc(pDrawable, pGC, pixel, spanData,
|
|
|
|
(LineFacePtr) NULL, &rightFace,
|
|
|
|
(double) 0.0, (double) 0.0, TRUE);
|
|
|
|
}
|
2003-11-14 16:54:54 +01:00
|
|
|
}
|
|
|
|
if (spanData)
|
2012-03-21 20:55:09 +01:00
|
|
|
miCleanupSpanData(pDrawable, pGC, spanData);
|
2003-11-14 16:54:54 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
#define V_TOP 0
|
|
|
|
#define V_RIGHT 1
|
|
|
|
#define V_BOTTOM 2
|
|
|
|
#define V_LEFT 3
|
|
|
|
|
|
|
|
static void
|
2012-03-21 20:55:09 +01:00
|
|
|
miWideDashSegment(DrawablePtr pDrawable,
|
|
|
|
GCPtr pGC,
|
|
|
|
SpanDataPtr spanData,
|
|
|
|
int *pDashOffset,
|
|
|
|
int *pDashIndex,
|
|
|
|
int x1,
|
|
|
|
int y1,
|
|
|
|
int x2,
|
|
|
|
int y2,
|
|
|
|
Bool projectLeft,
|
|
|
|
Bool projectRight,
|
|
|
|
LineFacePtr leftFace, LineFacePtr rightFace)
|
2003-11-14 16:54:54 +01:00
|
|
|
{
|
2012-03-21 20:55:09 +01:00
|
|
|
int dashIndex, dashRemain;
|
|
|
|
unsigned char *pDash;
|
|
|
|
double L, l;
|
|
|
|
double k;
|
|
|
|
PolyVertexRec vertices[4];
|
|
|
|
PolyVertexRec saveRight, saveBottom;
|
|
|
|
PolySlopeRec slopes[4];
|
2013-07-16 01:44:29 +02:00
|
|
|
PolyEdgeRec left[4], right[4];
|
2012-03-21 20:55:09 +01:00
|
|
|
LineFaceRec lcapFace, rcapFace;
|
|
|
|
int nleft, nright;
|
|
|
|
int h;
|
|
|
|
int y;
|
|
|
|
int dy, dx;
|
|
|
|
unsigned long pixel;
|
|
|
|
double LRemain;
|
|
|
|
double r;
|
|
|
|
double rdx, rdy;
|
|
|
|
double dashDx, dashDy;
|
|
|
|
double saveK = 0.0;
|
|
|
|
Bool first = TRUE;
|
|
|
|
double lcenterx, lcentery, rcenterx = 0.0, rcentery = 0.0;
|
|
|
|
unsigned long fgPixel, bgPixel;
|
|
|
|
|
2003-11-14 16:54:54 +01:00
|
|
|
dx = x2 - x1;
|
|
|
|
dy = y2 - y1;
|
|
|
|
dashIndex = *pDashIndex;
|
|
|
|
pDash = pGC->dash;
|
|
|
|
dashRemain = pDash[dashIndex] - *pDashOffset;
|
|
|
|
fgPixel = pGC->fgPixel;
|
|
|
|
bgPixel = pGC->bgPixel;
|
2012-03-21 20:55:09 +01:00
|
|
|
if (pGC->fillStyle == FillOpaqueStippled || pGC->fillStyle == FillTiled) {
|
|
|
|
bgPixel = fgPixel;
|
2003-11-14 16:54:54 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
l = ((double) pGC->lineWidth) / 2.0;
|
2012-03-21 20:55:09 +01:00
|
|
|
if (dx == 0) {
|
|
|
|
L = dy;
|
|
|
|
rdx = 0;
|
|
|
|
rdy = l;
|
|
|
|
if (dy < 0) {
|
|
|
|
L = -dy;
|
|
|
|
rdy = -l;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (dy == 0) {
|
|
|
|
L = dx;
|
|
|
|
rdx = l;
|
|
|
|
rdy = 0;
|
|
|
|
if (dx < 0) {
|
|
|
|
L = -dx;
|
|
|
|
rdx = -l;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
L = hypot((double) dx, (double) dy);
|
|
|
|
r = l / L;
|
|
|
|
|
|
|
|
rdx = r * dx;
|
|
|
|
rdy = r * dy;
|
2003-11-14 16:54:54 +01:00
|
|
|
}
|
|
|
|
k = l * L;
|
|
|
|
LRemain = L;
|
|
|
|
/* All position comments are relative to a line with dx and dy > 0,
|
|
|
|
* but the code does not depend on this */
|
|
|
|
/* top */
|
|
|
|
slopes[V_TOP].dx = dx;
|
|
|
|
slopes[V_TOP].dy = dy;
|
|
|
|
slopes[V_TOP].k = k;
|
|
|
|
/* right */
|
|
|
|
slopes[V_RIGHT].dx = -dy;
|
|
|
|
slopes[V_RIGHT].dy = dx;
|
|
|
|
slopes[V_RIGHT].k = 0;
|
|
|
|
/* bottom */
|
|
|
|
slopes[V_BOTTOM].dx = -dx;
|
|
|
|
slopes[V_BOTTOM].dy = -dy;
|
|
|
|
slopes[V_BOTTOM].k = k;
|
|
|
|
/* left */
|
|
|
|
slopes[V_LEFT].dx = dy;
|
|
|
|
slopes[V_LEFT].dy = -dx;
|
|
|
|
slopes[V_LEFT].k = 0;
|
|
|
|
|
|
|
|
/* preload the start coordinates */
|
|
|
|
vertices[V_RIGHT].x = vertices[V_TOP].x = rdy;
|
|
|
|
vertices[V_RIGHT].y = vertices[V_TOP].y = -rdx;
|
|
|
|
|
|
|
|
vertices[V_BOTTOM].x = vertices[V_LEFT].x = -rdy;
|
|
|
|
vertices[V_BOTTOM].y = vertices[V_LEFT].y = rdx;
|
|
|
|
|
2012-03-21 20:55:09 +01:00
|
|
|
if (projectLeft) {
|
|
|
|
vertices[V_TOP].x -= rdx;
|
|
|
|
vertices[V_TOP].y -= rdy;
|
2003-11-14 16:54:54 +01:00
|
|
|
|
2012-03-21 20:55:09 +01:00
|
|
|
vertices[V_LEFT].x -= rdx;
|
|
|
|
vertices[V_LEFT].y -= rdy;
|
2003-11-14 16:54:54 +01:00
|
|
|
|
2012-03-21 20:55:09 +01:00
|
|
|
slopes[V_LEFT].k = rdx * dx + rdy * dy;
|
2003-11-14 16:54:54 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
lcenterx = x1;
|
|
|
|
lcentery = y1;
|
|
|
|
|
2012-03-21 20:55:09 +01:00
|
|
|
if (pGC->capStyle == CapRound) {
|
|
|
|
lcapFace.dx = dx;
|
|
|
|
lcapFace.dy = dy;
|
|
|
|
lcapFace.x = x1;
|
|
|
|
lcapFace.y = y1;
|
|
|
|
|
|
|
|
rcapFace.dx = -dx;
|
|
|
|
rcapFace.dy = -dy;
|
|
|
|
rcapFace.x = x1;
|
|
|
|
rcapFace.y = y1;
|
|
|
|
}
|
|
|
|
while (LRemain > dashRemain) {
|
|
|
|
dashDx = (dashRemain * dx) / L;
|
|
|
|
dashDy = (dashRemain * dy) / L;
|
|
|
|
|
|
|
|
rcenterx = lcenterx + dashDx;
|
|
|
|
rcentery = lcentery + dashDy;
|
|
|
|
|
|
|
|
vertices[V_RIGHT].x += dashDx;
|
|
|
|
vertices[V_RIGHT].y += dashDy;
|
|
|
|
|
|
|
|
vertices[V_BOTTOM].x += dashDx;
|
|
|
|
vertices[V_BOTTOM].y += dashDy;
|
|
|
|
|
|
|
|
slopes[V_RIGHT].k = vertices[V_RIGHT].x * dx + vertices[V_RIGHT].y * dy;
|
|
|
|
|
|
|
|
if (pGC->lineStyle == LineDoubleDash || !(dashIndex & 1)) {
|
|
|
|
if (pGC->lineStyle == LineOnOffDash &&
|
|
|
|
pGC->capStyle == CapProjecting) {
|
|
|
|
saveRight = vertices[V_RIGHT];
|
|
|
|
saveBottom = vertices[V_BOTTOM];
|
|
|
|
saveK = slopes[V_RIGHT].k;
|
|
|
|
|
|
|
|
if (!first) {
|
|
|
|
vertices[V_TOP].x -= rdx;
|
|
|
|
vertices[V_TOP].y -= rdy;
|
|
|
|
|
|
|
|
vertices[V_LEFT].x -= rdx;
|
|
|
|
vertices[V_LEFT].y -= rdy;
|
|
|
|
|
|
|
|
slopes[V_LEFT].k = vertices[V_LEFT].x *
|
|
|
|
slopes[V_LEFT].dy -
|
|
|
|
vertices[V_LEFT].y * slopes[V_LEFT].dx;
|
|
|
|
}
|
|
|
|
|
|
|
|
vertices[V_RIGHT].x += rdx;
|
|
|
|
vertices[V_RIGHT].y += rdy;
|
|
|
|
|
|
|
|
vertices[V_BOTTOM].x += rdx;
|
|
|
|
vertices[V_BOTTOM].y += rdy;
|
|
|
|
|
|
|
|
slopes[V_RIGHT].k = vertices[V_RIGHT].x *
|
|
|
|
slopes[V_RIGHT].dy -
|
|
|
|
vertices[V_RIGHT].y * slopes[V_RIGHT].dx;
|
|
|
|
}
|
|
|
|
y = miPolyBuildPoly(vertices, slopes, 4, x1, y1,
|
|
|
|
left, right, &nleft, &nright, &h);
|
|
|
|
pixel = (dashIndex & 1) ? bgPixel : fgPixel;
|
|
|
|
miFillPolyHelper(pDrawable, pGC, pixel, spanData, y, h, left, right,
|
|
|
|
nleft, nright);
|
|
|
|
|
|
|
|
if (pGC->lineStyle == LineOnOffDash) {
|
|
|
|
switch (pGC->capStyle) {
|
|
|
|
case CapProjecting:
|
|
|
|
vertices[V_BOTTOM] = saveBottom;
|
|
|
|
vertices[V_RIGHT] = saveRight;
|
|
|
|
slopes[V_RIGHT].k = saveK;
|
|
|
|
break;
|
|
|
|
case CapRound:
|
|
|
|
if (!first) {
|
|
|
|
if (dx < 0) {
|
|
|
|
lcapFace.xa = -vertices[V_LEFT].x;
|
|
|
|
lcapFace.ya = -vertices[V_LEFT].y;
|
|
|
|
lcapFace.k = slopes[V_LEFT].k;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
lcapFace.xa = vertices[V_TOP].x;
|
|
|
|
lcapFace.ya = vertices[V_TOP].y;
|
|
|
|
lcapFace.k = -slopes[V_LEFT].k;
|
|
|
|
}
|
|
|
|
miLineArc(pDrawable, pGC, pixel, spanData,
|
|
|
|
&lcapFace, (LineFacePtr) NULL,
|
|
|
|
lcenterx, lcentery, FALSE);
|
|
|
|
}
|
|
|
|
if (dx < 0) {
|
|
|
|
rcapFace.xa = vertices[V_BOTTOM].x;
|
|
|
|
rcapFace.ya = vertices[V_BOTTOM].y;
|
|
|
|
rcapFace.k = slopes[V_RIGHT].k;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
rcapFace.xa = -vertices[V_RIGHT].x;
|
|
|
|
rcapFace.ya = -vertices[V_RIGHT].y;
|
|
|
|
rcapFace.k = -slopes[V_RIGHT].k;
|
|
|
|
}
|
|
|
|
miLineArc(pDrawable, pGC, pixel, spanData,
|
|
|
|
(LineFacePtr) NULL, &rcapFace,
|
|
|
|
rcenterx, rcentery, FALSE);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
LRemain -= dashRemain;
|
|
|
|
++dashIndex;
|
|
|
|
if (dashIndex == pGC->numInDashList)
|
|
|
|
dashIndex = 0;
|
|
|
|
dashRemain = pDash[dashIndex];
|
|
|
|
|
|
|
|
lcenterx = rcenterx;
|
|
|
|
lcentery = rcentery;
|
|
|
|
|
|
|
|
vertices[V_TOP] = vertices[V_RIGHT];
|
|
|
|
vertices[V_LEFT] = vertices[V_BOTTOM];
|
|
|
|
slopes[V_LEFT].k = -slopes[V_RIGHT].k;
|
|
|
|
first = FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (pGC->lineStyle == LineDoubleDash || !(dashIndex & 1)) {
|
|
|
|
vertices[V_TOP].x -= dx;
|
|
|
|
vertices[V_TOP].y -= dy;
|
|
|
|
|
|
|
|
vertices[V_LEFT].x -= dx;
|
|
|
|
vertices[V_LEFT].y -= dy;
|
|
|
|
|
|
|
|
vertices[V_RIGHT].x = rdy;
|
|
|
|
vertices[V_RIGHT].y = -rdx;
|
|
|
|
|
|
|
|
vertices[V_BOTTOM].x = -rdy;
|
|
|
|
vertices[V_BOTTOM].y = rdx;
|
|
|
|
|
|
|
|
if (projectRight) {
|
|
|
|
vertices[V_RIGHT].x += rdx;
|
|
|
|
vertices[V_RIGHT].y += rdy;
|
|
|
|
|
|
|
|
vertices[V_BOTTOM].x += rdx;
|
|
|
|
vertices[V_BOTTOM].y += rdy;
|
|
|
|
slopes[V_RIGHT].k = vertices[V_RIGHT].x *
|
|
|
|
slopes[V_RIGHT].dy - vertices[V_RIGHT].y * slopes[V_RIGHT].dx;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
slopes[V_RIGHT].k = 0;
|
|
|
|
|
|
|
|
if (!first && pGC->lineStyle == LineOnOffDash &&
|
|
|
|
pGC->capStyle == CapProjecting) {
|
|
|
|
vertices[V_TOP].x -= rdx;
|
|
|
|
vertices[V_TOP].y -= rdy;
|
|
|
|
|
|
|
|
vertices[V_LEFT].x -= rdx;
|
|
|
|
vertices[V_LEFT].y -= rdy;
|
|
|
|
slopes[V_LEFT].k = vertices[V_LEFT].x *
|
|
|
|
slopes[V_LEFT].dy - vertices[V_LEFT].y * slopes[V_LEFT].dx;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
slopes[V_LEFT].k += dx * dx + dy * dy;
|
|
|
|
|
|
|
|
y = miPolyBuildPoly(vertices, slopes, 4, x2, y2,
|
|
|
|
left, right, &nleft, &nright, &h);
|
|
|
|
|
|
|
|
pixel = (dashIndex & 1) ? pGC->bgPixel : pGC->fgPixel;
|
|
|
|
miFillPolyHelper(pDrawable, pGC, pixel, spanData, y, h, left, right,
|
|
|
|
nleft, nright);
|
|
|
|
if (!first && pGC->lineStyle == LineOnOffDash &&
|
|
|
|
pGC->capStyle == CapRound) {
|
|
|
|
lcapFace.x = x2;
|
|
|
|
lcapFace.y = y2;
|
|
|
|
if (dx < 0) {
|
|
|
|
lcapFace.xa = -vertices[V_LEFT].x;
|
|
|
|
lcapFace.ya = -vertices[V_LEFT].y;
|
|
|
|
lcapFace.k = slopes[V_LEFT].k;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
lcapFace.xa = vertices[V_TOP].x;
|
|
|
|
lcapFace.ya = vertices[V_TOP].y;
|
|
|
|
lcapFace.k = -slopes[V_LEFT].k;
|
|
|
|
}
|
|
|
|
miLineArc(pDrawable, pGC, pixel, spanData,
|
|
|
|
&lcapFace, (LineFacePtr) NULL, rcenterx, rcentery, FALSE);
|
|
|
|
}
|
2003-11-14 16:54:54 +01:00
|
|
|
}
|
|
|
|
dashRemain = ((double) dashRemain) - LRemain;
|
2012-03-21 20:55:09 +01:00
|
|
|
if (dashRemain == 0) {
|
|
|
|
dashIndex++;
|
|
|
|
if (dashIndex == pGC->numInDashList)
|
|
|
|
dashIndex = 0;
|
|
|
|
dashRemain = pDash[dashIndex];
|
2003-11-14 16:54:54 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
leftFace->x = x1;
|
|
|
|
leftFace->y = y1;
|
|
|
|
leftFace->dx = dx;
|
|
|
|
leftFace->dy = dy;
|
|
|
|
leftFace->xa = rdy;
|
|
|
|
leftFace->ya = -rdx;
|
|
|
|
leftFace->k = k;
|
|
|
|
|
|
|
|
rightFace->x = x2;
|
|
|
|
rightFace->y = y2;
|
|
|
|
rightFace->dx = -dx;
|
|
|
|
rightFace->dy = -dy;
|
|
|
|
rightFace->xa = -rdy;
|
|
|
|
rightFace->ya = rdx;
|
|
|
|
rightFace->k = k;
|
|
|
|
|
|
|
|
*pDashIndex = dashIndex;
|
|
|
|
*pDashOffset = pDash[dashIndex] - dashRemain;
|
|
|
|
}
|
|
|
|
|
Rework symbol visibility for easier maintenance
Save in a few special cases, _X_EXPORT should not be used in C source
files. Instead, it should be used in headers, and the proper C source
include that header. Some special cases are symbols that need to be
shared between modules, but not expected to be used by external drivers,
and symbols that are accessible via LoaderSymbol/dlopen.
This patch also adds conditionally some new sdk header files, depending
on extensions enabled. These files were added to match pattern for
other extensions/modules, that is, have the headers "deciding" symbol
visibility in the sdk. These headers are:
o Xext/panoramiXsrv.h, Xext/panoramiX.h
o fbpict.h (unconditionally)
o vidmodeproc.h
o mioverlay.h (unconditionally, used only by xaa)
o xfixes.h (unconditionally, symbols required by dri2)
LoaderSymbol and similar functions now don't have different prototypes,
in loaderProcs.h and xf86Module.h, so that both headers can be included,
without the need of defining IN_LOADER.
xf86NewInputDevice() device prototype readded to xf86Xinput.h, but
not exported (and with a comment about it).
2008-12-03 08:43:34 +01:00
|
|
|
void
|
2012-03-21 20:55:09 +01:00
|
|
|
miWideDash(DrawablePtr pDrawable, GCPtr pGC,
|
|
|
|
int mode, int npt, DDXPointPtr pPts)
|
2003-11-14 16:54:54 +01:00
|
|
|
{
|
2012-03-21 20:55:09 +01:00
|
|
|
int x1, y1, x2, y2;
|
|
|
|
unsigned long pixel;
|
|
|
|
Bool projectLeft, projectRight;
|
|
|
|
LineFaceRec leftFace, rightFace, prevRightFace;
|
|
|
|
LineFaceRec firstFace;
|
|
|
|
int first;
|
|
|
|
int dashIndex, dashOffset;
|
|
|
|
int prevDashIndex;
|
|
|
|
SpanDataRec spanDataRec;
|
|
|
|
SpanDataPtr spanData;
|
|
|
|
Bool somethingDrawn = FALSE;
|
|
|
|
Bool selfJoin;
|
|
|
|
Bool endIsFg = FALSE, startIsFg = FALSE;
|
|
|
|
Bool firstIsFg = FALSE, prevIsFg = FALSE;
|
2003-11-14 16:54:54 +01:00
|
|
|
|
2006-07-19 00:16:12 +02:00
|
|
|
#if 0
|
2003-11-14 16:54:54 +01:00
|
|
|
/* XXX backward compatibility */
|
2012-03-21 20:55:09 +01:00
|
|
|
if (pGC->lineWidth == 0) {
|
|
|
|
miZeroDashLine(pDrawable, pGC, mode, npt, pPts);
|
|
|
|
return;
|
2003-11-14 16:54:54 +01:00
|
|
|
}
|
2003-11-14 17:49:22 +01:00
|
|
|
#endif
|
2012-03-21 20:55:09 +01:00
|
|
|
if (pGC->lineStyle == LineDoubleDash &&
|
|
|
|
(pGC->fillStyle == FillOpaqueStippled || pGC->fillStyle == FillTiled)) {
|
|
|
|
miWideLine(pDrawable, pGC, mode, npt, pPts);
|
|
|
|
return;
|
2003-11-14 16:54:54 +01:00
|
|
|
}
|
|
|
|
if (npt == 0)
|
2012-03-21 20:55:09 +01:00
|
|
|
return;
|
|
|
|
spanData = miSetupSpanData(pGC, &spanDataRec, npt);
|
2003-11-14 16:54:54 +01:00
|
|
|
x2 = pPts->x;
|
|
|
|
y2 = pPts->y;
|
|
|
|
first = TRUE;
|
|
|
|
selfJoin = FALSE;
|
2012-03-21 20:55:09 +01:00
|
|
|
if (mode == CoordModePrevious) {
|
|
|
|
int nptTmp;
|
|
|
|
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;
|
2003-11-14 16:54:54 +01:00
|
|
|
}
|
|
|
|
projectLeft = pGC->capStyle == CapProjecting && !selfJoin;
|
|
|
|
projectRight = FALSE;
|
|
|
|
dashIndex = 0;
|
|
|
|
dashOffset = 0;
|
2012-03-21 20:55:09 +01:00
|
|
|
miStepDash((int) pGC->dashOffset, &dashIndex,
|
|
|
|
pGC->dash, (int) pGC->numInDashList, &dashOffset);
|
|
|
|
while (--npt) {
|
|
|
|
x1 = x2;
|
|
|
|
y1 = y2;
|
|
|
|
++pPts;
|
|
|
|
x2 = pPts->x;
|
|
|
|
y2 = pPts->y;
|
|
|
|
if (mode == CoordModePrevious) {
|
|
|
|
x2 += x1;
|
|
|
|
y2 += y1;
|
|
|
|
}
|
|
|
|
if (x1 != x2 || y1 != y2) {
|
|
|
|
somethingDrawn = TRUE;
|
|
|
|
if (npt == 1 && pGC->capStyle == CapProjecting &&
|
|
|
|
(!selfJoin || !firstIsFg))
|
|
|
|
projectRight = TRUE;
|
|
|
|
prevDashIndex = dashIndex;
|
|
|
|
miWideDashSegment(pDrawable, pGC, spanData, &dashOffset, &dashIndex,
|
|
|
|
x1, y1, x2, y2,
|
|
|
|
projectLeft, projectRight, &leftFace, &rightFace);
|
|
|
|
startIsFg = !(prevDashIndex & 1);
|
|
|
|
endIsFg = (dashIndex & 1) ^ (dashOffset != 0);
|
|
|
|
if (pGC->lineStyle == LineDoubleDash || startIsFg) {
|
|
|
|
pixel = startIsFg ? pGC->fgPixel : pGC->bgPixel;
|
|
|
|
if (first || (pGC->lineStyle == LineOnOffDash && !prevIsFg)) {
|
|
|
|
if (first && selfJoin) {
|
|
|
|
firstFace = leftFace;
|
|
|
|
firstIsFg = startIsFg;
|
|
|
|
}
|
|
|
|
else if (pGC->capStyle == CapRound)
|
|
|
|
miLineArc(pDrawable, pGC, pixel, spanData,
|
|
|
|
&leftFace, (LineFacePtr) NULL,
|
|
|
|
(double) 0.0, (double) 0.0, TRUE);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
miLineJoin(pDrawable, pGC, pixel, spanData, &leftFace,
|
|
|
|
&prevRightFace);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
prevRightFace = rightFace;
|
|
|
|
prevIsFg = endIsFg;
|
|
|
|
first = FALSE;
|
|
|
|
projectLeft = FALSE;
|
|
|
|
}
|
|
|
|
if (npt == 1 && somethingDrawn) {
|
|
|
|
if (pGC->lineStyle == LineDoubleDash || endIsFg) {
|
|
|
|
pixel = endIsFg ? pGC->fgPixel : pGC->bgPixel;
|
|
|
|
if (selfJoin && (pGC->lineStyle == LineDoubleDash || firstIsFg)) {
|
|
|
|
miLineJoin(pDrawable, pGC, pixel, spanData, &firstFace,
|
|
|
|
&rightFace);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
if (pGC->capStyle == CapRound)
|
|
|
|
miLineArc(pDrawable, pGC, pixel, spanData,
|
|
|
|
(LineFacePtr) NULL, &rightFace,
|
|
|
|
(double) 0.0, (double) 0.0, TRUE);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
/* glue a cap to the start of the line if
|
|
|
|
* we're OnOffDash and ended on odd dash
|
|
|
|
*/
|
|
|
|
if (selfJoin && firstIsFg) {
|
|
|
|
pixel = pGC->fgPixel;
|
|
|
|
if (pGC->capStyle == CapProjecting)
|
|
|
|
miLineProjectingCap(pDrawable, pGC, pixel, spanData,
|
|
|
|
&firstFace, TRUE,
|
|
|
|
(double) 0.0, (double) 0.0, TRUE);
|
|
|
|
else if (pGC->capStyle == CapRound)
|
|
|
|
miLineArc(pDrawable, pGC, pixel, spanData,
|
|
|
|
&firstFace, (LineFacePtr) NULL,
|
|
|
|
(double) 0.0, (double) 0.0, TRUE);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2003-11-14 16:54:54 +01:00
|
|
|
}
|
|
|
|
/* handle crock where all points are coincident */
|
2012-03-21 20:55:09 +01:00
|
|
|
if (!somethingDrawn &&
|
|
|
|
(pGC->lineStyle == LineDoubleDash || !(dashIndex & 1))) {
|
|
|
|
/* not the same as endIsFg computation above */
|
|
|
|
pixel = (dashIndex & 1) ? pGC->bgPixel : pGC->fgPixel;
|
|
|
|
switch (pGC->capStyle) {
|
|
|
|
case CapRound:
|
|
|
|
miLineArc(pDrawable, pGC, pixel, spanData,
|
|
|
|
(LineFacePtr) NULL, (LineFacePtr) NULL,
|
|
|
|
(double) x2, (double) y2, FALSE);
|
|
|
|
break;
|
|
|
|
case CapProjecting:
|
|
|
|
x1 = pGC->lineWidth;
|
|
|
|
miFillRectPolyHelper(pDrawable, pGC, pixel, spanData,
|
|
|
|
x2 - (x1 >> 1), y2 - (x1 >> 1), x1, x1);
|
|
|
|
break;
|
|
|
|
}
|
2003-11-14 16:54:54 +01:00
|
|
|
}
|
|
|
|
if (spanData)
|
2012-03-21 20:55:09 +01:00
|
|
|
miCleanupSpanData(pDrawable, pGC, spanData);
|
2003-11-14 16:54:54 +01:00
|
|
|
}
|
2014-05-07 18:56:39 +02:00
|
|
|
|
|
|
|
void
|
|
|
|
miPolylines(DrawablePtr drawable,
|
|
|
|
GCPtr gc,
|
|
|
|
int mode,
|
|
|
|
int n,
|
|
|
|
DDXPointPtr points)
|
|
|
|
{
|
|
|
|
if (gc->lineWidth == 0) {
|
|
|
|
if (gc->lineStyle == LineSolid)
|
|
|
|
miZeroLine(drawable, gc, mode, n, points);
|
|
|
|
else
|
|
|
|
miZeroDashLine(drawable, gc, mode, n, points);
|
|
|
|
} else {
|
|
|
|
if (gc->lineStyle == LineSolid)
|
|
|
|
miWideLine(drawable, gc, mode, n, points);
|
|
|
|
else
|
|
|
|
miWideDash(drawable, gc, mode, n, points);
|
|
|
|
}
|
|
|
|
}
|