typo
[AROS.git] / rom / hidds / graphics / BM_Class.c
blobc33c6b9e99144ad9159bce29dbeacd908f53fc3f
1 /*
2 Copyright © 1995-2013, The AROS Development Team. All rights reserved.
3 $Id$
5 Desc: Graphics bitmap class implementation.
6 Lang: english
7 */
9 /****************************************************************************************/
11 #define SDEBUG 0
12 #define DEBUG 0
13 #define DPUTPATTERN(x)
14 #define DUPDATE(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>
22 #include <oop/oop.h>
23 #include <oop/static_mid.h>
24 #include <graphics/text.h>
25 #include <graphics/scale.h>
26 #include <hidd/graphics.h>
28 #include <string.h>
29 #include <stdlib.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 /*****************************************************************************************
44 NAME
45 --background_bitmap--
47 LOCATION
48 hidd.graphics.bitmap
50 NOTES
51 Every display driver should implement at least one bitmap class for displayable
52 bitmaps.
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
67 implementation:
69 Displayable bitmap -
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
76 passed.
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 */
88 ULONG bufsize;
89 UWORD endy = starty + height;
90 UWORD y;
91 UBYTE *buf;
93 if (buflines == 0)
94 buflines = 1;
95 else if (buflines > height)
96 buflines = height;
98 bufsize = buflines * bytesperline;
99 buf = AllocMem(bufsize, MEMF_PUBLIC);
100 if (!buf && (buflines > 1))
102 /* Try to allocate single-line buffer */
103 buflines = 1;
104 bufsize = bytesperline;
105 buf = AllocMem(bufsize, MEMF_PUBLIC);
107 if (!buf)
108 return FALSE;
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 */
115 buflines = endy - y;
118 if (getimage)
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);
130 return TRUE;
133 /*****************************************************************************************
135 NAME
136 aoHidd_BitMap_Width
138 SYNOPSIS
139 [ISG], UWORD
141 LOCATION
142 hidd.graphics.bitmap
144 FUNCTION
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.
151 NOTES
153 EXAMPLE
155 BUGS
157 SEE ALSO
158 aoHidd_BitMap_Height
160 INTERNALS
162 *****************************************************************************************/
164 /*****************************************************************************************
166 NAME
167 aoHidd_BitMap_Height
169 SYNOPSIS
170 [ISG], UWORD
172 LOCATION
173 hidd.graphics.bitmap
175 FUNCTION
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.
182 NOTES
184 EXAMPLE
186 BUGS
188 SEE ALSO
189 aoHidd_BitMap_Width
191 INTERNALS
193 *****************************************************************************************/
195 /*****************************************************************************************
197 NAME
198 aoHidd_BitMap_Displayable
200 SYNOPSIS
201 [I.G], BOOL
203 LOCATION
204 hidd.graphics.bitmap
206 FUNCTION
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
211 to FALSE.
213 NOTES
215 EXAMPLE
217 BUGS
219 SEE ALSO
220 aoHidd_BitMap_ModeID
222 INTERNALS
224 *****************************************************************************************/
226 /*****************************************************************************************
228 NAME
229 aoHidd_BitMap_Visible
231 SYNOPSIS
232 [..G], BOOL
234 LOCATION
235 hidd.graphics.bitmap
237 FUNCTION
238 Check if the bitmap is currently visible on screen
240 NOTES
242 EXAMPLE
244 BUGS
245 Not all display drivers implement this attribute. No AROS components currently rely
246 on its value.
248 SEE ALSO
250 INTERNALS
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 /*****************************************************************************************
259 NAME
260 aoHidd_BitMap_IsLinearMem
262 SYNOPSIS
263 [..G], BOOL
265 LOCATION
266 hidd.graphics.bitmap
268 FUNCTION
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.
276 NOTES
277 Used by cybergraphics.library/GetCyberMapAttr() for providing CYBRMATTR_ISLINEARMEM
278 value.
280 EXAMPLE
282 BUGS
283 Currently no display drivers implement this attribute despite many native mode
284 drivers actually provide linear memory.
286 SEE ALSO
287 moHidd_BitMap_ObtainDirectAccess, moHidd_BitMap_ReleaseDirectAccess,
288 moHidd_BitMap_UpdateRect
290 INTERNALS
292 *****************************************************************************************/
294 /*****************************************************************************************
296 NAME
297 aoHidd_BitMap_BytesPerRow
299 SYNOPSIS
300 [ISG], ULONG
302 LOCATION
303 hidd.graphics.bitmap
305 FUNCTION
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.
317 NOTES
318 The returned value includes possible padding needed for alignment.
320 EXAMPLE
322 BUGS
324 SEE ALSO
325 aoHidd_BitMap_Align
327 INTERNALS
329 *****************************************************************************************/
331 /*****************************************************************************************
333 NAME
334 aoHidd_BitMap_ColorMap
336 SYNOPSIS
337 [..G], OOP_Object *
339 LOCATION
340 hidd.graphics.bitmap
342 FUNCTION
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.
352 NOTES
354 EXAMPLE
356 BUGS
358 SEE ALSO
359 moHidd_BitMap_SetColorMap, moHidd_BitMap_SetColors.
361 INTERNALS
363 *****************************************************************************************/
365 /*****************************************************************************************
367 NAME
368 aoHidd_BitMap_Friend
370 SYNOPSIS
371 [I.G], OOP_Object *
373 LOCATION
374 hidd.graphics.bitmap
376 FUNCTION
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
385 the friendship).
387 NOTES
389 EXAMPLE
391 BUGS
393 SEE ALSO
395 INTERNALS
397 *****************************************************************************************/
399 /*****************************************************************************************
401 NAME
402 aoHidd_BitMap_GfxHidd
404 SYNOPSIS
405 [I.G], OOP_Object *
407 LOCATION
408 hidd.graphics.bitmap
410 FUNCTION
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.
422 NOTES
424 EXAMPLE
426 BUGS
428 SEE ALSO
429 CLID_Hidd_Gfx/moHidd_Gfx_NewBitMap
431 INTERNALS
433 *****************************************************************************************/
435 /*****************************************************************************************
437 NAME
438 aoHidd_BitMap_StdPixFmt
440 SYNOPSIS
441 [I..], HIDDT_StdPixFmt
443 LOCATION
444 hidd.graphics.bitmap
446 FUNCTION
447 Specify standard pixelformat code (one of vHidd_StdPixFmt_... values) for the
448 bitmap.
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.
456 NOTES
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.
462 EXAMPLE
464 BUGS
466 SEE ALSO
467 aoHidd_BitMap_PixFmt, CLID_Hidd_Gfx/moHidd_Gfx_NewBitMap
469 INTERNALS
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 /*****************************************************************************************
483 NAME
484 aoHidd_BitMap_PixFmt
486 SYNOPSIS
487 [I.G], OOP_Object *
489 LOCATION
490 hidd.graphics.bitmap
492 FUNCTION
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.
498 NOTES
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.
503 EXAMPLE
505 BUGS
507 SEE ALSO
509 INTERNALS
511 *****************************************************************************************/
513 /*****************************************************************************************
515 NAME
516 aoHidd_BitMap_ModeID
518 SYNOPSIS
519 [ISG], HIDDT_ModeID
521 LOCATION
522 hidd.graphics.bitmap
524 FUNCTION
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.
537 NOTES
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
541 will be changed.
543 EXAMPLE
545 BUGS
547 SEE ALSO
549 INTERNALS
551 *****************************************************************************************/
553 /*****************************************************************************************
555 NAME
556 aoHidd_BitMap_ClassPtr
558 SYNOPSIS
559 [I..], OOP_Class *
561 LOCATION
562 hidd.graphics.bitmap
564 FUNCTION
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.
575 NOTES
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).
580 EXAMPLE
582 BUGS
584 SEE ALSO
585 aoHidd_BitMap_ClassID, CLID_Hidd_Gfx/moHidd_Gfx_NewBitMap
587 INTERNALS
589 *****************************************************************************************/
591 /*****************************************************************************************
593 NAME
594 aoHidd_BitMap_ClassID
596 SYNOPSIS
597 [I..]
599 LOCATION
600 hidd.graphics.bitmap
602 FUNCTION
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
611 of friend bitmap.
613 NOTES
615 EXAMPLE
617 BUGS
618 The pointer to a given class will not be remembered as aoHidd_BitMap_ClassPtr value.
620 SEE ALSO
621 aoHidd_BitMap_ClassPtr, CLID_Hidd_Gfx/moHidd_Gfx_NewBitMap
623 INTERNALS
625 *****************************************************************************************/
627 /*****************************************************************************************
629 NAME
630 aoHidd_BitMap_PixFmtTags
632 SYNOPSIS
633 [...]
635 LOCATION
636 hidd.graphics.bitmap
638 FUNCTION
639 Private, very obsolete and currently has no function. Considered reserved.
641 NOTES
643 EXAMPLE
645 BUGS
647 SEE ALSO
649 INTERNALS
651 *****************************************************************************************/
653 /*****************************************************************************************
655 NAME
656 aoHidd_BitMap_FrameBuffer
658 SYNOPSIS
659 [I.G], BOOL
661 LOCATION
662 hidd.graphics.bitmap
664 FUNCTION
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
671 to TRUE.
673 NOTES
675 EXAMPLE
677 BUGS
679 SEE ALSO
681 INTERNALS
683 *****************************************************************************************/
685 /*****************************************************************************************
687 NAME
688 aoHidd_BitMap_LeftEdge
690 SYNOPSIS
691 [.SG]
693 LOCATION
694 hidd.graphics.bitmap
696 FUNCTION
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.
713 NOTES
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).
718 EXAMPLE
720 BUGS
722 SEE ALSO
723 aoHidd_BitMap_TopEdge
725 INTERNALS
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 /*****************************************************************************************
734 NAME
735 aoHidd_BitMap_TopEdge
737 SYNOPSIS
738 [.SG]
740 LOCATION
741 hidd.graphics.bitmap
743 FUNCTION
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.
760 NOTES
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).
765 EXAMPLE
767 BUGS
769 SEE ALSO
771 INTERNALS
773 *****************************************************************************************/
775 /*****************************************************************************************
777 NAME
778 aoHidd_BitMap_Align
780 SYNOPSIS
781 [I.G]
783 LOCATION
784 hidd.graphics.bitmap
786 FUNCTION
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
791 value.
793 Direct specification of aoHidd_BitMap_BytesPerRow attribute overrides any value
794 of this attribute.
796 NOTES
797 Default value of this attribute is 16. This alignment is required by graphics.library
798 for AmigaOS(tm) compatibility reasons.
800 EXAMPLE
802 BUGS
804 SEE ALSO
805 aoHidd_BitMap_BytesPerRow
807 INTERNALS
809 *****************************************************************************************/
811 /*****************************************************************************************
813 NAME
814 aoHidd_BitMap_Depth
816 SYNOPSIS
817 [G.I]
819 LOCATION
820 hidd.graphics.bitmap
822 FUNCTION
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.
831 NOTES
833 EXAMPLE
835 BUGS
837 SEE ALSO
839 INTERNALS
841 *****************************************************************************************/
843 /****************************************************************************************/
845 #undef csd
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
866 * be changed to 0 ?
868 return width >> 3;
870 else
872 return width * bytesperpixel;
876 #define csd CSD(cl)
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);
887 if (NULL != obj)
889 struct TagItem colmap_tags[] =
891 { aHidd_ColorMap_NumEntries , 16 },
892 { TAG_DONE }
894 struct TagItem *tag, *tstate;
895 BOOL ok = TRUE;
896 struct HIDDBitMapData *data = OOP_INST_DATA(cl, obj);
898 /* Set some default values */
899 data->modeid = vHidd_ModeID_Invalid;
900 data->align = 16;
902 data->compositable = FALSE;
904 tstate = msg->attrList;
905 while ((tag = NextTagItem(&tstate)))
907 ULONG idx;
909 if (IS_BITMAP_ATTR(tag->ti_Tag, idx))
911 switch (idx)
913 case aoHidd_BitMap_BMStruct:
914 data->bmstruct = (struct BitMap *)tag->ti_Data;
915 break;
917 case aoHidd_BitMap_Width:
918 data->width = tag->ti_Data;
919 break;
921 case aoHidd_BitMap_Height:
922 data->height = tag->ti_Data;
923 break;
925 case aoHidd_BitMap_Align:
926 data->align = tag->ti_Data;
927 break;
929 case aoHidd_BitMap_BytesPerRow:
930 data->bytesPerRow = tag->ti_Data;
931 break;
933 case aoHidd_BitMap_GfxHidd:
934 data->gfxhidd = (OOP_Object *)tag->ti_Data;
935 break;
937 case aoHidd_BitMap_Friend:
938 data->friend = (OOP_Object *)tag->ti_Data;
939 break;
941 case aoHidd_BitMap_Displayable:
942 data->displayable = tag->ti_Data;
943 break;
945 case aoHidd_BitMap_Compositable:
946 data->compositable = tag->ti_Data;
947 break;
949 case aoHidd_BitMap_FrameBuffer:
950 data->framebuffer = tag->ti_Data;
951 break;
953 case aoHidd_BitMap_ModeID:
954 data->modeid = tag->ti_Data;
955 break;
957 case aoHidd_BitMap_PixFmt:
958 data->prot.pixfmt = (OOP_Object *)tag->ti_Data;
959 break;
964 /* aoHidd_BitMap_GfxHidd is mandatory */
965 if (!data->gfxhidd)
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"));
972 ok = FALSE;
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;
995 else
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;
1004 else
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 */
1013 if (!data->width)
1014 data->width = data->displayWidth;
1015 if (!data->height)
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;
1027 } /* if (ok) */
1029 if (ok)
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)
1040 ok = FALSE;
1042 else
1044 /* Otherwise we have what we calculated */
1045 data->bytesPerRow = bytesPerRow;
1050 if (ok)
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
1060 * these functions.
1062 #if USE_FAST_PUTPIXEL
1063 data->putpixel = OOP_GetMethod(obj, HiddBitMapBase + moHidd_BitMap_PutPixel, &data->putpixel_Class);
1064 #endif
1065 #if USE_FAST_GETPIXEL
1066 data->getpixel = OOP_GetMethod(obj, HiddBitMapBase + moHidd_BitMap_GetPixel, &data->getpixel_Class);
1067 #endif
1068 #if USE_FAST_DRAWPIXEL
1069 data->drawpixel = OOP_GetMethod(obj, HiddBitMapBase + moHidd_BitMap_DrawPixel, &data->drawpixel_Class);
1070 #endif
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)
1095 ok = FALSE;
1100 if (!ok)
1102 ULONG dispose_mid = OOP_GetMethodID(IID_Root, moRoot_Dispose);
1104 OOP_CoerceMethod(cl, obj, &dispose_mid);
1105 obj = NULL;
1107 } /* if(obj) */
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);
1142 ULONG idx;
1144 EnterFunc(bug("BitMap::Get() attrID: %i storage: %p\n", msg->attrID, msg->storage));
1146 if (IS_BITMAP_ATTR(msg->attrID, idx))
1148 switch(idx)
1150 case aoHidd_BitMap_BMStruct:
1151 *msg->storage = (IPTR)data->bmstruct;
1152 return;
1154 case aoHidd_BitMap_Width:
1155 *msg->storage = data->width;
1156 D(bug(" width: %i\n", data->width));
1157 return;
1159 case aoHidd_BitMap_Height:
1160 *msg->storage = data->height;
1161 return;
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;
1169 return;
1171 case aoHidd_BitMap_Displayable:
1172 *msg->storage = data->displayable;
1173 return;
1175 case aoHidd_BitMap_FrameBuffer:
1176 *msg->storage = data->framebuffer;
1177 return;
1179 case aoHidd_BitMap_PixFmt:
1180 *msg->storage = (IPTR)data->prot.pixfmt;
1181 return;
1183 case aoHidd_BitMap_Friend:
1184 *msg->storage = (IPTR)data->friend;
1185 return;
1187 case aoHidd_BitMap_ColorMap:
1188 *msg->storage = (IPTR)data->colmap;
1189 return;
1191 case aoHidd_BitMap_GfxHidd:
1192 *msg->storage = (IPTR)data->gfxhidd;
1193 return;
1195 case aoHidd_BitMap_ModeID:
1196 *msg->storage = data->modeid;
1197 return;
1199 case aoHidd_BitMap_Align:
1200 *msg->storage = data->align;
1201 return;
1203 case aoHidd_BitMap_BytesPerRow:
1204 *msg->storage = data->bytesPerRow;
1205 return;
1207 case aoHidd_BitMap_Visible:
1208 /* Framebuffer is always visible */
1209 *msg->storage = data->framebuffer ? TRUE : data->visible;
1210 return;
1212 case aoHidd_BitMap_Compositable:
1213 *msg->storage = (IPTR)data->compositable;
1214 return;
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;
1222 return;
1224 case aoHidd_BitMap_TopEdge:
1225 *msg->storage = -data->display.MinY;
1226 return;
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 /*****************************************************************************************
1242 NAME
1243 moHidd_BitMap_SetColors
1245 SYNOPSIS
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);
1251 LOCATION
1252 hidd.graphics.bitmap
1254 FUNCTION
1255 Sets values for one or more colors in the colormap object associated with the
1256 bitmap.
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.
1263 INPUTS
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
1269 RESULT
1270 TRUE on success, FALSE in case of some error (like out of memory)
1272 NOTES
1274 EXAMPLE
1276 BUGS
1278 SEE ALSO
1279 CLID_Hidd_ColorMap/moHidd_ColorMap_SetColors
1281 INTERNALS
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);
1290 BOOL ret = TRUE;
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 },
1301 { TAG_DONE }
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)
1310 return FALSE;
1313 /* Use the colormap class to set the colors */
1314 if (!HIDD_CM_SetColors(data->colmap, msg->colors,
1315 msg->firstColor, msg->numColors,
1316 data->prot.pixfmt))
1318 return FALSE;
1321 /* We may need to duplicate changes on framebuffer if running in mirrored mode */
1322 if (data->visible)
1324 ObtainSemaphoreShared(&data->lock);
1326 if (data->visible)
1328 ret = GFX__Hidd_Gfx__SetFBColors(CSD(cl)->gfxhiddclass, data->gfxhidd, msg);
1331 ReleaseSemaphore(&data->lock);
1334 return ret;
1337 /*******************************************************************************
1339 NAME
1340 moHidd_BitMap_PutPixel
1342 SYNOPSIS
1343 VOID OOP_DoMethod(OOP_Object *obj, struct pHidd_BitMap_PutPixel *msg);
1345 VOID HIDD_BM_PutPixel(OOP_Object *obj, WORD x, WORD y,
1346 HIDDT_Pixel pixel);
1348 LOCATION
1349 hidd.graphics.bitmap
1351 FUNCTION
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.
1356 INPUTS
1357 obj - bitmap to write to.
1358 x, y - coordinates of the pixel to write.
1359 pixel - the pixel's new color value.
1361 RESULT
1362 None.
1364 NOTES
1366 EXAMPLE
1368 BUGS
1370 SEE ALSO
1372 INTERNALS
1374 *******************************************************************************/
1376 /* PutPixel must be implemented in a subclass */
1378 /*****************************************************************************************
1380 NAME
1381 moHidd_BitMap_DrawPixel
1383 SYNOPSIS
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);
1388 LOCATION
1389 hidd.graphics.bitmap
1391 FUNCTION
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.
1396 INPUTS
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
1401 RESULT
1402 None.
1404 NOTES
1406 EXAMPLE
1408 BUGS
1410 SEE ALSO
1412 INTERNALS
1414 TODO
1415 - Support for shapeplane.
1416 - Optimize
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;
1426 OOP_Object *gc;
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
1432 unchanged
1434 data->colMask = 001111
1435 dest = 101100
1438 writeMask = ~data->colMask & dest
1439 = 110000 & 101100
1440 = 100000
1442 dest = data->fg && dest = 010100
1445 dest = dest & (writeMask | data->ColMask)
1446 = 010100 & (100000 | 001111)
1447 = 010100 & (101111)
1448 = 000100
1451 dest = dest | writeMask;
1452 = 000100 100000
1453 = 100100
1457 gc = msg->gc;
1459 src = GC_FG(gc);
1460 mode = GC_DRMD(gc);
1462 #if OPTIMIZE_DRAWPIXEL_FOR_COPY
1463 if (vHidd_GC_DrawMode_Copy == mode && GC_COLMASK(gc) == ~0)
1465 val = src;
1467 else
1468 #endif
1470 dest = GETPIXEL(cl, obj, msg->x, msg->y);
1471 writeMask = ~GC_COLMASK(gc) & dest;
1473 val = 0;
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 /*****************************************************************************************
1489 NAME
1490 moHidd_BitMap_DrawLine
1492 SYNOPSIS
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,
1496 WORD x2, WORD y2);
1498 LOCATION
1499 hidd.graphics.bitmap
1501 FUNCTION
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.
1505 INPUTS
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
1511 RESULT
1512 None.
1514 NOTES
1516 EXAMPLE
1518 BUGS
1520 SEE ALSO
1522 INTERNALS
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 */
1541 APTR doclip;
1542 BOOL opaque;
1543 OOP_Object *gc;
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));
1549 gc = msg->gc;
1550 doclip = GC_DOCLIP(gc);
1551 opaque = (GC_COLEXP(gc) & vHidd_GC_ColExp_Opaque) ? TRUE : FALSE;
1552 fg = GC_FG(gc);
1554 maskLine = 1 << GC_LINEPATCNT(gc);
1556 if (doclip)
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;
1564 else
1566 x1 = msg->x1; x2 = msg->x2;
1569 if (msg->y1 > msg->y2)
1571 y1 = msg->y2; y2 = msg->y1;
1573 else
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 */
1585 return;
1590 x1 = msg->x1;
1591 y1 = msg->y1;
1592 x2 = msg->x2;
1593 y2 = msg->y2;
1595 if (y1 == y2)
1598 Horizontal line drawing code.
1600 y = y1;
1602 /* Don't swap coordinates if x2 < x1! Because of linepattern! */
1604 if (x1 < x2)
1606 x2++;
1607 dx = 1;
1609 else
1611 x2--;
1612 dx = -1;
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);
1625 else if (opaque)
1627 GC_FG(gc) = GC_BG(gc);
1628 HIDD_BM_DrawPixel(obj, gc, i, y);
1629 GC_FG(gc) = fg;
1633 maskLine = maskLine >> 1;
1634 if (!maskLine) maskLine = 1L << 15;
1637 else if (x1 == x2)
1640 Vertical line drawing code.
1642 x = x1;
1644 /* Don't swap coordinates if y2 < y1! Because of linepattern! */
1646 if (y1 < y2)
1648 y2++;
1649 dy = 1;
1651 else
1653 y2--;
1654 dy = -1;
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);
1666 else if (opaque)
1668 GC_FG(gc) = GC_BG(gc);
1669 HIDD_BM_DrawPixel(obj, gc, x, i);
1670 GC_FG(gc) = fg;
1674 maskLine = maskLine >> 1;
1675 if (!maskLine) maskLine = 1L << 15;
1679 else
1682 Generic line drawing code.
1684 /* Calculate slope */
1685 dx = abs(x2 - x1);
1686 dy = abs(y2 - y1);
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 */
1693 if(dx < dy)
1695 d = dx;
1696 dx = dy;
1697 dy = d;
1698 t = 0;
1700 else
1702 t = 1;
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 */
1710 x = x1; y = y1;
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);
1721 else if (opaque)
1723 GC_FG(gc) = GC_BG(gc);
1724 HIDD_BM_DrawPixel(obj, gc, x, y);
1725 GC_FG(gc) = fg;
1729 if(d <= 0)
1731 if(t == 1)
1733 x = x + s1;
1735 else
1737 y = y + s2;
1740 d = d + incrE;
1742 else
1744 x = x + s1;
1745 y = y + s2;
1746 d = d + incrNE;
1749 maskLine = maskLine >> 1;
1750 if (!maskLine) maskLine = 1L << 15;
1755 ReturnVoid("BitMap::DrawLine ");
1758 /*****************************************************************************************
1760 NAME
1761 moHidd_BitMap_DrawRect
1763 SYNOPSIS
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);
1769 LOCATION
1770 hidd.graphics.bitmap
1772 FUNCTION
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.
1778 INPUTS
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
1784 RESULT
1785 None.
1787 NOTES
1788 This method is not used by the system and considered reserved.
1790 EXAMPLE
1792 BUGS
1794 SEE ALSO
1796 INTERNALS
1798 TODO
1800 *****************************************************************************************/
1802 VOID BM__Hidd_BitMap__DrawRect(OOP_Class *cl, OOP_Object *obj,
1803 struct pHidd_BitMap_DrawRect *msg)
1805 #ifdef __RESERVED__
1806 OOP_Object *gc = msg->gc;
1807 WORD addX, addY;
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);
1818 #endif
1820 ReturnVoid("BitMap::DrawRect");
1823 /*****************************************************************************************
1825 NAME
1826 moHidd_BitMap_FillRect
1828 SYNOPSIS
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);
1834 LOCATION
1835 hidd.graphics.bitmap
1837 FUNCTION
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.
1844 INPUTS
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
1850 RESULT
1851 None.
1853 NOTES
1855 EXAMPLE
1857 BUGS
1859 SEE ALSO
1861 INTERNALS
1863 TODO
1864 Fill with pattern
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;
1872 WORD y = msg->minY;
1873 UWORD linepat;
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 /*****************************************************************************************
1892 NAME
1893 moHidd_BitMap_DrawEllipse
1895 SYNOPSIS
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,
1899 WORD rx, WORD ry);
1901 LOCATION
1902 hidd.graphics.bitmap
1904 FUNCTION
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.
1909 INPUTS
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
1915 RESULT
1916 None.
1918 NOTES
1920 EXAMPLE
1922 BUGS
1923 Because of overflow the current code do not work with big
1924 values of rx and ry.
1926 SEE ALSO
1928 INTERNALS
1930 TODO
1931 Bugfix
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 */
1959 if (doclip)
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);
1975 else
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 */
1984 t9 = t9 + t3;
1985 if (d1 < 0) /* move straight up */
1987 d1 = d1 + t9 + t2;
1988 d2 = d2 + t9;
1990 else /* move up and left */
1992 x--;
1993 t8 = t8 - t6;
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 */
2002 #if 1
2003 if (doclip)
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);
2019 else
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);
2027 #else
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);
2033 #endif
2034 x--; /* always move left here */
2035 t8 = t8 - t6;
2036 if (d2 < 0) /* move up and left */
2038 y++;
2039 t9 = t9 + t3;
2040 d2 = d2 + t9 + t5 - t8;
2042 else /* move straight left */
2044 d2 = d2 + t5 - t8;
2047 } while (x >= 0);
2050 ReturnVoid("BitMap::DrawEllipse");
2053 /*****************************************************************************************
2055 NAME
2056 moHidd_BitMap_FillEllipse
2058 SYNOPSIS
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,
2062 WORD ry, WORD rx);
2064 LOCATION
2065 hidd.graphics.bitmap
2067 FUNCTION
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.
2072 INPUTS
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
2078 RESULT
2079 None.
2081 NOTES
2082 This method is not used by the system and considered reserved.
2084 EXAMPLE
2086 Because of overflow the current code do not work with big
2087 values of rx and ry.
2089 SEE ALSO
2091 INTERNALS
2093 TODO
2094 Bugfix
2096 *****************************************************************************************/
2098 VOID BM__Hidd_BitMap__FillEllipse(OOP_Class *cl, OOP_Object *obj,
2099 struct pHidd_BitMap_DrawEllipse *msg)
2101 #ifdef __RESERVED__
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 */
2121 t9 = t9 + t3;
2122 if (d1 < 0) /* move straight up */
2124 d1 = d1 + t9 + t2;
2125 d2 = d2 + t9;
2127 else /* move up and left */
2129 x--;
2130 t8 = t8 - t6;
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 */
2143 t8 = t8 - t6;
2144 if (d2 < 0) /* move up and left */
2146 y++;
2147 t9 = t9 + t3;
2148 d2 = d2 + t9 + t5 - t8;
2150 else /* move straight left */
2152 d2 = d2 + t5 - t8;
2155 } while (x >= 0);
2156 #endif
2158 ReturnVoid("BitMap::FillEllipse");
2161 /*****************************************************************************************
2163 NAME
2164 moHidd_BitMap_DrawPolygon
2166 SYNOPSIS
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);
2171 LOCATION
2172 hidd.graphics.bitmap
2174 FUNCTION
2175 Draws a hollow polygon from the list of coordinates in coords[].
2176 The function does not clip the polygon against the drawing area.
2178 INPUTS
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
2184 RESULT
2185 None.
2187 NOTES
2188 This method is not used by the system and considered reserved.
2190 EXAMPLE
2192 BUGS
2194 SEE ALSO
2196 INTERNALS
2198 TODO
2200 *****************************************************************************************/
2202 VOID BM__Hidd_BitMap__DrawPolygon(OOP_Class *cl, OOP_Object *obj,
2203 struct pHidd_BitMap_DrawPolygon *msg)
2205 #ifdef __RESERVED__
2206 OOP_Object *gc = msg->gc;
2207 WORD i;
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]);
2216 #endif
2218 ReturnVoid("BitMap::DrawPolygon");
2221 /*****************************************************************************************
2223 NAME
2224 moHidd_BitMap_FillPolygon
2226 SYNOPSIS
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);
2231 LOCATION
2232 hidd.graphics.bitmap
2234 FUNCTION
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.
2239 INPUTS
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
2245 RESULT
2246 None
2248 NOTES
2250 EXAMPLE
2252 BUGS
2253 Never used and implemented
2255 SEE ALSO
2257 INTERNALS
2259 TODO
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 /*****************************************************************************************
2270 NAME
2271 moHidd_BitMap_DrawText
2273 SYNOPSIS
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);
2279 LOCATION
2280 hidd.graphics.bitmap
2282 FUNCTION
2283 Draws the first length characters of text at (x, y).
2284 The function does not clip the text against the drawing area.
2286 INPUTS
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
2291 first character.
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
2296 RESULT
2297 None.
2299 NOTES
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.
2304 EXAMPLE
2306 BUGS
2307 The default implementation in the base class does not process styles,
2308 color and alpha-blended fonts.
2310 SEE ALSO
2312 INTERNALS
2314 TODO
2316 *****************************************************************************************/
2318 VOID BM__Hidd_BitMap__DrawText(OOP_Class *cl, OOP_Object *obj,
2319 struct pHidd_BitMap_DrawText *msg)
2321 #ifdef __RESERVED__
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;
2326 ULONG charLog;
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;
2332 WORD x, y, i;
2335 EnterFunc(bug("BitMap::DrawText()"));
2337 for(i = 0; i < msg->length; i++)
2339 ch = msg->text[i];
2341 if((ch < font->tf_LoChar) || (ch > font->tf_HiChar))
2343 ch = font->tf_HiChar - font->tf_LoChar + 1;
2345 else
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 */
2359 y = yMem;
2361 for(fy = 0; fy < font->tf_YSize; fy ++)
2363 x = xMem;
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);
2371 x++;
2374 y++;
2377 if(font->tf_Flags & FPF_PROPORTIONAL)
2379 xMem = xMem + ((UWORD *) font->tf_CharSpace)[ch];
2381 else
2383 xMem = xMem + font->tf_XSize;
2386 #endif
2387 ReturnVoid("BitMap::DrawText");
2390 /*****************************************************************************************
2392 NAME
2393 moHidd_BitMap_FillText
2395 SYNOPSIS
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);
2401 LOCATION
2402 hidd.graphics.bitmap
2404 FUNCTION
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.
2411 INPUTS
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
2416 first character.
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
2421 RESULT
2423 NOTES
2425 EXAMPLE
2427 BUGS
2429 SEE ALSO
2431 INTERNALS
2433 TODO
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 /*****************************************************************************************
2444 NAME
2445 moHidd_BitMap_FillSpan
2447 SYNOPSIS
2448 VOID OOP_DoMethod(OOP_Object *obj, struct pHidd_BitMap_DrawText *msg);
2450 LOCATION
2451 hidd.graphics.bitmap
2453 FUNCTION
2454 Reserved, never implemented method. The definition will change in future.
2456 INPUTS
2458 RESULT
2459 None.
2461 NOTES
2463 EXAMPLE
2465 BUGS
2467 SEE ALSO
2469 INTERNALS
2471 TODO
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 /*****************************************************************************************
2482 NAME
2483 moHidd_BitMap_Clear
2485 SYNOPSIS
2486 OOP_DoMethod(OOP_Object *obj, struct pHidd_BitMap_Clear *msg);
2488 VOID HIDD_BM_Clear (OOP_Object *obj, OOP_Object *gc);
2490 LOCATION
2491 hidd.graphics.bitmap
2493 FUNCTION
2494 Sets all pixels of the drawing area to the background color.
2496 INPUTS
2497 obj - A bitmap to clear.
2498 gc - A GC object, specifies background color value
2500 RESULT
2502 NOTES
2503 This method is not used by the system and considered reserved. However it can
2504 be useful for display driver's own needs.
2506 EXAMPLE
2508 BUGS
2509 Default implementation in the base class sets all pixels to zero color instead of
2510 the background color from GC
2512 SEE ALSO
2514 INTERNALS
2516 TODO
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;
2523 WORD x, y;
2524 IPTR width, height;
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;
2547 OOP_Object *pf;
2548 struct HIDDBitMapData *data;
2549 SIPTR bpp = -1;
2551 data = OOP_INST_DATA(cl, o);
2553 switch (stdpf)
2555 case vHidd_StdPixFmt_Native:
2556 OOP_GetAttr(data->prot.pixfmt, aHidd_PixFmt_BytesPerPixel, &bpp);
2557 break;
2559 case vHidd_StdPixFmt_Native32:
2560 bpp = sizeof (HIDDT_Pixel);
2561 break;
2563 default:
2564 pf = HIDD_Gfx_GetPixFmt(data->gfxhidd, stdpf);
2566 if (NULL == pf)
2568 D(bug("!!! INVALID PIXFMT IN BitMap::PutImage(): %d !!!\n", stdpf));
2570 else
2572 OOP_GetAttr(pf, aHidd_PixFmt_BytesPerPixel, &bpp);
2574 break;
2577 return bpp;
2580 /*****************************************************************************************
2582 NAME
2583 moHidd_BitMap_GetImage
2585 SYNOPSIS
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);
2591 LOCATION
2592 hidd.graphics.bitmap
2594 FUNCTION
2596 INPUTS
2597 obj -
2598 pixels -
2599 modulo -
2600 x, y -
2601 width -
2602 height -
2603 pixFmt -
2605 RESULT
2607 NOTES
2609 EXAMPLE
2611 BUGS
2613 SEE ALSO
2615 INTERNALS
2617 *****************************************************************************************/
2619 VOID BM__Hidd_BitMap__GetImage(OOP_Class *cl, OOP_Object *o,
2620 struct pHidd_BitMap_GetImage *msg)
2622 WORD x, y;
2623 UBYTE *pixarray = (UBYTE *)msg->pixels;
2624 APTR ppixarray = &pixarray;
2625 WORD bpp;
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);
2635 if (-1 == bpp)
2637 D(bug("!!! INVALID PIXFMT IN BitMap::GetImage(): %d !!!\n", msg->pixFmt));
2638 return;
2642 switch(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);
2654 switch (bpp)
2656 case 1:
2657 *pixarray++ = pix;
2658 break;
2660 case 2:
2661 *((UWORD *)pixarray) = pix;
2662 pixarray += 2;
2663 break;
2665 case 3:
2666 #if AROS_BIG_ENDIAN
2667 pixarray[0] = (pix >> 16) & 0xFF;
2668 pixarray[1] = (pix >> 8) & 0xFF;
2669 pixarray[2] = pix & 0xFF;
2670 #else
2671 pixarray[0] = pix & 0xFF;
2672 pixarray[1] = (pix >> 8) & 0xFF;
2673 pixarray[2] = (pix >> 16) & 0xFF;
2674 #endif
2675 pixarray += 3;
2676 break;
2678 case 4:
2679 *(ULONG *)pixarray = pix;
2680 pixarray += 4;
2681 break;
2686 pixarray += (msg->modulo - msg->width * bpp);
2689 break;
2691 default:
2693 OOP_Object *dstpf;
2694 APTR buf, srcPixels;
2696 dstpf = HIDD_Gfx_GetPixFmt(data->gfxhidd, msg->pixFmt);
2698 buf = srcPixels = AllocVec(msg->width * sizeof(HIDDT_Pixel), MEMF_PUBLIC);
2699 if (buf)
2701 for(y = 0; y < msg->height; y++)
2703 HIDD_BM_GetImage(o,
2704 buf,
2706 msg->x,
2707 msg->y + y,
2708 msg->width,
2710 vHidd_StdPixFmt_Native);
2712 HIDD_BM_ConvertPixels(o,
2713 &srcPixels,
2714 (HIDDT_PixelFormat *)data->prot.pixfmt,
2716 (APTR *)ppixarray,
2717 (HIDDT_PixelFormat *)dstpf,
2718 msg->modulo,
2719 msg->width,
2721 NULL);
2724 FreeVec(buf);
2727 break;
2729 } /* switch(msg->pixFmt) */
2731 ReturnVoid("BitMap::GetImage");
2734 /*****************************************************************************************
2736 NAME
2737 moHidd_BitMap_PutImage
2739 SYNOPSIS
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);
2745 LOCATION
2746 hidd.graphics.bitmap
2748 FUNCTION
2750 INPUTS
2751 obj -
2752 gc -
2753 pixels -
2754 modulo -
2755 x, y -
2756 width -
2757 height -
2758 pixFmt -
2760 RESULT
2762 NOTES
2764 EXAMPLE
2766 BUGS
2768 SEE ALSO
2770 INTERNALS
2772 *****************************************************************************************/
2774 VOID BM__Hidd_BitMap__PutImage(OOP_Class *cl, OOP_Object *o,
2775 struct pHidd_BitMap_PutImage *msg)
2777 WORD x, y;
2778 UBYTE *pixarray = (UBYTE *)msg->pixels;
2779 APTR ppixarray = &pixarray;
2780 ULONG old_fg;
2781 WORD bpp;
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)
2791 return;
2793 bpp = getpixfmtbpp(cl, o, msg->pixFmt);
2794 if (-1 == bpp)
2796 D(bug("!!! INVALID PIXFMT IN BitMap::PutImage(): %d !!!\n", msg->pixFmt));
2797 return;
2800 switch(msg->pixFmt)
2802 case vHidd_StdPixFmt_Native:
2803 case vHidd_StdPixFmt_Native32:
2805 /* Preserve old fg pen */
2806 old_fg = GC_FG(gc);
2808 for (y = 0; y < msg->height; y ++)
2810 for (x = 0; x < msg->width; x ++)
2812 register HIDDT_Pixel pix = 0;
2814 switch (bpp)
2816 case 1:
2817 pix = *((UBYTE *)pixarray);
2818 pixarray ++;
2819 break;
2821 case 2:
2822 pix = *((UWORD *)pixarray);
2823 pixarray += 2;
2824 break;
2826 case 3:
2827 #if AROS_BIG_ENDIAN
2828 pix = ((UBYTE *)pixarray)[0] << 16;
2829 pix |= ((UBYTE *)pixarray)[1] << 8;
2830 pix |= ((UBYTE *)pixarray)[2];
2831 #else
2832 pix = ((UBYTE *)pixarray)[2] << 16;
2833 pix |= ((UBYTE *)pixarray)[1] << 8;
2834 pix |= ((UBYTE *)pixarray)[0];
2835 #endif
2836 pixarray += 3;
2837 break;
2839 case 4:
2840 pix = *((ULONG *)pixarray); pixarray += 4;
2841 break;
2845 GC_FG(gc) = pix;
2847 HIDD_BM_DrawPixel(o, gc, x + msg->x , y + msg->y);
2849 pixarray += (msg->modulo - msg->width * bpp);
2852 GC_FG(gc) = old_fg;
2853 break;
2855 default:
2857 OOP_Object *srcpf;
2858 APTR buf, destPixels;
2860 srcpf = HIDD_Gfx_GetPixFmt(data->gfxhidd, msg->pixFmt);
2862 buf = destPixels = AllocVec(msg->width * sizeof(HIDDT_Pixel), MEMF_PUBLIC);
2863 if (buf)
2865 for(y = 0; y < msg->height; y++)
2867 HIDD_BM_ConvertPixels(o,
2868 (APTR *)ppixarray,
2869 (HIDDT_PixelFormat *)srcpf,
2870 msg->modulo,
2871 &destPixels,
2872 (HIDDT_PixelFormat *)data->prot.pixfmt,
2874 msg->width,
2876 NULL);
2878 HIDD_BM_PutImage(o,
2879 msg->gc,
2880 buf,
2882 msg->x,
2883 msg->y + y,
2884 msg->width,
2886 vHidd_StdPixFmt_Native);
2888 FreeVec(buf);
2891 break;
2893 } /* switch(msg->pixFmt) */
2895 ReturnVoid("BitMap::PutImage");
2898 /****************************************************************************************/
2900 int static inline
2901 __attribute__((always_inline, const)) do_alpha(int a, int v)
2903 int tmp = (a*v);
2904 return ((tmp<<8) + tmp + 32768)>>16;
2907 #if AROS_BIG_ENDIAN
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))
2924 #else
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))
2941 #endif
2943 /*****************************************************************************************
2945 NAME
2946 moHidd_BitMap_PutAlphaImage
2948 SYNOPSIS
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);
2954 LOCATION
2955 hidd.graphics.bitmap
2957 FUNCTION
2958 Perform an alpha-blending operation between a bitmap and ARGB pixel array.
2960 INPUTS
2961 obj - A bitmap to operate on
2962 gc - A GC object, internally needed to perform the operation. All its attributes
2963 are ignored.
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.
2970 RESULT
2971 None.
2973 NOTES
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.
2978 EXAMPLE
2980 BUGS
2982 SEE ALSO
2984 INTERNALS
2986 *****************************************************************************************/
2988 struct paib_data
2990 void *pixels;
2991 ULONG modulo;
2995 * TODOs:
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)
3006 UWORD x, y;
3008 for (y = 0; y < height; y++)
3010 ULONG *pixarray = data->pixels;
3012 for (x = 0; x < width; x++)
3014 ULONG destpix;
3015 ULONG srcpix;
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))
3023 xbuf[x] = srcpix;
3025 else if (ARGB32_ALPHA(srcpix) != 0)
3027 ARGB32_DECOMPOSE(src_alpha, src_red, src_green, src_blue, srcpix);
3029 destpix = xbuf[x];
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);
3040 xbuf += width;
3041 data->pixels += data->modulo;
3045 VOID BM__Hidd_BitMap__PutAlphaImage(OOP_Class *cl, OOP_Object *o,
3046 struct pHidd_BitMap_PutAlphaImage *msg)
3048 WORD x, y;
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)
3055 return;
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;
3068 HIDDT_Color col;
3069 ULONG srcpix;
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 /*****************************************************************************************
3104 NAME
3105 moHidd_BitMap_PutTemplate
3107 SYNOPSIS
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);
3113 LOCATION
3114 hidd.graphics.bitmap
3116 FUNCTION
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
3124 left unchanged.
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).
3128 INPUTS
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
3139 RESULT
3140 None
3142 NOTES
3144 EXAMPLE
3146 BUGS
3148 SEE ALSO
3150 INTERNALS
3152 *****************************************************************************************/
3154 struct ptb_data
3156 void *bitarray;
3157 ULONG bitmask;
3158 ULONG modulo;
3159 ULONG fg;
3160 ULONG bg;
3161 UWORD invert;
3164 static void JAM1TemplateBuffered(ULONG *xbuf, UWORD starty, UWORD width, UWORD height, struct ptb_data *data)
3166 UWORD x, y;
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))
3177 xbuf[x] = data->fg;
3179 mask >>= 1;
3180 if (!mask)
3182 mask = 0x8000;
3183 array++;
3184 bitword = AROS_BE2WORD(*array);
3188 xbuf += width;
3189 data->bitarray += data->modulo;
3193 static void ComplementTemplateBuffered(ULONG *xbuf, UWORD starty, UWORD width, UWORD height, struct ptb_data *data)
3195 UWORD x, y;
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))
3206 xbuf[x] = ~xbuf[x];
3208 mask >>= 1;
3209 if (!mask)
3211 mask = 0x8000;
3212 array++;
3213 bitword = AROS_BE2WORD(*array);
3217 xbuf += width;
3218 data->bitarray += data->modulo;
3222 static void JAM2TemplateBuffered(ULONG *xbuf, UWORD starty, UWORD width, UWORD height, struct ptb_data *data)
3224 UWORD x, y;
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))
3235 xbuf[x] = data->fg;
3236 else
3237 xbuf[x] = data->bg;
3239 mask >>= 1;
3240 if (!mask)
3242 mask = 0x8000;
3243 array++;
3244 bitword = AROS_BE2WORD(*array);
3248 xbuf += width;
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;
3256 BOOL get = TRUE;
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)
3264 return;
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;
3274 else
3276 op = JAM2TemplateBuffered;
3277 get = FALSE;
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 /*****************************************************************************************
3296 NAME
3297 moHidd_BitMap_PutAlphaTemplate
3299 SYNOPSIS
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);
3305 LOCATION
3306 hidd.graphics.bitmap
3308 FUNCTION
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.
3319 INPUTS
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
3329 RESULT
3330 None
3332 NOTES
3334 EXAMPLE
3336 BUGS
3338 SEE ALSO
3340 INTERNALS
3342 *****************************************************************************************/
3344 struct patb_data
3346 UBYTE *pixarray;
3347 ULONG modulo;
3348 LONG a_red, a_green, a_blue;
3349 LONG b_red, b_green, b_blue;
3350 UBYTE invert;
3353 static void JAM1AlphaTemplateBuffered(ULONG *xbuf, UWORD starty, UWORD width, UWORD height, struct patb_data *data)
3355 UWORD x, y;
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);
3375 xbuf += width;
3376 data->pixarray += data->modulo;
3380 static void ComplementAlphaTemplateBuffered(ULONG *xbuf, UWORD starty, UWORD width, UWORD height, struct patb_data *data)
3382 UWORD x, y;
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;
3392 if (alpha >= 0x80)
3393 xbuf[x] = ~xbuf[x];
3396 xbuf += width;
3397 data->pixarray += data->modulo;
3401 static void JAM2AlphaTemplateBuffered(ULONG *xbuf, UWORD starty, UWORD width, UWORD height, struct patb_data *data)
3403 UWORD x, y;
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);
3422 xbuf += width;
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;
3431 BOOL get = TRUE;
3432 void (*op)(ULONG *, UWORD, UWORD, UWORD, struct patb_data *);
3433 struct patb_data data;
3434 HIDDT_Color color;
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)
3440 return;
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;
3455 else
3457 op = JAM2AlphaTemplateBuffered;
3458 get = FALSE;
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 /*****************************************************************************************
3479 NAME
3480 moHidd_BitMap_PutPattern
3482 SYNOPSIS
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);
3491 LOCATION
3492 hidd.graphics.bitmap
3494 FUNCTION
3496 INPUTS
3497 obj - A bitmap to draw on
3498 gc - A GC object to use for drawing
3499 pattern -
3500 patternsrcx -
3501 patternsrcy -
3502 patternheight -
3503 patterndepth -
3504 patternlut -
3505 invertpattern -
3506 mask -
3507 maskmodulo -
3508 masksrcx -
3509 x, y -
3510 width -
3511 height -
3513 RESULT
3514 None
3516 NOTES
3518 EXAMPLE
3520 BUGS
3522 SEE ALSO
3524 INTERNALS
3526 *****************************************************************************************/
3528 struct ppb_data
3530 UWORD *patarray;
3531 void *maskarray;
3532 ULONG *patternlut;
3533 UWORD patternsrcy;
3534 UWORD desty;
3535 UWORD patternheight;
3536 ULONG maskmodulo;
3537 ULONG fg;
3538 ULONG bg;
3539 UWORD patmask;
3540 UWORD maskmask;
3541 UWORD patterndepth;
3542 UWORD invert;
3545 static void JAM1PatternBuffered(ULONG *xbuf, UWORD starty, UWORD width, UWORD height, struct ppb_data *data)
3547 UWORD x, y;
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))
3563 xbuf[x] = data->fg;
3566 if (marray)
3568 mmask >>= 1;
3569 if (!mmask)
3571 mmask = 0x8000;
3572 marray++;
3573 maskword = AROS_BE2WORD(*marray);
3577 pmask >>= 1;
3578 if (!pmask)
3579 pmask = 0x8000;
3581 } /* for (x) */
3583 xbuf += width;
3584 if (data->maskarray)
3585 data->maskarray += data->maskmodulo;
3587 } /* for (y) */
3590 static void ComplementPatternBuffered(ULONG *xbuf, UWORD starty, UWORD width, UWORD height, struct ppb_data *data)
3592 UWORD x, y;
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))
3608 xbuf[x] = ~xbuf[x];
3611 if (marray)
3613 mmask >>= 1;
3614 if (!mmask)
3616 mmask = 0x8000;
3617 marray++;
3618 maskword = AROS_BE2WORD(*marray);
3622 pmask >>= 1;
3623 if (!pmask)
3624 pmask = 0x8000;
3626 } /* for (x) */
3628 xbuf += width;
3629 if (data->maskarray)
3630 data->maskarray += data->maskmodulo;
3632 } /* for (y) */
3635 static void JAM2PatternBuffered(ULONG *xbuf, UWORD starty, UWORD width, UWORD height, struct ppb_data *data)
3637 UWORD x, y;
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))
3653 xbuf[x] = data->fg;
3654 else
3655 xbuf[x] = data->bg;
3658 if (marray)
3660 mmask >>= 1;
3661 if (!mmask)
3663 mmask = 0x8000;
3664 marray++;
3665 maskword = AROS_BE2WORD(*marray);
3669 pmask >>= 1;
3670 if (!pmask)
3671 pmask = 0x8000;
3673 } /* for (x) */
3675 xbuf += width;
3676 if (data->maskarray)
3677 data->maskarray += data->maskmodulo;
3679 } /* for (y) */
3682 static void ColorPatternBuffered(ULONG *xbuf, UWORD starty, UWORD width, UWORD height, struct ppb_data *data)
3684 UWORD x, y;
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)
3699 UWORD plane;
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];
3714 xbuf[x] = pixel;
3717 if (marray)
3719 mmask >>= 1;
3720 if (!mmask)
3722 mmask = 0x8000;
3723 marray++;
3724 maskword = AROS_BE2WORD(*marray);
3728 pmask >>= 1;
3729 if (!pmask)
3730 pmask = 0x8000;
3732 } /* for (x) */
3734 xbuf += width;
3735 if (data->maskarray)
3736 data->maskarray += data->maskmodulo;
3738 } /* for (y) */
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);
3745 BOOL get = TRUE;
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)
3752 return;
3754 if (msg->patterndepth > 1)
3756 DPUTPATTERN(bug("[PutPattern] Color\n"));
3757 op = ColorPatternBuffered;
3758 get = FALSE;
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;
3770 else
3772 DPUTPATTERN(bug("[PutPattern] JAM2\n"));
3773 op = JAM2PatternBuffered;
3774 get = FALSE;
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;
3790 if (data.maskarray)
3792 data.maskarray += (msg->masksrcx / 16) * 2;
3793 data.maskmask = 0x8000 >> (msg->masksrcx & 0xF);
3794 get = TRUE;
3796 else
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 /*****************************************************************************************
3810 NAME
3811 moHidd_BitMap_PutImageLUT
3813 SYNOPSIS
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);
3819 LOCATION
3820 hidd.graphics.bitmap
3822 FUNCTION
3824 INPUTS
3825 obj -
3826 gc -
3827 pixels -
3828 modulo -
3829 x, y -
3830 width -
3831 height -
3832 pixlut -
3834 RESULT
3836 NOTES
3838 EXAMPLE
3840 BUGS
3842 SEE ALSO
3844 INTERNALS
3846 *****************************************************************************************/
3848 VOID BM__Hidd_BitMap__PutImageLUT(OOP_Class *cl, OOP_Object *o,
3849 struct pHidd_BitMap_PutImageLUT *msg)
3851 WORD x, y;
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)
3862 return;
3864 linebuf = AllocVec(msg->width * sizeof(HIDDT_Pixel), MEMF_PUBLIC);
3866 for(y = 0; y < msg->height; y++)
3868 if (linebuf)
3870 if (lut)
3872 for(x = 0; x < msg->width; x++)
3874 linebuf[x] = lut[pixarray[x]];
3877 else
3879 for(x = 0; x < msg->width; x++)
3881 linebuf[x] = pixarray[x];
3884 pixarray += msg->modulo;
3886 HIDD_BM_PutImage(o,
3887 msg->gc,
3888 (UBYTE *)linebuf,
3890 msg->x,
3891 msg->y + y,
3892 msg->width,
3894 vHidd_StdPixFmt_Native32);
3896 } /* if (linebuf) */
3897 else
3899 ULONG old_fg;
3901 /* Preserve old fg pen */
3902 old_fg = GC_FG(gc);
3904 if (lut)
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);
3912 else
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);
3920 GC_FG(gc) = old_fg;
3922 pixarray += msg->modulo;
3924 } /* if (linebuf) else ... */
3926 } /* for(y = 0; y < msg->height; y++) */
3928 FreeVec(linebuf);
3930 ReturnVoid("BitMap::PutImageLUT");
3932 /*****************************************************************************************
3934 NAME
3935 moHidd_BitMap_PutTranspImageLUT
3937 SYNOPSIS
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);
3944 LOCATION
3945 hidd.graphics.bitmap
3947 FUNCTION
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.
3956 INPUTS
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
3967 transparent
3969 RESULT
3970 None
3972 NOTES
3974 EXAMPLE
3976 BUGS
3978 SEE ALSO
3980 INTERNALS
3982 *****************************************************************************************/
3984 #undef csd /* Bad hack, but there's no other way */
3986 struct ptilb_data
3988 UBYTE *pixarray;
3989 ULONG *lut;
3990 OOP_Object *colmap;
3991 struct class_static_data *csd;
3992 ULONG modulo;
3993 UBYTE transparent;
3996 static void PutTranspImageLUTBuffered(ULONG *xbuf, UWORD starty, UWORD width, UWORD height, struct ptilb_data *data)
3998 struct class_static_data *csd = data->csd;
3999 UWORD x, y;
4001 for (y = 0; y < height; y++)
4003 UBYTE *pixarray = data->pixarray;
4005 if (data->lut)
4007 for (x = 0; x < width; x++)
4009 UBYTE pix = *pixarray++;
4011 if (pix != data->transparent)
4012 xbuf[x] = data->lut[pix];
4014 } /* for (x) */
4016 else
4018 for (x = 0; x < width; x++)
4020 UBYTE pix = *pixarray++;
4022 if (pix != data->transparent)
4024 if (data->colmap)
4025 pix = HIDD_CM_GetPixel(data->colmap, pix);
4027 xbuf[x] = pix;
4030 } /* for (x) */
4033 xbuf += width;
4034 data->pixarray += data->modulo;
4035 } /* for (y) */
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 =
4044 msg->pixels,
4045 NULL,
4046 data->colmap,
4047 CSD(cl),
4048 msg->modulo,
4049 msg->transparent
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)
4056 return;
4058 if (msg->pixlut)
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");
4069 #define csd CSD(cl)
4071 /*****************************************************************************************
4073 NAME
4074 moHidd_BitMap_GetImageLUT
4076 SYNOPSIS
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);
4082 LOCATION
4083 hidd.graphics.bitmap
4085 FUNCTION
4087 INPUTS
4088 obj -
4089 pixels -
4090 modulo -
4091 x, y -
4092 width -
4093 height -
4094 pixlut -
4096 RESULT
4098 NOTES
4100 EXAMPLE
4102 BUGS
4104 SEE ALSO
4106 INTERNALS
4108 *****************************************************************************************/
4110 VOID BM__Hidd_BitMap__GetImageLUT(OOP_Class *cl, OOP_Object *o,
4111 struct pHidd_BitMap_GetImageLUT *msg)
4113 WORD x, y;
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++)
4126 if (linebuf)
4128 HIDD_BM_GetImage(o,
4129 (UBYTE *)linebuf,
4131 msg->x,
4132 msg->y + y,
4133 msg->width,
4135 vHidd_StdPixFmt_Native32);
4136 if (lut)
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];
4144 else
4146 for(x = 0; x < msg->width; x++)
4148 pixarray[x] = (UBYTE)linebuf[x];
4151 pixarray += msg->modulo;
4153 } /* if (linebuf) */
4154 else
4156 if (lut)
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);
4164 else
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++) */
4178 FreeVec(linebuf);
4180 ReturnVoid("BitMap::GetImageLUT");
4183 /*****************************************************************************************
4185 NAME
4186 moHidd_BitMap_BlitColorExpansion
4188 SYNOPSIS
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);
4195 LOCATION
4196 hidd.graphics.bitmap
4198 FUNCTION
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.
4207 INPUTS
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
4215 RESULT
4216 None.
4218 NOTES
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.
4223 EXAMPLE
4225 BUGS
4227 SEE ALSO
4229 INTERNALS
4231 *****************************************************************************************/
4233 VOID BM__Hidd_BitMap__BlitColorExpansion(OOP_Class *cl, OOP_Object *o,
4234 struct pHidd_BitMap_BlitColorExpansion *msg)
4236 #ifdef __RESERVED__
4237 ULONG cemd;
4238 ULONG fg, bg;
4239 WORD x, y;
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);
4247 fg = GC_FG(gc);
4248 bg = GC_BG(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
4252 , cemd, fg, bg);
4254 for (y = 0; y < msg->height; y ++)
4256 for (x = 0; x < msg->width; x ++)
4258 ULONG is_set;
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);
4264 if (is_set)
4265 bug("#");
4266 else
4267 bug(" ");
4269 if (is_set)
4271 HIDD_BM_DrawPixel(o, gc, x + msg->destX, y + msg->destY);
4273 else
4275 if (cemd & vHidd_GC_ColExp_Opaque)
4277 /* Write bixel with BG pen */
4278 GC_FG(gc) = bg;
4279 HIDD_BM_DrawPixel(o, gc, x + msg->destX, y + msg->destY);
4280 /* Reset to FG pen */
4281 GC_FG(gc) = fg;
4284 } /* if () */
4286 } /* for (each x) */
4288 bug("\n");
4290 } /* for ( each y ) */
4291 #endif
4293 ReturnVoid("BitMap::BlitColorExpansion");
4296 /*****************************************************************************************
4298 NAME
4299 moHidd_BitMap_BytesPerLine
4301 SYNOPSIS
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);
4306 LOCATION
4307 hidd.graphics.bitmap
4309 FUNCTION
4310 This method is currently not used and reserved.
4312 INPUTS
4313 obj -
4314 pixFmt -
4315 width -
4317 RESULT
4319 NOTES
4321 EXAMPLE
4323 BUGS
4325 SEE ALSO
4327 INTERNALS
4329 *****************************************************************************************/
4331 ULONG BM__Hidd_BitMap__BytesPerLine(OOP_Class *cl, OOP_Object *o, struct pHidd_BitMap_BytesPerLine *msg)
4333 #ifdef __RESERVED__
4334 ULONG bpl;
4336 switch (msg->pixFmt)
4338 case vHidd_StdPixFmt_Native32:
4339 bpl = sizeof (HIDDT_Pixel) * msg->width;
4340 break;
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;
4349 break;
4352 default:
4354 OOP_Object *pf;
4355 struct HIDDBitMapData *data;
4357 data = OOP_INST_DATA(cl, o);
4359 pf = HIDD_Gfx_GetPixFmt(data->gfxhidd, msg->pixFmt);
4361 if (NULL == pf)
4363 D(bug("!!! COULD NOT GET STD PIXFMT IN BitMap::BytesPerLine() !!!\n"));
4364 return 0;
4367 bpl = ((HIDDT_PixelFormat *)pf)->bytes_per_pixel * msg->width;
4368 break;
4372 return bpl;
4373 #else
4374 return 0;
4375 #endif
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
4384 bitmap subclass.
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;
4395 ULONG idx;
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;
4423 else
4425 /* Bad ModeID given, request rejected */
4426 return FALSE;
4429 /* Process the rest of tags. */
4430 BM__Hidd_BitMap__SetBitMapTags(cl, obj, msg->attrList);
4432 else
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;
4464 * FIXME:
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;
4470 if (xoffset < 0)
4471 xoffset = 0;
4472 else if (xoffset > limit)
4473 xoffset = limit;
4474 D(bug("[BitMap] xoffset requested %ld, got %d\n", -tag->ti_Data, xoffset));
4475 break;
4477 case aoHidd_BitMap_TopEdge:
4478 yoffset = -tag->ti_Data;
4479 limit = data->height - data->displayHeight;
4480 if (yoffset < 0)
4481 yoffset = 0;
4482 else if (yoffset > limit)
4483 yoffset = limit;
4484 D(bug("[BitMap] yoffset requested %ld, got %d\n", -tag->ti_Data, yoffset));
4485 break;
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;
4498 if (data->visible)
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 */
4510 return TRUE;
4513 /*****************************************************************************************
4515 NAME
4516 moHidd_BitMap_SetColorMap
4518 SYNOPSIS
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);
4523 LOCATION
4524 hidd.graphics.bitmap
4526 FUNCTION
4528 INPUTS
4529 obj -
4530 colorMap -
4532 RESULT
4534 NOTES
4536 EXAMPLE
4538 BUGS
4540 SEE ALSO
4542 INTERNALS
4544 *****************************************************************************************/
4546 OOP_Object *BM__Hidd_BitMap__SetColorMap(OOP_Class *cl, OOP_Object *o,
4547 struct pHidd_BitMap_SetColorMap *msg)
4549 struct HIDDBitMapData *data;
4550 OOP_Object *old;
4552 data = OOP_INST_DATA(cl, o);
4554 old = data->colmap;
4555 data->colmap = msg->colorMap;
4557 return old;
4560 /*****************************************************************************************
4562 NAME
4563 moHidd_BitMap_MapColor
4565 SYNOPSIS
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);
4570 LOCATION
4571 hidd.graphics.bitmap
4573 FUNCTION
4575 INPUTS
4576 obj -
4577 color -
4579 RESULT
4581 NOTES
4583 EXAMPLE
4585 BUGS
4587 SEE ALSO
4589 INTERNALS
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);
4604 #undef SQR
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);
4632 else
4634 msg->color->pixval = MAP_RGBA(red, green, blue, alpha, pf);
4637 else
4639 struct HIDDBitMapData *data = OOP_INST_DATA(cl, o);
4640 HIDDT_Color *ctab;
4641 HIDDT_ColorLUT *cmap;
4642 UWORD i;
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++) {
4649 ULONG dist;
4651 dist = colorDistance(&ctab[i], msg->color);
4652 if (dist < best_dist) {
4653 best_dist = dist;
4654 best_ndx = i;
4658 if (best_dist != ~0)
4659 msg->color->pixval = ctab[best_ndx].pixval;
4662 return msg->color->pixval;
4665 /*****************************************************************************************
4667 NAME
4668 moHidd_BitMap_UnmapPixel
4670 SYNOPSIS
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);
4675 LOCATION
4676 hidd.graphics.bitmap
4678 FUNCTION
4680 INPUTS
4681 obj -
4682 pixel -
4683 color -
4685 RESULT
4687 NOTES
4689 EXAMPLE
4691 BUGS
4693 SEE ALSO
4695 INTERNALS
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);
4719 else
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)
4730 return;
4732 *msg->color = clut->colors[msg->pixel];
4736 /* Unnecessary, but... */
4737 msg->color->pixval = msg->pixel;
4740 /*****************************************************************************************
4742 NAME
4743 moHidd_BitMap_ObtainDirectAccess
4745 SYNOPSIS
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);
4752 LOCATION
4753 hidd.graphics.bitmap
4755 FUNCTION
4757 INPUTS
4758 obj -
4759 addressReturn -
4760 widthReturn -
4761 heightReturn -
4762 bankSizeReturn -
4763 memSizeReturn -
4765 RESULT
4766 BOOL
4768 NOTES
4770 EXAMPLE
4772 BUGS
4774 SEE ALSO
4776 INTERNALS
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 */
4784 return FALSE;
4787 /*****************************************************************************************
4789 NAME
4790 moHidd_BitMap_ReleaseDirectAccess
4792 SYNOPSIS
4793 VOID OOP_DoMethod(OOP_Object *obj, struct pHidd_BitMap_ReleaseDirectAccess *msg);
4795 VOID HIDD_BM_ReleaseDirectAccess(OOP_Object *obj);
4797 LOCATION
4798 hidd.graphics.bitmap
4800 FUNCTION
4802 INPUTS
4803 obj -
4805 RESULT
4807 NOTES
4809 EXAMPLE
4811 BUGS
4813 SEE ALSO
4815 INTERNALS
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"));
4825 return;
4828 /*****************************************************************************************
4830 NAME
4831 moHidd_BitMap_BitMapScale
4833 SYNOPSIS
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);
4839 LOCATION
4840 hidd.graphics.bitmap
4842 FUNCTION
4844 INPUTS
4845 obj -
4846 src -
4847 dest -
4848 bsa -
4849 gc -
4851 RESULT
4853 NOTES
4855 EXAMPLE
4857 BUGS
4859 SEE ALSO
4861 INTERNALS
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;
4870 WORD srcline = -1;
4871 UWORD *linepattern;
4872 UWORD count;
4873 UWORD ys = bsa->bsa_SrcY;
4874 UWORD xs = bsa->bsa_SrcX;
4875 UWORD dyd = bsa->bsa_DestHeight;
4876 UWORD dxd = bsa->bsa_DestWidth;
4877 LONG accuys = dyd;
4878 LONG accuxs = dxd;
4879 UWORD dxs = bsa->bsa_SrcWidth;
4880 UWORD dys = bsa->bsa_SrcHeight;
4881 LONG accuyd = - (dys >> 1);
4882 LONG accuxd = - (dxs >> 1);
4883 UWORD x;
4885 if ((srcbuf = AllocVec(bsa->bsa_SrcWidth * sizeof(ULONG), 0)) == NULL)
4886 return;
4888 if ((dstbuf = AllocVec(bsa->bsa_DestWidth * sizeof(ULONG), 0)) == NULL) {
4889 FreeVec(srcbuf);
4890 return;
4893 if ((linepattern = (UWORD *) AllocVec(bsa->bsa_DestWidth * sizeof(UWORD), 0)) == NULL) {
4894 FreeVec(dstbuf);
4895 FreeVec(srcbuf);
4896 return;
4899 count = 0;
4900 while (count < bsa->bsa_DestWidth) {
4901 accuxd += dxs;
4902 while (accuxd > accuxs) {
4903 xs++;
4904 accuxs += dxd;
4907 linepattern[count] = xs;
4909 count++;
4912 count = bsa->bsa_DestY;
4913 while (count < bsa->bsa_DestHeight + bsa->bsa_DestY) {
4914 accuyd += dys;
4915 while (accuyd > accuys) {
4916 ys++;
4917 accuys += dyd;
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);
4922 srcline = ys;
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);
4930 count++;
4933 FreeVec(linepattern);
4935 FreeVec(dstbuf);
4936 FreeVec(srcbuf);
4939 /*****************************************************************************************
4941 NAME
4942 moHidd_BitMap_SetRGBConversionFunction
4944 SYNOPSIS
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);
4953 LOCATION
4954 hidd.graphics.bitmap
4956 FUNCTION
4958 INPUTS
4960 RESULT
4962 NOTES
4964 EXAMPLE
4966 BUGS
4968 SEE ALSO
4970 INTERNALS
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;
4986 else
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);
4993 return old;
4997 /*****************************************************************************************
4999 NAME
5000 moHidd_BitMap_UpdateRect
5002 SYNOPSIS
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);
5007 LOCATION
5008 hidd.graphics.bitmap
5010 FUNCTION
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!
5024 INPUTS
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
5030 RESULT
5031 None.
5033 NOTES
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.
5037 EXAMPLE
5039 BUGS
5041 SEE ALSO
5043 INTERNALS
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.
5062 if (data->visible)
5064 ObtainSemaphoreShared(&data->lock);
5066 if (data->visible)
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,
5091 o, srcX, srcY,
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)))
5117 ULONG idx;
5119 if (IS_BITMAP_ATTR(tag->ti_Tag, idx))
5121 switch (idx)
5123 case aoHidd_BitMap_Width:
5124 data->width = tag->ti_Data;
5125 break;
5127 case aoHidd_BitMap_Height:
5128 data->height = tag->ti_Data;
5129 break;
5131 case aoHidd_BitMap_BytesPerRow:
5132 data->bytesPerRow = tag->ti_Data;
5133 break;
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;
5142 if (data->friend)
5144 OOP_GetAttr(data->friend, aHidd_BitMap_ModeID, &compositmodeid);
5146 else
5147 compositmodeid = data->modeid;
5149 if (compositmodeid == vHidd_ModeID_Invalid)
5151 data->compositable = FALSE;
5153 else
5155 OOP_Object *sync, *pf;
5157 if (!HIDD_Gfx_GetMode(data->gfxhidd, compositmodeid, &sync, &pf))
5159 data->compositable = FALSE;
5161 else
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);