wip build_with_cmake macro
[AROS.git] / rom / graphics / areaend.c
blobd0ba6e1326c60f9aa4578b3dfa01642895bbd19d
1 /*
2 Copyright © 1995-2013, The AROS Development Team. All rights reserved.
3 $Id$
5 Desc: Graphics function AreaEnd()
6 Lang: english
7 */
8 #include <exec/types.h>
9 #include <graphics/rastport.h>
10 #include "graphics_intern.h"
12 /*****************************************************************************
14 NAME */
15 #include <proto/graphics.h>
17 AROS_LH1(LONG, AreaEnd,
19 /* SYNOPSIS */
20 AROS_LHA(struct RastPort *, rp, A1),
22 /* LOCATION */
23 struct GfxBase *, GfxBase, 44, Graphics)
25 /* FUNCTION
26 Process the filled vector buffer.
27 After the operation the buffer is reinitialized for
28 processing of further Area functions.
29 Makes use of the raster given by the TmpRas structure that
30 is linked to the rastport.
32 INPUTS
33 rp - pointer to a valid RastPort structure with a pointer to
34 the previously initialized AreaInfo structure.
37 RESULT
38 error - 0 for success
39 -1 a error occurred
41 NOTES
43 EXAMPLE
45 BUGS
46 There is still a problem when some polygons are filled that
47 pixels are missing. This could be due to the way lines are
48 drawn. All lines should be drawn from lower
49 y coordinates to higher y coordinates since this is the
50 way the algorithm calculates lines here. For example, it
51 might make a difference whether a line is drawn from lower
52 to higher y coordinates. Examples for two same lines with
53 different layout:
55 **** *****
56 ***** ****
59 SEE ALSO
60 InitArea(), AreaDraw(), AreaEllipse(), AreaCircle()
61 graphics/rastport.h
63 INTERNALS
65 HISTORY
67 *****************************************************************************/
69 AROS_LIBFUNC_INIT
71 struct AreaInfo * areainfo = rp->AreaInfo;
73 /* is there anything in the matrix at all ? And do we have a TmpRas in the rastport? */
74 if (areainfo->Count && rp->TmpRas)
76 WORD first_idx = 0;
77 WORD last_idx = -1;
78 ULONG BytesPerRow;
79 UWORD * CurVctr = areainfo -> VctrTbl;
80 BYTE * CurFlag = areainfo -> FlagTbl;
81 UWORD Count;
82 UWORD Rem_APen = GetAPen(rp);
83 UWORD Rem_Flags = rp->Flags;
84 /* I don't know whether this function may corrupt the
85 cursor position of the rastport. So I save it for later.*/
87 UWORD Rem_cp_x = rp->cp_x;
88 UWORD Rem_cp_y = rp->cp_y;
89 /* This rectangle serves as a "frame" for the tmpras for filling */
90 struct Rectangle bounds;
93 areaclosepolygon(areainfo);
95 Count = areainfo->Count;
97 //kprintf("%d coord to process\n",Count);
99 /* process the list of vectors */
100 while (Count > 0)
102 //kprintf("\n******** Flags:%d Coord: (%d,%d)\n",CurFlag[0], CurVctr[0],CurVctr[1]);
104 last_idx ++;
105 switch((unsigned char)CurFlag[0])
107 case AREAINFOFLAG_MOVE:
108 /* set the graphical cursor to a starting position */
109 Move(rp, CurVctr[0], CurVctr[1]);
111 bounds.MinX = CurVctr[0];
112 bounds.MaxX = CurVctr[0];
113 bounds.MinY = CurVctr[1];
114 bounds.MaxY = CurVctr[1];
116 CurVctr = &CurVctr[2];
117 CurFlag = &CurFlag[1];
118 break;
120 case AREAINFOFLAG_CLOSEDRAW:
121 /* this indicates that this Polygon is closed with this coordinate */
123 * Must draw from lower y's to higher ones otherwise
124 * the fill algo does not work nicely.
126 #if 1
127 if (rp->cp_y <= CurVctr[1]) {
128 Draw(rp, CurVctr[0], CurVctr[1]);
129 } else {
130 int _x = rp->cp_x;
131 int _y = rp->cp_y;
132 rp->cp_x = CurVctr[0];
133 rp->cp_y = CurVctr[1];
134 Draw(rp, _x, _y);
135 rp->cp_x = CurVctr[0];
136 rp->cp_y = CurVctr[1];
138 #endif
139 CurVctr = &CurVctr[2];
140 CurFlag = &CurFlag[1];
142 no need to set the boundaries here like in case above as
143 this coord closes the polygon and therefore is the same
144 one as the first coordinate of the polygon.
146 /* check whether there's anything to fill at all. I cannot
147 fill a line (=3 coordinates) */
148 if (first_idx+2 <= last_idx)
150 /* BytesPerRow must be a multiple of 2 bytes */
152 BytesPerRow = bounds.MaxX - bounds.MinX + 1;
153 if (0 != (BytesPerRow & 0x0f ))
154 BytesPerRow =((BytesPerRow >> 3) & 0xfffe )+ 2;
155 else
156 BytesPerRow = (BytesPerRow >> 3) & 0xfffe;
158 if ((ULONG)rp->TmpRas->Size < BytesPerRow * (bounds.MaxY - bounds.MinY + 1))
159 return -1;
162 kprintf("first: %d, last: %d\n",first_idx,last_idx);
163 kprintf("(%d,%d)-(%d,%d)\n",bounds.MinX,bounds.MinY,
164 bounds.MaxX,bounds.MaxY);
165 kprintf("width: %d, bytesperrow: %d\n",bounds.MaxX-bounds.MinX+1,
166 BytesPerRow);
168 #if 1
169 if (areafillpolygon(rp,
170 &bounds,
171 first_idx,
172 last_idx,
173 BytesPerRow,
174 GfxBase))
177 Blit the area fill pattern through the mask provided
178 by rp->TmpRas.
181 BltPattern(
183 rp->TmpRas->RasPtr,
184 bounds.MinX,
185 bounds.MinY,
186 bounds.MaxX,
187 bounds.MaxY,
188 BytesPerRow
191 if (rp->Flags & AREAOUTLINE)
193 SetAPen(rp, GetOutlinePen(rp));
194 PolyDraw(rp, last_idx - first_idx + 1, &areainfo->VctrTbl[first_idx * 2]);
195 SetAPen(rp, Rem_APen);
196 rp->Flags = Rem_Flags;
200 #endif
202 /* set first_idx for a possible next polygon to draw */
203 first_idx = last_idx + 1;
204 break;
206 case AREAINFOFLAG_DRAW:
207 /* Draw a line to new position */
208 #if 1
210 * Must draw from lower y's to higher ones otherwise
211 * the fill algo does not work nicely.
213 if (rp->cp_y <= CurVctr[1]) {
214 Draw(rp, CurVctr[0], CurVctr[1]);
215 } else {
216 int _x = rp->cp_x;
217 int _y = rp->cp_y;
218 rp->cp_x = CurVctr[0];
219 rp->cp_y = CurVctr[1];
220 Draw(rp, _x, _y);
221 rp->cp_x = CurVctr[0];
222 rp->cp_y = CurVctr[1];
224 #endif
225 if (bounds.MinX > CurVctr[0])
226 bounds.MinX = CurVctr[0];
227 if (bounds.MaxX < CurVctr[0])
228 bounds.MaxX = CurVctr[0];
229 if (bounds.MinY > CurVctr[1])
230 bounds.MinY = CurVctr[1];
231 if (bounds.MaxY < CurVctr[1])
232 bounds.MaxY = CurVctr[1];
233 CurVctr = &CurVctr[2];
234 CurFlag = &CurFlag[1];
235 break;
237 case AREAINFOFLAG_ELLIPSE:
238 bounds.MinX = CurVctr[0] - CurVctr[2];
239 bounds.MaxX = CurVctr[0] + CurVctr[2];
240 bounds.MinY = CurVctr[1] - CurVctr[3];
241 bounds.MaxY = CurVctr[1] + CurVctr[3];
242 BytesPerRow = bounds.MaxX - bounds.MinX + 1;
244 if (0 != (BytesPerRow & 0x0f ))
245 BytesPerRow =((BytesPerRow >> 3) & 0xfffe )+ 2;
246 else
247 BytesPerRow = (BytesPerRow >> 3) & 0xfffe;
249 if ((ULONG)rp->TmpRas->Size < BytesPerRow * (bounds.MaxY - bounds.MinY + 1))
250 return -1;
252 /* Draw an Ellipse and fill it */
253 /* see how the data are stored by the second entry */
254 /* I get cx,cy,cx+a,cy+b*/
256 DrawEllipse(rp,CurVctr[0],
257 CurVctr[1],
258 CurVctr[2],
259 CurVctr[3]);
261 /* area-fill the ellipse with the pattern given
262 in rp->AreaPtrn , AreaPtSz */
264 areafillellipse(rp,
265 &bounds,
266 CurVctr,
267 BytesPerRow,
268 GfxBase);
270 Blit the area fill pattern through the mask provided
271 by rp->TmpRas.
274 BltPattern(
276 rp->TmpRas->RasPtr,
277 bounds.MinX,
278 bounds.MinY,
279 bounds.MaxX,
280 bounds.MaxY,
281 BytesPerRow
284 if (rp->Flags & AREAOUTLINE)
286 SetAPen(rp, GetOutlinePen(rp));
288 DrawEllipse(rp,CurVctr[0],
289 CurVctr[1],
290 CurVctr[2],
291 CurVctr[3]);
293 SetAPen(rp, Rem_APen);
294 rp->Flags = Rem_Flags;
297 CurVctr = &CurVctr[4];
298 CurFlag = &CurFlag[2];
299 Count--;
300 last_idx++; /* there were two coords here! */
302 /* set first_idx for a possible next polygon to draw */
303 first_idx = last_idx + 1;
304 break;
306 default:
307 /* this is an error */
308 SetAPen(rp, Rem_APen);
309 rp->Flags = Rem_Flags;
311 /* also restore old graphics cursor position */
312 rp->cp_x = Rem_cp_x;
313 rp->cp_y = Rem_cp_y;
314 return -1;
316 } /* switch((unsigned char)CurFlag[0]) */
317 Count--;
319 } /* while (Count > 0) */
321 /* restore areainfo structure for a new beginning */
322 areainfo->VctrPtr = areainfo->VctrTbl;
323 areainfo->FlagPtr = areainfo->FlagTbl;
324 areainfo->Count = 0;
326 /* restore old graphics cursor position */
327 rp->cp_x = Rem_cp_x;
328 rp->cp_y = Rem_cp_y;
330 } /* if vectorlist is not empty and rastport has a tmpras */
332 return 0;
334 AROS_LIBFUNC_EXIT
336 } /* AreaEnd */