1428d7b3dSmrg/*
2428d7b3dSmrg * Copyright © 1998 Keith Packard
3428d7b3dSmrg * Copyright © 2012 Intel Corporation
4428d7b3dSmrg *
5428d7b3dSmrg * Permission to use, copy, modify, distribute, and sell this software and its
6428d7b3dSmrg * documentation for any purpose is hereby granted without fee, provided that
7428d7b3dSmrg * the above copyright notice appear in all copies and that both that
8428d7b3dSmrg * copyright notice and this permission notice appear in supporting
9428d7b3dSmrg * documentation, and that the name of Keith Packard not be used in
10428d7b3dSmrg * advertising or publicity pertaining to distribution of the software without
11428d7b3dSmrg * specific, written prior permission.  Keith Packard makes no
12428d7b3dSmrg * representations about the suitability of this software for any purpose.  It
13428d7b3dSmrg * is provided "as is" without express or implied warranty.
14428d7b3dSmrg *
15428d7b3dSmrg * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
16428d7b3dSmrg * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
17428d7b3dSmrg * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR
18428d7b3dSmrg * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
19428d7b3dSmrg * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
20428d7b3dSmrg * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
21428d7b3dSmrg * PERFORMANCE OF THIS SOFTWARE.
22428d7b3dSmrg */
23428d7b3dSmrg
24428d7b3dSmrg#define isClipped(c,ul,lr)  (((c) | ((c) - (ul)) | ((lr) - (c))) & 0x80008000)
25428d7b3dSmrg#define RROP(b,a,x)	WRITE((b), FbDoRRop (READ(b), (a), (x)))
26428d7b3dSmrg
27428d7b3dSmrg#define ARCCOPY(d)  WRITE(d,xorBits)
28428d7b3dSmrg#define ARCRROP(d)  RROP(d,andBits,xorBits)
29428d7b3dSmrg
30428d7b3dSmrgstatic void
31428d7b3dSmrgARC(FbBits * dst,
32428d7b3dSmrg    FbStride dstStride,
33428d7b3dSmrg    int dstBpp, xArc * arc, int drawX, int drawY, FbBits and, FbBits xor)
34428d7b3dSmrg{
35428d7b3dSmrg	BITS *bits;
36428d7b3dSmrg	FbStride bitsStride;
37428d7b3dSmrg	miZeroArcRec info;
38428d7b3dSmrg	Bool do360;
39428d7b3dSmrg	int x;
40428d7b3dSmrg	BITS *yorgp, *yorgop;
41428d7b3dSmrg	BITS andBits, xorBits;
42428d7b3dSmrg	int yoffset, dyoffset;
43428d7b3dSmrg	int y, a, b, d, mask;
44428d7b3dSmrg	int k1, k3, dx, dy;
45428d7b3dSmrg
46428d7b3dSmrg	bits = (BITS *) dst;
47428d7b3dSmrg	bitsStride = dstStride * (sizeof(FbBits) / sizeof(BITS));
48428d7b3dSmrg	andBits = (BITS) and;
49428d7b3dSmrg	xorBits = (BITS) xor;
50428d7b3dSmrg	do360 = miZeroArcSetup(arc, &info, TRUE);
51428d7b3dSmrg	yorgp = bits + ((info.yorg + drawY) * bitsStride);
52428d7b3dSmrg	yorgop = bits + ((info.yorgo + drawY) * bitsStride);
53428d7b3dSmrg	info.xorg = (info.xorg + drawX);
54428d7b3dSmrg	info.xorgo = (info.xorgo + drawX);
55428d7b3dSmrg	MIARCSETUP();
56428d7b3dSmrg	yoffset = y ? bitsStride : 0;
57428d7b3dSmrg	dyoffset = 0;
58428d7b3dSmrg	mask = info.initialMask;
59428d7b3dSmrg
60428d7b3dSmrg	if (!(arc->width & 1)) {
61428d7b3dSmrg		if (andBits == 0) {
62428d7b3dSmrg			if (mask & 2)
63428d7b3dSmrg				ARCCOPY(yorgp + info.xorgo);
64428d7b3dSmrg			if (mask & 8)
65428d7b3dSmrg				ARCCOPY(yorgop + info.xorgo);
66428d7b3dSmrg		} else {
67428d7b3dSmrg			if (mask & 2)
68428d7b3dSmrg				ARCRROP(yorgp + info.xorgo);
69428d7b3dSmrg			if (mask & 8)
70428d7b3dSmrg				ARCRROP(yorgop + info.xorgo);
71428d7b3dSmrg		}
72428d7b3dSmrg	}
73428d7b3dSmrg	if (!info.end.x || !info.end.y) {
74428d7b3dSmrg		mask = info.end.mask;
75428d7b3dSmrg		info.end = info.altend;
76428d7b3dSmrg	}
77428d7b3dSmrg	if (do360 && (arc->width == arc->height) && !(arc->width & 1)) {
78428d7b3dSmrg		int xoffset = bitsStride;
79428d7b3dSmrg		BITS *yorghb = yorgp + (info.h * bitsStride) + info.xorg;
80428d7b3dSmrg		BITS *yorgohb = yorghb - info.h;
81428d7b3dSmrg
82428d7b3dSmrg		yorgp += info.xorg;
83428d7b3dSmrg		yorgop += info.xorg;
84428d7b3dSmrg		yorghb += info.h;
85428d7b3dSmrg		while (1) {
86428d7b3dSmrg			if (andBits == 0) {
87428d7b3dSmrg				ARCCOPY(yorgp + yoffset + x);
88428d7b3dSmrg				ARCCOPY(yorgp + yoffset - x);
89428d7b3dSmrg				ARCCOPY(yorgop - yoffset - x);
90428d7b3dSmrg				ARCCOPY(yorgop - yoffset + x);
91428d7b3dSmrg			} else {
92428d7b3dSmrg				ARCRROP(yorgp + yoffset + x);
93428d7b3dSmrg				ARCRROP(yorgp + yoffset - x);
94428d7b3dSmrg				ARCRROP(yorgop - yoffset - x);
95428d7b3dSmrg				ARCRROP(yorgop - yoffset + x);
96428d7b3dSmrg			}
97428d7b3dSmrg			if (a < 0)
98428d7b3dSmrg				break;
99428d7b3dSmrg			if (andBits == 0) {
100428d7b3dSmrg				ARCCOPY(yorghb - xoffset - y);
101428d7b3dSmrg				ARCCOPY(yorgohb - xoffset + y);
102428d7b3dSmrg				ARCCOPY(yorgohb + xoffset + y);
103428d7b3dSmrg				ARCCOPY(yorghb + xoffset - y);
104428d7b3dSmrg			} else {
105428d7b3dSmrg				ARCRROP(yorghb - xoffset - y);
106428d7b3dSmrg				ARCRROP(yorgohb - xoffset + y);
107428d7b3dSmrg				ARCRROP(yorgohb + xoffset + y);
108428d7b3dSmrg				ARCRROP(yorghb + xoffset - y);
109428d7b3dSmrg			}
110428d7b3dSmrg			xoffset += bitsStride;
111428d7b3dSmrg			MIARCCIRCLESTEP(yoffset += bitsStride;
112428d7b3dSmrg				       );
113428d7b3dSmrg		}
114428d7b3dSmrg		yorgp -= info.xorg;
115428d7b3dSmrg		yorgop -= info.xorg;
116428d7b3dSmrg		x = info.w;
117428d7b3dSmrg		yoffset = info.h * bitsStride;
118428d7b3dSmrg	} else if (do360) {
119428d7b3dSmrg		while (y < info.h || x < info.w) {
120428d7b3dSmrg			MIARCOCTANTSHIFT(dyoffset = bitsStride;
121428d7b3dSmrg					);
122428d7b3dSmrg			if (andBits == 0) {
123428d7b3dSmrg				ARCCOPY(yorgp + yoffset + info.xorg + x);
124428d7b3dSmrg				ARCCOPY(yorgp + yoffset + info.xorgo - x);
125428d7b3dSmrg				ARCCOPY(yorgop - yoffset + info.xorgo - x);
126428d7b3dSmrg				ARCCOPY(yorgop - yoffset + info.xorg + x);
127428d7b3dSmrg			} else {
128428d7b3dSmrg				ARCRROP(yorgp + yoffset + info.xorg + x);
129428d7b3dSmrg				ARCRROP(yorgp + yoffset + info.xorgo - x);
130428d7b3dSmrg				ARCRROP(yorgop - yoffset + info.xorgo - x);
131428d7b3dSmrg				ARCRROP(yorgop - yoffset + info.xorg + x);
132428d7b3dSmrg			}
133428d7b3dSmrg			MIARCSTEP(yoffset += dyoffset;
134428d7b3dSmrg				  , yoffset += bitsStride;
135428d7b3dSmrg				 );
136428d7b3dSmrg		}
137428d7b3dSmrg	} else {
138428d7b3dSmrg		while (y < info.h || x < info.w) {
139428d7b3dSmrg			MIARCOCTANTSHIFT(dyoffset = bitsStride;
140428d7b3dSmrg					);
141428d7b3dSmrg			if ((x == info.start.x) || (y == info.start.y)) {
142428d7b3dSmrg				mask = info.start.mask;
143428d7b3dSmrg				info.start = info.altstart;
144428d7b3dSmrg			}
145428d7b3dSmrg			if (andBits == 0) {
146428d7b3dSmrg				if (mask & 1)
147428d7b3dSmrg					ARCCOPY(yorgp + yoffset + info.xorg + x);
148428d7b3dSmrg				if (mask & 2)
149428d7b3dSmrg					ARCCOPY(yorgp + yoffset + info.xorgo - x);
150428d7b3dSmrg				if (mask & 4)
151428d7b3dSmrg					ARCCOPY(yorgop - yoffset + info.xorgo - x);
152428d7b3dSmrg				if (mask & 8)
153428d7b3dSmrg					ARCCOPY(yorgop - yoffset + info.xorg + x);
154428d7b3dSmrg			} else {
155428d7b3dSmrg				if (mask & 1)
156428d7b3dSmrg					ARCRROP(yorgp + yoffset + info.xorg + x);
157428d7b3dSmrg				if (mask & 2)
158428d7b3dSmrg					ARCRROP(yorgp + yoffset + info.xorgo - x);
159428d7b3dSmrg				if (mask & 4)
160428d7b3dSmrg					ARCRROP(yorgop - yoffset + info.xorgo - x);
161428d7b3dSmrg				if (mask & 8)
162428d7b3dSmrg					ARCRROP(yorgop - yoffset + info.xorg + x);
163428d7b3dSmrg			}
164428d7b3dSmrg			if ((x == info.end.x) || (y == info.end.y)) {
165428d7b3dSmrg				mask = info.end.mask;
166428d7b3dSmrg				info.end = info.altend;
167428d7b3dSmrg			}
168428d7b3dSmrg			MIARCSTEP(yoffset += dyoffset;
169428d7b3dSmrg				  , yoffset += bitsStride;
170428d7b3dSmrg				 );
171428d7b3dSmrg		}
172428d7b3dSmrg	}
173428d7b3dSmrg	if ((x == info.start.x) || (y == info.start.y))
174428d7b3dSmrg		mask = info.start.mask;
175428d7b3dSmrg	if (andBits == 0) {
176428d7b3dSmrg		if (mask & 1)
177428d7b3dSmrg			ARCCOPY(yorgp + yoffset + info.xorg + x);
178428d7b3dSmrg		if (mask & 4)
179428d7b3dSmrg			ARCCOPY(yorgop - yoffset + info.xorgo - x);
180428d7b3dSmrg		if (arc->height & 1) {
181428d7b3dSmrg			if (mask & 2)
182428d7b3dSmrg				ARCCOPY(yorgp + yoffset + info.xorgo - x);
183428d7b3dSmrg			if (mask & 8)
184428d7b3dSmrg				ARCCOPY(yorgop - yoffset + info.xorg + x);
185428d7b3dSmrg		}
186428d7b3dSmrg	} else {
187428d7b3dSmrg		if (mask & 1)
188428d7b3dSmrg			ARCRROP(yorgp + yoffset + info.xorg + x);
189428d7b3dSmrg		if (mask & 4)
190428d7b3dSmrg			ARCRROP(yorgop - yoffset + info.xorgo - x);
191428d7b3dSmrg		if (arc->height & 1) {
192428d7b3dSmrg			if (mask & 2)
193428d7b3dSmrg				ARCRROP(yorgp + yoffset + info.xorgo - x);
194428d7b3dSmrg			if (mask & 8)
195428d7b3dSmrg				ARCRROP(yorgop - yoffset + info.xorg + x);
196428d7b3dSmrg		}
197428d7b3dSmrg	}
198428d7b3dSmrg}
199428d7b3dSmrg
200428d7b3dSmrg#undef ARCCOPY
201428d7b3dSmrg#undef ARCRROP
202428d7b3dSmrg
203428d7b3dSmrg#undef RROP
204428d7b3dSmrg#undef isClipped
205