Added missing properties.
[AROS.git] / rom / graphics / bitmapscale.c
blob0e5b3d4eb79b0427a7823f0b7ba5fd91b5ed7869
1 /*
2 Copyright © 1995-2011, The AROS Development Team. All rights reserved.
3 $Id$
5 Desc: Graphics function BitMapScale()
6 Lang: english
7 */
9 #include <aros/debug.h>
10 #include <graphics/scale.h>
11 #include <proto/exec.h>
12 #include <proto/oop.h>
14 #include "graphics_intern.h"
15 #include "gfxfuncsupport.h"
16 #include "objcache.h"
18 /*****************************************************************************
20 NAME */
21 #include <proto/graphics.h>
23 AROS_LH1(void, BitMapScale,
25 /* SYNOPSIS */
26 AROS_LHA(struct BitScaleArgs *, bitScaleArgs, A0),
28 /* LOCATION */
29 struct GfxBase *, GfxBase, 113, Graphics)
31 /* FUNCTION
32 Scale a source bit map to a destination bit map other than
33 the source bit map.
35 INPUTS
36 Pass a BitScaleArgs structure filled with the following arguments
37 to this function:
38 bsa_SrcX, bsa_SrcY - upper left coordinate in source bitmap
39 bsa_SrcWidth, bsa_SrcHeight - Width and Height or source bitmap
40 bsa_DestX, bsa_DestY - upper left coordinate in destination
41 bitmap
42 bsa_DestWidth, bsa_DestHeight - this function will set these
43 values. Use the bsa_???Factor for scaling
44 bsa_XSrcFactor:bsa_XDestFactor - Set these to get approximately
45 the same ratio as bsa_SrcWidth:bsa_DestWidth, but
46 usually not exactly the same number.
47 bsa_YSrcFactor:bsa_YDestFactor - Set these to get approximately
48 the same ratio as bsa_SrcHeight:DestHeight, but
49 usually not exactly the same number.
50 bsa_SrcBitMap - pointer to source bitmap to be scaled
51 bsa_DestBitMap - pointer to destination bitmap which will
52 will hold the scaled bitmap. Make sure it's
53 big enough!
54 bsa_Flags - reserved for future use. Set it to zero!
55 bsa_XDDA, bsa_YDDA - for future use.
56 bsa_Reserved1, bsa_Reserved2 - for future use.
58 RESULT
59 bsa_DestWidth and bsa_DestHeight will be set by this function
61 NOTES
62 - Overlapping source and destination bitmaps are not supported
63 - Make sure that you provide enough memory for the destination
64 bitmap to hold the result
65 - In the destination bitmap only the area where the scaled
66 source bitmap is put into is changed. A frame of the old
67 bitmap is left.
69 EXAMPLE
71 BUGS
73 SEE ALSO
74 ScalerDiv(), graphics/scale.h
76 INTERNALS
78 HISTORY
80 *****************************************************************************/
82 AROS_LIBFUNC_INIT
84 if (bitScaleArgs->bsa_SrcBitMap->pad != 0 ||
85 bitScaleArgs->bsa_DestBitMap->pad != 0 ||
86 bitScaleArgs->bsa_SrcBitMap->Flags & BMF_SPECIALFMT ||
87 bitScaleArgs->bsa_DestBitMap->Flags & BMF_SPECIALFMT)
89 ULONG srcflags = 0;
90 ULONG dstflags = 0;
92 BOOL src_colmap_set = FALSE;
93 BOOL dst_colmap_set = FALSE;
94 BOOL success = TRUE;
95 BOOL colmaps_ok = TRUE;
97 OOP_Object *srcbm_obj;
98 OOP_Object *dstbm_obj;
99 OOP_Object *tmp_gc;
101 srcbm_obj = OBTAIN_HIDD_BM(bitScaleArgs->bsa_SrcBitMap);
102 dstbm_obj = OBTAIN_HIDD_BM(bitScaleArgs->bsa_DestBitMap);
103 tmp_gc = obtain_cache_object(CDD(GfxBase)->gc_cache, GfxBase);
105 /* We must lock any HIDD_BM_SetColorMap calls */
106 LOCK_BLIT
107 if (srcbm_obj && dstbm_obj && tmp_gc)
109 /* Try to get a CLUT for the bitmaps */
110 if (IS_HIDD_BM(bitScaleArgs->bsa_SrcBitMap)) {
111 if (NULL != HIDD_BM_COLMAP(bitScaleArgs->bsa_SrcBitMap))
112 srcflags |= FLG_HASCOLMAP;
113 srcflags |= GET_COLMOD_FLAGS(bitScaleArgs->bsa_SrcBitMap);
114 } else {
115 /* Amiga BM */
116 srcflags |= FLG_PALETTE;
119 if (IS_HIDD_BM(bitScaleArgs->bsa_DestBitMap)) {
120 if (NULL != HIDD_BM_COLMAP(bitScaleArgs->bsa_DestBitMap))
121 dstflags |= FLG_HASCOLMAP;
122 dstflags |= GET_COLMOD_FLAGS(bitScaleArgs->bsa_DestBitMap);
123 } else {
124 /* Amiga BM */
125 dstflags |= FLG_PALETTE;
129 if ( (srcflags == FLG_PALETTE || srcflags == FLG_STATICPALETTE)) {
130 /* palettized with no colmap. Neew to get a colmap from dest*/
131 if (dstflags == FLG_TRUECOLOR) {
133 D(bug("!!! NO WAY GETTING PALETTE FOR src IN BltBitMap\n"));
134 colmaps_ok = FALSE;
135 success = FALSE;
137 } else if (dstflags == (FLG_TRUECOLOR | FLG_HASCOLMAP)) {
139 /* Use the dest colmap for src */
140 HIDD_BM_SetColorMap(srcbm_obj, HIDD_BM_COLMAP(bitScaleArgs->bsa_DestBitMap));
145 if ( (dstflags == FLG_PALETTE || dstflags == FLG_STATICPALETTE)) {
146 /* palettized with no pixtab. Nees to get a pixtab from dest*/
147 if (srcflags == FLG_TRUECOLOR) {
148 D(bug("!!! NO WAY GETTING PALETTE FOR dst IN BltBitMap\n"));
149 colmaps_ok = FALSE;
150 success = FALSE;
152 } else if (srcflags == (FLG_TRUECOLOR | FLG_HASCOLMAP)) {
154 /* Use the src colmap for dst */
155 HIDD_BM_SetColorMap(dstbm_obj, HIDD_BM_COLMAP(bitScaleArgs->bsa_SrcBitMap));
157 dst_colmap_set = TRUE;
161 if (success && colmaps_ok)
163 struct monitor_driverdata *driver, *dst_driver;
164 OOP_Object *bm_obj;
165 HIDDT_DrawMode old_drmd;
166 struct TagItem cbtags[] = {
167 { aHidd_GC_DrawMode, vHidd_GC_DrawMode_Copy },
168 { TAG_DONE, 0 }
171 OOP_GetAttr(tmp_gc, aHidd_GC_DrawMode, &old_drmd);
172 OOP_SetAttrs(tmp_gc, cbtags);
174 bitScaleArgs->bsa_DestWidth = ScalerDiv(bitScaleArgs->bsa_SrcWidth,
175 bitScaleArgs->bsa_XDestFactor,
176 bitScaleArgs->bsa_XSrcFactor);
178 bitScaleArgs->bsa_DestHeight = ScalerDiv(bitScaleArgs->bsa_SrcHeight,
179 bitScaleArgs->bsa_YDestFactor,
180 bitScaleArgs->bsa_YSrcFactor);
183 * Select a driver to call. The same as in BltBitMap(), but select
184 * bitmap object instead of driver object.
186 driver = GET_BM_DRIVERDATA(bitScaleArgs->bsa_SrcBitMap);
187 dst_driver = GET_BM_DRIVERDATA(bitScaleArgs->bsa_DestBitMap);
189 if (driver == (struct monitor_driverdata *)CDD(GfxBase))
190 bm_obj = dstbm_obj;
191 else if (dst_driver->flags & DF_UseFakeGfx)
192 bm_obj = dstbm_obj;
193 else
194 bm_obj = srcbm_obj;
196 HIDD_BM_BitMapScale(bm_obj
197 , srcbm_obj
198 , dstbm_obj
199 , bitScaleArgs
200 , tmp_gc
202 update_bitmap(bitScaleArgs->bsa_DestBitMap, dstbm_obj,
203 bitScaleArgs->bsa_DestX, bitScaleArgs->bsa_DestY,
204 bitScaleArgs->bsa_DestWidth, bitScaleArgs->bsa_DestHeight,
205 GfxBase);
207 cbtags[0].ti_Data = old_drmd;
208 OOP_SetAttrs(tmp_gc, cbtags);
209 } /* if () */
211 if (src_colmap_set)
212 HIDD_BM_SetColorMap(srcbm_obj, NULL);
213 if (dst_colmap_set)
214 HIDD_BM_SetColorMap(dstbm_obj, NULL);
217 if (dstbm_obj)
218 RELEASE_HIDD_BM(dstbm_obj, bitScaleArgs->bsa_DestBitMap);
220 if (srcbm_obj)
221 RELEASE_HIDD_BM(srcbm_obj, bitScaleArgs->bsa_SrcBitMap);
223 if (tmp_gc)
224 release_cache_object(CDD(GfxBase)->gc_cache, tmp_gc, GfxBase);
226 ULOCK_BLIT
229 else
232 * Algorithm for plain Amiga bitmaps.
235 * Unfortunately it's not possible to use 16/32 bit copying on bitmaps with this
236 * algorithm as there might be an odd number of bits per line in a bitmap and
237 * this creates problems when accessing the 2nd, 4th and so on line.
241 #define DEF_USIZE ULONG
242 #define DEF_SIZE LONG
243 #define DEF_NUMBITSMINUS1 31
244 #define DEF_MASK 31
245 #define DEF_READMASK 0x80000000
246 #define DEF_SHIFTY 2
247 #define DEF_SHIFTX 5
250 /* The following lines are necessary for BYTE copying and have to be used right
251 * now!!
254 #define DEF_USIZE UBYTE
255 #define DEF_SIZE BYTE
256 #define DEF_NUMBITSMINUS1 7
257 #define DEF_ANDMASK 7
258 #define DEF_READMASK 0x80
259 #define DEF_SHIFTY 0
260 #define DEF_SHIFTX 3
262 UWORD * LinePattern;
263 bitScaleArgs -> bsa_DestWidth = ScalerDiv(bitScaleArgs -> bsa_SrcWidth,
264 bitScaleArgs -> bsa_XDestFactor,
265 bitScaleArgs -> bsa_XSrcFactor);
267 bitScaleArgs -> bsa_DestHeight= ScalerDiv(bitScaleArgs -> bsa_SrcHeight,
268 bitScaleArgs -> bsa_YDestFactor,
269 bitScaleArgs -> bsa_YSrcFactor);
271 /* first of all lets allocate DestHeight words of memory so we can
272 precalculate which original line goes to which destination lines */
274 if (NULL ==(LinePattern = (UWORD *) AllocMem(sizeof(UWORD)*bitScaleArgs ->bsa_DestHeight, 0)))
275 return;
278 UWORD DestHeight = bitScaleArgs -> bsa_DestHeight;
279 UWORD ys = bitScaleArgs -> bsa_SrcY;
280 ULONG count = 0;
281 ULONG dyd = bitScaleArgs -> bsa_DestHeight;
282 ULONG dys = bitScaleArgs -> bsa_SrcHeight;
283 LONG accuys = dyd;
284 LONG accuyd = - (dys >> 1);
285 while (count < DestHeight)
287 accuyd += dys;
288 while (accuyd > accuys )
290 ys++;
291 accuys += dyd;
293 LinePattern[count] = ys;
294 count++;
300 /* now let's go for the real thing: scaling */
302 UWORD DestWidth = bitScaleArgs -> bsa_DestWidth + bitScaleArgs -> bsa_DestX;
303 ULONG xs = bitScaleArgs -> bsa_SrcX;
304 ULONG count = bitScaleArgs -> bsa_DestX;
305 ULONG dxd = bitScaleArgs -> bsa_DestWidth;
306 ULONG dxs = bitScaleArgs -> bsa_SrcWidth;
307 LONG accuxs = dxd;
308 LONG accuxd = - (dxs >> 1);
309 DEF_USIZE ReadMask;
310 ULONG possible_columns, columncounter;
311 ULONG this_x;
313 while (count < DestWidth)
315 accuxd += dxs;
316 while (accuxd > accuxs )
318 xs++;
319 accuxs += dxd;
322 /* instead of copying column by column we can *maybe* even
323 copy more than one column at a time - we'll have to see */
325 if ((count & DEF_ANDMASK) > (xs & DEF_ANDMASK))
326 possible_columns = DEF_NUMBITSMINUS1 - (count & DEF_ANDMASK);
327 else
328 possible_columns = DEF_NUMBITSMINUS1 - (xs & DEF_ANDMASK);
330 columncounter = 1; /* one row, that's for sure!*/
331 this_x = xs; /* in counter we find the x-coord of the current source pixels */
333 LONG accuxd_tmp = accuxd;
334 LONG accuxs_tmp = accuxs;
335 ULONG next_x = xs;
336 ULONG count2 = count + 1;
338 while (possible_columns > 0 && count2 < DestWidth)
340 /* where's the next x-source-coordinate going to be? */
341 accuxd_tmp += dxs;
342 while (accuxd_tmp > accuxs_tmp )
344 next_x++;
345 accuxs_tmp += dxd;
348 if (this_x + 1 == next_x)
350 /* it's the immediately following coordinate */
351 columncounter++;
352 this_x++;
353 count2++;
355 else
357 /* we're copying more than on column then we have to change
358 * accuxd and accuxs
360 if (columncounter != 1)
362 accuxd = accuxd_tmp;
363 accuxs = accuxs_tmp;
365 break; /* the next column is not the neighbouring one */
368 /* determine how many more columns we can copy */
369 possible_columns--;
370 } /* while */
374 /* let's generate a mask that's columncounter bits wide */
375 ReadMask = DEF_READMASK;
376 ReadMask = (DEF_SIZE)ReadMask >> (columncounter - 1);
377 /* let's adjust this mask to the correct position */
378 ReadMask = ReadMask >> (xs & DEF_ANDMASK);
379 /* The leftmost set bit is xs & DEF_MASK away from the highest bit */
381 /* now that we have generated the read-mask we can copy all the columns
382 * that need copying in all bitmaps.
386 ULONG i,y;
387 ULONG ind;
388 LONG preshift = (xs & DEF_ANDMASK) - (count & DEF_ANDMASK);
389 ULONG shift;
390 ULONG AndMask;
391 struct BitMap * SrcBitMap = bitScaleArgs -> bsa_SrcBitMap;
392 struct BitMap * DestBitMap = bitScaleArgs -> bsa_DestBitMap;
394 if (preshift > 0)
396 shift = preshift;
397 AndMask = (ReadMask << shift) ^ (DEF_SIZE)(-1);
399 else
401 shift = -preshift;
402 AndMask = (ReadMask >> shift) ^ (DEF_SIZE)(-1);
405 /* treat all the Bitmaps after another */
406 for (i = 0; (i < DestBitMap -> Depth) && (i < SrcBitMap -> Depth); i++)
408 for (y = 0; y < bitScaleArgs -> bsa_DestHeight; y++)
410 DEF_USIZE CopyData;
411 ind = LinePattern[y] * (SrcBitMap -> BytesPerRow >> DEF_SHIFTY) + /* y-Coord */
412 (xs >> DEF_SHIFTX); /* x-Coord */
413 CopyData = ((DEF_USIZE *)SrcBitMap -> Planes[i])[ind];
414 CopyData = CopyData & ReadMask;
416 if (preshift > 0)
417 CopyData = CopyData << shift;
418 else
419 CopyData = CopyData >> shift;
421 /* ind correctly calculates the destination Address for the CopyData */
422 ind = y * ((bitScaleArgs -> bsa_DestY + DestBitMap -> BytesPerRow) >> DEF_SHIFTY) + /* y-Coord */
423 (count >> DEF_SHIFTX); /* x-Coord */
424 /* Leave a previous picture in the bitmap untouched except for in the
425 * area where the scaled picture goes into
427 ((DEF_USIZE *)DestBitMap ->Planes[i])[ind] =
428 (((DEF_USIZE *)DestBitMap ->Planes[i])[ind] & AndMask) | CopyData;
430 kprintf("Dest: %x\n\n",(LONG)((DEF_USIZE *)DestBitMap ->Planes[i])[ind]);
432 } /* for () */
433 } /* for () */
435 xs = this_x;
437 /* go to next x-coordinate */
438 count += columncounter;
439 } /* while */
442 /* let's get rid of the allocated memory */
443 FreeMem(LinePattern, sizeof(UWORD) * bitScaleArgs -> bsa_DestHeight);
445 #undef DEF_USIZE
446 #undef DEF_SIZE
447 #undef DEF_NUMBITSMINUS1
448 #undef DEF_ANDMASK
449 #undef DEF_READMASK
450 #undef DEF_SHIFTY
451 #undef DEF_SHIFTX
454 AROS_LIBFUNC_EXIT
455 } /* BitMapScale */