123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314 |
- /***********************************************************
- Copyright 1987, 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.
- 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.
- ******************************************************************/
- #ifdef HAVE_DIX_CONFIG_H
- #include <dix-config.h>
- #endif
- #include "regionstr.h"
- #include "mistruct.h"
- #include "mifpoly.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.
- */
- miDashPtr
- miDashLine(npt, ppt, nDash, pDash, offset, pnseg)
- int npt;
- DDXPointPtr ppt;
- unsigned int nDash;
- unsigned char *pDash;
- unsigned int offset;
- int *pnseg;
- {
- DDXPointRec 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, /* base pointer */
- int nseg, /* number of segment we want to write to */
- int *pnsegMax) /* size (in segments) of list so far */
- {
- if (nseg > *pnsegMax)
- {
- miDashPtr newppseg;
- *pnsegMax += NSEGDELTA;
- newppseg = (miDashPtr)realloc(*ppseg,
- (*pnsegMax)*sizeof(miDashRec));
- if (!newppseg)
- {
- free(*ppseg);
- return (miDashPtr)NULL;
- }
- *ppseg = newppseg;
- }
- return(*ppseg+(nseg-1));
- }
- _X_EXPORT void
- miStepDash (dist, pDashIndex, pDash, numInDashList, pDashOffset)
- 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 */
- {
- 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 && totallen <= dist)
- dist = dist % totallen;
- while (dist >= pDash[dashIndex])
- {
- dist -= pDash[dashIndex];
- if (++dashIndex == numInDashList)
- dashIndex = 0;
- }
- *pDashIndex = dashIndex;
- *pDashOffset = dist;
- }
|