2 Copyright © 1995-2013, The AROS Development Team. All rights reserved.
5 Desc: Graphics bitmap class implementation.
9 /****************************************************************************************/
13 #define DPUTPATTERN(x)
16 #include <aros/debug.h>
17 #include <proto/exec.h>
18 #include <proto/utility.h>
19 #include <proto/oop.h>
20 #include <exec/memory.h>
21 #include <utility/tagitem.h>
23 #include <oop/static_mid.h>
24 #include <graphics/text.h>
25 #include <graphics/scale.h>
26 #include <hidd/graphics.h>
32 #include "graphics_intern.h"
34 /****************************************************************************************/
36 #define POINT_OUTSIDE_CLIP(gc, x, y) \
37 ( (x) < GC_CLIPX1(gc) \
38 || (x) > GC_CLIPX2(gc) \
39 || (y) < GC_CLIPY1(gc) \
40 || (y) > GC_CLIPY2(gc) )
42 /*****************************************************************************************
51 Every display driver should implement at least one bitmap class for displayable
54 Normally this class doesn't need to have public ID. In order to use it the driver
55 should pass class pointer as aoHidd_BitMap_ClassPtr value to the graphics base class
56 in its moHidd_Gfx_NewBitMap implementation.
58 BitMap base class is in C++ terminology a pure virtual
59 baseclass. It will not allocate any bitmap data at all;
60 that is up to the subclass to do.
62 The main task of the BitMap baseclass is to store some information about the bitmap
63 like its size and pixelformat. A pixelformat is an object of private class which
64 stores the actual information about the format.
66 There are two ways that we can find out the pixfmt in our moHidd_Gfx_NewBitMap
70 The tags will contain a modeid.
71 One can use this modeid to get a pointer to an
72 already registered pixfmt.
74 Non-displayable bitmap -
75 The aoHidd_BitMap_StdPixFmt or aoHidd_BitMap_Friend attribute will always be
78 *****************************************************************************************/
80 #define PIXBUFBYTES 16384
82 static BOOL
DoBufferedOperation(OOP_Class
*cl
, OOP_Object
*o
, UWORD startx
, UWORD starty
, UWORD width
, UWORD height
,
83 BOOL getimage
, HIDDT_StdPixFmt stdpf
, VOID_FUNC operation
, void *userdata
)
85 struct HIDDBitMapData
*data
= OOP_INST_DATA(cl
, o
);
86 ULONG bytesperline
= width
* sizeof(ULONG
);
87 UWORD buflines
= PIXBUFBYTES
/ 4; /* Remove slow division */
89 UWORD endy
= starty
+ height
;
95 else if (buflines
> height
)
98 bufsize
= buflines
* bytesperline
;
99 buf
= AllocMem(bufsize
, MEMF_PUBLIC
);
100 if (!buf
&& (buflines
> 1))
102 /* Try to allocate single-line buffer */
104 bufsize
= bytesperline
;
105 buf
= AllocMem(bufsize
, MEMF_PUBLIC
);
110 for (y
= starty
; y
< endy
; y
+= buflines
)
112 if (y
+ buflines
> endy
)
114 /* This prevents overflow on last pass, buffer may be used only partially */
120 /* For some operations this can be optimized away */
121 HIDD_BM_GetImage(o
, buf
, bytesperline
, startx
, y
, width
, buflines
, stdpf
);
124 operation(buf
, y
, width
, buflines
, userdata
);
126 HIDD_BM_PutImage(o
, data
->gc
, buf
, bytesperline
, startx
, y
, width
, buflines
, stdpf
);
129 FreeMem(buf
, bufsize
);
133 /*****************************************************************************************
145 Specifies bitmap width in pixels.
147 Setting this attribute does not cause actual bitmap resize, just updates the information
148 about it. Use this only from within subclasses only if you know what you do. For example
149 SDL hosted driver sets it when framebufer changes the resolution.
162 *****************************************************************************************/
164 /*****************************************************************************************
176 Specifies bitmap height in pixels.
178 Setting this attribute does not cause actual bitmap resize, just updates the information
179 about it. Use this only from within subclasses only if you know what you do. For example
180 SDL hosted driver sets it when framebufer changes the resolution.
193 *****************************************************************************************/
195 /*****************************************************************************************
198 aoHidd_BitMap_Displayable
207 The bitmap is displayable. A displayable bitmap is always managed by a display
208 driver and must have valid display mode ID specification.
210 If this attribute is not supplied during bitmap creation, its value defaults
224 *****************************************************************************************/
226 /*****************************************************************************************
229 aoHidd_BitMap_Visible
238 Check if the bitmap is currently visible on screen
245 Not all display drivers implement this attribute. No AROS components currently rely
251 Some drivers may choose to have this attribute internally setable. Do not rely on it
252 in any way and do not attempt to set it manually from within applications, this will
253 not do any nice things.
255 *****************************************************************************************/
257 /*****************************************************************************************
260 aoHidd_BitMap_IsLinearMem
269 Check if the bitmap provides linear memory access. This means that bitmap's
270 pixelbuffer is directly addressable by the CPU.
272 Bitmaps with no linear memory may implement moHidd_BitMap_ObtainDirectAccess,
273 but this means that this method will rely on mirrored buffer. In such a case
274 the user must call moHidd_BitMap_UpdateRect after modifying bitmap's contents.
277 Used by cybergraphics.library/GetCyberMapAttr() for providing CYBRMATTR_ISLINEARMEM
283 Currently no display drivers implement this attribute despite many native mode
284 drivers actually provide linear memory.
287 moHidd_BitMap_ObtainDirectAccess, moHidd_BitMap_ReleaseDirectAccess,
288 moHidd_BitMap_UpdateRect
292 *****************************************************************************************/
294 /*****************************************************************************************
297 aoHidd_BitMap_BytesPerRow
306 Specify or query number of bytes per row in the bitmap storage buffer.
308 Setting this attribute doesn't actually cause changing buffer layout, just updates
309 the information about it. Use this only from within subclasses and only if you
310 exactly know why you do this.
312 Specifying this attribute during object creation overrides the value calculated
313 based on aoHidd_BitMap_Width and aoHidd_BitMap_Align values. Useful for wrapping
314 own buffers into bitmap objects, for example, in conjunction with
315 aoHidd_ChunkyBM_Buffer.
318 The returned value includes possible padding needed for alignment.
329 *****************************************************************************************/
331 /*****************************************************************************************
334 aoHidd_BitMap_ColorMap
343 Return associated colormap (palette) object.
345 By default only displayable bitmaps have colormaps. However a colormap can be attached
346 to any bitmap using moHidd_BitMap_SetColors or moHidd_BitMap_SetColorMap.
348 Note that manual attaching of a colormap to a nondisplayable bitmap may cause undesired
349 side-effects on graphics.library behavior. It's better not to do this at all. The system
350 knows what it does better than you.
359 moHidd_BitMap_SetColorMap, moHidd_BitMap_SetColors.
363 *****************************************************************************************/
365 /*****************************************************************************************
377 Specify a friend bitmap. The bitmap will be allocated so that it
378 is optimized for blitting to this bitmap.
380 Display drivers may query this attribute and then query friend bitmap
381 for anything they want (like pixelformat, mode ID, etc).
383 Note that explicit specification of mode ID and/or standard pixelformat
384 should override defaults provided by friend bitmap (i.e. actually breaking
397 *****************************************************************************************/
399 /*****************************************************************************************
402 aoHidd_BitMap_GfxHidd
411 Specify display driver object this bitmap was created with.
413 Normally the user doesn't have to supply this attribute. Instead you should use
414 driver's moHidd_Gfx_NewBitMap method in order to create bitmaps. In this case
415 aoHidd_BitMap_GfxHidd attribute will be provided by graphics driver base class
416 with the correct value.
418 It is illegal to manually create bitmap objects with no driver associated.
419 graphics.library maintains at least a memory driver for nondisplayable
420 bitmaps in system RAM without any acceleration.
429 CLID_Hidd_Gfx/moHidd_Gfx_NewBitMap
433 *****************************************************************************************/
435 /*****************************************************************************************
438 aoHidd_BitMap_StdPixFmt
441 [I..], HIDDT_StdPixFmt
447 Specify standard pixelformat code (one of vHidd_StdPixFmt_... values) for the
450 Values less than num_Hidd_PseudoStdPixFmt are illegal for this attribute.
452 Actually the bitmap class itself ignores this attribute. It is processed by
453 CLID_Hidd_Gfx/moHidd_Gfx_NewBitMap method in order to look up a corresponding
454 pixelformat object in the system's database.
457 Bitmaps with this attribute set should be created as RAM bitmaps with direct CPU
458 access. It is not recommended to replace them with, for example, virtual surfaces on
459 hosted AROS. Such bitmaps are expected to be directly addressable and breaking
460 this may cause undesired side effects.
467 aoHidd_BitMap_PixFmt, CLID_Hidd_Gfx/moHidd_Gfx_NewBitMap
470 Currently all display drivers omit specifying own bitmap class for bitmaps with this
471 attribute set, letting base class (actually memory driver) to select an appropriate
472 class for it. This way it ends up in a bitmap of CLID_Hidd_ChunkyBM or CLID_Hidd_PlanarBM
473 class. It is recommended to follow this rule. It's not prohibited, however, to do some
474 adjustments to the bitmap (like alignment) in order to optimize blitting to/from it.
475 In fact if the display driver was asked to create such a bitmap, this means that
476 the standard bitmap is being created as a friend of some bitmap which was allocated
477 using this driver. This way the bitmap is expected to be friendly to this driver.
479 *****************************************************************************************/
481 /*****************************************************************************************
493 Specify or query pixelformat descriptor object associated with the bitmap.
495 Every bitmap has some associated pixelformat object. Pixelformat objects are
496 shared data storages, so many bitmaps may refer to the same pixelformat objects.
499 This attribute is internally specified during bitmap creation, but it's illegal
500 to do this for the user. NewBitMap method of graphics driver performs an explicit
501 check against this. It's up to graphics base classes to figure out its value.
511 *****************************************************************************************/
513 /*****************************************************************************************
525 Specify display mode ID for displayable bitmap.
527 A displayable bitmap must have this attribute supplied with valid value. A nondisplayable
528 one may miss it, however it may remember it if it was created as a friend of displayable
529 one. This way you may create another displayable bitmap as a friend of nondisplayable
530 one which in turn is a friend of displayable one.
532 This attribute can be set on a framebuffer bitmap. Doing so means an explicit request
533 for the driver to change current display mode on the hardware. Dependent parameters
534 (width, height and pixelformat) will be automatically adjusted, if not explicitly
535 specified in the attributes list.
538 If the given ModeID is not supported, the operation causes an error. You can check
539 for this by checking return value of OOP_SetAttrs() function. It will be TRUE in
540 case of success and FALSE upon failure. In case of failure none of bitmap attributes
551 *****************************************************************************************/
553 /*****************************************************************************************
556 aoHidd_BitMap_ClassPtr
565 Explicitly specify bitmap's class pointer.
567 This attribute is not actually a bitmap's attribute. Your display driver class can
568 supply it to base class' moHidd_Gfx_NewBitMap method in order to select a class on
569 which to call OOP_NewObject().
571 If neither this attribute nor aoHidd_BitMap_ClassID attribute is provided for
572 moHidd_Gfx_NewBitMap, graphics base class will do its best in order to find out the
573 correct class based on aoHidd_StdPixFmt attribute value or friend bitmap.
576 If a friend bitmap is given, the new bitmap will have the same class, if your driver
577 doesn't override it by supplying explicit class specification (using either
578 aoHidd_BitMap_ClassPtr or aoHidd_BitMap_ClassID attribute).
585 aoHidd_BitMap_ClassID, CLID_Hidd_Gfx/moHidd_Gfx_NewBitMap
589 *****************************************************************************************/
591 /*****************************************************************************************
594 aoHidd_BitMap_ClassID
603 Explicitly specify bitmap's class ID.
605 The purpose of this attribute is to let graphics driver base class to select a class
606 on which to call OOP_NewObject() in its moHidd_Gfx_NewBitMap implementation.
608 If neither this attribute nor aoHidd_BitMap_ClassPtr attribute is provided for
609 moHidd_Gfx_NewBitMap, graphics base class will do its best in order to find out the
610 correct class based on aoHidd_StdPixFmt attribute value or aoHidd_BitMap_ClassPtr value
618 The pointer to a given class will not be remembered as aoHidd_BitMap_ClassPtr value.
621 aoHidd_BitMap_ClassPtr, CLID_Hidd_Gfx/moHidd_Gfx_NewBitMap
625 *****************************************************************************************/
627 /*****************************************************************************************
630 aoHidd_BitMap_PixFmtTags
639 Private, very obsolete and currently has no function. Considered reserved.
651 *****************************************************************************************/
653 /*****************************************************************************************
656 aoHidd_BitMap_FrameBuffer
665 Specifies that the bitmap is a framebuffer bitmap.
667 A detailed description of a framebuffer is given in CLID_Hidd_Gfx/moHidd_Gfx_NewBitMap
668 and in CLID_Hidd_Gfx/moHidd_Gfx_Show documentation.
670 Specifying this attribute causes also implicit setting of aoHidd_BitMap_Displayable
683 *****************************************************************************************/
685 /*****************************************************************************************
688 aoHidd_BitMap_LeftEdge
697 Controls horizontal position of a scrollable screen bitmap.
699 Size of displayable bitmaps may differ from actual screen size. In this case the
700 bitmap can be scrolled around the whole display area. If the bitmap is larger than
701 the display, only its part can be visible.
703 Setting this attribute causes changing left origin point of the bitmap. The value
704 of this attribute represents an offset from the physical edge of the display to the
705 logical edge of the bitmap. This means that if a large bitmap scrolls to the left in
706 order to reveal its right part, the offset will be negative. If the bitmap scrolls
707 to the left (possibly revealing another bitmap behind it), the offset will be positive.
709 It's up to the display driver to set scroll limits. If the value of the attribute
710 becomes unacceptable for any reason, the driver should adjust it and provide the real
711 resulting value back.
714 Implementing screen scrolling does not enforce to implement screen composition, despite
715 the composition is really based on scrolling (in case of composition scrolling a bitmap
716 off-display is expected to reveal another bitmap behing it instead of empty space).
723 aoHidd_BitMap_TopEdge
726 Base class will always provide zero value for this attribute and ignore all attempts
727 to set it. This means that by default bitmaps don't scroll and this needs explicit
728 implementation in the display driver.
730 *****************************************************************************************/
732 /*****************************************************************************************
735 aoHidd_BitMap_TopEdge
744 Controls vertical position of a scrollable screen bitmap.
746 Size of displayable bitmaps may differ from actual screen size. In this case the
747 bitmap can be scrolled around the whole display area. If the bitmap is larger than
748 the display, only its part can be visible.
750 Setting this attribute causes changing top origin point of the bitmap. The value
751 of this attribute represents an offset from the physical edge of the display to the
752 logical edge of the bitmap. This means that if a large bitmap scrolls upwards in
753 order to reveal its bottom part, the offset will be negative. If the bitmap scrolls
754 downdards (possibly revealing another bitmap behind it), the offset will be positive.
756 It's up to the display driver to set scroll limits. If the value of the attribute
757 becomes unacceptable for any reason, the driver should adjust it and provide the real
758 resulting value back.
761 Implementing screen scrolling does not enforce to implement screen composition, despite
762 the composition is really based on scrolling (in case of composition scrolling a bitmap
763 off-display is expected to reveal another bitmap behing it instead of empty space).
773 *****************************************************************************************/
775 /*****************************************************************************************
787 Specify number of pixels to align bitmap data width to.
789 This attribute can be added in order to enforce alignment needed for example by
790 blitting hardware. It will have an impact on default aoHidd_BitMap_BytesPerRow
793 Direct specification of aoHidd_BitMap_BytesPerRow attribute overrides any value
797 Default value of this attribute is 16. This alignment is required by graphics.library
798 for AmigaOS(tm) compatibility reasons.
805 aoHidd_BitMap_BytesPerRow
809 *****************************************************************************************/
811 /*****************************************************************************************
823 Specify or query the actual bitmap depth.
825 This a convenience attribute to simplify handling planar bitmaps, whose actual depth
826 may vary. Default implementation in base class simply returns depth of bitmap's
827 pixelformat, and is ignored during initialization. Planar bitmap class returns the
828 actual depth here. If your specific bitmap class also operates on bitmaps with variable
829 depths, you need to implement this attribute in it.
841 *****************************************************************************************/
843 /****************************************************************************************/
848 * Calculate suggested bytes per row value based on bitmap's default alignment
849 * and pixelformat's bytes per pixel value.
851 static ULONG
GetBytesPerRow(struct HIDDBitMapData
*data
, struct class_static_data
*csd
)
853 struct Library
*OOPBase
= csd
->cs_OOPBase
;
854 UWORD align
= data
->align
- 1;
855 UWORD width
= (data
->width
+ align
) & ~align
;
856 IPTR bytesperpixel
, stdpf
;
858 OOP_GetAttr(data
->prot
.pixfmt
, aHidd_PixFmt_BytesPerPixel
, &bytesperpixel
);
859 OOP_GetAttr(data
->prot
.pixfmt
, aHidd_PixFmt_StdPixFmt
, &stdpf
);
861 if (stdpf
== vHidd_StdPixFmt_Plane
)
864 * Planar format actually have 8 pixels per one byte.
865 * However bytesperpixel == 1 for them. Perhaps this should
872 return width
* bytesperpixel
;
878 OOP_Object
*BM__Root__New(OOP_Class
*cl
, OOP_Object
*obj
, struct pRoot_New
*msg
)
880 struct Library
*OOPBase
= CSD(cl
)->cs_OOPBase
;
881 struct Library
*UtilityBase
= CSD(cl
)->cs_UtilityBase
;
883 EnterFunc(bug("BitMap::New()\n"));
885 obj
= (OOP_Object
*)OOP_DoSuperMethod(cl
, obj
, (OOP_Msg
) msg
);
889 struct TagItem colmap_tags
[] =
891 { aHidd_ColorMap_NumEntries
, 16 },
894 struct TagItem
*tag
, *tstate
;
896 struct HIDDBitMapData
*data
= OOP_INST_DATA(cl
, obj
);
898 /* Set some default values */
899 data
->modeid
= vHidd_ModeID_Invalid
;
902 data
->compositable
= FALSE
;
904 tstate
= msg
->attrList
;
905 while ((tag
= NextTagItem(&tstate
)))
909 if (IS_BITMAP_ATTR(tag
->ti_Tag
, idx
))
913 case aoHidd_BitMap_BMStruct
:
914 data
->bmstruct
= (struct BitMap
*)tag
->ti_Data
;
917 case aoHidd_BitMap_Width
:
918 data
->width
= tag
->ti_Data
;
921 case aoHidd_BitMap_Height
:
922 data
->height
= tag
->ti_Data
;
925 case aoHidd_BitMap_Align
:
926 data
->align
= tag
->ti_Data
;
929 case aoHidd_BitMap_BytesPerRow
:
930 data
->bytesPerRow
= tag
->ti_Data
;
933 case aoHidd_BitMap_GfxHidd
:
934 data
->gfxhidd
= (OOP_Object
*)tag
->ti_Data
;
937 case aoHidd_BitMap_Friend
:
938 data
->friend = (OOP_Object
*)tag
->ti_Data
;
941 case aoHidd_BitMap_Displayable
:
942 data
->displayable
= tag
->ti_Data
;
945 case aoHidd_BitMap_Compositable
:
946 data
->compositable
= tag
->ti_Data
;
949 case aoHidd_BitMap_FrameBuffer
:
950 data
->framebuffer
= tag
->ti_Data
;
953 case aoHidd_BitMap_ModeID
:
954 data
->modeid
= tag
->ti_Data
;
957 case aoHidd_BitMap_PixFmt
:
958 data
->prot
.pixfmt
= (OOP_Object
*)tag
->ti_Data
;
964 /* aoHidd_BitMap_GfxHidd is mandatory */
967 D(bug("!!!! BM CLASS DID NOT GET GFX HIDD !!!\n"));
968 D(bug("!!!! The reason for this is that the gfxhidd subclass NewBitmap() method\n"));
969 D(bug("!!!! has not left it to the baseclass to actually create the object,\n"));
970 D(bug("!!!! but rather done it itself. This MUST be corrected in the gfxhidd subclass\n"));
975 /* FrameBuffer implies Displayable */
976 if (data
->framebuffer
)
977 data
->displayable
= TRUE
;
979 if (ok
&& (data
->displayable
|| data
->compositable
))
981 HIDDT_ModeID bmmodeid
= data
->modeid
;
983 /* We should always get modeid, but we check anyway */
984 if ((data
->compositable
) && (data
->friend))
986 OOP_GetAttr(data
->friend, aHidd_BitMap_ModeID
, &bmmodeid
);
987 D(bug("!!! BitMap:New() Using Friends ModeID - 0x%08X !!!\n", bmmodeid
));
990 if (bmmodeid
== vHidd_ModeID_Invalid
)
992 D(bug("!!! BitMap:New() NO VALID MODEID SPECIFIED FOR DISPLAYABLE BITMAP !!!\n"));
993 data
->compositable
= ok
= FALSE
;
997 OOP_Object
*sync
, *pf
;
999 if (!HIDD_Gfx_GetMode(data
->gfxhidd
, bmmodeid
, &sync
, &pf
))
1001 D(bug("!!! BitMap::New() RECEIVED INVALID MODEID 0x%08X\n", bmmodeid
));
1002 data
->compositable
= ok
= FALSE
;
1006 /* Get display size from the modeid */
1007 OOP_GetAttr(sync
, aHidd_Sync_HDisp
, &data
->displayWidth
);
1008 OOP_GetAttr(sync
, aHidd_Sync_VDisp
, &data
->displayHeight
);
1009 data
->display
.MaxX
= data
->displayWidth
;
1010 data
->display
.MaxY
= data
->displayHeight
;
1012 /* Update the missing bitmap data */
1014 data
->width
= data
->displayWidth
;
1016 data
->height
= data
->displayHeight
;
1018 D(bug("[BitMap] Bitmap %dx%d, display %dx%d\n", data
->width
, data
->height
, data
->display
.width
, data
->display
.height
));
1020 if (!data
->prot
.pixfmt
)
1022 /* The PixFmt is allready registered and locked in the PixFmt database */
1023 data
->prot
.pixfmt
= pf
;
1031 /* * PixFmt will be NULL in case of e.g. planarbm late initialization. */
1032 if (data
->prot
.pixfmt
)
1034 ULONG bytesPerRow
= GetBytesPerRow(data
, CSD(cl
));
1036 if (data
->bytesPerRow
)
1038 /* If we have user-supplied BytesPerRow value, make sure it's suitable */
1039 if (data
->bytesPerRow
< bytesPerRow
)
1044 /* Otherwise we have what we calculated */
1045 data
->bytesPerRow
= bytesPerRow
;
1052 InitSemaphore(&data
->lock
);
1054 /* Cache default GC */
1055 OOP_GetAttr(data
->gfxhidd
, aHidd_Gfx_DefaultGC
, (IPTR
*)&data
->gc
);
1058 * Initialize the direct method calling.
1059 * We don't check against errors because our base class contains all
1062 #if USE_FAST_PUTPIXEL
1063 data
->putpixel
= OOP_GetMethod(obj
, HiddBitMapBase
+ moHidd_BitMap_PutPixel
, &data
->putpixel_Class
);
1065 #if USE_FAST_GETPIXEL
1066 data
->getpixel
= OOP_GetMethod(obj
, HiddBitMapBase
+ moHidd_BitMap_GetPixel
, &data
->getpixel_Class
);
1068 #if USE_FAST_DRAWPIXEL
1069 data
->drawpixel
= OOP_GetMethod(obj
, HiddBitMapBase
+ moHidd_BitMap_DrawPixel
, &data
->drawpixel_Class
);
1073 * Try to create the colormap.
1075 * stegerg: Only add a ColorMap for a visible bitmap (screen). This
1076 * is important because one can create for example a bitmap
1077 * in PIXFMT_LUT8 without friend bitmap and then copy this
1078 * bitmap to a 16 bit screen. During copy the screen bitmap
1079 * CLUT must be used, which would not happen if our PIXFMT_LUT8
1080 * also had a colormap itself because then bltbitmap would use the
1081 * colormap of the PIXFMT_LUT8 bitmap as lookup, which in this
1082 * case would just cause everything to become black in the
1083 * destination (screen) bitmap, because noone ever sets up the
1084 * colormap of the PIXFMT_LUT8 bitmap
1086 * sonic: CHECKME: Why does the colormap always have 16 colors? May be calculate this
1087 * based on depth ? The colormap auto-enlarges itself if SetColors method requests
1088 * missing entries, but is it so good?
1091 if (data
->displayable
)
1093 data
->colmap
= OOP_NewObject(NULL
, CLID_Hidd_ColorMap
, colmap_tags
);
1094 if (NULL
== data
->colmap
)
1102 ULONG dispose_mid
= OOP_GetMethodID(IID_Root
, moRoot_Dispose
);
1104 OOP_CoerceMethod(cl
, obj
, &dispose_mid
);
1109 } /* if (NULL != obj) */
1111 ReturnPtr("BitMap::New", OOP_Object
*, obj
);
1114 /****************************************************************************************/
1116 void BM__Root__Dispose(OOP_Class
*cl
, OOP_Object
*obj
, OOP_Msg
*msg
)
1118 struct Library
*OOPBase
= CSD(cl
)->cs_OOPBase
;
1119 struct HIDDBitMapData
*data
= OOP_INST_DATA(cl
, obj
);
1121 EnterFunc(bug("BitMap::Dispose()\n"));
1123 if (NULL
!= data
->colmap
)
1124 OOP_DisposeObject(data
->colmap
);
1126 D(bug("Calling super\n"));
1128 /* Release the previously registered pixel format */
1129 if (data
->pf_registered
)
1130 GFX__Hidd_Gfx__ReleasePixFmt(CSD(cl
)->gfxhiddclass
, data
->prot
.pixfmt
);
1132 OOP_DoSuperMethod(cl
, obj
, (OOP_Msg
) msg
);
1134 ReturnVoid("BitMap::Dispose");
1137 /****************************************************************************************/
1139 VOID
BM__Root__Get(OOP_Class
*cl
, OOP_Object
*obj
, struct pRoot_Get
*msg
)
1141 struct HIDDBitMapData
*data
= OOP_INST_DATA(cl
, obj
);
1144 EnterFunc(bug("BitMap::Get() attrID: %i storage: %p\n", msg
->attrID
, msg
->storage
));
1146 if (IS_BITMAP_ATTR(msg
->attrID
, idx
))
1150 case aoHidd_BitMap_BMStruct
:
1151 *msg
->storage
= (IPTR
)data
->bmstruct
;
1154 case aoHidd_BitMap_Width
:
1155 *msg
->storage
= data
->width
;
1156 D(bug(" width: %i\n", data
->width
));
1159 case aoHidd_BitMap_Height
:
1160 *msg
->storage
= data
->height
;
1163 case aoHidd_BitMap_Depth
:
1165 * Generally our bitmaps have a fixed depth, which depends on pixelformat.
1166 * If this is not true for your bitmap, overload aoHidd_BitMap_Depth in your class.
1168 *msg
->storage
= ((HIDDT_PixelFormat
*)data
->prot
.pixfmt
)->depth
;
1171 case aoHidd_BitMap_Displayable
:
1172 *msg
->storage
= data
->displayable
;
1175 case aoHidd_BitMap_FrameBuffer
:
1176 *msg
->storage
= data
->framebuffer
;
1179 case aoHidd_BitMap_PixFmt
:
1180 *msg
->storage
= (IPTR
)data
->prot
.pixfmt
;
1183 case aoHidd_BitMap_Friend
:
1184 *msg
->storage
= (IPTR
)data
->friend;
1187 case aoHidd_BitMap_ColorMap
:
1188 *msg
->storage
= (IPTR
)data
->colmap
;
1191 case aoHidd_BitMap_GfxHidd
:
1192 *msg
->storage
= (IPTR
)data
->gfxhidd
;
1195 case aoHidd_BitMap_ModeID
:
1196 *msg
->storage
= data
->modeid
;
1199 case aoHidd_BitMap_Align
:
1200 *msg
->storage
= data
->align
;
1203 case aoHidd_BitMap_BytesPerRow
:
1204 *msg
->storage
= data
->bytesPerRow
;
1207 case aoHidd_BitMap_Visible
:
1208 /* Framebuffer is always visible */
1209 *msg
->storage
= data
->framebuffer
? TRUE
: data
->visible
;
1212 case aoHidd_BitMap_Compositable
:
1213 *msg
->storage
= (IPTR
)data
->compositable
;
1217 * The following two are stored with inverted sign!
1218 * Verbose explanation is in Set method.
1220 case aoHidd_BitMap_LeftEdge
:
1221 *msg
->storage
= -data
->display
.MinX
;
1224 case aoHidd_BitMap_TopEdge
:
1225 *msg
->storage
= -data
->display
.MinY
;
1228 D(default: bug("UNKNOWN ATTR IN BITMAP BASECLASS: %d\n", idx
);)
1232 OOP_DoSuperMethod(cl
, obj
, &msg
->mID
);
1233 ReturnVoid("BitMap::Get");
1236 /****************************************************************************************/
1238 #define UB(x) ((UBYTE *)x)
1240 /*****************************************************************************************
1243 moHidd_BitMap_SetColors
1246 BOOL OOP_DoMethod(OOP_Object *obj, struct pHidd_BitMap_SetColors *msg);
1248 BOOL HIDD_BM_SetColors (OOP_Object *obj, HIDDT_Color *colors,
1249 UWORD firstColor, UWORD numColors);
1252 hidd.graphics.bitmap
1255 Sets values for one or more colors in the colormap object associated with the
1258 The colormap will be created if it does not exist.
1260 Only ARGB values from the source array are taken into account. pixval member is
1261 updated with the real pixel value for every color.
1264 obj - A bitmap object whose colormap needs to be set
1265 colors - A pointer to source data array
1266 firstColor - Number of the first color to set
1267 numColors - Number of subsequent colors to set
1270 TRUE on success, FALSE in case of some error (like out of memory)
1279 CLID_Hidd_ColorMap/moHidd_ColorMap_SetColors
1283 *****************************************************************************************/
1285 BOOL
BM__Hidd_BitMap__SetColors(OOP_Class
*cl
, OOP_Object
*o
, struct pHidd_BitMap_SetColors
*msg
)
1287 /* Copy the colors into the internal buffer */
1288 struct Library
*OOPBase
= CSD(cl
)->cs_OOPBase
;
1289 struct HIDDBitMapData
*data
= OOP_INST_DATA(cl
, o
);
1292 /* Subclass has initialized HIDDT_Color->pixelVal field and such.
1293 Just copy it into the colortab.
1296 if (NULL
== data
->colmap
)
1298 struct TagItem colmap_tags
[] =
1300 { aHidd_ColorMap_NumEntries
, 0 },
1304 colmap_tags
[0].ti_Data
= msg
->firstColor
+ msg
->numColors
;
1305 data
->colmap
= OOP_NewObject(NULL
, CLID_Hidd_ColorMap
, colmap_tags
);
1308 if (NULL
== data
->colmap
)
1313 /* Use the colormap class to set the colors */
1314 if (!HIDD_CM_SetColors(data
->colmap
, msg
->colors
,
1315 msg
->firstColor
, msg
->numColors
,
1321 /* We may need to duplicate changes on framebuffer if running in mirrored mode */
1324 ObtainSemaphoreShared(&data
->lock
);
1328 ret
= GFX__Hidd_Gfx__SetFBColors(CSD(cl
)->gfxhiddclass
, data
->gfxhidd
, msg
);
1331 ReleaseSemaphore(&data
->lock
);
1337 /*******************************************************************************
1340 moHidd_BitMap_PutPixel
1343 VOID OOP_DoMethod(OOP_Object *obj, struct pHidd_BitMap_PutPixel *msg);
1345 VOID HIDD_BM_PutPixel(OOP_Object *obj, WORD x, WORD y,
1349 hidd.graphics.bitmap
1352 Sets a new color value for the pixel at (x,y). The actual color stored
1353 may be an approximation, due to the limited color depth or palette size
1354 of the bitmap. This function does not check the coordinates.
1357 obj - bitmap to write to.
1358 x, y - coordinates of the pixel to write.
1359 pixel - the pixel's new color value.
1374 *******************************************************************************/
1376 /* PutPixel must be implemented in a subclass */
1378 /*****************************************************************************************
1381 moHidd_BitMap_DrawPixel
1384 VOID OOP_DoMethod(OOP_Object *obj, struct pHidd_BitMap_DrawPixel *msg);
1386 VOID HIDD_BM_DrawPixel(OOP_Object *obj, OOP_Object *gc, WORD x, WORD y);
1389 hidd.graphics.bitmap
1392 Changes the pixel at (x,y). The color of the pixel depends on the
1393 attributes of gc, eg. colors, drawmode, colormask etc.
1394 This function does not check the coordinates.
1397 obj - A bitmap to draw on
1398 gc - A GC (graphics context) object to use for drawing
1399 x, y - Coordinates of the pixel to draw
1415 - Support for shapeplane.
1418 *****************************************************************************************/
1420 VOID
BM__Hidd_BitMap__DrawPixel(OOP_Class
*cl
, OOP_Object
*obj
,
1421 struct pHidd_BitMap_DrawPixel
*msg
)
1423 HIDDT_Pixel src
, dest
, val
;
1424 HIDDT_DrawMode mode
;
1425 HIDDT_Pixel writeMask
;
1428 /* EnterFunc(bug("BitMap::DrawPixel() x: %i, y: %i\n", msg->x, msg->y));
1431 Example: Pixels whose bits are set to 0 in the colMask must be
1434 data->colMask = 001111
1438 writeMask = ~data->colMask & dest
1442 dest = data->fg && dest = 010100
1445 dest = dest & (writeMask | data->ColMask)
1446 = 010100 & (100000 | 001111)
1451 dest = dest | writeMask;
1462 #if OPTIMIZE_DRAWPIXEL_FOR_COPY
1463 if (vHidd_GC_DrawMode_Copy
== mode
&& GC_COLMASK(gc
) == ~0)
1470 dest
= GETPIXEL(cl
, obj
, msg
->x
, msg
->y
);
1471 writeMask
= ~GC_COLMASK(gc
) & dest
;
1475 if(mode
& 1) val
= ( src
& dest
);
1476 if(mode
& 2) val
= ( src
& ~dest
) | val
;
1477 if(mode
& 4) val
= (~src
& dest
) | val
;
1478 if(mode
& 8) val
= (~src
& ~dest
) | val
;
1480 val
= (val
& (writeMask
| GC_COLMASK(gc
) )) | writeMask
;
1484 PUTPIXEL(cl
, obj
, msg
->x
, msg
->y
, val
);
1487 /*****************************************************************************************
1490 moHidd_BitMap_DrawLine
1493 VOID OOP_DoMethod(OOP_Object *obj, struct pHidd_BitMap_DrawPixel *msg);
1495 VOID HIDD_BM_DrawLine(OOP_Object *obj, OOP_Object *gc, WORD x1, WORD y1,
1499 hidd.graphics.bitmap
1502 Draws a line from (x1,y1) to (x2,y2) in the specified gc.
1503 The function does not clip the line against the drawing area.
1506 obj - A bitmap to draw on
1507 gc - A graphics context object to use
1508 x1,y1 - start point of the line in pixels
1509 x2,y2 - end point of the line in pixels
1523 Uses midpoint line ("Bresenham") algorithm([FOL90] 3.2.2)
1525 TODO Support for line pattern
1526 Optimize remove if t == 1 ...
1527 Implement better clipping: Should be no reason to calculate
1528 more than the part of the line that is inside the cliprect
1530 *****************************************************************************************/
1532 VOID BM__Hidd_BitMap__DrawLine
1534 OOP_Class
*cl
, OOP_Object
*obj
, struct pHidd_BitMap_DrawLine
*msg
1537 WORD dx
, dy
, incrE
, incrNE
, d
, x
, y
, s1
, s2
, t
, i
;
1538 WORD x1
, y1
, x2
, y2
;
1539 UWORD maskLine
; /* for line pattern */
1540 ULONG fg
; /* foreground pen */
1546 /* bug("BitMap::DrawLine()\n");
1547 */ EnterFunc(bug("BitMap::DrawLine() x1: %i, y1: %i x2: %i, y2: %i\n", msg
->x1
, msg
->y1
, msg
->x2
, msg
->y2
));
1550 doclip
= GC_DOCLIP(gc
);
1551 opaque
= (GC_COLEXP(gc
) & vHidd_GC_ColExp_Opaque
) ? TRUE
: FALSE
;
1554 maskLine
= 1 << GC_LINEPATCNT(gc
);
1558 /* If line is not inside cliprect, then just return */
1559 /* Normalize coords */
1560 if (msg
->x1
> msg
->x2
)
1562 x1
= msg
->x2
; x2
= msg
->x1
;
1566 x1
= msg
->x1
; x2
= msg
->x2
;
1569 if (msg
->y1
> msg
->y2
)
1571 y1
= msg
->y2
; y2
= msg
->y1
;
1575 y1
= msg
->y1
; y2
= msg
->y2
;
1578 if ( x1
> GC_CLIPX2(gc
)
1579 || x2
< GC_CLIPX1(gc
)
1580 || y1
> GC_CLIPY2(gc
)
1581 || y2
< GC_CLIPY1(gc
) )
1584 /* Line is not inside cliprect, so just return */
1598 Horizontal line drawing code.
1602 /* Don't swap coordinates if x2 < x1! Because of linepattern! */
1615 for(i
= x1
; i
!= x2
; i
+= dx
)
1617 /* Pixel inside ? */
1619 if (!doclip
|| !POINT_OUTSIDE_CLIP(gc
, i
, y
))
1621 if(GC_LINEPAT(gc
) & maskLine
)
1623 HIDD_BM_DrawPixel(obj
, gc
, i
, y
);
1627 GC_FG(gc
) = GC_BG(gc
);
1628 HIDD_BM_DrawPixel(obj
, gc
, i
, y
);
1633 maskLine
= maskLine
>> 1;
1634 if (!maskLine
) maskLine
= 1L << 15;
1640 Vertical line drawing code.
1644 /* Don't swap coordinates if y2 < y1! Because of linepattern! */
1657 for(i
= y1
; i
!= y2
; i
+= dy
)
1659 /* Pixel inside ? */
1660 if (!doclip
|| !POINT_OUTSIDE_CLIP(gc
, x
, i
))
1662 if(GC_LINEPAT(gc
) & maskLine
)
1664 HIDD_BM_DrawPixel(obj
, gc
, x
, i
);
1668 GC_FG(gc
) = GC_BG(gc
);
1669 HIDD_BM_DrawPixel(obj
, gc
, x
, i
);
1674 maskLine
= maskLine
>> 1;
1675 if (!maskLine
) maskLine
= 1L << 15;
1682 Generic line drawing code.
1684 /* Calculate slope */
1688 /* which direction? */
1689 if((x2
- x1
) > 0) s1
= 1; else s1
= - 1;
1690 if((y2
- y1
) > 0) s2
= 1; else s2
= - 1;
1692 /* change axes if dx < dy */
1705 d
= 2 * dy
- dx
; /* initial value of d */
1707 incrE
= 2 * dy
; /* Increment use for move to E */
1708 incrNE
= 2 * (dy
- dx
); /* Increment use for move to NE */
1712 for(i
= 0; i
<= dx
; i
++)
1714 /* Pixel inside ? */
1715 if (!doclip
|| !POINT_OUTSIDE_CLIP(gc
, x
, y
))
1717 if(GC_LINEPAT(gc
) & maskLine
)
1719 HIDD_BM_DrawPixel(obj
, gc
, x
, y
);
1723 GC_FG(gc
) = GC_BG(gc
);
1724 HIDD_BM_DrawPixel(obj
, gc
, x
, y
);
1749 maskLine
= maskLine
>> 1;
1750 if (!maskLine
) maskLine
= 1L << 15;
1755 ReturnVoid("BitMap::DrawLine ");
1758 /*****************************************************************************************
1761 moHidd_BitMap_DrawRect
1764 OOP_DoMethod(OOP_Object *obj, struct pHidd_BitMap_DrawRect *msg);
1766 VOID HIDD_BM_DrawRect (OOP_Object *obj, OOP_Object *gc, WORD minX, WORD minY,
1767 WORD maxX, WORD maxY);
1770 hidd.graphics.bitmap
1773 Draws a hollow rectangle. minX and minY specifies the upper
1774 left corner of the rectangle. minY and maxY specifies the lower
1775 right corner of the rectangle.
1776 The function does not clip the rectangle against the drawing area.
1779 obj - A bitmap to draw on
1780 gc - A GC object to use for drawing
1781 minX, minY - upper left corner of the rectangle in pixels
1782 maxX, maxY - lower right corner of the rectangle in pixels
1788 This method is not used by the system and considered reserved.
1800 *****************************************************************************************/
1802 VOID
BM__Hidd_BitMap__DrawRect(OOP_Class
*cl
, OOP_Object
*obj
,
1803 struct pHidd_BitMap_DrawRect
*msg
)
1806 OOP_Object
*gc
= msg
->gc
;
1809 EnterFunc(bug("BitMap::DrawRect()"));
1811 if(msg
->minX
== msg
->maxX
) addX
= 0; else addX
= 1;
1812 if(msg
->minY
== msg
->maxY
) addY
= 0; else addY
= 1;
1814 HIDD_BM_DrawLine(obj
, gc
, msg
->minX
, msg
->minY
, msg
->maxX
, msg
->minY
);
1815 HIDD_BM_DrawLine(obj
, gc
, msg
->maxX
, msg
->minY
+ addY
, msg
->maxX
, msg
->maxY
);
1816 HIDD_BM_DrawLine(obj
, gc
, msg
->maxX
- addX
, msg
->maxY
, msg
->minX
, msg
->maxY
);
1817 HIDD_BM_DrawLine(obj
, gc
, msg
->minX
, msg
->maxY
- addY
, msg
->minX
, msg
->minY
+ addY
);
1820 ReturnVoid("BitMap::DrawRect");
1823 /*****************************************************************************************
1826 moHidd_BitMap_FillRect
1829 VOID OOP_DoMethod(OOP_Object *obj, struct pHidd_BitMap_DrawRect *msg);
1831 VOID HIDD_BM_FillRect (OOP_Object *obj, OOP_Object *gc, WORD minX, WORD minY,
1832 WORD maxX, WORD maxY);
1835 hidd.graphics.bitmap
1839 Draws a solid rectangle. minX and minY specifies the upper
1840 left corner of the rectangle. minY and maxY specifies the lower
1841 right corner of the rectangle.
1842 The function does not clip the rectangle against the drawing area.
1845 obj - A bitmap to draw on
1846 gc - A GC object to use for drawing
1847 minX, minY - upper left corner of the rectangle in pixels
1848 maxX, maxY - lower right corner of the rectangle in pixels
1866 *****************************************************************************************/
1868 VOID
BM__Hidd_BitMap__FillRect(OOP_Class
*cl
, OOP_Object
*obj
,
1869 struct pHidd_BitMap_DrawRect
*msg
)
1871 OOP_Object
*gc
= msg
->gc
;
1875 EnterFunc(bug("BitMap::FillRect()"));
1877 linepat
= GC_LINEPAT(gc
);
1878 GC_LINEPAT(gc
) = ~0;
1880 for(; y
<= msg
->maxY
; y
++)
1882 HIDD_BM_DrawLine(obj
, gc
, msg
->minX
, y
, msg
->maxX
, y
);
1885 GC_LINEPAT(gc
) = linepat
;
1887 ReturnVoid("BitMap::FillRect");
1890 /*****************************************************************************************
1893 moHidd_BitMap_DrawEllipse
1896 VOID OOP_DoMethod(OOP_Object *obj, struct pHidd_BitMap_DrawEllipse *msg);
1898 VOID HIDD_BM_DrawEllipse (OOP_Object *obj, OOP_Object *gc, WORD x, WORD y,
1902 hidd.graphics.bitmap
1905 Draws a hollow ellipse from the center point (x,y) with the radii
1906 rx and ry in the specified bitmap.
1907 The function does not clip the ellipse against the drawing area.
1910 obj - A bitmap to draw on
1911 gc - A GC object to use for drawing
1912 x,y - Coordinates of center point in pixels
1913 rx,ry - ry and ry radius in pixels
1923 Because of overflow the current code do not work with big
1924 values of rx and ry.
1933 *****************************************************************************************/
1935 /* TODO: Try to opimize clipping here */
1937 VOID
BM__Hidd_BitMap__DrawEllipse(OOP_Class
*cl
, OOP_Object
*obj
,
1938 struct pHidd_BitMap_DrawEllipse
*msg
)
1940 OOP_Object
*gc
= msg
->gc
;
1941 WORD x
= msg
->rx
, y
= 0; /* ellipse points */
1943 /* intermediate terms to speed up loop */
1944 LONG t1
= msg
->rx
* msg
->rx
, t2
= t1
<< 1, t3
= t2
<< 1;
1945 LONG t4
= msg
->ry
* msg
->ry
, t5
= t4
<< 1, t6
= t5
<< 1;
1946 LONG t7
= msg
->rx
* t5
, t8
= t7
<< 1, t9
= 0L;
1947 LONG d1
= t2
- t7
+ (t4
>> 1); /* error terms */
1948 LONG d2
= (t1
>> 1) - t8
+ t5
;
1950 APTR doclip
= GC_DOCLIP(gc
);
1953 EnterFunc(bug("BitMap::DrawEllipse()"));
1955 while (d2
< 0) /* till slope = -1 */
1957 /* draw 4 points using symmetry */
1962 if (!POINT_OUTSIDE_CLIP(gc
, msg
->x
+ x
, msg
->y
+ y
))
1963 HIDD_BM_DrawPixel(obj
, gc
, msg
->x
+ x
, msg
->y
+ y
);
1965 if (!POINT_OUTSIDE_CLIP(gc
, msg
->x
+ x
, msg
->y
- y
))
1966 HIDD_BM_DrawPixel(obj
, gc
, msg
->x
+ x
, msg
->y
- y
);
1968 if (!POINT_OUTSIDE_CLIP(gc
, msg
->x
- x
, msg
->y
+ y
))
1969 HIDD_BM_DrawPixel(obj
, gc
, msg
->x
- x
, msg
->y
+ y
);
1971 if (!POINT_OUTSIDE_CLIP(gc
, msg
->x
- x
, msg
->y
- y
))
1972 HIDD_BM_DrawPixel(obj
, gc
, msg
->x
- x
, msg
->y
- y
);
1977 HIDD_BM_DrawPixel(obj
, gc
, msg
->x
+ x
, msg
->y
+ y
);
1978 HIDD_BM_DrawPixel(obj
, gc
, msg
->x
+ x
, msg
->y
- y
);
1979 HIDD_BM_DrawPixel(obj
, gc
, msg
->x
- x
, msg
->y
+ y
);
1980 HIDD_BM_DrawPixel(obj
, gc
, msg
->x
- x
, msg
->y
- y
);
1983 y
++; /* always move up here */
1985 if (d1
< 0) /* move straight up */
1990 else /* move up and left */
1994 d1
= d1
+ t9
+ t2
- t8
;
1995 d2
= d2
+ t9
+ t5
- t8
;
1999 do /* rest of top right quadrant */
2001 /* draw 4 points using symmetry */
2006 if (!POINT_OUTSIDE_CLIP(gc
, msg
->x
+ x
, msg
->y
+ y
))
2007 HIDD_BM_DrawPixel(obj
, gc
, msg
->x
+ x
, msg
->y
+ y
);
2009 if (!POINT_OUTSIDE_CLIP(gc
, msg
->x
+ x
, msg
->y
- y
))
2010 HIDD_BM_DrawPixel(obj
, gc
, msg
->x
+ x
, msg
->y
- y
);
2012 if (!POINT_OUTSIDE_CLIP(gc
, msg
->x
- x
, msg
->y
+ y
))
2013 HIDD_BM_DrawPixel(obj
, gc
, msg
->x
- x
, msg
->y
+ y
);
2015 if (!POINT_OUTSIDE_CLIP(gc
, msg
->x
- x
, msg
->y
- y
))
2016 HIDD_BM_DrawPixel(obj
, gc
, msg
->x
- x
, msg
->y
- y
);
2022 HIDD_BM_DrawPixel(obj
, gc
, msg
->x
+ x
, msg
->y
+ y
);
2023 HIDD_BM_DrawPixel(obj
, gc
, msg
->x
+ x
, msg
->y
- y
);
2024 HIDD_BM_DrawPixel(obj
, gc
, msg
->x
- x
, msg
->y
+ y
);
2025 HIDD_BM_DrawPixel(obj
, gc
, msg
->x
- x
, msg
->y
- y
);
2029 HIDD_BM_DrawPixel(obj
, gc
, msg
->x
+ x
, msg
->y
+ y
);
2030 HIDD_BM_DrawPixel(obj
, gc
, msg
->x
+ x
, msg
->y
- y
);
2031 HIDD_BM_DrawPixel(obj
, gc
, msg
->x
- x
, msg
->y
+ y
);
2032 HIDD_BM_DrawPixel(obj
, gc
, msg
->x
- x
, msg
->y
- y
);
2034 x
--; /* always move left here */
2036 if (d2
< 0) /* move up and left */
2040 d2
= d2
+ t9
+ t5
- t8
;
2042 else /* move straight left */
2050 ReturnVoid("BitMap::DrawEllipse");
2053 /*****************************************************************************************
2056 moHidd_BitMap_FillEllipse
2059 VOID OOP_DoMethod(OOP_Object *obj, struct pHidd_BitMap_DrawEllipse *msg);
2061 VOID HIDD_BM_FillEllipse (OOP_Object *obj, OOP_Object *gc, WORD x, WORD y,
2065 hidd.graphics.bitmap
2068 Draws a solid ellipse from the center point (x,y) with the radii
2069 rx and ry in the specified bitmap.
2070 The function does not clip the ellipse against the drawing area.
2073 obj - A bitmap to draw on
2074 gc - A GC object to use for drawing
2075 x,y - Coordinates of center point in pixels
2076 rx,ry - ry and ry radius in pixels
2082 This method is not used by the system and considered reserved.
2086 Because of overflow the current code do not work with big
2087 values of rx and ry.
2096 *****************************************************************************************/
2098 VOID
BM__Hidd_BitMap__FillEllipse(OOP_Class
*cl
, OOP_Object
*obj
,
2099 struct pHidd_BitMap_DrawEllipse
*msg
)
2102 OOP_Object
*gc
= msg
->gc
;
2103 WORD x
= msg
->rx
, y
= 0; /* ellipse points */
2105 /* intermediate terms to speed up loop */
2106 LONG t1
= msg
->rx
* msg
->rx
, t2
= t1
<< 1, t3
= t2
<< 1;
2107 LONG t4
= msg
->ry
* msg
->ry
, t5
= t4
<< 1, t6
= t5
<< 1;
2108 LONG t7
= msg
->rx
* t5
, t8
= t7
<< 1, t9
= 0L;
2109 LONG d1
= t2
- t7
+ (t4
>> 1); /* error terms */
2110 LONG d2
= (t1
>> 1) - t8
+ t5
;
2112 EnterFunc(bug("BitMap::FillEllipse()"));
2114 while (d2
< 0) /* till slope = -1 */
2116 /* draw 4 points using symmetry */
2117 HIDD_BM_DrawLine(obj
, gc
, msg
->x
- x
, msg
->y
+ y
, msg
->x
+ x
, msg
->y
+ y
);
2118 HIDD_BM_DrawLine(obj
, gc
, msg
->x
- x
, msg
->y
- y
, msg
->x
+ x
, msg
->y
- y
);
2120 y
++; /* always move up here */
2122 if (d1
< 0) /* move straight up */
2127 else /* move up and left */
2131 d1
= d1
+ t9
+ t2
- t8
;
2132 d2
= d2
+ t9
+ t5
- t8
;
2136 do /* rest of top right quadrant */
2138 /* draw 4 points using symmetry */
2139 HIDD_BM_DrawLine(obj
, gc
, msg
->x
- x
, msg
->y
+ y
, msg
->x
+ x
, msg
->y
+ y
);
2140 HIDD_BM_DrawLine(obj
, gc
, msg
->x
- x
, msg
->y
- y
, msg
->x
+ x
, msg
->y
- y
);
2142 x
--; /* always move left here */
2144 if (d2
< 0) /* move up and left */
2148 d2
= d2
+ t9
+ t5
- t8
;
2150 else /* move straight left */
2158 ReturnVoid("BitMap::FillEllipse");
2161 /*****************************************************************************************
2164 moHidd_BitMap_DrawPolygon
2167 VOID OOP_DoMethod(OOP_Object *obj, struct pHidd_BitMap_DrawPolygon *msg);
2169 VOID HIDD_BM_DrawPolygon (OOP_Object *obj, OOP_Object *gc, UWORD n, WORD *coords);
2172 hidd.graphics.bitmap
2175 Draws a hollow polygon from the list of coordinates in coords[].
2176 The function does not clip the polygon against the drawing area.
2179 obj - A bitmap to draw on
2180 gc - A GC object to use for drawing
2181 n - number of coordinate pairs
2182 coords - array of n (x, y) coordinates in pixels
2188 This method is not used by the system and considered reserved.
2200 *****************************************************************************************/
2202 VOID
BM__Hidd_BitMap__DrawPolygon(OOP_Class
*cl
, OOP_Object
*obj
,
2203 struct pHidd_BitMap_DrawPolygon
*msg
)
2206 OOP_Object
*gc
= msg
->gc
;
2209 EnterFunc(bug("BitMap::DrawPolygon()"));
2211 for(i
= 2; i
< (2 * msg
->n
); i
= i
+ 2)
2213 HIDD_BM_DrawLine(obj
, gc
, msg
->coords
[i
- 2], msg
->coords
[i
- 1],
2214 msg
->coords
[i
], msg
->coords
[i
+ 1]);
2218 ReturnVoid("BitMap::DrawPolygon");
2221 /*****************************************************************************************
2224 moHidd_BitMap_FillPolygon
2227 VOID OOP_DoMethod(OOP_Object *obj, struct pHidd_BitMap_DrawPolygon *msg);
2229 VOID HIDD_BM_FillPolygon (OOP_Object *obj, OOP_Object *gc, UWORD n, WORD *coords);
2232 hidd.graphics.bitmap
2235 This method was initially designed for drawing solid polygons, however it was never
2236 used and implemented. At the moment it is considered reserved, its synopsis and
2237 semantics may change in future.
2240 obj - A bitmap to draw on
2241 gc - A GC object to use for drawing
2242 n - number of coordinate pairs
2243 coords - array of n (x, y) coordinates in pixels
2253 Never used and implemented
2261 *****************************************************************************************/
2263 VOID
BM__Hidd_BitMap__FillPolygon(OOP_Class
*cl
, OOP_Object
*obj
, struct pHidd_BitMap_DrawPolygon
*msg
)
2265 D(bug("Sorry, FillPolygon() not implemented yet in bitmap baseclass\n"));
2268 /*****************************************************************************************
2271 moHidd_BitMap_DrawText
2274 OOP_DoMethod(OOP_Object *obj, struct pHidd_BitMap_DrawText *msg);
2276 VOID HIDD_BM_DrawText (OOP_Object *obj, OOP_Object *gc, WORD x, WORD y,
2277 STRPTR text, UWORD length);
2280 hidd.graphics.bitmap
2283 Draws the first length characters of text at (x, y).
2284 The function does not clip the text against the drawing area.
2287 obj - A bitmap to draw on
2288 gc - A GC object to use for drawing and font specification
2289 x, y - Position to start drawing in pixels. The x
2290 coordinate is relativ to the left side of the
2292 The y coordinate is relative to the baseline of the font.
2293 text - Pointer to a Latin 1 string
2294 length - Number of characters to draw
2300 At the moment text drawing is processed entirely by graphics.library
2301 using BltTemplate(), which in turn uses moHodd_BitMap_PutTemplate.
2302 This method is considered obsolete.
2307 The default implementation in the base class does not process styles,
2308 color and alpha-blended fonts.
2316 *****************************************************************************************/
2318 VOID
BM__Hidd_BitMap__DrawText(OOP_Class
*cl
, OOP_Object
*obj
,
2319 struct pHidd_BitMap_DrawText
*msg
)
2322 OOP_Object
*gc
= msg
->gc
;
2323 struct TextFont
*font
= GC_FONT(gc
);
2324 UBYTE
*charPatternPtr
= font
->tf_CharData
;
2325 UWORD modulo
= font
->tf_Modulo
;
2327 UBYTE ch
; /* current character to print */
2328 WORD fx
, fx2
, fy
, fw
; /* position and length of character in the */
2329 /* character bitmap */
2330 WORD xMem
= msg
->x
; /* position in bitmap */
2331 WORD yMem
= msg
->y
- font
->tf_Baseline
;
2335 EnterFunc(bug("BitMap::DrawText()"));
2337 for(i
= 0; i
< msg
->length
; i
++)
2341 if((ch
< font
->tf_LoChar
) || (ch
> font
->tf_HiChar
))
2343 ch
= font
->tf_HiChar
- font
->tf_LoChar
+ 1;
2347 ch
= ch
- font
->tf_LoChar
;
2350 if(font
->tf_Flags
& FPF_PROPORTIONAL
)
2352 xMem
= xMem
+ ((UWORD
*) font
->tf_CharKern
)[ch
];
2355 charLog
= ((ULONG
*) font
->tf_CharLoc
)[ch
];
2356 fx2
= charLog
>> 16; /* x position of character pattern in character bitmap */
2357 fw
= (UWORD
) charLog
; /* width of character pattern in character bitmap */
2361 for(fy
= 0; fy
< font
->tf_YSize
; fy
++)
2365 for(fx
= fx2
; fx
< fw
+ fx2
; fx
++)
2367 if(*(charPatternPtr
+ fx
/ 8 + fy
* modulo
) & (128 >> (fx
% 8)))
2369 HIDD_BM_DrawPixel(obj
, msg
->gc
, x
, y
);
2377 if(font
->tf_Flags
& FPF_PROPORTIONAL
)
2379 xMem
= xMem
+ ((UWORD
*) font
->tf_CharSpace
)[ch
];
2383 xMem
= xMem
+ font
->tf_XSize
;
2387 ReturnVoid("BitMap::DrawText");
2390 /*****************************************************************************************
2393 moHidd_BitMap_FillText
2396 VOID OOP_DoMethod(OOP_Object *obj, struct pHidd_BitMap_DrawText *msg);
2398 VOID HIDD_BM_FillText (OOP_Object *obj, OOP_Object *gc, WORD x, WORD y,
2399 STRPTR text, UWORD length);
2402 hidd.graphics.bitmap
2405 Historically this method was designed to draw a text with background.
2406 It was never implemented.
2408 Currently this method is considered reserved. Its synopsis and semantics
2409 may change in future.
2412 obj - A bitmap to draw on
2413 gc - A GC object to use for drawing
2414 x, y - Position to start drawing in pixels. The x
2415 coordinate is relative to the left side of the
2417 The y coordinate is relative to the baseline of the font.
2418 text - Pointer to a Latin 1 string
2419 length - Number of characters to draw
2435 *****************************************************************************************/
2437 VOID
BM__Hidd_BitMap__FillText(OOP_Class
*cl
, OOP_Object
*obj
, struct pHidd_BitMap_DrawText
*msg
)
2439 D(bug("Sorry, FillText() not implemented yet in bitmap baseclass\n"));
2442 /*****************************************************************************************
2445 moHidd_BitMap_FillSpan
2448 VOID OOP_DoMethod(OOP_Object *obj, struct pHidd_BitMap_DrawText *msg);
2451 hidd.graphics.bitmap
2454 Reserved, never implemented method. The definition will change in future.
2473 *****************************************************************************************/
2475 VOID
BM__Hidd_BitMap__FillSpan(OOP_Class
*cl
, OOP_Object
*obj
, struct pHidd_BitMap_DrawText
*msg
)
2477 D(bug("Sorry, FillSpan() not implemented yet\n"));
2480 /*****************************************************************************************
2486 OOP_DoMethod(OOP_Object *obj, struct pHidd_BitMap_Clear *msg);
2488 VOID HIDD_BM_Clear (OOP_Object *obj, OOP_Object *gc);
2491 hidd.graphics.bitmap
2494 Sets all pixels of the drawing area to the background color.
2497 obj - A bitmap to clear.
2498 gc - A GC object, specifies background color value
2503 This method is not used by the system and considered reserved. However it can
2504 be useful for display driver's own needs.
2509 Default implementation in the base class sets all pixels to zero color instead of
2510 the background color from GC
2518 *****************************************************************************************/
2520 VOID
BM__Hidd_BitMap__Clear(OOP_Class
*cl
, OOP_Object
*obj
, struct pHidd_BitMap_Clear
*msg
)
2522 struct Library
*OOPBase
= CSD(cl
)->cs_OOPBase
;
2526 EnterFunc(bug("BitMap::Clear()\n"));
2528 OOP_GetAttr(obj
, aHidd_BitMap_Width
, &width
);
2529 OOP_GetAttr(obj
, aHidd_BitMap_Height
, &height
);
2531 for(y
= 0; y
< height
; y
++)
2533 for(x
= 0; x
< width
; x
++)
2535 HIDD_BM_PutPixel(obj
, x
, y
, 0);
2539 ReturnVoid("BitMap::Clear");
2542 /****************************************************************************************/
2544 static LONG
inline getpixfmtbpp(OOP_Class
*cl
, OOP_Object
*o
, HIDDT_StdPixFmt stdpf
)
2546 struct Library
*OOPBase
= CSD(cl
)->cs_OOPBase
;
2548 struct HIDDBitMapData
*data
;
2551 data
= OOP_INST_DATA(cl
, o
);
2555 case vHidd_StdPixFmt_Native
:
2556 OOP_GetAttr(data
->prot
.pixfmt
, aHidd_PixFmt_BytesPerPixel
, &bpp
);
2559 case vHidd_StdPixFmt_Native32
:
2560 bpp
= sizeof (HIDDT_Pixel
);
2564 pf
= HIDD_Gfx_GetPixFmt(data
->gfxhidd
, stdpf
);
2568 D(bug("!!! INVALID PIXFMT IN BitMap::PutImage(): %d !!!\n", stdpf
));
2572 OOP_GetAttr(pf
, aHidd_PixFmt_BytesPerPixel
, &bpp
);
2580 /*****************************************************************************************
2583 moHidd_BitMap_GetImage
2586 VOID OOP_DoMethod(OOP_Object *obj, struct pHidd_BitMap_GetImage *msg);
2588 VOID HIDD_BM_GetImage (OOP_Object *obj, UBYTE *pixels, ULONG modulo, WORD x, WORD y,
2589 WORD width, WORD height, HIDDT_StdPixFmt pixFmt);
2592 hidd.graphics.bitmap
2617 *****************************************************************************************/
2619 VOID
BM__Hidd_BitMap__GetImage(OOP_Class
*cl
, OOP_Object
*o
,
2620 struct pHidd_BitMap_GetImage
*msg
)
2623 UBYTE
*pixarray
= (UBYTE
*)msg
->pixels
;
2624 APTR ppixarray
= &pixarray
;
2626 struct HIDDBitMapData
*data
;
2628 data
= OOP_INST_DATA(cl
, o
);
2630 EnterFunc(bug("BitMap::GetImage(x=%d, y=%d, width=%d, height=%d)\n"
2631 , msg
->x
, msg
->y
, msg
->width
, msg
->height
));
2634 bpp
= getpixfmtbpp(cl
, o
, msg
->pixFmt
);
2637 D(bug("!!! INVALID PIXFMT IN BitMap::GetImage(): %d !!!\n", msg
->pixFmt
));
2644 case vHidd_StdPixFmt_Native
:
2645 case vHidd_StdPixFmt_Native32
:
2646 for (y
= 0; y
< msg
->height
; y
++)
2648 for (x
= 0; x
< msg
->width
; x
++)
2650 register HIDDT_Pixel pix
;
2652 pix
= HIDD_BM_GetPixel(o
, x
+ msg
->x
, y
+ msg
->y
);
2661 *((UWORD
*)pixarray
) = pix
;
2667 pixarray
[0] = (pix
>> 16) & 0xFF;
2668 pixarray
[1] = (pix
>> 8) & 0xFF;
2669 pixarray
[2] = pix
& 0xFF;
2671 pixarray
[0] = pix
& 0xFF;
2672 pixarray
[1] = (pix
>> 8) & 0xFF;
2673 pixarray
[2] = (pix
>> 16) & 0xFF;
2679 *(ULONG
*)pixarray
= pix
;
2686 pixarray
+= (msg
->modulo
- msg
->width
* bpp
);
2694 APTR buf
, srcPixels
;
2696 dstpf
= HIDD_Gfx_GetPixFmt(data
->gfxhidd
, msg
->pixFmt
);
2698 buf
= srcPixels
= AllocVec(msg
->width
* sizeof(HIDDT_Pixel
), MEMF_PUBLIC
);
2701 for(y
= 0; y
< msg
->height
; y
++)
2710 vHidd_StdPixFmt_Native
);
2712 HIDD_BM_ConvertPixels(o
,
2714 (HIDDT_PixelFormat
*)data
->prot
.pixfmt
,
2717 (HIDDT_PixelFormat
*)dstpf
,
2729 } /* switch(msg->pixFmt) */
2731 ReturnVoid("BitMap::GetImage");
2734 /*****************************************************************************************
2737 moHidd_BitMap_PutImage
2740 VOID OOP_DoMethod(OOP_Object *obj, struct pHidd_BitMap_PutImage *msg);
2742 VOID HIDD_BM_PutImage (OOP_Object *obj, OOP_Object *gc, UBYTE *pixels, ULONG modulo,
2743 WORD x, WORD y, WORD width, WORD height, HIDDT_StdPixFmt pixFmt);
2746 hidd.graphics.bitmap
2772 *****************************************************************************************/
2774 VOID
BM__Hidd_BitMap__PutImage(OOP_Class
*cl
, OOP_Object
*o
,
2775 struct pHidd_BitMap_PutImage
*msg
)
2778 UBYTE
*pixarray
= (UBYTE
*)msg
->pixels
;
2779 APTR ppixarray
= &pixarray
;
2782 struct HIDDBitMapData
*data
;
2783 OOP_Object
*gc
= msg
->gc
;
2785 data
= OOP_INST_DATA(cl
, o
);
2787 EnterFunc(bug("BitMap::PutImage(x=%d, y=%d, width=%d, height=%d)\n"
2788 , msg
->x
, msg
->y
, msg
->width
, msg
->height
));
2790 if (msg
->width
<= 0 || msg
->height
<= 0)
2793 bpp
= getpixfmtbpp(cl
, o
, msg
->pixFmt
);
2796 D(bug("!!! INVALID PIXFMT IN BitMap::PutImage(): %d !!!\n", msg
->pixFmt
));
2802 case vHidd_StdPixFmt_Native
:
2803 case vHidd_StdPixFmt_Native32
:
2805 /* Preserve old fg pen */
2808 for (y
= 0; y
< msg
->height
; y
++)
2810 for (x
= 0; x
< msg
->width
; x
++)
2812 register HIDDT_Pixel pix
= 0;
2817 pix
= *((UBYTE
*)pixarray
);
2822 pix
= *((UWORD
*)pixarray
);
2828 pix
= ((UBYTE
*)pixarray
)[0] << 16;
2829 pix
|= ((UBYTE
*)pixarray
)[1] << 8;
2830 pix
|= ((UBYTE
*)pixarray
)[2];
2832 pix
= ((UBYTE
*)pixarray
)[2] << 16;
2833 pix
|= ((UBYTE
*)pixarray
)[1] << 8;
2834 pix
|= ((UBYTE
*)pixarray
)[0];
2840 pix
= *((ULONG
*)pixarray
); pixarray
+= 4;
2847 HIDD_BM_DrawPixel(o
, gc
, x
+ msg
->x
, y
+ msg
->y
);
2849 pixarray
+= (msg
->modulo
- msg
->width
* bpp
);
2858 APTR buf
, destPixels
;
2860 srcpf
= HIDD_Gfx_GetPixFmt(data
->gfxhidd
, msg
->pixFmt
);
2862 buf
= destPixels
= AllocVec(msg
->width
* sizeof(HIDDT_Pixel
), MEMF_PUBLIC
);
2865 for(y
= 0; y
< msg
->height
; y
++)
2867 HIDD_BM_ConvertPixels(o
,
2869 (HIDDT_PixelFormat
*)srcpf
,
2872 (HIDDT_PixelFormat
*)data
->prot
.pixfmt
,
2886 vHidd_StdPixFmt_Native
);
2893 } /* switch(msg->pixFmt) */
2895 ReturnVoid("BitMap::PutImage");
2898 /****************************************************************************************/
2901 __attribute__((always_inline
, const)) do_alpha(int a
, int v
)
2904 return ((tmp
<<8) + tmp
+ 32768)>>16;
2909 #define RGB32_DECOMPOSE(red, green, blue, pix) \
2910 red = ((pix) & 0x00FF0000) >> 16; \
2911 green = ((pix) & 0x0000FF00) >> 8; \
2912 blue = ((pix) & 0x000000FF);
2914 #define ARGB32_ALPHA(pix) ((pix) & 0xFF000000)
2916 #define ARGB32_DECOMPOSE(alpha, red, green, blue, pix) \
2917 alpha = ((pix) & 0xFF000000) >> 24; \
2918 red = ((pix) & 0x00FF0000) >> 16; \
2919 green = ((pix) & 0x0000FF00) >> 8; \
2920 blue = ((pix) & 0x000000FF);
2922 #define ARGB32_COMPOSE(red, green, blue, old) (((old) & 0xFF000000) + ((red) << 16) + ((green) << 8) + (blue))
2926 #define RGB32_DECOMPOSE(red, green, blue, pix) \
2927 red = (pix & 0x0000FF00) >> 8; \
2928 green = (pix & 0x00FF0000) >> 16; \
2929 blue = (pix & 0xFF000000) >> 24
2931 #define ARGB32_ALPHA(pix) ((pix) & 0x000000FF)
2933 #define ARGB32_DECOMPOSE(alpha, red, green, blue, pix) \
2934 alpha = (pix & 0x000000FF); \
2935 red = (pix & 0x0000FF00) >> 8; \
2936 green = (pix & 0x00FF0000) >> 16; \
2937 blue = (pix & 0xFF000000) >> 24
2939 #define ARGB32_COMPOSE(red, green, blue, old) (((blue) << 24) + ((green) << 16) + ((red) << 8) + ((old) & 0x000000FF))
2943 /*****************************************************************************************
2946 moHidd_BitMap_PutAlphaImage
2949 VOID OOP_DoMethod(OOP_Object *obj, struct pHidd_BitMap_PutAlphaImage *msg);
2951 VOID HIDD_BM_PutAlphaImage (OOP_Object *obj, OOP_Object *gc, UBYTE *pixels, ULONG modulo,
2952 WORD x, WORD y, WORD width, WORD height);
2955 hidd.graphics.bitmap
2958 Perform an alpha-blending operation between a bitmap and ARGB pixel array.
2961 obj - A bitmap to operate on
2962 gc - A GC object, internally needed to perform the operation. All its attributes
2964 pixels - A pointer to an array of pixels
2965 modulo - Number of bytes per row in pixel array
2966 x, y - Top-left corner of affected bitmap's region
2967 width - Width of the modified rectangle.
2968 height - Height of the modified rectangle.
2974 Do not rely on 'gc' parameter being valid when implementing this method in own
2975 display driver. This parameter is actually obsolete, and will be set to NULL in
2976 future AROS versions. Current base class implementation ignores it.
2986 *****************************************************************************************/
2996 * 1. Merge buffered and slow versions of PutAlphaImage(), use the same processing algorithm
2997 * (convert array's pixels to bitmap's format, not vice versa)
2998 * 2. Make DoBufferedOperation() public, to be used for cybergraphics.library/ProcessPixelArray()
2999 * implementation, and for some other functions in graphics.library and cybergraphics.library,
3000 * currently using own implementation of pixel buffer.
3001 * 3. Reuse the new code for other buffered operations (currently using old macros).
3004 static void PutAlphaImageBuffered(ULONG
*xbuf
, UWORD starty
, UWORD width
, UWORD height
, struct paib_data
*data
)
3008 for (y
= 0; y
< height
; y
++)
3010 ULONG
*pixarray
= data
->pixels
;
3012 for (x
= 0; x
< width
; x
++)
3016 ULONG src_red
, src_green
, src_blue
, src_alpha
;
3017 ULONG dst_red
, dst_green
, dst_blue
;
3019 srcpix
= *pixarray
++;
3021 if (ARGB32_ALPHA(srcpix
) == ARGB32_ALPHA(0xFFFFFFFF))
3025 else if (ARGB32_ALPHA(srcpix
) != 0)
3027 ARGB32_DECOMPOSE(src_alpha
, src_red
, src_green
, src_blue
, srcpix
);
3030 RGB32_DECOMPOSE(dst_red
, dst_green
, dst_blue
, destpix
);
3032 dst_red
+= do_alpha(src_alpha
, src_red
- dst_red
);
3033 dst_green
+= do_alpha(src_alpha
, src_green
- dst_green
);
3034 dst_blue
+= do_alpha(src_alpha
, src_blue
- dst_blue
);
3036 xbuf
[x
] = ARGB32_COMPOSE(dst_red
, dst_green
, dst_blue
, destpix
);
3041 data
->pixels
+= data
->modulo
;
3045 VOID
BM__Hidd_BitMap__PutAlphaImage(OOP_Class
*cl
, OOP_Object
*o
,
3046 struct pHidd_BitMap_PutAlphaImage
*msg
)
3049 struct paib_data data
= {msg
->pixels
, msg
->modulo
};
3051 EnterFunc(bug("BitMap::PutAlphaImage(x=%d, y=%d, width=%d, height=%d)\n"
3052 , msg
->x
, msg
->y
, msg
->width
, msg
->height
));
3054 if (msg
->width
<= 0 || msg
->height
<= 0)
3057 if (!DoBufferedOperation(cl
, o
, msg
->x
, msg
->y
, msg
->width
, msg
->height
, TRUE
, vHidd_StdPixFmt_ARGB32
,
3058 (VOID_FUNC
)PutAlphaImageBuffered
, &data
))
3060 /* Buffered method failed, use slow pixel-by-pixel method */
3061 for (y
= msg
->y
; y
< msg
->y
+ msg
->height
; y
++)
3063 ULONG
*pixarray
= data
.pixels
;
3065 for (x
= msg
->x
; x
< msg
->x
+ msg
->width
; x
++)
3067 HIDDT_Pixel destpix
;
3070 LONG src_red
, src_green
, src_blue
, src_alpha
;
3071 LONG dst_red
, dst_green
, dst_blue
;
3073 destpix
= HIDD_BM_GetPixel(o
, x
, y
);
3074 HIDD_BM_UnmapPixel(o
, destpix
, &col
);
3076 srcpix
= *pixarray
++;
3077 ARGB32_DECOMPOSE(src_alpha
, src_red
, src_green
, src_blue
, srcpix
);
3079 dst_red
= col
.red
>> 8;
3080 dst_green
= col
.green
>> 8;
3081 dst_blue
= col
.blue
>> 8;
3083 dst_red
+= do_alpha(src_alpha
, src_red
- dst_red
);
3084 dst_green
+= do_alpha(src_alpha
, src_green
- dst_green
);
3085 dst_blue
+= do_alpha(src_alpha
, src_blue
- dst_blue
);
3087 col
.red
= dst_red
<< 8;
3088 col
.green
= dst_green
<< 8;
3089 col
.blue
= dst_blue
<< 8;
3091 HIDD_BM_PutPixel(o
, x
, y
, HIDD_BM_MapColor(o
, &col
));
3093 } /* for(x = msg->x; x < msg->x + msg->width; x++) */
3095 data
.pixels
+= msg
->modulo
;
3097 } /* for(y = msg->y; y < msg->y + msg->height; y++) */
3099 ReturnVoid("BitMap::PutAlphaImage");
3102 /*****************************************************************************************
3105 moHidd_BitMap_PutTemplate
3108 VOID OOP_DoMethod(OOP_Object *obj, struct pHidd_BitMap_PutTemplate *msg);
3110 VOID HIDD_BM_PutTemplate (OOP_Object *obj, OOP_Object *gc, UBYTE *masktemplate, ULONG modulo,
3111 WORD srcx, WORD x, WORD y, WORD width, WORD height, BOOL inverttemplate);
3114 hidd.graphics.bitmap
3117 Apply a single-bit mask to the given portion of the bitmap. Pixels set to 1 in the mask will be filled
3118 by foreground color. Pixels set to 0 in the mask will be filled by background color or left unchanged,
3119 according to the following GC attributes:
3120 Foreground - a foreground color
3121 Background - a background color
3122 DrawMode - if set to Invert, foreground and background colors will be ignored. Instead,
3123 pixels which are set to 1 in the mask, will be inverted. Other pixels will be
3125 ColorExpansion - if set to Transparent, only pixels which are set to 1 in the mask, will be modified.
3126 Other pixels will not be changed (background color will be ignored).
3129 obj - A bitmap to draw on
3130 gc - A GC object, holding operation parameters
3131 masktemplate - A pointer to a bit mask
3132 modulo - Number of bytes per line in the mask
3133 srcx - Horizontal offset of the mask
3134 x, y - Top-left corner of the bitmap's region to affect
3135 width - Width of the affected region
3136 height - Height of the affected region
3137 inverttemplate - If set to TRUE, bit mask will be interpreted in inverted form
3152 *****************************************************************************************/
3164 static void JAM1TemplateBuffered(ULONG
*xbuf
, UWORD starty
, UWORD width
, UWORD height
, struct ptb_data
*data
)
3168 for (y
= 0; y
< height
; y
++)
3170 ULONG mask
= data
->bitmask
;
3171 UWORD
*array
= data
->bitarray
;
3172 UWORD bitword
= AROS_BE2WORD(*array
);
3174 for (x
= 0; x
< width
; x
++)
3176 if ((bitword
& mask
) == (data
->invert
& mask
))
3184 bitword
= AROS_BE2WORD(*array
);
3189 data
->bitarray
+= data
->modulo
;
3193 static void ComplementTemplateBuffered(ULONG
*xbuf
, UWORD starty
, UWORD width
, UWORD height
, struct ptb_data
*data
)
3197 for (y
= 0; y
< height
; y
++)
3199 ULONG mask
= data
->bitmask
;
3200 UWORD
*array
= data
->bitarray
;
3201 UWORD bitword
= AROS_BE2WORD(*array
);
3203 for (x
= 0; x
< width
; x
++)
3205 if ((bitword
& mask
) == (data
->invert
& mask
))
3213 bitword
= AROS_BE2WORD(*array
);
3218 data
->bitarray
+= data
->modulo
;
3222 static void JAM2TemplateBuffered(ULONG
*xbuf
, UWORD starty
, UWORD width
, UWORD height
, struct ptb_data
*data
)
3226 for (y
= 0; y
< height
; y
++)
3228 ULONG mask
= data
->bitmask
;
3229 UWORD
*array
= data
->bitarray
;
3230 UWORD bitword
= AROS_BE2WORD(*array
);
3232 for (x
= 0; x
< width
; x
++)
3234 if ((bitword
& mask
) == (data
->invert
& mask
))
3244 bitword
= AROS_BE2WORD(*array
);
3249 data
->bitarray
+= data
->modulo
;
3253 VOID
BM__Hidd_BitMap__PutTemplate(OOP_Class
*cl
, OOP_Object
*o
, struct pHidd_BitMap_PutTemplate
*msg
)
3255 OOP_Object
*gc
= msg
->gc
;
3257 void (*op
)(ULONG
*, UWORD
, UWORD
, UWORD
, struct ptb_data
*);
3258 struct ptb_data data
;
3260 EnterFunc(bug("BitMap::PutTemplate(x=%d, y=%d, width=%d, height=%d)\n"
3261 , msg
->x
, msg
->y
, msg
->width
, msg
->height
));
3263 if (msg
->width
<= 0 || msg
->height
<= 0)
3266 if (GC_COLEXP(gc
) == vHidd_GC_ColExp_Transparent
)
3268 op
= JAM1TemplateBuffered
;
3270 else if (GC_DRMD(gc
) == vHidd_GC_DrawMode_Invert
)
3272 op
= ComplementTemplateBuffered
;
3276 op
= JAM2TemplateBuffered
;
3280 data
.bitarray
= msg
->masktemplate
+ ((msg
->srcx
/ 16) * 2);
3281 data
.bitmask
= 0x8000 >> (msg
->srcx
& 0xF);
3282 data
.modulo
= msg
->modulo
;
3283 data
.fg
= GC_FG(msg
->gc
);
3284 data
.bg
= GC_BG(msg
->gc
);
3285 data
.invert
= msg
->inverttemplate
? 0 : 0xFFFF;
3287 DoBufferedOperation(cl
, o
, msg
->x
, msg
->y
, msg
->width
, msg
->height
, get
, vHidd_StdPixFmt_Native32
, (VOID_FUNC
)op
, &data
);
3289 /* TODO: write fallback */
3291 ReturnVoid("BitMap::PutTemplate");
3294 /*****************************************************************************************
3297 moHidd_BitMap_PutAlphaTemplate
3300 VOID OOP_DoMethod(OOP_Object *obj, struct pHidd_BitMap_PutAlphaTemplate *msg);
3302 VOID HIDD_BM_PutAlphaTemplate (OOP_Object *obj, OOP_Object *gc, UBYTE *alpha, ULONG modulo,
3303 WORD x, WORD y, WORD width, WORD height, BOOL invertalpha);
3306 hidd.graphics.bitmap
3309 Perform a drawing with current foreground color, using 8-bit alpha channel mask. The following
3310 GC attributes are considered:
3311 Foreground - a foreground color
3312 Background - a background color
3313 DrawMode - if set to Invert, foreground and background colors will be ignored. Instead,
3314 pixels, for which alpha channel value is greater than 127, will be inverted.
3315 Other pixels will be left unchanged.
3316 ColorExpansion - if set to Opaque, alpha blending will happen between foreground and background
3317 colors, instead of between foreground color and old bitmap contents.
3320 obj - A bitmap to draw on
3321 gc - A GC object specifying drawing parameters
3322 alpha - A pointer to an 8-bit per pixel alpha channel mask
3323 modulo - Number of bytes per line in the mask
3324 x, y - Top-left corner of the affected bitmap's region
3325 width - Width of the affected bitmap's region
3326 height - Height of the affected bitmap's region
3327 invertalpha - If set to TRUE, alpha mask values will be treated in inverted form
3342 *****************************************************************************************/
3348 LONG a_red
, a_green
, a_blue
;
3349 LONG b_red
, b_green
, b_blue
;
3353 static void JAM1AlphaTemplateBuffered(ULONG
*xbuf
, UWORD starty
, UWORD width
, UWORD height
, struct patb_data
*data
)
3357 for (y
= 0; y
< height
; y
++)
3359 UBYTE
*pixarray
= data
->pixarray
;
3361 for (x
= 0; x
< width
; x
++)
3363 LONG dst_red
, dst_green
, dst_blue
, alpha
;
3365 alpha
= (*pixarray
++) ^ data
->invert
;
3366 RGB32_DECOMPOSE(dst_red
, dst_green
, dst_blue
, xbuf
[x
]);
3368 dst_red
+= do_alpha(alpha
, data
->a_red
- dst_red
);
3369 dst_green
+= do_alpha(alpha
, data
->a_green
- dst_green
);
3370 dst_blue
+= do_alpha(alpha
, data
->a_blue
- dst_blue
);
3372 xbuf
[x
] = ARGB32_COMPOSE(dst_red
, dst_green
, dst_blue
, 0);
3376 data
->pixarray
+= data
->modulo
;
3380 static void ComplementAlphaTemplateBuffered(ULONG
*xbuf
, UWORD starty
, UWORD width
, UWORD height
, struct patb_data
*data
)
3384 for (y
= 0; y
< height
; y
++)
3386 UBYTE
*pixarray
= data
->pixarray
;
3388 for (x
= 0; x
< width
; x
++)
3390 UBYTE alpha
= (*pixarray
++) ^ data
->invert
;
3397 data
->pixarray
+= data
->modulo
;
3401 static void JAM2AlphaTemplateBuffered(ULONG
*xbuf
, UWORD starty
, UWORD width
, UWORD height
, struct patb_data
*data
)
3405 for (y
= 0; y
< height
; y
++)
3407 UBYTE
*pixarray
= data
->pixarray
;
3409 for (x
= 0; x
< width
; x
++)
3411 LONG dst_red
, dst_green
, dst_blue
, alpha
;
3413 alpha
= (*pixarray
++) ^ data
->invert
;
3415 dst_red
= data
->b_red
+ ((data
->a_red
- data
->b_red
) * alpha
) / 256;
3416 dst_green
= data
->b_green
+ ((data
->a_green
- data
->b_green
) * alpha
) / 256;
3417 dst_blue
= data
->b_blue
+ ((data
->a_blue
- data
->b_blue
) * alpha
) / 256;
3419 xbuf
[x
] = ARGB32_COMPOSE(dst_red
, dst_green
, dst_blue
, 0);
3423 data
->pixarray
+= data
->modulo
;
3427 VOID
BM__Hidd_BitMap__PutAlphaTemplate(OOP_Class
*cl
, OOP_Object
*o
,
3428 struct pHidd_BitMap_PutAlphaTemplate
*msg
)
3430 OOP_Object
*gc
= msg
->gc
;
3432 void (*op
)(ULONG
*, UWORD
, UWORD
, UWORD
, struct patb_data
*);
3433 struct patb_data data
;
3436 EnterFunc(bug("BitMap::PutAlphaTemplate(x=%d, y=%d, width=%d, height=%d)\n"
3437 , msg
->x
, msg
->y
, msg
->width
, msg
->height
));
3439 if (msg
->width
<= 0 || msg
->height
<= 0)
3442 HIDD_BM_UnmapPixel(o
, GC_FG(gc
), &color
);
3443 data
.a_red
= color
.red
>> 8;
3444 data
.a_green
= color
.green
>> 8;
3445 data
.a_blue
= color
.blue
>> 8;
3447 if (GC_COLEXP(gc
) == vHidd_GC_ColExp_Transparent
)
3449 op
= JAM1AlphaTemplateBuffered
;
3451 else if (GC_DRMD(gc
) == vHidd_GC_DrawMode_Invert
)
3453 op
= ComplementAlphaTemplateBuffered
;
3457 op
= JAM2AlphaTemplateBuffered
;
3460 HIDD_BM_UnmapPixel(o
, GC_BG(gc
), &color
);
3461 data
.b_red
= color
.red
>> 8;
3462 data
.b_green
= color
.green
>> 8;
3463 data
.b_blue
= color
.blue
>> 8;
3466 data
.pixarray
= msg
->alpha
;
3467 data
.modulo
= msg
->modulo
;
3468 data
.invert
= msg
->invertalpha
? 255 : 0;
3470 DoBufferedOperation(cl
, o
, msg
->x
, msg
->y
, msg
->width
, msg
->height
, get
, vHidd_StdPixFmt_ARGB32
, (VOID_FUNC
)op
, &data
);
3472 /* TODO: write fallback */
3474 ReturnVoid("BitMap::PutAlphaTemplate");
3477 /*****************************************************************************************
3480 moHidd_BitMap_PutPattern
3483 VOID OOP_DoMethod(OOP_Object *o, struct pHidd_BitMap_PutPattern *msg);
3485 VOID HIDD_BM_PutPattern(OOP_Object *obj, OOP_Object *gc, UBYTE *pattern,
3486 WORD patternsrcx, WORD patternsrcy, WORD patternheight, WORD patterndepth,
3487 HIDDT_PixelLUT *patternlut, BOOL invertpattern, UBYTE *mask,
3488 ULONG maskmodulo, WORD masksrcx, WORD x, WORD y,
3489 WORD width, WORD height);
3492 hidd.graphics.bitmap
3497 obj - A bitmap to draw on
3498 gc - A GC object to use for drawing
3526 *****************************************************************************************/
3535 UWORD patternheight
;
3545 static void JAM1PatternBuffered(ULONG
*xbuf
, UWORD starty
, UWORD width
, UWORD height
, struct ppb_data
*data
)
3549 for (y
= 0; y
< height
; y
++)
3551 UWORD pmask
= data
->patmask
;
3552 UWORD mmask
= data
->maskmask
;
3553 UWORD
*parray
= data
->patarray
+ ((y
+ starty
+ data
->patternsrcy
- data
->desty
) % data
->patternheight
);
3554 UWORD patword
= AROS_BE2WORD(*parray
);
3555 UWORD
*marray
= data
->maskarray
;
3556 UWORD maskword
= marray
? AROS_BE2WORD(*marray
) : 0xFFFF;
3558 for (x
= 0; x
< width
; x
++)
3560 if (maskword
& mmask
)
3562 if ((patword
& pmask
) == (data
->invert
& pmask
))
3573 maskword
= AROS_BE2WORD(*marray
);
3584 if (data
->maskarray
)
3585 data
->maskarray
+= data
->maskmodulo
;
3590 static void ComplementPatternBuffered(ULONG
*xbuf
, UWORD starty
, UWORD width
, UWORD height
, struct ppb_data
*data
)
3594 for (y
= 0; y
< height
; y
++)
3596 UWORD pmask
= data
->patmask
;
3597 UWORD mmask
= data
->maskmask
;
3598 UWORD
*parray
= data
->patarray
+ ((y
+ starty
+ data
->patternsrcy
- data
->desty
) % data
->patternheight
);
3599 UWORD patword
= AROS_BE2WORD(*parray
);
3600 UWORD
*marray
= data
->maskarray
;
3601 UWORD maskword
= marray
? AROS_BE2WORD(*marray
) : 0xFFFF;
3603 for (x
= 0; x
< width
; x
++)
3605 if (maskword
& mmask
)
3607 if ((patword
& pmask
) == (data
->invert
& pmask
))
3618 maskword
= AROS_BE2WORD(*marray
);
3629 if (data
->maskarray
)
3630 data
->maskarray
+= data
->maskmodulo
;
3635 static void JAM2PatternBuffered(ULONG
*xbuf
, UWORD starty
, UWORD width
, UWORD height
, struct ppb_data
*data
)
3639 for (y
= 0; y
< height
; y
++)
3641 UWORD pmask
= data
->patmask
;
3642 UWORD mmask
= data
->maskmask
;
3643 UWORD
*parray
= data
->patarray
+ ((y
+ starty
+ data
->patternsrcy
- data
->desty
) % data
->patternheight
);
3644 UWORD patword
= AROS_BE2WORD(*parray
);
3645 UWORD
*marray
= data
->maskarray
;
3646 UWORD maskword
= marray
? AROS_BE2WORD(*marray
) : 0xFFFF;
3648 for (x
= 0; x
< width
; x
++)
3650 if (maskword
& mmask
)
3652 if ((patword
& pmask
) == (data
->invert
& pmask
))
3665 maskword
= AROS_BE2WORD(*marray
);
3676 if (data
->maskarray
)
3677 data
->maskarray
+= data
->maskmodulo
;
3682 static void ColorPatternBuffered(ULONG
*xbuf
, UWORD starty
, UWORD width
, UWORD height
, struct ppb_data
*data
)
3686 for (y
= 0; y
< height
; y
++)
3688 UWORD pmask
= data
->patmask
;
3689 UWORD mmask
= data
->maskmask
;
3690 UWORD
*parray
= data
->patarray
+ ((y
+ starty
+ data
->patternsrcy
- data
->desty
) % data
->patternheight
);
3691 UWORD patword
= AROS_BE2WORD(*parray
);
3692 UWORD
*marray
= data
->maskarray
;
3693 UWORD maskword
= marray
? AROS_BE2WORD(*marray
) : 0xFFFF;
3695 for (x
= 0; x
< width
; x
++)
3697 if (maskword
& mmask
)
3700 ULONG pixel
= (patword
& pmask
) ? 1 : 0; /* CHECKME: Shouldn't we handle INVERSVID here too ? */
3702 for (plane
= 1; plane
< data
->patterndepth
; plane
++)
3704 UWORD
*_parray
= parray
+ plane
* data
->patternheight
;
3705 UWORD _patword
= AROS_BE2WORD(*_parray
);
3707 if (_patword
& pmask
)
3708 pixel
|= 1L << plane
;
3711 if (data
->patternlut
)
3712 pixel
= data
->patternlut
[pixel
];
3724 maskword
= AROS_BE2WORD(*marray
);
3735 if (data
->maskarray
)
3736 data
->maskarray
+= data
->maskmodulo
;
3741 VOID
BM__Hidd_BitMap__PutPattern(OOP_Class
*cl
, OOP_Object
*o
,
3742 struct pHidd_BitMap_PutPattern
*msg
)
3744 void (*op
)(ULONG
*xbuf
, UWORD starty
, UWORD width
, UWORD height
, struct ppb_data
*data
);
3746 struct ppb_data data
;
3748 DPUTPATTERN(bug("BitMap::PutPattern(x=%d, y=%d, width=%d, height=%d)\n",
3749 msg
->x
, msg
->y
, msg
->width
, msg
->height
));
3751 if (msg
->width
<= 0 || msg
->height
<= 0)
3754 if (msg
->patterndepth
> 1)
3756 DPUTPATTERN(bug("[PutPattern] Color\n"));
3757 op
= ColorPatternBuffered
;
3760 else if (GC_COLEXP(msg
->gc
) == vHidd_GC_ColExp_Transparent
)
3762 DPUTPATTERN(bug("[PutPattern] JAM1\n"));
3763 op
= JAM1PatternBuffered
;
3765 else if (GC_DRMD(msg
->gc
) == vHidd_GC_DrawMode_Invert
)
3767 DPUTPATTERN(bug("[PutPattern] Complement\n"));
3768 op
= ComplementPatternBuffered
;
3772 DPUTPATTERN(bug("[PutPattern] JAM2\n"));
3773 op
= JAM2PatternBuffered
;
3777 data
.patarray
= (UWORD
*)msg
->pattern
;
3778 data
.patmask
= 0x8000 >> (msg
->patternsrcx
& 0xF);
3779 data
.maskarray
= msg
->mask
;
3780 data
.patternlut
= msg
->patternlut
? msg
->patternlut
->pixels
: NULL
;
3781 data
.patternsrcy
= msg
->patternsrcy
;
3782 data
.desty
= msg
->y
;
3783 data
.patternheight
= msg
->patternheight
;
3784 data
.patterndepth
= msg
->patterndepth
;
3785 data
.maskmodulo
= msg
->maskmodulo
;
3786 data
.fg
= GC_FG(msg
->gc
);
3787 data
.bg
= GC_BG(msg
->gc
);
3788 data
.invert
= msg
->invertpattern
? 0 : 0xFFFF;
3792 data
.maskarray
+= (msg
->masksrcx
/ 16) * 2;
3793 data
.maskmask
= 0x8000 >> (msg
->masksrcx
& 0xF);
3797 data
.maskmask
= 0xFFFF;
3799 DPUTPATTERN(bug("[PutPattern] MaskArray 0x%p, MaskMask 0x%04X\n", data
.maskarray
, data
.maskmask
));
3801 DoBufferedOperation(cl
, o
, msg
->x
, msg
->y
, msg
->width
, msg
->height
, get
, vHidd_StdPixFmt_Native32
, (VOID_FUNC
)op
, &data
);
3803 /* TODO: Write fallback */
3805 ReturnVoid("BitMap::PutPattern");
3808 /*****************************************************************************************
3811 moHidd_BitMap_PutImageLUT
3814 VOID OOP_DoMethod(OOP_Object *o, struct pHidd_BitMap_PutImageLUT *msg);
3816 VOID HIDD_BM_PutImageLUT (OOP_Object *obj, OOP_Object *gc, UBYTE *pixels, ULONG modulo,
3817 WORD x, WORD y, WORD width, WORD height, HIDDT_PixelLUT *pixlut);
3820 hidd.graphics.bitmap
3846 *****************************************************************************************/
3848 VOID
BM__Hidd_BitMap__PutImageLUT(OOP_Class
*cl
, OOP_Object
*o
,
3849 struct pHidd_BitMap_PutImageLUT
*msg
)
3852 UBYTE
*pixarray
= (UBYTE
*)msg
->pixels
;
3853 HIDDT_PixelLUT
*pixlut
= msg
->pixlut
;
3854 HIDDT_Pixel
*lut
= pixlut
? pixlut
->pixels
: NULL
;
3855 HIDDT_Pixel
*linebuf
;
3856 OOP_Object
*gc
= msg
->gc
;
3858 EnterFunc(bug("BitMap::PutImageLUT(x=%d, y=%d, width=%d, height=%d)\n"
3859 , msg
->x
, msg
->y
, msg
->width
, msg
->height
));
3861 if (msg
->width
<= 0 || msg
->height
<= 0)
3864 linebuf
= AllocVec(msg
->width
* sizeof(HIDDT_Pixel
), MEMF_PUBLIC
);
3866 for(y
= 0; y
< msg
->height
; y
++)
3872 for(x
= 0; x
< msg
->width
; x
++)
3874 linebuf
[x
] = lut
[pixarray
[x
]];
3879 for(x
= 0; x
< msg
->width
; x
++)
3881 linebuf
[x
] = pixarray
[x
];
3884 pixarray
+= msg
->modulo
;
3894 vHidd_StdPixFmt_Native32
);
3896 } /* if (linebuf) */
3901 /* Preserve old fg pen */
3906 for(x
= 0; x
< msg
->width
; x
++)
3908 GC_FG(gc
) = lut
[pixarray
[x
]];
3909 HIDD_BM_DrawPixel(o
, gc
, msg
->x
+ x
, msg
->y
+ y
);
3914 for(x
= 0; x
< msg
->width
; x
++)
3916 GC_FG(gc
) = pixarray
[x
];
3917 HIDD_BM_DrawPixel(o
, gc
, msg
->x
+ x
, msg
->y
+ y
);
3922 pixarray
+= msg
->modulo
;
3924 } /* if (linebuf) else ... */
3926 } /* for(y = 0; y < msg->height; y++) */
3930 ReturnVoid("BitMap::PutImageLUT");
3932 /*****************************************************************************************
3935 moHidd_BitMap_PutTranspImageLUT
3938 VOID OOP_DoMethod(OOP_Object *obj, struct pHidd_BitMap_PutTranspImageLUT *msg);
3940 VOID HIDD_BM_PutTranspImageLUT (OOP_Object *obj, OOP_Object *gc, UBYTE *pixels,
3941 ULONG modulo, WORD x, WORD y, WORD width, WORD height,
3942 HIDDT_PixelLUT *pixlut, UBYTE transparent);
3945 hidd.graphics.bitmap
3948 Copy an array of 8-bit LUT pixels to the bitmap at the specified position making
3949 one of colors transparent.
3951 Pixels are converted to bitmap's native format using either user-supplied LUT (if
3952 given) or bitmap's own colormap.
3954 Draw mode of the supplied GC is ignored, the operation is always bulk copy.
3957 obj - A bitmap to draw image on
3958 gc - A GC used for drawing
3959 pixels - A pointer to source pixel array
3960 modulo - Total number of bytes per line in the source array
3961 x, y - Top-left corner of the destination rectangle
3962 width - Width of the image to draw
3963 height - Height of the image to draw
3964 pixlut - An optional pointer to a LUT to use. NULL means using bitmap's
3965 own colormap (if available)
3966 transparent - Value of pixels in the source array which will be made
3982 *****************************************************************************************/
3984 #undef csd /* Bad hack, but there's no other way */
3991 struct class_static_data
*csd
;
3996 static void PutTranspImageLUTBuffered(ULONG
*xbuf
, UWORD starty
, UWORD width
, UWORD height
, struct ptilb_data
*data
)
3998 struct class_static_data
*csd
= data
->csd
;
4001 for (y
= 0; y
< height
; y
++)
4003 UBYTE
*pixarray
= data
->pixarray
;
4007 for (x
= 0; x
< width
; x
++)
4009 UBYTE pix
= *pixarray
++;
4011 if (pix
!= data
->transparent
)
4012 xbuf
[x
] = data
->lut
[pix
];
4018 for (x
= 0; x
< width
; x
++)
4020 UBYTE pix
= *pixarray
++;
4022 if (pix
!= data
->transparent
)
4025 pix
= HIDD_CM_GetPixel(data
->colmap
, pix
);
4034 data
->pixarray
+= data
->modulo
;
4038 VOID
BM__Hidd_BitMap__PutTranspImageLUT(OOP_Class
*cl
, OOP_Object
*o
,
4039 struct pHidd_BitMap_PutTranspImageLUT
*msg
)
4041 struct HIDDBitMapData
*data
= OOP_INST_DATA(cl
, o
);
4042 struct ptilb_data userdata
=
4052 EnterFunc(bug("BitMap::PutTranspImageLUT(x=%d, y=%d, width=%d, height=%d)\n"
4053 , msg
->x
, msg
->y
, msg
->width
, msg
->height
));
4055 if (msg
->width
<= 0 || msg
->height
<= 0)
4059 userdata
.lut
= msg
->pixlut
->pixels
;
4061 DoBufferedOperation(cl
, o
, msg
->x
, msg
->y
, msg
->width
, msg
->height
, TRUE
, vHidd_StdPixFmt_Native32
,
4062 (VOID_FUNC
)PutTranspImageLUTBuffered
, &userdata
);
4064 /* TODO: Write fallback */
4066 ReturnVoid("BitMap::PutTranspImageLUT");
4071 /*****************************************************************************************
4074 moHidd_BitMap_GetImageLUT
4077 VOID OOP_DoMethod(OOP_Object *obj, struct pHidd_BitMap_GetImageLUT *msg);
4079 VOID HIDD_BM_GetImageLUT (OOP_Object *obj, UBYTE *pixels, ULONG modulo, WORD x, WORD y,
4080 WORD width, WORD height, HIDDT_PixelLUT *pixlut);
4083 hidd.graphics.bitmap
4108 *****************************************************************************************/
4110 VOID
BM__Hidd_BitMap__GetImageLUT(OOP_Class
*cl
, OOP_Object
*o
,
4111 struct pHidd_BitMap_GetImageLUT
*msg
)
4114 UBYTE
*pixarray
= (UBYTE
*)msg
->pixels
;
4115 HIDDT_PixelLUT
*pixlut
= msg
->pixlut
;
4116 HIDDT_Pixel
*lut
= pixlut
? pixlut
->pixels
: NULL
;
4117 HIDDT_Pixel
*linebuf
;
4119 EnterFunc(bug("BitMap::GetImageLUT(x=%d, y=%d, width=%d, height=%d)\n"
4120 , msg
->x
, msg
->y
, msg
->width
, msg
->height
));
4122 linebuf
= AllocVec(msg
->width
* sizeof(HIDDT_Pixel
), MEMF_PUBLIC
);
4124 for(y
= 0; y
< msg
->height
; y
++)
4135 vHidd_StdPixFmt_Native32
);
4138 /* FIXME: This is wrong, but HIDD_BM_GetImageLUT on hi/truecolor screens does not really make sense anyway */
4139 for(x
= 0; x
< msg
->width
; x
++)
4141 pixarray
[x
] = (UBYTE
)linebuf
[x
];
4146 for(x
= 0; x
< msg
->width
; x
++)
4148 pixarray
[x
] = (UBYTE
)linebuf
[x
];
4151 pixarray
+= msg
->modulo
;
4153 } /* if (linebuf) */
4158 /* FIXME: This is wrong, but HIDD_BM_GetImageLUT on hi/truecolor screens does not really make sense anyway */
4159 for(x
= 0; x
< msg
->width
; x
++)
4161 pixarray
[x
] = (UBYTE
)HIDD_BM_GetPixel(o
, msg
->x
+ x
, msg
->y
+ y
);
4166 for(x
= 0; x
< msg
->width
; x
++)
4168 pixarray
[x
] = (UBYTE
)HIDD_BM_GetPixel(o
, msg
->x
+ x
, msg
->y
+ y
);
4172 pixarray
+= msg
->modulo
;
4174 } /* if (linebuf) else ... */
4176 } /* for(y = 0; y < msg->height; y++) */
4180 ReturnVoid("BitMap::GetImageLUT");
4183 /*****************************************************************************************
4186 moHidd_BitMap_BlitColorExpansion
4189 VOID OOP_DoMethod(OOP_Object *obj, struct pHidd_BitMap_BlitColorExpansion *msg);
4191 VOID HIDD_BM_BlitColorExpansion (OOP_Object *obj, OOP_Object *gc, OOP_Object *srcBitMap,
4192 WORD srcX, WORD srcY, WORD destX, WORD destY,
4193 UWORD width, UWORD height);
4196 hidd.graphics.bitmap
4199 Perform a color expansion of the mask in srcBitMap according to foreground and background
4200 colors and expansion mode specified by the supplied GC. Pixels which are set to zero in
4201 the mask bitmap will be either painted by background (in opaque mode) or left without
4202 change (in transparent mode). Pixels which are set to nonzero in the mask will be painted
4203 by foreground color.
4205 The result of expansion is blitted onto the destination bitmap accorging to GC's draw mode.
4208 obj - A bitmap to draw on
4209 gc - A GC object to use for drawing
4210 srcBitMap - A bitmap object containing mask image.
4211 srcX, srcY - A top-left coordinate of the used rectangle in the source bitmap
4212 destX, destY - A top-left coordinate of the destination rectangle to draw in
4213 width, height - A size of the rectangle to blit
4219 This method was previously used by graphics.library/Text() to draw fonts with no
4220 styles specified. Currently graphics.library always uses BltTemplate() and this
4221 method is considered obsolete.
4231 *****************************************************************************************/
4233 VOID
BM__Hidd_BitMap__BlitColorExpansion(OOP_Class
*cl
, OOP_Object
*o
,
4234 struct pHidd_BitMap_BlitColorExpansion
*msg
)
4241 OOP_Object
*gc
= msg
->gc
;
4243 EnterFunc(bug("BitMap::BlitColorExpansion(srcBM=%p, srcX=%d, srcY=%d, destX=%d, destY=%d, width=%d, height=%d)\n",
4244 msg
->srcBitMap
, msg
->srcX
, msg
->srcY
, msg
->destX
, msg
->destY
, msg
->width
, msg
->height
));
4246 cemd
= GC_COLEXP(gc
);
4250 /* bug("------------- Blit_ColExp: (%d, %d, %d, %d, %d, %d) cemd=%d, fg=%p, bg=%p -------------\n"
4251 , msg->srcX, msg->srcY, msg->destX, msg->destY, msg->width, msg->height
4254 for (y
= 0; y
< msg
->height
; y
++)
4256 for (x
= 0; x
< msg
->width
; x
++)
4260 /* Pixel value is either 0 or 1 for BM of depth 1 */
4261 is_set
= HIDD_BM_GetPixel(msg
->srcBitMap
, x
+ msg
->srcX
, y
+ msg
->srcY
);
4271 HIDD_BM_DrawPixel(o
, gc
, x
+ msg
->destX
, y
+ msg
->destY
);
4275 if (cemd
& vHidd_GC_ColExp_Opaque
)
4277 /* Write bixel with BG pen */
4279 HIDD_BM_DrawPixel(o
, gc
, x
+ msg
->destX
, y
+ msg
->destY
);
4280 /* Reset to FG pen */
4286 } /* for (each x) */
4290 } /* for ( each y ) */
4293 ReturnVoid("BitMap::BlitColorExpansion");
4296 /*****************************************************************************************
4299 moHidd_BitMap_BytesPerLine
4302 ULONG OOP_DoMethod(OOP_Object *obj, struct pHidd_BitMap_BytesPerLine *msg);
4304 ULONG HIDD_BM_BytesPerLine(OOP_Object *obj, HIDDT_StdPixFmt pixFmt, UWORD width);
4307 hidd.graphics.bitmap
4310 This method is currently not used and reserved.
4329 *****************************************************************************************/
4331 ULONG
BM__Hidd_BitMap__BytesPerLine(OOP_Class
*cl
, OOP_Object
*o
, struct pHidd_BitMap_BytesPerLine
*msg
)
4336 switch (msg
->pixFmt
)
4338 case vHidd_StdPixFmt_Native32
:
4339 bpl
= sizeof (HIDDT_Pixel
) * msg
->width
;
4342 case vHidd_StdPixFmt_Native
:
4344 struct HIDDBitMapData
*data
;
4346 data
= OOP_INST_DATA(cl
, o
);
4348 bpl
= ((HIDDT_PixelFormat
*)data
->prot
.pixfmt
)->bytes_per_pixel
* msg
->width
;
4355 struct HIDDBitMapData
*data
;
4357 data
= OOP_INST_DATA(cl
, o
);
4359 pf
= HIDD_Gfx_GetPixFmt(data
->gfxhidd
, msg
->pixFmt
);
4363 D(bug("!!! COULD NOT GET STD PIXFMT IN BitMap::BytesPerLine() !!!\n"));
4367 bpl
= ((HIDDT_PixelFormat
*)pf
)->bytes_per_pixel
* msg
->width
;
4379 /****************************************************************************************/
4382 This makes it easier to create a subclass of the graphics hidd.
4383 It is only allowed to use this method in the p_RootNew method of a
4387 /****************************************************************************************/
4389 IPTR
BM__Root__Set(OOP_Class
*cl
, OOP_Object
*obj
, struct pRoot_Set
*msg
)
4391 struct Library
*UtilityBase
= CSD(cl
)->cs_UtilityBase
;
4392 struct Library
*OOPBase
= CSD(cl
)->cs_OOPBase
;
4393 struct HIDDBitMapData
*data
= OOP_INST_DATA(cl
, obj
);
4394 struct TagItem
*tag
, *tstate
;
4396 WORD xoffset
, yoffset
, limit
;
4398 if (data
->framebuffer
)
4401 * If this is a framebuffer, we can process ModeID change.
4402 * We do it before parsing the rest of tags, because here we retrieve
4403 * defaults for new bitmap parameters (size and pixelformat).
4404 * They can be overriden by other tags. For example we can imagine
4405 * a hardware scrollable framebuffer whose width and height are larger
4406 * than visible part.
4408 HIDDT_ModeID modeid
= GetTagData(aHidd_BitMap_ModeID
, vHidd_ModeID_Invalid
, msg
->attrList
);
4409 OOP_Object
*sync
, *pixfmt
;
4411 if (HIDD_Gfx_GetMode(data
->gfxhidd
, modeid
, &sync
, &pixfmt
))
4413 data
->modeid
= modeid
;
4415 * Set defaults based on the ModeID.
4416 * They can be overriden lated, in SetBitMapTags.
4418 data
->width
= OOP_GET(sync
, aHidd_Sync_HDisp
);
4419 data
->height
= OOP_GET(sync
, aHidd_Sync_VDisp
);
4420 data
->bytesPerRow
= GetBytesPerRow(data
, CSD(cl
));
4421 data
->prot
.pixfmt
= pixfmt
;
4425 /* Bad ModeID given, request rejected */
4429 /* Process the rest of tags. */
4430 BM__Hidd_BitMap__SetBitMapTags(cl
, obj
, msg
->attrList
);
4435 * This is not a framebuffer.
4436 * We can modify size data (CHECKME: is it really used anywhere ?)
4437 * and also we can scroll (makes sense only if this is displayable
4438 * bitmap in mirrored framebuffer mode.
4440 BM__Hidd_BitMap__SetBitMapTags(cl
, obj
, msg
->attrList
);
4443 * And now we process position change.
4444 * One trick: we store our 'display' rectangle in bitmap's coordinates.
4445 * In other words, these are screen coordinates relative to bitmap, not
4446 * bitmap's ones relative to screen. As a result, we have to invert the sign.
4447 * This is done in order to simplify calculations in UpdateBitMap method of
4448 * graphics base class. It needs to perform intersection of update rectangle
4449 * with display rectangle, and they need to be in the same coordinate system
4450 * in order to be able to do this.
4451 * Update operation is performance-critical, so we perform this conversion
4452 * for display rectangle here.
4454 xoffset
= data
->display
.MinX
;
4455 yoffset
= data
->display
.MinY
;
4456 tstate
= msg
->attrList
;
4457 while ((tag
= NextTagItem(&tstate
)))
4459 Hidd_BitMap_Switch(tag
->ti_Tag
, idx
)
4461 case aoHidd_BitMap_LeftEdge
:
4462 xoffset
= -tag
->ti_Data
;
4465 * Our bitmap can not be smaller than display size because of fakegfx.hidd
4466 * limitations (it can't place cursor beyond bitmap edges). Otherwize Intuition
4467 * will provide strange user experience (mouse cursor will disappear)
4469 limit
= data
->width
- data
->displayWidth
;
4472 else if (xoffset
> limit
)
4474 D(bug("[BitMap] xoffset requested %ld, got %d\n", -tag
->ti_Data
, xoffset
));
4477 case aoHidd_BitMap_TopEdge
:
4478 yoffset
= -tag
->ti_Data
;
4479 limit
= data
->height
- data
->displayHeight
;
4482 else if (yoffset
> limit
)
4484 D(bug("[BitMap] yoffset requested %ld, got %d\n", -tag
->ti_Data
, yoffset
));
4489 if ((xoffset
!= data
->display
.MinX
) || (yoffset
!= data
->display
.MinY
))
4491 ObtainSemaphore(&data
->lock
);
4493 data
->display
.MinX
= xoffset
;
4494 data
->display
.MinY
= yoffset
;
4495 data
->display
.MaxX
= xoffset
+ data
->displayWidth
;
4496 data
->display
.MaxY
= yoffset
+ data
->displayHeight
;
4500 GFX__Hidd_Gfx__UpdateFB(CSD(cl
)->gfxhiddclass
, data
->gfxhidd
,
4501 obj
, data
->display
.MinX
, data
->display
.MinY
,
4502 0, 0, data
->displayWidth
, data
->displayHeight
);
4505 ReleaseSemaphore(&data
->lock
);
4509 /* There's no superclass above us */
4513 /*****************************************************************************************
4516 moHidd_BitMap_SetColorMap
4519 OOP_Object * OOP_DoMethod(OOP_Object *obj, struct pHidd_BitMap_SetColorMap *msg);
4521 OOP_Object * HIDD_BM_SetColorMap(OOP_Object *obj, OOP_Object *colorMap);
4524 hidd.graphics.bitmap
4544 *****************************************************************************************/
4546 OOP_Object
*BM__Hidd_BitMap__SetColorMap(OOP_Class
*cl
, OOP_Object
*o
,
4547 struct pHidd_BitMap_SetColorMap
*msg
)
4549 struct HIDDBitMapData
*data
;
4552 data
= OOP_INST_DATA(cl
, o
);
4555 data
->colmap
= msg
->colorMap
;
4560 /*****************************************************************************************
4563 moHidd_BitMap_MapColor
4566 HIDDT_Pixel OOP_DoMethod(OOP_Object *obj, struct pHidd_BitMap_MapColor *msg);
4568 HIDDT_Pixel HIDD_BM_MapColor(OOP_Object *obj, HIDDT_Color *color);
4571 hidd.graphics.bitmap
4591 *****************************************************************************************/
4593 /* We only care about magnitudes here, so we don't
4594 * have to perform the square root operation to get
4595 * the real distance.
4597 static ULONG
colorDistance(HIDDT_Color
*a
, HIDDT_Color
*b
)
4599 #define SQR(x) ((x) * (x))
4600 return SQR((int)a
->red
- (int)b
->red
) +
4601 SQR((int)a
->blue
- (int)b
->blue
) +
4602 SQR((int)a
->green
- (int)b
->green
) +
4603 SQR((int)a
->alpha
- (int)b
->alpha
);
4607 HIDDT_Pixel
BM__Hidd_BitMap__MapColor(OOP_Class
*cl
, OOP_Object
*o
,
4608 struct pHidd_BitMap_MapColor
*msg
)
4610 HIDDT_PixelFormat
*pf
= BM_PIXFMT(o
);
4612 HIDDT_Pixel red
= msg
->color
->red
;
4613 HIDDT_Pixel green
= msg
->color
->green
;
4614 HIDDT_Pixel blue
= msg
->color
->blue
;
4615 HIDDT_Pixel alpha
= msg
->color
->alpha
;
4617 /* This code assumes that sizeof(HIDDT_Pixel) is a multiple of sizeof(col->#?),
4618 which should be true for most (all?) systems. I have never heard
4619 of any system with for example 3 byte types.
4622 if (IS_TRUECOLOR(pf
))
4624 if (HIDD_PF_SWAPPIXELBYTES(pf
))
4626 /* FIXME: BM__Hidd_BitMap__MapColor assuming that SwapPixelBytes flag only set for 2-byte/16-bit pixel formats */
4628 HIDDT_Pixel pixel
= MAP_RGBA(red
, green
, blue
, alpha
, pf
);
4630 msg
->color
->pixval
= SWAPBYTES_WORD(pixel
);
4634 msg
->color
->pixval
= MAP_RGBA(red
, green
, blue
, alpha
, pf
);
4639 struct HIDDBitMapData
*data
= OOP_INST_DATA(cl
, o
);
4641 HIDDT_ColorLUT
*cmap
;
4643 ULONG best_ndx
= ~0, best_dist
= ~0;
4645 cmap
= (HIDDT_ColorLUT
*)data
->colmap
;
4646 ctab
= cmap
->colors
;
4647 /* Search for the best match in the color table */
4648 for (i
= 0; i
< cmap
->entries
; i
++) {
4651 dist
= colorDistance(&ctab
[i
], msg
->color
);
4652 if (dist
< best_dist
) {
4658 if (best_dist
!= ~0)
4659 msg
->color
->pixval
= ctab
[best_ndx
].pixval
;
4662 return msg
->color
->pixval
;
4665 /*****************************************************************************************
4668 moHidd_BitMap_UnmapPixel
4671 VOID OOP_DoMethod(OOP_Object *obj, struct pHidd_BitMap_UnmapPixel *msg);
4673 VOID HIDD_BM_UnmapPixel(OOP_Object *obj, HIDDT_Pixel pixel, HIDDT_Color *color);
4676 hidd.graphics.bitmap
4697 *****************************************************************************************/
4699 VOID
BM__Hidd_BitMap__UnmapPixel(OOP_Class
*cl
, OOP_Object
*o
, struct pHidd_BitMap_UnmapPixel
*msg
)
4702 HIDDT_PixelFormat
*pf
= BM_PIXFMT(o
);
4704 if (IS_TRUECOLOR(pf
))
4706 HIDDT_Pixel pixel
= msg
->pixel
;
4708 if (HIDD_PF_SWAPPIXELBYTES(pf
))
4710 /* FIXME: bitmap_unmappixel assuming that SwapPixelBytes flag only set for 2-byte/16-bit pixel formats */
4711 pixel
= SWAPBYTES_WORD(pixel
);
4714 msg
->color
->red
= RED_COMP (pixel
, pf
);
4715 msg
->color
->green
= GREEN_COMP (pixel
, pf
);
4716 msg
->color
->blue
= BLUE_COMP (pixel
, pf
);
4717 msg
->color
->alpha
= ALPHA_COMP (pixel
, pf
);
4721 struct HIDDBitMapData
*data
= OOP_INST_DATA(cl
, o
);
4722 HIDDT_ColorLUT
*clut
;
4724 clut
= (HIDDT_ColorLUT
*)data
->colmap
;
4728 /* FIXME: Use CLUT shift and CLUT mask here */
4729 if (msg
->pixel
< 0 || msg
->pixel
>= clut
->entries
)
4732 *msg
->color
= clut
->colors
[msg
->pixel
];
4736 /* Unnecessary, but... */
4737 msg
->color
->pixval
= msg
->pixel
;
4740 /*****************************************************************************************
4743 moHidd_BitMap_ObtainDirectAccess
4746 BOOL OOP_DoMethod(OOP_Object *obj, struct pHidd_BitMap_ObtainDirectAccess *msg);
4748 BOOL HIDD_BM_ObtainDirectAccess(OOP_Object *obj, UBYTE **addressReturn,
4749 ULONG *widthReturn, ULONG *heightReturn,
4750 ULONG *bankSizeReturn, ULONG *memSizeReturn);
4753 hidd.graphics.bitmap
4778 *****************************************************************************************/
4780 BOOL
BM__Hidd_BitMap__ObtainDirectAccess(OOP_Class
*cl
, OOP_Object
*o
,
4781 struct pHidd_BitMap_ObtainDirectAccess
*msg
)
4783 /* Default implementation of direct access funcs. Just return FALSE */
4787 /*****************************************************************************************
4790 moHidd_BitMap_ReleaseDirectAccess
4793 VOID OOP_DoMethod(OOP_Object *obj, struct pHidd_BitMap_ReleaseDirectAccess *msg);
4795 VOID HIDD_BM_ReleaseDirectAccess(OOP_Object *obj);
4798 hidd.graphics.bitmap
4817 *****************************************************************************************/
4819 VOID
BM__Hidd_BitMap__ReleaseDirectAccess(OOP_Class
*cl
, OOP_Object
*o
,
4820 struct pHidd_BitMap_ReleaseDirectAccess
*msg
)
4822 D(bug("!!! BitMap BaseClasse ReleaseDirectAccess() called !!!\n"));
4823 D(bug("!!! This should never happen and is probably due to a buggy implementation in the subclass !!!\n"));
4828 /*****************************************************************************************
4831 moHidd_BitMap_BitMapScale
4834 VOID OOP_DoMethod(OOP_Object *obj, struct pHidd_BitMap_BitMapScale * msg);
4836 VOID HIDD_BM_BitMapScale(OOP_Object *obj, OOP_Object *src, OOP_Object *dest,
4837 struct BitScaleArgs * bsa, OOP_Object *gc);
4840 hidd.graphics.bitmap
4863 *****************************************************************************************/
4865 VOID
BM__Hidd_BitMap__BitMapScale(OOP_Class
* cl
, OOP_Object
*o
,
4866 struct pHidd_BitMap_BitMapScale
* msg
)
4868 struct BitScaleArgs
*bsa
= msg
->bsa
;
4869 ULONG
*srcbuf
, *dstbuf
;
4873 UWORD ys
= bsa
->bsa_SrcY
;
4874 UWORD xs
= bsa
->bsa_SrcX
;
4875 UWORD dyd
= bsa
->bsa_DestHeight
;
4876 UWORD dxd
= bsa
->bsa_DestWidth
;
4879 UWORD dxs
= bsa
->bsa_SrcWidth
;
4880 UWORD dys
= bsa
->bsa_SrcHeight
;
4881 LONG accuyd
= - (dys
>> 1);
4882 LONG accuxd
= - (dxs
>> 1);
4885 if ((srcbuf
= AllocVec(bsa
->bsa_SrcWidth
* sizeof(ULONG
), 0)) == NULL
)
4888 if ((dstbuf
= AllocVec(bsa
->bsa_DestWidth
* sizeof(ULONG
), 0)) == NULL
) {
4893 if ((linepattern
= (UWORD
*) AllocVec(bsa
->bsa_DestWidth
* sizeof(UWORD
), 0)) == NULL
) {
4900 while (count
< bsa
->bsa_DestWidth
) {
4902 while (accuxd
> accuxs
) {
4907 linepattern
[count
] = xs
;
4912 count
= bsa
->bsa_DestY
;
4913 while (count
< bsa
->bsa_DestHeight
+ bsa
->bsa_DestY
) {
4915 while (accuyd
> accuys
) {
4920 if (srcline
!= ys
) {
4921 HIDD_BM_GetImage(msg
->src
, (UBYTE
*) srcbuf
, bsa
->bsa_SrcWidth
* sizeof(ULONG
), bsa
->bsa_SrcX
, bsa
->bsa_SrcY
+ ys
, bsa
->bsa_SrcWidth
, 1, vHidd_StdPixFmt_Native32
);
4924 for (x
= 0; x
< bsa
->bsa_DestWidth
; x
++)
4925 dstbuf
[x
] = srcbuf
[linepattern
[x
]];
4928 HIDD_BM_PutImage(msg
->dst
, msg
->gc
, (UBYTE
*) dstbuf
, bsa
->bsa_DestWidth
* sizeof(ULONG
), bsa
->bsa_DestX
, count
, bsa
->bsa_DestWidth
, 1, vHidd_StdPixFmt_Native32
);
4933 FreeVec(linepattern
);
4939 /*****************************************************************************************
4942 moHidd_BitMap_SetRGBConversionFunction
4945 HIDDT_RGBConversionFunction
4946 OOP_DoMethod(OOP_Object *obj, struct pHidd_BitMap_SetRGBConversionFunction *msg);
4948 HIDDT_RGBConversionFunction
4949 HIDD_BM_SetRGBConversionFunction(OOP_Object *obj, HIDDT_StdPixFmt srcPixFmt,
4950 HIDDT_StdPixFmt dstPixFmt,
4951 HIDDT_RGBConversionFunction function);
4954 hidd.graphics.bitmap
4972 *****************************************************************************************/
4974 HIDDT_RGBConversionFunction
BM__Hidd_BitMap__SetRGBConversionFunction(OOP_Class
* cl
, OOP_Object
*o
,
4975 struct pHidd_BitMap_SetRGBConversionFunction
* msg
)
4977 HIDDT_RGBConversionFunction old
;
4979 if ((msg
->srcPixFmt
< FIRST_RGB_STDPIXFMT
) ||
4980 (msg
->dstPixFmt
< FIRST_RGB_STDPIXFMT
) ||
4981 (msg
->srcPixFmt
> LAST_RGB_STDPIXFMT
) ||
4982 (msg
->dstPixFmt
> LAST_RGB_STDPIXFMT
))
4984 return (HIDDT_RGBConversionFunction
)-1;
4988 ObtainSemaphore(&CSD(cl
)->rgbconvertfuncs_sem
);
4989 old
= CSD(cl
)->rgbconvertfuncs
[msg
->srcPixFmt
- FIRST_RGB_STDPIXFMT
][msg
->dstPixFmt
- FIRST_RGB_STDPIXFMT
];
4990 CSD(cl
)->rgbconvertfuncs
[msg
->srcPixFmt
- FIRST_RGB_STDPIXFMT
][msg
->dstPixFmt
- FIRST_RGB_STDPIXFMT
] = msg
->function
;
4991 ReleaseSemaphore(&CSD(cl
)->rgbconvertfuncs_sem
);
4997 /*****************************************************************************************
5000 moHidd_BitMap_UpdateRect
5003 VOID OOP_DoMethod(OOP_Object *obj, struct pHidd_BitMap_UpdateRect *msg);
5005 VOID HIDD_BM_UpdateRect(OOP_Object *obj, WORD x, WORD y, WORD width, WORD height);
5008 hidd.graphics.bitmap
5011 Update displayed image of the given rectangle.
5013 Some drivers (like VGA and VESA) may work not with VRAM directly, but with a mirrored
5014 copy of it. Usually it is done in case if VRAM reading is slow. This method is called
5015 by the system after it completes any drawing operation, in order to make sure that
5016 changes made are visible on the actual screen. If your driver uses mirroring, this method
5017 should copy the given rectangle (at least) from the mirror buffer to the actual VRAM.
5019 This method is also called after changing currently visible bitmap (after moHidd_Gfx_Show
5020 method call) in order to allow the mirroring driver to refresh the screen after current bitmap
5021 changed. Note that moHidd_Gfx_ShowViewPorts is very different and moHidd_BitMap_UpdateRect
5022 will not be called if it succeeded!
5025 obj - an object whose image to refresh
5026 x, y - A top-left edge of the rectangle to refresh
5027 width - Width of the rectangle to refresh
5028 height - Height of the rectangle to refresh
5034 This method is called also on offscreen bitmaps. You should track visible state of your bitmap
5035 and ignore these calls if it's not currently visible on the screen.
5045 *****************************************************************************************/
5047 VOID
BM__Hidd_BitMap__UpdateRect(OOP_Class
*cl
, OOP_Object
*o
, struct pHidd_BitMap_UpdateRect
*msg
)
5049 struct HIDDBitMapData
*data
= OOP_INST_DATA(cl
, o
);
5051 DUPDATE(bug("[BitMap] UpdateRect(0x%p, %d, %d, %d, %d)\n", o
, msg
->x
, msg
->y
, msg
->width
, msg
->height
));
5054 * We check data->visible twice in order to avoid unnecessary locking
5055 * when our bitmap is not on display (it may be not displayable at all).
5056 * However the second check is still needed in order to make sure that
5057 * this bitmap is still on display, because we could be preempted between
5058 * the test and ObtainSemaphoreShared() by concurrently running Show() call.
5059 * We use shared lock because it's safe to have two concurrently running
5060 * updates even on the same region.
5064 ObtainSemaphoreShared(&data
->lock
);
5069 * Complete update rectangle.
5070 * Display rectangle is already in bitmap's coordinates.
5072 UWORD srcX
= msg
->x
;
5073 UWORD srcY
= msg
->y
;
5074 UWORD xLimit
= srcX
+ msg
->width
;
5075 UWORD yLimit
= srcY
+ msg
->height
;
5077 /* Intersect rectangles */
5078 if (data
->display
.MinX
> srcX
)
5079 srcX
= data
->display
.MinX
;
5080 if (data
->display
.MinY
> srcY
)
5081 srcY
= data
->display
.MinY
;
5082 if (data
->display
.MaxX
< xLimit
)
5083 xLimit
= data
->display
.MaxX
;
5084 if (data
->display
.MaxY
< yLimit
)
5085 yLimit
= data
->display
.MaxY
;
5087 /* Update the intersection region, if any */
5088 if ((xLimit
> srcX
) && (yLimit
> srcY
))
5090 GFX__Hidd_Gfx__UpdateFB(CSD(cl
)->gfxhiddclass
, data
->gfxhidd
,
5092 srcX
- data
->display
.MinX
, srcY
- data
->display
.MinY
,
5093 xLimit
- srcX
, yLimit
- srcY
);
5097 ReleaseSemaphore(&data
->lock
);
5101 /****************************************************************************************/
5104 * Private methods follow.
5105 * They are implemented as non-virtual, for speed up.
5108 /* This is a private form of Set method. Doesn't need a standard message. */
5109 void BM__Hidd_BitMap__SetBitMapTags(OOP_Class
*cl
, OOP_Object
*o
, struct TagItem
*bitMapTags
)
5111 struct Library
*UtilityBase
= CSD(cl
)->cs_UtilityBase
;
5112 struct HIDDBitMapData
*data
= OOP_INST_DATA(cl
, o
);
5113 struct TagItem
*tag
;
5115 while ((tag
= NextTagItem(&bitMapTags
)))
5119 if (IS_BITMAP_ATTR(tag
->ti_Tag
, idx
))
5123 case aoHidd_BitMap_Width
:
5124 data
->width
= tag
->ti_Data
;
5127 case aoHidd_BitMap_Height
:
5128 data
->height
= tag
->ti_Data
;
5131 case aoHidd_BitMap_BytesPerRow
:
5132 data
->bytesPerRow
= tag
->ti_Data
;
5135 case aoHidd_BitMap_Compositable
:
5136 data
->compositable
= tag
->ti_Data
;
5137 if (data
->compositable
)
5139 HIDDT_ModeID compositmodeid
;
5140 struct Library
*OOPBase
= csd
->cs_OOPBase
;
5144 OOP_GetAttr(data
->friend, aHidd_BitMap_ModeID
, &compositmodeid
);
5147 compositmodeid
= data
->modeid
;
5149 if (compositmodeid
== vHidd_ModeID_Invalid
)
5151 data
->compositable
= FALSE
;
5155 OOP_Object
*sync
, *pf
;
5157 if (!HIDD_Gfx_GetMode(data
->gfxhidd
, compositmodeid
, &sync
, &pf
))
5159 data
->compositable
= FALSE
;
5163 /* Get display size from the modeid */
5164 OOP_GetAttr(sync
, aHidd_Sync_HDisp
, &data
->displayWidth
);
5165 OOP_GetAttr(sync
, aHidd_Sync_VDisp
, &data
->displayHeight
);
5166 data
->display
.MaxX
= data
->displayWidth
;
5167 data
->display
.MaxY
= data
->displayHeight
;
5169 D(bug("[BitMap] Bitmap %dx%d, display %dx%d\n", data
->width
, data
->height
, data
->display
.width
, data
->display
.height
));
5179 * Updates bitmap's pixelformat.
5180 * Used from within planarbm subclass, and would be extremely dangerous to expose
5181 * as setable aHidd_BitMap_PixFmt, so implemented as a separate method.
5183 void BM__Hidd_BitMap__SetPixFmt(OOP_Class
*cl
, OOP_Object
*o
, OOP_Object
*pf
)
5185 struct HIDDBitMapData
*data
= OOP_INST_DATA(cl
, o
);
5187 /* Already a pixfmt registered? */
5188 if (data
->pf_registered
)
5189 GFX__Hidd_Gfx__ReleasePixFmt(CSD(cl
)->gfxhiddclass
, data
->prot
.pixfmt
);
5191 /* Remember the new pixelformat */
5192 data
->prot
.pixfmt
= pf
;
5195 * This pixelformat was obtained using GFX__Hidd_Gfx__RegisterPixFmt().
5196 * It increases number of pixfmt users, so we'll need to release it when
5197 * not used any more.
5199 data
->pf_registered
= TRUE
;
5203 * Change visible state of the bitmap.
5204 * Used in mirrored framebuffer mode. Actually needed because
5205 * of semaphore barrier, which makes sure that bitmap state does
5206 * not change during scrolling or updating operation. Prevents possibilities
5207 * of screen corruption during concurrently running scrolling with Show.
5209 void BM__Hidd_BitMap__SetVisible(OOP_Class
*cl
, OOP_Object
*o
, BOOL val
)
5211 struct HIDDBitMapData
*data
= OOP_INST_DATA(cl
, o
);
5213 ObtainSemaphore(&data
->lock
);
5214 data
->visible
= val
;
5215 ReleaseSemaphore(&data
->lock
);