some fixes to accented characters
[tangerine.git] / rom / graphics / allocbitmap.c
blobff9bcf5d3747c47974788b253c0628daed79523e
1 /*
2 Copyright © 1995-2007, The AROS Development Team. All rights reserved.
3 $Id$
5 Desc: Create a new BitMap
6 Lang: english
7 */
8 #include <aros/debug.h>
9 #include <string.h>
10 #include <exec/memory.h>
11 #include <proto/exec.h>
12 #include <proto/oop.h>
13 #include <cybergraphx/cybergraphics.h>
14 #include "graphics_intern.h"
15 #include "gfxfuncsupport.h"
17 #define SET_TAG(tags, idx, tag, val) \
18 tags[idx].ti_Tag = tag ; tags[idx].ti_Data = (IPTR)val;
20 #define SET_BM_TAG(tags, idx, tag, val) \
21 SET_TAG(tags, idx, aHidd_BitMap_ ## tag, val)
23 /*****************************************************************************
25 NAME */
26 #include <graphics/gfx.h>
27 #include <proto/graphics.h>
29 AROS_LH5(struct BitMap *, AllocBitMap,
31 /* SYNOPSIS */
32 AROS_LHA(ULONG , sizex, D0),
33 AROS_LHA(ULONG , sizey, D1),
34 AROS_LHA(ULONG , depth, D2),
35 AROS_LHA(ULONG , flags, D3),
36 AROS_LHA(struct BitMap *, friend_bitmap, A0),
38 /* LOCATION */
39 struct GfxBase *, GfxBase, 153, Graphics)
41 /* FUNCTION
42 Allocates and initializes a bitmap structure. Allocates and
43 initializes bitplane data, and sets the bitmap's planes to point to
44 it.
46 INPUTS
47 sizex, sizey - The width and height in pixels
49 depth - The depth of the bitmap. A depth of 1 will allocate a
50 bitmap for two colors, a depth of 24 will allocate a bitmap for
51 16 million colors. Pixels with AT LEAST this many bits will be
52 allocated.
54 flags - One of these flags:
56 BMF_CLEAR: Fill the bitmap with color 0.
58 BMF_DISPLAYABLE: to specify that this bitmap data should
59 be allocated in such a manner that it can be displayed.
60 Displayable data has more severe alignment restrictions
61 than non-displayable data in some systems.
63 BMF_INTERLEAVED: tells graphics that you would like your
64 bitmap to be allocated with one large chunk of display
65 memory for all bitplanes. This minimizes color flashing on
66 deep displays. If there is not enough contiguous RAM for an
67 interleaved bitmap, graphics.library will fall back to a
68 non-interleaved one.
70 BMF_MINPLANES: causes graphics to only allocate enough
71 space in the bitmap structure for "depth" plane pointers.
72 This is for system use and should not be used by
73 applications use as it is inefficient, and may waste
74 memory.
76 BMF_SPECIALFMT: causes graphics to allocate a bitmap
77 of a standard CyberGraphX format. The format
78 (PIXFMT_????) must be stored in the 8 most significant bits.
80 friend_bitmap - pointer to another bitmap, or NULL. If this pointer
81 is passed, then the bitmap data will be allocated in
82 the most efficient form for blitting to friend_bitmap.
84 RESULT
85 A pointer to the new bitmap.
87 NOTES
88 When allocating using a friend_bitmap bitmap, it is not safe to assume
89 anything about the structure of the bitmap data if that friend_bitmap
90 BitMap might not be a standard Amiga bitmap (for instance, if the
91 workbench is running on a non-Amiga display device, its
92 Screen->RastPort->BitMap won't be in standard Amiga format. The
93 only safe operations to perform on a non-standard BitMap are:
95 blitting it to another bitmap, which must be either a
96 standard Amiga bitmap, or a friend_bitmap of this bitmap.
98 blitting from this bitmap to a friend_bitmap bitmap or to a
99 standard Amiga bitmap.
101 attaching it to a rastport and making rendering calls.
103 Good arguments to pass for the friend_bitmap are your window's
104 RPort->BitMap, and your screen's RastPort->BitMap. Do NOT pass
105 &(screenptr->BitMap)!
107 BitMaps not allocated with BMF_DISPLAYABLE may not be used as
108 Intuition Custom BitMaps or as RasInfo->BitMaps. They may be
109 blitted to a BMF_DISPLAYABLE BitMap, using one of the BltBitMap()
110 family of functions.
112 EXAMPLE
114 BUGS
116 SEE ALSO
117 FreeBitMap()
119 INTERNALS
121 HISTORY
123 *****************************************************************************/
125 AROS_LIBFUNC_INIT
127 struct BitMap *nbm;
128 ULONG attributes;
129 HIDDT_ModeID hiddmode = vHidd_ModeID_Invalid;
132 If the depth is too large or the bitmap should be displayable or
133 there is a friend_bitmap bitmap and that's not a normal bitmap, then
134 call the RTG driver.
137 /* Hack: see AllocScreenBitMap */
139 if ((LONG)depth < 0)
141 depth = (ULONG)(-((LONG)depth));
142 hiddmode = (HIDDT_ModeID)friend_bitmap;
143 friend_bitmap = NULL;
145 else if (flags & HIDD_BMF_SCREEN_BITMAP) // (flags & BMF_DISPLAYABLE)
147 /* Make real BMF_DISPLAYABLE bitmap only, if a friend bitmap was
148 specified which is displayable (ie. a screen bitmap). Because
149 as the gfxhidd stuff is now, displayable bitmap needs to have
150 a Display ModeID "known" to them. */
152 if (friend_bitmap && IS_HIDD_BM(friend_bitmap) && (HIDD_BM_FLAGS(friend_bitmap) & HIDD_BMF_SCREEN_BITMAP)) // (friend_bitmap->Flags & BMF_DISPLAYABLE))
154 hiddmode = HIDD_BM_HIDDMODE(friend_bitmap);
156 else
158 flags &= ~HIDD_BMF_SCREEN_BITMAP; //flags &= ~BMF_DISPLAYABLE;
162 ASSERT_VALID_PTR_OR_NULL(friend_bitmap);
164 if (
165 depth > 8
166 || (flags & HIDD_BMF_SCREEN_BITMAP) // (flags & BMF_DISPLAYABLE)
167 /* || (friend_bitmap && friend_bitmap->pad != 0) */
168 || (friend_bitmap && friend_bitmap->Flags & BMF_AROS_HIDD)
169 #warning Should we also check for BMF_MINPLANES ?
170 || (flags & BMF_SPECIALFMT) /* Cybergfx bitmap */
174 struct TagItem bm_tags[8]; /* Tags for offscreen bitmaps */
177 bug("driver_AllocBitMap(sizex=%d, sizey=%d, depth=%d, flags=%d, friend_bitmap=%p)\n",
178 sizex, sizey, depth, flags, friend_bitmap);
182 SET_BM_TAG( bm_tags, 0, Width, sizex );
183 SET_BM_TAG( bm_tags, 1, Height, sizey );
185 if (flags & HIDD_BMF_SCREEN_BITMAP) // (flags & BMF_DISPLAYABLE)
187 /* Use the hiddmode instead of depth/friend_bitmap */
188 if (vHidd_ModeID_Invalid == hiddmode)
189 ReturnPtr("driver_AllocBitMap(Invalid modeID)", struct BitMap *, NULL);
191 SET_BM_TAG(bm_tags, 2, ModeID, hiddmode);
192 SET_BM_TAG(bm_tags, 3, Displayable, TRUE);
193 SET_TAG(bm_tags, 4, TAG_DONE, 0);
195 else
197 SET_TAG(bm_tags, 2, TAG_IGNORE, 0);
199 if (NULL != friend_bitmap)
201 if (IS_HIDD_BM(friend_bitmap))
202 SET_BM_TAG(bm_tags, 2, Friend, HIDD_BM_OBJ(friend_bitmap));
205 if (flags & BMF_SPECIALFMT)
207 HIDDT_StdPixFmt stdpf;
209 stdpf = cyber2hidd_pixfmt(DOWNSHIFT_PIXFMT(flags), GfxBase);
210 SET_BM_TAG(bm_tags, 3, StdPixFmt, stdpf);
212 else
214 SET_TAG(bm_tags, 3, TAG_IGNORE, 0);
217 SET_TAG(bm_tags, 4, TAG_DONE, 0);
220 nbm = AllocMem (sizeof (struct BitMap), MEMF_ANY|MEMF_CLEAR);
221 if (NULL != nbm)
224 OOP_Object *bm_obj;
225 OOP_Object *gfxhidd;
227 gfxhidd = SDD(GfxBase)->gfxhidd;
229 /* Create HIDD bitmap object */
230 if (NULL != gfxhidd)
232 bm_obj = HIDD_Gfx_NewBitMap(gfxhidd, bm_tags);
233 if (NULL != bm_obj)
236 OOP_Object *pf;
237 OOP_Object *colmap = 0;
238 HIDDT_ColorModel colmod;
239 BOOL ok = FALSE;
240 IPTR width, height, val;
243 /* It is possible that the HIDD had to allocate
244 a larger depth than that supplied, so
245 we should get back the correct depth.
246 This is because layers.library might
247 want to allocate offscreen bitmaps to
248 store obscured areas, and then those
249 offscreen bitmaps should be of the same depth as
250 the onscreen ones.
253 OOP_GetAttr(bm_obj, aHidd_BitMap_Width, &width);
254 OOP_GetAttr(bm_obj, aHidd_BitMap_Height, &height);
255 OOP_GetAttr(bm_obj, aHidd_BitMap_PixFmt, (IPTR *)&pf);
257 OOP_GetAttr(pf, aHidd_PixFmt_Depth, &val);
258 depth = val;
260 OOP_GetAttr(pf, aHidd_PixFmt_ColorModel, &val);
261 colmod = val;
263 OOP_GetAttr(bm_obj, aHidd_BitMap_ColorMap, (IPTR *)&colmap);
265 /* Store it in plane array */
266 HIDD_BM_OBJ(nbm) = bm_obj;
267 HIDD_BM_COLMOD(nbm) = colmod;
268 HIDD_BM_COLMAP(nbm) = colmap;
269 HIDD_BM_REALDEPTH(nbm) = depth;
270 HIDD_BM_HIDDMODE(nbm) = hiddmode;
272 nbm->Rows = height;
273 nbm->BytesPerRow = WIDTH_TO_BYTES(width);
274 #if BMDEPTH_COMPATIBILITY
275 nbm->Depth = (depth > 8) ? 8 : depth;
276 #else
277 nbm->Depth = depth;
278 #endif
279 nbm->Flags = flags | BMF_AROS_HIDD;
281 /* If this is a displayable bitmap, create a color table for it */
283 if (flags & HIDD_BMF_SCREEN_BITMAP) // (flags & BMF_DISPLAYABLE)
285 HIDD_BM_FLAGS(nbm) |= HIDD_BMF_SCREEN_BITMAP;
287 if (friend_bitmap)
289 OOP_Object *oldcolmap;
291 oldcolmap = HIDD_BM_SetColorMap(HIDD_BM_OBJ(nbm), HIDD_BM_COLMAP(friend_bitmap));
292 if (oldcolmap) OOP_DisposeObject(oldcolmap);
294 HIDD_BM_COLMAP(nbm) = HIDD_BM_COLMAP(friend_bitmap);
295 HIDD_BM_PIXTAB(nbm) = HIDD_BM_PIXTAB(friend_bitmap);
296 HIDD_BM_COLMOD(nbm) = HIDD_BM_COLMOD(friend_bitmap);
297 HIDD_BM_REALDEPTH(nbm) = HIDD_BM_REALDEPTH(friend_bitmap);
299 HIDD_BM_FLAGS(nbm) |= HIDD_BMF_SHARED_PIXTAB;
301 ok = TRUE;
303 else
305 /* Allcoate a pixtab */
306 HIDD_BM_PIXTAB(nbm) = AllocVec(sizeof (HIDDT_Pixel) * AROS_PALETTE_SIZE, MEMF_ANY);
308 if (NULL != HIDD_BM_PIXTAB(nbm))
310 /* Set this palette to all black by default */
312 HIDDT_Color col;
313 ULONG i;
315 col.red = 0;
316 col.green = 0;
317 col.blue = 0;
318 col.alpha = 0;
320 if (vHidd_ColorModel_Palette == colmod ||
321 vHidd_ColorModel_TrueColor == colmod)
323 ULONG numcolors;
325 numcolors = 1L << ((depth <= 8) ? depth : 8);
327 /* Set palette to all black */
328 for (i = 0; i < numcolors; i ++)
330 HIDD_BM_SetColors(HIDD_BM_OBJ(nbm), &col, i, 1);
331 HIDD_BM_PIXTAB(nbm)[i] = col.pixval;
335 ok = TRUE;
337 } /* if (pixtab successfully allocated) */
341 } /* if (flags & HIDD_BMF_SCREEN_BITMAP) ... (flags & BMF_DISPLAYABLE) */
342 else
344 if (friend_bitmap)
346 /* We got a friend_bitmap bitmap. We inherit its colormap
347 !!! NOTE !!! If this is used after the friend_bitmap bitmap is freed
348 it means trouble, as the colortab mem
349 will no longer be valid
351 if (IS_HIDD_BM(nbm))
354 HIDD_BM_COLMAP(nbm) = HIDD_BM_COLMAP(friend_bitmap);
355 HIDD_BM_COLMOD(nbm) = HIDD_BM_COLMOD(friend_bitmap);
356 HIDD_BM_PIXTAB(nbm) = HIDD_BM_PIXTAB(friend_bitmap);
357 HIDD_BM_REALDEPTH(nbm) = HIDD_BM_REALDEPTH(friend_bitmap);
358 ok = TRUE;
363 else
365 HIDD_BM_REALDEPTH(nbm) = depth;
366 ok = TRUE;
370 if (ok)
372 if (flags & BMF_CLEAR)
374 BltBitMap(nbm
375 , 0, 0
376 , nbm
377 , 0, 0
378 , width, height
379 , 0x00
380 , 0xFF
381 , NULL
384 ReturnPtr("driver_AllocBitMap", struct BitMap *, nbm);
387 OOP_DisposeObject(bm_obj);
389 } /* if (bitmap object allocated) */
391 } /* if (gfxhidd) */
392 FreeMem(nbm, sizeof (struct BitMap));
393 nbm = NULL;
395 } /* if (nbm) */
398 else /* Otherwise init a plain Amiga bitmap */
400 nbm = AllocMem (sizeof(struct BitMap) + ((depth > 8) ? (depth - 8) * sizeof(PLANEPTR) : 0),
401 MEMF_ANY | MEMF_CLEAR);
403 if (nbm)
405 ULONG plane;
407 nbm->BytesPerRow = ((sizex + 15) >> 4) * 2;
408 nbm->Rows = sizey;
409 nbm->Flags = flags;
410 nbm->Depth = depth;
411 nbm->pad = 0;
413 for (plane=0; plane<depth; plane++)
415 nbm->Planes[plane] = AllocRaster (sizex, sizey);
417 if (!nbm->Planes[plane])
418 break;
420 if (flags & BMF_CLEAR)
421 memset (nbm->Planes[plane], 0, RASSIZE(sizex,sizey));
424 if (plane != depth)
426 for (plane=0; plane<depth; plane++)
427 if (nbm->Planes[plane])
428 FreeRaster (nbm->Planes[plane], sizex, sizey);
430 FreeMem (nbm, sizeof (struct BitMap));
432 nbm = 0;
437 return nbm;
439 AROS_LIBFUNC_EXIT
441 } /* AllocBitMap */