Update to lasso handling. Adjust scroll amount based on difference between mouse...
[AROS.git] / rom / graphics / draw.c
blob836fca5f87d3fc8b2e771b20e7b5a4bdad4b5aa2
1 /*
2 Copyright © 1995-2007, The AROS Development Team. All rights reserved.
3 $Id$
5 Desc: Graphics function Draw()
6 Lang: english
7 */
9 #include <aros/debug.h>
10 #include <clib/macros.h>
11 #include <graphics/rastport.h>
12 #include <proto/graphics.h>
13 #include <proto/oop.h>
14 #include "gfxfuncsupport.h"
15 #include "graphics_intern.h"
16 #include "intregions.h"
17 #include <stdlib.h>
19 /*****************************************************************************
21 NAME */
23 AROS_LH3(void, Draw,
25 /* SYNOPSIS */
26 AROS_LHA(struct RastPort *, rp, A1),
27 AROS_LHA(LONG , x, D0),
28 AROS_LHA(LONG , y, D1),
30 /* LOCATION */
31 struct GfxBase *, GfxBase, 41, Graphics)
33 /* FUNCTION
34 Draw a line from the current pen position to the given coordinate.
36 INPUTS
37 rp - destination RastPort.
38 x,y - line end coordinate.
40 RESULT
42 NOTES
43 Not yet implemented:
45 - handle layer->Scroll_X/Scroll_Y.
47 - handle FRST_DOT which indicates whether to draw
48 or to don't draw first pixel of line. Important
49 for COMPLEMENT drawmode.
51 EXAMPLE
53 BUGS
55 SEE ALSO
57 INTERNALS
59 HISTORY
60 29-10-95 digulla automatically created from
61 graphics_lib.fd and clib/graphics_protos.h
63 *****************************************************************************/
65 AROS_LIBFUNC_INIT
68 struct Rectangle rr;
69 OOP_Object *gc;
70 struct Layer *L = rp->Layer;
71 struct BitMap *bm = rp->BitMap;
72 struct Rectangle rp_clip_rectangle;
73 BOOL have_rp_cliprectangle;
74 LONG dx, dy;
75 LONG x1, y1;
77 if (!OBTAIN_DRIVERDATA(rp, GfxBase))
78 return;
80 FIX_GFXCOORD(x);
81 FIX_GFXCOORD(y);
83 x1 = rp->cp_x;
84 y1 = rp->cp_y;
86 gc = GetDriverData(rp)->dd_GC;
88 if (x1 > x)
90 rr.MinX = x;
91 rr.MaxX = x1;
93 else
95 rr.MinX = x1;
96 rr.MaxX = x;
99 if (y1 > y)
101 rr.MinY = y;
102 rr.MaxY = y1;
104 else
106 rr.MinY = y1;
107 rr.MaxY = y;
111 UWORD lineptrn = rp->LinePtrn;
113 if (rp->DrawMode & INVERSVID) lineptrn = ~lineptrn;
116 struct TagItem gctags[] =
118 {aHidd_GC_LinePattern , lineptrn },
119 {aHidd_GC_LinePatternCnt, rp->linpatcnt },
120 {TAG_DONE }
123 OOP_SetAttrs( gc, gctags);
128 if (NULL == L)
130 /* No layer, probably a screen, but may be a user inited bitmap */
131 OOP_Object *bm_obj;
133 bm_obj = OBTAIN_HIDD_BM(bm);
134 if (bm_obj)
136 /* No need for clipping */
137 HIDD_BM_DrawLine(bm_obj, gc, x1, y1, x, y);
139 RELEASE_HIDD_BM(bm_obj, bm);
143 else
145 struct ClipRect *CR;
146 WORD xrel;
147 WORD yrel;
148 struct Rectangle torender, intersect;
149 OOP_Object *bm_obj;
151 LockLayerRom(L);
153 x1 -= L->Scroll_X;
154 y1 -= L->Scroll_Y;
155 x -= L->Scroll_X;
156 y -= L->Scroll_Y;
158 have_rp_cliprectangle = GetRPClipRectangleForLayer(rp, L, &rp_clip_rectangle, GfxBase);
160 xrel = L->bounds.MinX;
161 yrel = L->bounds.MinY;
163 torender.MinX = rr.MinX + xrel - L->Scroll_X;
164 torender.MinY = rr.MinY + yrel - L->Scroll_Y;
165 torender.MaxX = rr.MaxX + xrel - L->Scroll_X;
166 torender.MaxY = rr.MaxY + yrel - L->Scroll_Y;
168 CR = L->ClipRect;
170 for (;NULL != CR; CR = CR->Next)
172 D(bug("Cliprect (%d, %d, %d, %d), lobs=%p\n",
173 CR->bounds.MinX, CR->bounds.MinY, CR->bounds.MaxX, CR->bounds.MaxY,
174 CR->lobs));
176 /* Does this cliprect intersect with area to rectfill ? */
177 if (_AndRectRect(&CR->bounds, &torender, &intersect))
179 if (!have_rp_cliprectangle || _AndRectRect(&rp_clip_rectangle, &intersect, &intersect))
181 if (NULL == CR->lobs)
183 /* Set clip rectangle */
184 HIDD_GC_SetClipRect(gc
185 , intersect.MinX
186 , intersect.MinY
187 , intersect.MaxX
188 , intersect.MaxY
191 bm_obj = OBTAIN_HIDD_BM(bm);
192 if (bm_obj)
194 HIDD_BM_DrawLine(bm_obj
195 , gc
196 , x1 + xrel
197 , y1 + yrel
198 , x + xrel
199 , y + yrel
202 RELEASE_HIDD_BM(bm_obj, bm);
205 HIDD_GC_UnsetClipRect(gc);
208 else
210 /* Render into offscreen cliprect bitmap */
211 if (L->Flags & LAYERSIMPLE)
212 continue;
213 else if (L->Flags & LAYERSUPER)
215 D(bug("do_render_func(): Superbitmap not handled yet\n"));
217 else
219 LONG bm_rel_minx, bm_rel_miny, bm_rel_maxx, bm_rel_maxy;
220 LONG layer_rel_x, layer_rel_y;
222 layer_rel_x = intersect.MinX - xrel;
223 layer_rel_y = intersect.MinY - yrel;
226 bm_rel_minx = intersect.MinX - CR->bounds.MinX;
227 bm_rel_miny = intersect.MinY - CR->bounds.MinY;
228 bm_rel_maxx = intersect.MaxX - CR->bounds.MinX;
229 bm_rel_maxy = intersect.MaxY - CR->bounds.MinY;
231 HIDD_GC_SetClipRect(gc
232 , bm_rel_minx + ALIGN_OFFSET(CR->bounds.MinX)
233 , bm_rel_miny
234 , bm_rel_maxx + ALIGN_OFFSET(CR->bounds.MinX)
235 , bm_rel_maxy
238 bm_obj = OBTAIN_HIDD_BM(CR->BitMap);
239 if (bm_obj)
241 HIDD_BM_DrawLine(bm_obj
242 , gc
243 , bm_rel_minx - (layer_rel_x - x1) + ALIGN_OFFSET(CR->bounds.MinX)
244 , bm_rel_miny - (layer_rel_y - y1)
245 , bm_rel_minx - (layer_rel_x - x) + ALIGN_OFFSET(CR->bounds.MinX)
246 , bm_rel_miny - (layer_rel_y - y)
249 RELEASE_HIDD_BM(bm_obj, CR->BitMap);
251 HIDD_GC_UnsetClipRect(gc);
254 } /* if (CR->lobs == NULL) */
256 } /* if it also intersects with possible rastport clip rectangle */
258 } /* if (cliprect intersects with area to render into) */
260 } /* for (each cliprect in the layer) */
262 UnlockLayerRom(L);
264 } /* if (rp->Layer) */
266 dx = abs(x1 - x);
267 dy = abs(y1 - y);
268 if (dy > dx) dx = dy;
270 rp->linpatcnt = ((LONG)rp->linpatcnt - dx) & 15;
272 rp->cp_x = x;
273 rp->cp_y = y;
275 RELEASE_DRIVERDATA(rp, GfxBase);
277 AROS_LIBFUNC_EXIT
279 } /* Draw */