Some fixes.
[cake.git] / rom / graphics / bltbitmap.c
blob5c0f740e64e6fd6c8b75107f9d45ab2f55586bab
1 /*
2 Copyright © 1995-2007, The AROS Development Team. All rights reserved.
3 $Id$
5 Desc: Copy a rectangle in a bitmap to another place or another bitmap.
6 Lang: english
7 */
8 #include <aros/debug.h>
9 #include <string.h>
10 #include <exec/memory.h>
11 #include <graphics/gfx.h>
12 #include <proto/exec.h>
13 #include "graphics_intern.h"
14 #include "gfxfuncsupport.h"
15 #include "objcache.h"
17 static void copyonepixel (PLANEPTR src, ULONG xsrc, PLANEPTR dest,
18 ULONG xdest, ULONG minterm);
20 /*****************************************************************************
22 NAME */
23 #include <graphics/gfx.h>
24 #include <proto/graphics.h>
26 AROS_LH11(LONG, BltBitMap,
28 /* SYNOPSIS */
29 AROS_LHA(struct BitMap *, srcBitMap, A0),
30 AROS_LHA(LONG , xSrc, D0),
31 AROS_LHA(LONG , ySrc, D1),
32 AROS_LHA(struct BitMap *, destBitMap, A1),
33 AROS_LHA(LONG , xDest, D2),
34 AROS_LHA(LONG , yDest, D3),
35 AROS_LHA(LONG , xSize, D4),
36 AROS_LHA(LONG , ySize, D5),
37 AROS_LHA(ULONG , minterm, D6),
38 AROS_LHA(ULONG , mask, D7),
39 AROS_LHA(PLANEPTR , tempA, A2),
41 /* LOCATION */
42 struct GfxBase *, GfxBase, 5, Graphics)
44 /* FUNCTION
45 Moves a part of a bitmap around or into another bitmaps.
47 INPUTS
48 srcBitMap - Copy from this bitmap.
49 xSrc, ySrc - This is the upper left corner of the area to copy.
50 destBitMap - Copy to this bitmap. May be the same as srcBitMap.
51 xDest, yDest - Upper left corner where to place the copy
52 xSize, ySize - The size of the area to copy
53 minterm - How to copy. Most useful values are 0x00C0 for a vanilla
54 copy, 0x0030 to invert the source and then copy or 0x0050
55 to ignore the source and just invert the destination. If
56 you want to calculate other values, then you must know that
57 channel A is set, if you are inside the rectangle, channel
58 B is the source and channel C is the destination of the
59 rectangle.
61 Bit ABC
62 0 000
63 1 001
64 2 010
65 3 011
66 4 100
67 5 101
68 6 110
69 7 111
71 So 0x00C0 means: D is set if one is inside the rectangle
72 (A is set) and B (the source) is set and cleared otherwise.
74 To fill the rectangle, you would want to set D when A is
75 set, so the value is 0x00F0.
77 mask - Which planes should be copied. Typically, you should set
78 this to ~0L.
79 tempA - If the copy overlaps exactly to the left or right (i.e. the
80 scan line addresses overlap), and tempA is non-zero, it
81 points to enough chip accessible memory to hold a line of a
82 source for the blit (i.e. CHIP RAM). BltBitMap will allocate
83 (and free) the needed TempA if none is provided and one is
84 needed. Blit overlap is determined from the relation of
85 the first non-masked planes in the source and destination
86 bit maps.
88 RESULT
89 The number of planes actually involved in the blit.
91 NOTES
92 If a special hardware is available, this function will use it.
94 As a special case, plane pointers of destBitMap can contain NULL
95 or -1, which will act as if the plane was filled with 0's or 1's,
96 respectively.
98 EXAMPLE
100 BUGS
102 SEE ALSO
103 ClipBlit(), BltBitMapRastPort()
105 INTERNALS
107 HISTORY
109 *****************************************************************************/
111 AROS_LIBFUNC_INIT
112 LONG planecnt;
114 FIX_GFXCOORD(xSrc);
115 FIX_GFXCOORD(ySrc);
116 FIX_GFXCOORD(xDest);
117 FIX_GFXCOORD(yDest);
119 /* nlorentz: Also check for BMF_AROS_DISPLAYED flag which if set tells
120 that this is a HIDD bitmap and should be handled by the driver */
122 if ( srcBitMap->pad != 0 || destBitMap->pad != 0
123 || srcBitMap->Flags & BMF_AROS_HIDD || destBitMap->Flags & BMF_AROS_HIDD)
125 ULONG wSrc, wDest;
126 ULONG x;
127 ULONG depth;
129 OOP_Object *tmp_gc;
131 EnterFunc(bug("driver_BltBitMap()\n"));
133 /* bug("BltBitMap(%p, %d, %d, %p, %d, %d, %d, %d, %x)\n"
134 ,srcBitMap, xSrc, ySrc, destBitMap, xDest, yDest, xSize, ySize, minterm);
138 wSrc = GetBitMapAttr( srcBitMap, BMA_WIDTH);
139 wDest = GetBitMapAttr(destBitMap, BMA_WIDTH);
141 /* Clip all blits */
143 depth = GetBitMapAttr ( srcBitMap, BMA_DEPTH);
144 x = GetBitMapAttr (destBitMap, BMA_DEPTH);
146 if (x < depth) depth = x;
148 /* Clip X and Y */
149 if (xSrc < 0)
151 xDest += -xSrc;
152 xSize -= -xSrc;
153 xSrc = 0;
156 if (ySrc < 0)
158 yDest += -ySrc;
159 ySize -= -ySrc;
160 ySrc = 0;
163 /* Clip width and height for source and dest */
164 if (ySrc + ySize > srcBitMap->Rows)
166 ySize = srcBitMap->Rows - ySrc;
169 if (yDest + ySize > destBitMap->Rows)
171 ySize = destBitMap->Rows - yDest;
174 if ((ULONG)(xSrc + xSize) >= wSrc)
176 xSize = wSrc - xSrc;
179 if ((ULONG)(xDest + xSize) >= wDest)
181 xSize = wDest - xDest;
184 /* If the size is illegal or we need not copy anything, return */
185 if (ySize <= 0 || xSize <= 0 || !mask) return 0;
187 tmp_gc = obtain_cache_object(SDD(GfxBase)->gc_cache, GfxBase);
188 if (NULL != tmp_gc)
190 OOP_Object *srcbm_obj;
192 srcbm_obj = OBTAIN_HIDD_BM(srcBitMap);
193 if (NULL != srcbm_obj)
195 OOP_Object *dstbm_obj;
197 dstbm_obj = OBTAIN_HIDD_BM(destBitMap);
198 if (NULL != dstbm_obj)
201 int_bltbitmap(srcBitMap, srcbm_obj
202 , xSrc, ySrc
203 , destBitMap, dstbm_obj
204 , xDest, yDest
205 , xSize, ySize
206 , minterm
207 , tmp_gc
208 , GfxBase);
209 HIDD_BM_UpdateRect(dstbm_obj, xDest, yDest, xSize, ySize);
211 RELEASE_HIDD_BM(dstbm_obj, destBitMap);
214 RELEASE_HIDD_BM(srcbm_obj, srcBitMap);
216 release_cache_object(SDD(GfxBase)->gc_cache, tmp_gc, GfxBase);
219 #warning: dummy return value
220 planecnt = 8;
223 else
225 ULONG wSrc, wDest;
226 ULONG x, y, plane;
227 ULONG depth;
228 PLANEPTR src, dest, temp;
230 wSrc = GetBitMapAttr( srcBitMap, BMA_WIDTH);
231 wDest = GetBitMapAttr(destBitMap, BMA_WIDTH);
232 temp = NULL;
234 depth = GetBitMapAttr ( srcBitMap, BMA_DEPTH);
235 x = GetBitMapAttr (destBitMap, BMA_DEPTH);
236 if (x < depth)
237 depth = x;
239 /* Clip X and Y */
240 if (xSrc < 0)
242 xDest += -xSrc;
243 xSize -= -xSrc;
244 xSrc = 0;
247 if (ySrc < 0)
249 yDest += -ySrc;
250 ySize -= -ySrc;
251 ySrc = 0;
254 /* Clip width and height for source and dest */
255 if (ySrc + ySize > srcBitMap->Rows)
257 ySize = srcBitMap->Rows - ySrc;
260 if (yDest + ySize > destBitMap->Rows)
262 ySize = destBitMap->Rows - yDest;
265 if ((ULONG)(xSrc + xSize) >= wSrc)
267 xSize = wSrc - xSrc;
270 if ((ULONG)(xDest + xSize) >= wDest)
272 xSize = wDest - xDest;
275 /* If the size is illegal or we need not copy anything, return */
276 if (ySize <= 0 || xSize <= 0 || !mask)
277 return 0;
279 planecnt = 0;
281 /* For all planes */
282 for (plane=0; plane<depth; plane ++)
284 /* Don't do anything if destination planeptr is NULL (means treat like
285 a plane with all zeros) or -1 (means treat like a plane with all ones) */
287 if ((destBitMap->Planes[plane] != NULL) && (destBitMap->Planes[plane] != (PLANEPTR)-1))
289 /* Copy this plane ? */
290 if ((1L << plane) & mask)
293 planecnt ++; /* count it */
295 for (y=0; y<(ULONG)ySize; y++)
297 src = srcBitMap->Planes[plane] + (y+ySrc) * srcBitMap->BytesPerRow;
298 dest = destBitMap->Planes[plane] + (y+yDest)*destBitMap->BytesPerRow;
301 If the source address is less or equal to
302 the destination address
304 if ((src <= dest && src+srcBitMap->BytesPerRow > dest)
305 || (dest <= src && dest+destBitMap->BytesPerRow > src)
308 if (!temp)
310 if (tempA)
311 temp = tempA;
312 else
313 temp = AllocMem (srcBitMap->BytesPerRow, MEMF_ANY);
315 if (!temp)
316 return 0;
319 memmove (temp, src, srcBitMap->BytesPerRow);
321 for (x=0; x<(ULONG)xSize; x++)
322 copyonepixel (temp, x+xSrc, dest, x+xDest, minterm);
324 else
326 for (x=0; x<(ULONG)xSize; x++)
327 copyonepixel (src, x+xSrc, dest, x+xDest, minterm);
330 } /* for (y=0; y<ySize; y++) */
332 } /* if ((1L << plane) & mask) */
334 } /* if dest plane != NULL and dest plane != -1 */
336 } /* for (plane=0; plane<depth; plane ++) */
338 if (temp && !tempA)
339 FreeMem (temp, srcBitMap->BytesPerRow);
342 return planecnt;
344 AROS_LIBFUNC_EXIT
346 } /* BltBitMap */
348 /****************************************************************************************/
350 static void copyonepixel (PLANEPTR src, ULONG xsrc, PLANEPTR dest, ULONG xdest,
351 ULONG minterm)
353 ULONG sByte, sSet;
354 ULONG dByte, dSet;
355 UBYTE sBit;
356 UBYTE dBit;
357 BOOL set;
359 if (src == NULL)
361 sSet = FALSE;
362 } else if (src == (PLANEPTR)-1)
364 sSet = TRUE;
365 } else {
366 sByte = xsrc >> 3;
367 sBit = 1L << (7 - (xsrc & 0x07));
368 sSet = (src[sByte] & sBit) != 0;
371 /* dest PLANEPTR here will never be NULL or -1 */
372 dByte = xdest >> 3;
373 dBit = 1L << (7 - (xdest & 0x07));
374 dSet = (dest[dByte] & dBit) != 0;
376 set = 0;
378 if (minterm & 0x0010)
380 if (!sSet && !dSet)
381 set = 1;
383 if (minterm & 0x0020)
385 if (!sSet && dSet)
386 set = 1;
388 if (minterm & 0x0040)
390 if (sSet && !dSet)
391 set = 1;
393 if (minterm & 0x0080)
395 if (sSet && dSet)
396 set = 1;
399 if (set)
400 dest[dByte] |= dBit;
401 else
402 dest[dByte] &= ~dBit;
405 /****************************************************************************************/