forked from AuroraMiddleware/gtk
6de551b504
2004-11-10 Matthias Clasen <mclasen@redhat.com> * gdk/linux-fb/*: Fix many sparse warnings. (#157253, Kjartan Maraas.
311 lines
7.3 KiB
C
311 lines
7.3 KiB
C
/***********************************************************
|
|
|
|
Copyright 1987, 1998 The Open Group
|
|
|
|
All Rights Reserved.
|
|
|
|
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.
|
|
|
|
|
|
Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts.
|
|
|
|
All Rights Reserved
|
|
|
|
Permission to use, copy, modify, and distribute this software and its
|
|
documentation for any purpose and without fee is hereby granted,
|
|
provided that the above copyright notice appear in all copies and that
|
|
both that copyright notice and this permission notice appear in
|
|
supporting documentation, and that the name of Digital not be
|
|
used in advertising or publicity pertaining to distribution of the
|
|
software without specific, written prior permission.
|
|
|
|
DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
|
|
ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
|
|
DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
|
|
ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
|
|
WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
|
|
ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
|
|
SOFTWARE.
|
|
|
|
******************************************************************/
|
|
/* $TOG: midash.c /main/14 1998/02/09 14:46:34 kaleb $ */
|
|
|
|
#include <config.h>
|
|
#include "mi.h"
|
|
|
|
static miDashPtr
|
|
CheckDashStorage(miDashPtr *ppseg, int nseg, int *pnsegMax);
|
|
|
|
/* return a list of DashRec. there will be an extra
|
|
entry at the end holding the last point of the polyline.
|
|
this means that the code that actually draws dashes can
|
|
get a pair of points for every dash. only the point in the last
|
|
dash record is useful; the other fields are not used.
|
|
nseg is the number of segments, not the number of points.
|
|
|
|
example:
|
|
|
|
dash1.start
|
|
dash2.start
|
|
dash3.start
|
|
last-point
|
|
|
|
defines a list of segments
|
|
(dash1.pt, dash2.pt)
|
|
(dash2.pt, dash3.pt)
|
|
(dash3.pt, last-point)
|
|
and nseg == 3.
|
|
|
|
NOTE:
|
|
EVEN_DASH == ~ODD_DASH
|
|
|
|
NOTE ALSO:
|
|
miDashLines may return 0 segments, going from pt[0] to pt[0] with one dash.
|
|
*/
|
|
|
|
enum { EVEN_DASH=0, ODD_DASH=1 };
|
|
|
|
#define sign(x) ((x)>0)?1:( ((x)<0)?-1:0 )
|
|
|
|
miDashPtr
|
|
miDashLine(int npt, GdkPoint *ppt, unsigned int nDash,
|
|
unsigned char *pDash, unsigned int offset, int *pnseg)
|
|
{
|
|
GdkPoint pt1, pt2;
|
|
int lenCur; /* npt used from this dash */
|
|
int lenMax; /* npt in this dash */
|
|
int iDash = 0; /* index of current dash */
|
|
int which; /* EVEN_DASH or ODD_DASH */
|
|
miDashPtr pseg; /* list of dash segments */
|
|
miDashPtr psegBase; /* start of list */
|
|
int nseg = 0; /* number of dashes so far */
|
|
int nsegMax = 0; /* num segs we can fit in this list */
|
|
|
|
int x, y, len;
|
|
int adx, ady, signdx, signdy;
|
|
int du, dv, e1, e2, e, base_e = 0;
|
|
|
|
lenCur = offset;
|
|
which = EVEN_DASH;
|
|
while(lenCur >= pDash[iDash])
|
|
{
|
|
lenCur -= pDash[iDash];
|
|
iDash++;
|
|
if (iDash >= nDash)
|
|
iDash = 0;
|
|
which = ~which;
|
|
}
|
|
lenMax = pDash[iDash];
|
|
|
|
psegBase = (miDashPtr)NULL;
|
|
pt2 = ppt[0]; /* just in case there is only one point */
|
|
|
|
while(--npt)
|
|
{
|
|
if (PtEqual(ppt[0], ppt[1]))
|
|
{
|
|
ppt++;
|
|
continue; /* no duplicated points in polyline */
|
|
}
|
|
pt1 = *ppt++;
|
|
pt2 = *ppt;
|
|
|
|
adx = pt2.x - pt1.x;
|
|
ady = pt2.y - pt1.y;
|
|
signdx = sign(adx);
|
|
signdy = sign(ady);
|
|
adx = abs(adx);
|
|
ady = abs(ady);
|
|
|
|
if (adx > ady)
|
|
{
|
|
du = adx;
|
|
dv = ady;
|
|
len = adx;
|
|
}
|
|
else
|
|
{
|
|
du = ady;
|
|
dv = adx;
|
|
len = ady;
|
|
}
|
|
|
|
e1 = dv * 2;
|
|
e2 = e1 - 2*du;
|
|
e = e1 - du;
|
|
x = pt1.x;
|
|
y = pt1.y;
|
|
|
|
nseg++;
|
|
pseg = CheckDashStorage(&psegBase, nseg, &nsegMax);
|
|
if (!pseg)
|
|
return (miDashPtr)NULL;
|
|
pseg->pt = pt1;
|
|
pseg->e1 = e1;
|
|
pseg->e2 = e2;
|
|
base_e = pseg->e = e;
|
|
pseg->which = which;
|
|
pseg->newLine = 1;
|
|
|
|
while (len--)
|
|
{
|
|
if (adx > ady)
|
|
{
|
|
/* X_AXIS */
|
|
if (((signdx > 0) && (e < 0)) ||
|
|
((signdx <=0) && (e <=0))
|
|
)
|
|
{
|
|
e += e1;
|
|
}
|
|
else
|
|
{
|
|
y += signdy;
|
|
e += e2;
|
|
}
|
|
x += signdx;
|
|
}
|
|
else
|
|
{
|
|
/* Y_AXIS */
|
|
if (((signdx > 0) && (e < 0)) ||
|
|
((signdx <=0) && (e <=0))
|
|
)
|
|
{
|
|
e +=e1;
|
|
}
|
|
else
|
|
{
|
|
x += signdx;
|
|
e += e2;
|
|
}
|
|
y += signdy;
|
|
}
|
|
|
|
lenCur++;
|
|
if (lenCur >= lenMax && (len || npt <= 1))
|
|
{
|
|
nseg++;
|
|
pseg = CheckDashStorage(&psegBase, nseg, &nsegMax);
|
|
if (!pseg)
|
|
return (miDashPtr)NULL;
|
|
pseg->pt.x = x;
|
|
pseg->pt.y = y;
|
|
pseg->e1 = e1;
|
|
pseg->e2 = e2;
|
|
pseg->e = e;
|
|
which = ~which;
|
|
pseg->which = which;
|
|
pseg->newLine = 0;
|
|
|
|
/* move on to next dash */
|
|
iDash++;
|
|
if (iDash >= nDash)
|
|
iDash = 0;
|
|
lenMax = pDash[iDash];
|
|
lenCur = 0;
|
|
}
|
|
} /* while len-- */
|
|
} /* while --npt */
|
|
|
|
if (lenCur == 0 && nseg != 0)
|
|
{
|
|
nseg--;
|
|
which = ~which;
|
|
}
|
|
*pnseg = nseg;
|
|
pseg = CheckDashStorage(&psegBase, nseg+1, &nsegMax);
|
|
if (!pseg)
|
|
return (miDashPtr)NULL;
|
|
pseg->pt = pt2;
|
|
pseg->e = base_e;
|
|
pseg->which = which;
|
|
pseg->newLine = 0;
|
|
return psegBase;
|
|
}
|
|
|
|
|
|
#define NSEGDELTA 16
|
|
|
|
/* returns a pointer to the pseg[nseg-1], growing the storage as
|
|
necessary. this interface seems unnecessarily cumbersome.
|
|
|
|
*/
|
|
|
|
static miDashPtr
|
|
CheckDashStorage(miDashPtr *ppseg, int nseg, int *pnsegMax)
|
|
#if 0
|
|
miDashPtr *ppseg; /* base pointer */
|
|
int nseg; /* number of segment we want to write to */
|
|
int *pnsegMax; /* size (in segments) of list so far */
|
|
#endif
|
|
{
|
|
if (nseg > *pnsegMax)
|
|
{
|
|
miDashPtr newppseg;
|
|
|
|
*pnsegMax += NSEGDELTA;
|
|
newppseg = (miDashPtr)g_realloc(*ppseg,
|
|
(*pnsegMax)*sizeof(miDashRec));
|
|
if (!newppseg)
|
|
{
|
|
g_free(*ppseg);
|
|
return (miDashPtr)NULL;
|
|
}
|
|
*ppseg = newppseg;
|
|
}
|
|
return(*ppseg+(nseg-1));
|
|
}
|
|
|
|
void
|
|
miStepDash (int dist, int *pDashIndex, unsigned char *pDash,
|
|
int numInDashList, int *pDashOffset)
|
|
#if 0
|
|
int dist; /* distance to step */
|
|
int *pDashIndex; /* current dash */
|
|
unsigned char *pDash; /* dash list */
|
|
int numInDashList; /* total length of dash list */
|
|
int *pDashOffset; /* offset into current dash */
|
|
#endif
|
|
{
|
|
int dashIndex, dashOffset;
|
|
int totallen;
|
|
int i;
|
|
|
|
dashIndex = *pDashIndex;
|
|
dashOffset = *pDashOffset;
|
|
if (dist < pDash[dashIndex] - dashOffset)
|
|
{
|
|
*pDashOffset = dashOffset + dist;
|
|
return;
|
|
}
|
|
dist -= pDash[dashIndex] - dashOffset;
|
|
if (++dashIndex == numInDashList)
|
|
dashIndex = 0;
|
|
totallen = 0;
|
|
for (i = 0; i < numInDashList; i++)
|
|
totallen += pDash[i];
|
|
if (totallen <= dist)
|
|
dist = dist % totallen;
|
|
while (dist >= pDash[dashIndex])
|
|
{
|
|
dist -= pDash[dashIndex];
|
|
if (++dashIndex == numInDashList)
|
|
dashIndex = 0;
|
|
}
|
|
*pDashIndex = dashIndex;
|
|
*pDashOffset = dist;
|
|
}
|