2 Copyright © 1995-2011, The AROS Development Team. All rights reserved.
5 Desc: Copy content of a rastport to another rastport
9 #include <aros/debug.h>
10 #include <clib/macros.h>
11 #include <exec/memory.h>
12 #include <graphics/gfx.h>
13 #include <proto/exec.h>
14 #include <proto/layers.h>
15 #include <graphics/regions.h>
16 #include <graphics/layers.h>
17 #include <graphics/clip.h>
19 #include "graphics_intern.h"
20 #include "gfxfuncsupport.h"
22 #define LayersBase (struct LayersBase *)(GfxBase->gb_LayersBase)
24 /*****************************************************************************
27 #include <proto/graphics.h>
29 AROS_LH9(void, ClipBlit
,
32 AROS_LHA(struct RastPort
*, srcRP
, A0
),
33 AROS_LHA(LONG
, xSrc
, D0
),
34 AROS_LHA(LONG
, ySrc
, D1
),
35 AROS_LHA(struct RastPort
*, destRP
, A1
),
36 AROS_LHA(LONG
, xDest
, D2
),
37 AROS_LHA(LONG
, yDest
, D3
),
38 AROS_LHA(LONG
, xSize
, D4
),
39 AROS_LHA(LONG
, ySize
, D5
),
40 AROS_LHA(UBYTE
, minterm
, D6
),
43 struct GfxBase
*, GfxBase
, 92, Graphics
)
46 Copies the contents of one rastport to another rastport.
47 Takes care of layered and non-layered source and destination
49 If you have a window you should always use this function instead
53 srcRP - Copy from this RastPort.
54 xSrc, ySrc - This is the upper left corner of the area to copy.
55 destRP - Copy to this RastPort.
56 xDest, yDest - Upper left corner where to place the copy
57 xSize, ySize - The size of the area to copy
58 minterm - How to copy. Most useful values are 0x00C0 for a vanilla
59 copy, 0x0030 to invert the source and then copy or 0x0050
60 to ignore the source and just invert the destination. If
61 you want to calculate other values, then you must know that
62 channel A is set, if you are inside the rectangle, channel
63 B is the source and channel C is the destination of the
76 So 0x00C0 means: D is set if one is inside the rectangle
77 (A is set) and B (the source) is set and cleared otherwise.
79 To fill the rectangle, you would want to set D when A is
80 set, so the value is 0x00F0.
100 *****************************************************************************/
104 BOOL li_locked
= FALSE
;
112 /* overlapping and non-overlapping blits are handled differently. */
116 (srcRP
->Layer
!= destRP
->Layer
) &&
117 (srcRP
->Layer
->LayerInfo
== destRP
->Layer
->LayerInfo
))
119 /* If two layers which belong to the same LayerInfo (~screen)
120 have to be locked, lock first LayerInfo, otherwise there
121 is a potential deadlock problem */
122 LockLayerInfo(srcRP
->Layer
->LayerInfo
);
126 if (srcRP
->Layer
) LockLayerRom( srcRP
->Layer
);
127 if (destRP
->Layer
&& (destRP
->Layer
!= srcRP
->Layer
)) LockLayerRom(destRP
->Layer
);
129 /* Once the layers are locked there's no more need to hold the layerinfo lock */
131 if (li_locked
) UnlockLayerInfo(srcRP
->Layer
->LayerInfo
);
133 /* check for overlapping blits */
134 if ( srcRP
== destRP
)
136 struct Rectangle Rect
;
138 /* Combine source and destination rectangles to check for overlapping areas */
139 Rect
.MinX
= MAX(xSrc
, xDest
);
140 Rect
.MinY
= MAX(ySrc
, yDest
);
141 Rect
.MaxX
= MIN(xSrc
+ xSize
- 1, xDest
+ xSize
- 1);
142 Rect
.MaxY
= MIN(ySrc
+ ySize
- 1, yDest
+ ySize
- 1);
144 /* check whether they overlap */
145 if ((Rect
.MaxX
>= Rect
.MinX
) && (Rect
.MaxY
> Rect
.MinY
))
148 * It's overlapping; depending on how bad it is overlapping I
149 * will have to split this up into several calls to the
150 * internal ClipBlit routine.
151 * The first thing to do is to convert our Rect into Region (we'll use XOR afterwards).
153 struct Region
*R
= NewRegion();
154 struct RegionRectangle
*RR
;
160 if (!OrRectRegion(R
, &Rect
))
166 RR
= R
->RegionRectangle
;
170 if (xs
< 0) xs
= -xs
;
171 if (ys
< 0) ys
= -ys
;
174 if the destination area is overlapping more than half of the
175 width or height of the source area, then it is the more
179 if (xs
* 2 < xSize
||
183 In this case I use a special routine to copy the rectangle
189 (xSrc
< xDest
) ? xSrc
: xDest
,
190 (ySrc
< yDest
) ? ySrc
: yDest
,
191 (xSrc
> xDest
) ? xSrc
+ xSize
- 1 : xDest
+ xSize
- 1,
192 (ySrc
> yDest
) ? ySrc
+ ySize
- 1 : yDest
+ ySize
- 1,
201 This case is not as difficult as the overlapping
202 part can be copied first and then the other parts can
205 /* first copy the overlapping part to its destination */
207 dx
= R
->bounds
.MinX
+ RR
->bounds
.MinX
- xSrc
;
208 dy
= R
->bounds
.MinY
+ RR
->bounds
.MinY
- ySrc
;
210 internal_ClipBlit(srcRP
,
216 RR
->bounds
.MaxX
-RR
->bounds
.MinX
+1,
217 RR
->bounds
.MaxY
-RR
->bounds
.MinY
+1,
221 /* and now I invert the Region with the source rectangle */
222 if (!XorRectRegion(R
, &Rect
))
224 /* too bad! no more memory */
228 RR
= R
->RegionRectangle
;
232 dx
= R
->bounds
.MinX
+ RR
->bounds
.MinX
- xSrc
;
233 dy
= R
->bounds
.MinY
+ RR
->bounds
.MinY
- ySrc
;
235 internal_ClipBlit(srcRP
,
241 RR
->bounds
.MaxX
-RR
->bounds
.MinX
+1,
242 RR
->bounds
.MaxY
-RR
->bounds
.MinY
+1,
253 } /* if (src and dest overlap) */
256 /* they don't overlap */
257 internal_ClipBlit(srcRP
,
269 } /* if (destRP == srcRP) */
273 /* here: process the case when the source and destination rastports
276 internal_ClipBlit(srcRP
,
288 /* the way out, even in failure */
291 if (destRP
->Layer
&& (destRP
->Layer
!= srcRP
->Layer
)) UnlockLayerRom(destRP
->Layer
);
292 if (srcRP
->Layer
) UnlockLayerRom( srcRP
->Layer
);
298 struct clipblit_render_data
300 struct render_special_info rsi
;
302 struct RastPort
*destRP
;
307 static ULONG
clipblit_render(APTR data
, LONG srcx
, LONG srcy
,
308 OOP_Object
*dstbm_obj
, OOP_Object
*dst_gc
,
309 struct Rectangle
*rect
, struct GfxBase
*GfxBase
)
311 struct clipblit_render_data
*crd
= data
;
313 BltBitMapRastPort(crd
->rsi
.curbm
, rect
->MinX
, rect
->MinY
,
314 crd
->destRP
, crd
->xDest
+ srcx
, crd
->yDest
+ srcy
,
315 rect
->MaxX
- rect
->MinX
+ 1,
316 rect
->MaxY
- rect
->MinY
+ 1,
322 void internal_ClipBlit(struct RastPort
* srcRP
,
325 struct RastPort
* destRP
,
331 struct GfxBase
* GfxBase
)
333 struct clipblit_render_data data
;
334 struct Rectangle rect
;
336 data
.minterm
= minterm
;
337 data
.destRP
= destRP
;
343 rect
.MaxX
= xSrc
+ xSize
- 1;
344 rect
.MaxY
= ySrc
+ ySize
- 1;
346 do_render_func(srcRP
, NULL
, &rect
, clipblit_render
, &data
, FALSE
, TRUE
, GfxBase
);