1/*
2 * Copyright © 1998 Keith Packard
3 * Copyright © 2012 Intel Corporation
4 *
5 * Permission to use, copy, modify, distribute, and sell this software and its
6 * documentation for any purpose is hereby granted without fee, provided that
7 * the above copyright notice appear in all copies and that both that
8 * copyright notice and this permission notice appear in supporting
9 * documentation, and that the name of Keith Packard not be used in
10 * advertising or publicity pertaining to distribution of the software without
11 * specific, written prior permission.  Keith Packard makes no
12 * representations about the suitability of this software for any purpose.  It
13 * is provided "as is" without express or implied warranty.
14 *
15 * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
16 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
17 * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR
18 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
19 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
20 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
21 * PERFORMANCE OF THIS SOFTWARE.
22 */
23
24#define isClipped(c,ul,lr)  (((c) | ((c) - (ul)) | ((lr) - (c))) & 0x80008000)
25#define RROP(b,a,x)	WRITE((b), FbDoRRop (READ(b), (a), (x)))
26
27#define ARCCOPY(d)  WRITE(d,xorBits)
28#define ARCRROP(d)  RROP(d,andBits,xorBits)
29
30static void
31ARC(FbBits * dst,
32    FbStride dstStride,
33    int dstBpp, xArc * arc, int drawX, int drawY, FbBits and, FbBits xor)
34{
35	BITS *bits;
36	FbStride bitsStride;
37	miZeroArcRec info;
38	Bool do360;
39	int x;
40	BITS *yorgp, *yorgop;
41	BITS andBits, xorBits;
42	int yoffset, dyoffset;
43	int y, a, b, d, mask;
44	int k1, k3, dx, dy;
45
46	bits = (BITS *) dst;
47	bitsStride = dstStride * (sizeof(FbBits) / sizeof(BITS));
48	andBits = (BITS) and;
49	xorBits = (BITS) xor;
50	do360 = miZeroArcSetup(arc, &info, TRUE);
51	yorgp = bits + ((info.yorg + drawY) * bitsStride);
52	yorgop = bits + ((info.yorgo + drawY) * bitsStride);
53	info.xorg = (info.xorg + drawX);
54	info.xorgo = (info.xorgo + drawX);
55	MIARCSETUP();
56	yoffset = y ? bitsStride : 0;
57	dyoffset = 0;
58	mask = info.initialMask;
59
60	if (!(arc->width & 1)) {
61		if (andBits == 0) {
62			if (mask & 2)
63				ARCCOPY(yorgp + info.xorgo);
64			if (mask & 8)
65				ARCCOPY(yorgop + info.xorgo);
66		} else {
67			if (mask & 2)
68				ARCRROP(yorgp + info.xorgo);
69			if (mask & 8)
70				ARCRROP(yorgop + info.xorgo);
71		}
72	}
73	if (!info.end.x || !info.end.y) {
74		mask = info.end.mask;
75		info.end = info.altend;
76	}
77	if (do360 && (arc->width == arc->height) && !(arc->width & 1)) {
78		int xoffset = bitsStride;
79		BITS *yorghb = yorgp + (info.h * bitsStride) + info.xorg;
80		BITS *yorgohb = yorghb - info.h;
81
82		yorgp += info.xorg;
83		yorgop += info.xorg;
84		yorghb += info.h;
85		while (1) {
86			if (andBits == 0) {
87				ARCCOPY(yorgp + yoffset + x);
88				ARCCOPY(yorgp + yoffset - x);
89				ARCCOPY(yorgop - yoffset - x);
90				ARCCOPY(yorgop - yoffset + x);
91			} else {
92				ARCRROP(yorgp + yoffset + x);
93				ARCRROP(yorgp + yoffset - x);
94				ARCRROP(yorgop - yoffset - x);
95				ARCRROP(yorgop - yoffset + x);
96			}
97			if (a < 0)
98				break;
99			if (andBits == 0) {
100				ARCCOPY(yorghb - xoffset - y);
101				ARCCOPY(yorgohb - xoffset + y);
102				ARCCOPY(yorgohb + xoffset + y);
103				ARCCOPY(yorghb + xoffset - y);
104			} else {
105				ARCRROP(yorghb - xoffset - y);
106				ARCRROP(yorgohb - xoffset + y);
107				ARCRROP(yorgohb + xoffset + y);
108				ARCRROP(yorghb + xoffset - y);
109			}
110			xoffset += bitsStride;
111			MIARCCIRCLESTEP(yoffset += bitsStride;
112				       );
113		}
114		yorgp -= info.xorg;
115		yorgop -= info.xorg;
116		x = info.w;
117		yoffset = info.h * bitsStride;
118	} else if (do360) {
119		while (y < info.h || x < info.w) {
120			MIARCOCTANTSHIFT(dyoffset = bitsStride;
121					);
122			if (andBits == 0) {
123				ARCCOPY(yorgp + yoffset + info.xorg + x);
124				ARCCOPY(yorgp + yoffset + info.xorgo - x);
125				ARCCOPY(yorgop - yoffset + info.xorgo - x);
126				ARCCOPY(yorgop - yoffset + info.xorg + x);
127			} else {
128				ARCRROP(yorgp + yoffset + info.xorg + x);
129				ARCRROP(yorgp + yoffset + info.xorgo - x);
130				ARCRROP(yorgop - yoffset + info.xorgo - x);
131				ARCRROP(yorgop - yoffset + info.xorg + x);
132			}
133			MIARCSTEP(yoffset += dyoffset;
134				  , yoffset += bitsStride;
135				 );
136		}
137	} else {
138		while (y < info.h || x < info.w) {
139			MIARCOCTANTSHIFT(dyoffset = bitsStride;
140					);
141			if ((x == info.start.x) || (y == info.start.y)) {
142				mask = info.start.mask;
143				info.start = info.altstart;
144			}
145			if (andBits == 0) {
146				if (mask & 1)
147					ARCCOPY(yorgp + yoffset + info.xorg + x);
148				if (mask & 2)
149					ARCCOPY(yorgp + yoffset + info.xorgo - x);
150				if (mask & 4)
151					ARCCOPY(yorgop - yoffset + info.xorgo - x);
152				if (mask & 8)
153					ARCCOPY(yorgop - yoffset + info.xorg + x);
154			} else {
155				if (mask & 1)
156					ARCRROP(yorgp + yoffset + info.xorg + x);
157				if (mask & 2)
158					ARCRROP(yorgp + yoffset + info.xorgo - x);
159				if (mask & 4)
160					ARCRROP(yorgop - yoffset + info.xorgo - x);
161				if (mask & 8)
162					ARCRROP(yorgop - yoffset + info.xorg + x);
163			}
164			if ((x == info.end.x) || (y == info.end.y)) {
165				mask = info.end.mask;
166				info.end = info.altend;
167			}
168			MIARCSTEP(yoffset += dyoffset;
169				  , yoffset += bitsStride;
170				 );
171		}
172	}
173	if ((x == info.start.x) || (y == info.start.y))
174		mask = info.start.mask;
175	if (andBits == 0) {
176		if (mask & 1)
177			ARCCOPY(yorgp + yoffset + info.xorg + x);
178		if (mask & 4)
179			ARCCOPY(yorgop - yoffset + info.xorgo - x);
180		if (arc->height & 1) {
181			if (mask & 2)
182				ARCCOPY(yorgp + yoffset + info.xorgo - x);
183			if (mask & 8)
184				ARCCOPY(yorgop - yoffset + info.xorg + x);
185		}
186	} else {
187		if (mask & 1)
188			ARCRROP(yorgp + yoffset + info.xorg + x);
189		if (mask & 4)
190			ARCRROP(yorgop - yoffset + info.xorgo - x);
191		if (arc->height & 1) {
192			if (mask & 2)
193				ARCRROP(yorgp + yoffset + info.xorgo - x);
194			if (mask & 8)
195				ARCRROP(yorgop - yoffset + info.xorg + x);
196		}
197	}
198}
199
200#undef ARCCOPY
201#undef ARCRROP
202
203#undef RROP
204#undef isClipped
205