Added basic implementation of destroying a GPT table: just delete the
[AROS.git] / rom / graphics / areaend.c
blobe42d759677d358bff30d0f481a8218c11cb8961b
1 /*
2 Copyright © 1995-2007, 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 /* I don't know whether this function may corrupt the
84 cursor position of the rastport. So I save it for later.*/
86 UWORD Rem_cp_x = rp->cp_x;
87 UWORD Rem_cp_y = rp->cp_y;
88 /* This rectangle serves as a "frame" for the tmpras for filling */
89 struct Rectangle bounds;
92 areaclosepolygon(areainfo);
94 Count = areainfo->Count;
96 //kprintf("%d coord to process\n",Count);
98 /* process the list of vectors */
99 while (Count > 0)
101 //kprintf("\n******** Flags:%d Coord: (%d,%d)\n",CurFlag[0], CurVctr[0],CurVctr[1]);
103 last_idx ++;
104 switch((unsigned char)CurFlag[0])
106 case AREAINFOFLAG_MOVE:
107 /* set the graphical cursor to a starting position */
108 Move(rp, CurVctr[0], CurVctr[1]);
110 bounds.MinX = CurVctr[0];
111 bounds.MaxX = CurVctr[0];
112 bounds.MinY = CurVctr[1];
113 bounds.MaxY = CurVctr[1];
115 CurVctr = &CurVctr[2];
116 CurFlag = &CurFlag[1];
117 break;
119 case AREAINFOFLAG_CLOSEDRAW:
120 /* this indicates that this Polygon is closed with this coordinate */
122 * Must draw from lower y's to higher ones otherwise
123 * the fill algo does not work nicely.
125 #if 1
126 if (rp->cp_y <= CurVctr[1]) {
127 Draw(rp, CurVctr[0], CurVctr[1]);
128 } else {
129 int _x = rp->cp_x;
130 int _y = rp->cp_y;
131 rp->cp_x = CurVctr[0];
132 rp->cp_y = CurVctr[1];
133 Draw(rp, _x, _y);
134 rp->cp_x = CurVctr[0];
135 rp->cp_y = CurVctr[1];
137 #endif
138 CurVctr = &CurVctr[2];
139 CurFlag = &CurFlag[1];
141 no need to set the bundaries here like in case above as
142 this coord closes the polygon and therefore is the same
143 one as the first coordinate of the polygon.
145 /* check whether there's anything to fill at all. I cannot
146 fill a line (=3 coordinates) */
147 if (first_idx+2 <= last_idx)
149 /* BytesPerRow must be a multiple of 2 bytes */
151 BytesPerRow = bounds.MaxX - bounds.MinX + 1;
152 if (0 != (BytesPerRow & 0x0f ))
153 BytesPerRow =((BytesPerRow >> 3) & 0xfffe )+ 2;
154 else
155 BytesPerRow = (BytesPerRow >> 3) & 0xfffe;
157 if ((ULONG)rp->TmpRas->Size < BytesPerRow * (bounds.MaxY - bounds.MinY + 1))
158 return -1;
161 kprintf("first: %d, last: %d\n",first_idx,last_idx);
162 kprintf("(%d,%d)-(%d,%d)\n",bounds.MinX,bounds.MinY,
163 bounds.MaxX,bounds.MaxY);
164 kprintf("width: %d, bytesperrow: %d\n",bounds.MaxX-bounds.MinX+1,
165 BytesPerRow);
167 #if 1
168 if (areafillpolygon(rp,
169 &bounds,
170 first_idx,
171 last_idx,
172 BytesPerRow,
173 GfxBase))
176 Blit the area fill pattern through the mask provided
177 by rp->TmpRas.
180 BltPattern(
182 rp->TmpRas->RasPtr,
183 bounds.MinX,
184 bounds.MinY,
185 bounds.MaxX,
186 bounds.MaxY,
187 BytesPerRow
190 if (rp->Flags & AREAOUTLINE)
192 SetAPen(rp, GetOutlinePen(rp));
193 PolyDraw(rp, last_idx - first_idx + 1, &areainfo->VctrTbl[first_idx]);
194 SetAPen(rp, Rem_APen);
198 #endif
200 /* set first_idx for a possible next polygon to draw */
201 first_idx = last_idx + 1;
202 break;
204 case AREAINFOFLAG_DRAW:
205 /* Draw a line to new position */
206 #if 1
208 * Must draw from lower y's to higher ones otherwise
209 * the fill algo does not work nicely.
211 if (rp->cp_y <= CurVctr[1]) {
212 Draw(rp, CurVctr[0], CurVctr[1]);
213 } else {
214 int _x = rp->cp_x;
215 int _y = rp->cp_y;
216 rp->cp_x = CurVctr[0];
217 rp->cp_y = CurVctr[1];
218 Draw(rp, _x, _y);
219 rp->cp_x = CurVctr[0];
220 rp->cp_y = CurVctr[1];
222 #endif
223 if (bounds.MinX > CurVctr[0])
224 bounds.MinX = CurVctr[0];
225 if (bounds.MaxX < CurVctr[0])
226 bounds.MaxX = CurVctr[0];
227 if (bounds.MinY > CurVctr[1])
228 bounds.MinY = CurVctr[1];
229 if (bounds.MaxY < CurVctr[1])
230 bounds.MaxY = CurVctr[1];
231 CurVctr = &CurVctr[2];
232 CurFlag = &CurFlag[1];
233 break;
235 case AREAINFOFLAG_ELLIPSE:
236 bounds.MinX = CurVctr[0] - CurVctr[2];
237 bounds.MaxX = CurVctr[0] + CurVctr[2];
238 bounds.MinY = CurVctr[1] - CurVctr[3];
239 bounds.MaxY = CurVctr[1] + CurVctr[3];
240 BytesPerRow = bounds.MaxX - bounds.MinX + 1;
242 if (0 != (BytesPerRow & 0x0f ))
243 BytesPerRow =((BytesPerRow >> 3) & 0xfffe )+ 2;
244 else
245 BytesPerRow = (BytesPerRow >> 3) & 0xfffe;
247 if ((ULONG)rp->TmpRas->Size < BytesPerRow * (bounds.MaxY - bounds.MinY + 1))
248 return -1;
250 /* Draw an Ellipse and fill it */
251 /* see how the data are stored by the second entry */
252 /* I get cx,cy,cx+a,cy+b*/
254 DrawEllipse(rp,CurVctr[0],
255 CurVctr[1],
256 CurVctr[2],
257 CurVctr[3]);
259 /* area-fill the ellipse with the pattern given
260 in rp->AreaPtrn , AreaPtSz */
262 areafillellipse(rp,
263 &bounds,
264 CurVctr,
265 BytesPerRow,
266 GfxBase);
268 Blit the area fill pattern through the mask provided
269 by rp->TmpRas.
272 BltPattern(
274 rp->TmpRas->RasPtr,
275 bounds.MinX,
276 bounds.MinY,
277 bounds.MaxX,
278 bounds.MaxY,
279 BytesPerRow
282 if (rp->Flags & AREAOUTLINE)
284 SetAPen(rp, GetOutlinePen(rp));
286 DrawEllipse(rp,CurVctr[0],
287 CurVctr[1],
288 CurVctr[2],
289 CurVctr[3]);
291 SetAPen(rp, Rem_APen);
294 CurVctr = &CurVctr[4];
295 CurFlag = &CurFlag[2];
296 Count--;
297 last_idx++; /* there were two coords here! */
299 /* set first_idx for a possible next polygon to draw */
300 first_idx = last_idx + 1;
301 break;
303 default:
304 /* this is an error */
305 SetAPen(rp, Rem_APen);
306 /* also restore old graphics cursor position */
307 rp->cp_x = Rem_cp_x;
308 rp->cp_y = Rem_cp_y;
309 return -1;
311 } /* switch((unsigned char)CurFlag[0]) */
312 Count--;
314 } /* while (Count > 0) */
316 /* restore areainfo structure for a new beginning */
317 areainfo->VctrPtr = areainfo->VctrTbl;
318 areainfo->FlagPtr = areainfo->FlagTbl;
319 areainfo->Count = 0;
321 /* restore old APen */
322 SetAPen(rp, Rem_APen);
323 /* also restore old graphics cursor position */
324 rp->cp_x = Rem_cp_x;
325 rp->cp_y = Rem_cp_y;
327 } /* if vectorlist is not empty and rastport has a tmpras */
329 return 0;
331 AROS_LIBFUNC_EXIT
333 } /* AreaEnd */