wip prep commit in lieu of gfx subsystem update changes, part 2.
[AROS.git] / rom / hidds / gfx / gfx_bitmapclass.c
blob67db26d0d9e659aefe871a119b2dd72fe7a3c8da
1 /*
2 Copyright © 1995-2017, The AROS Development Team. All rights reserved.
3 $Id$
5 Desc: Gfx BitMap class implementation.
6 Lang: english
7 */
9 /****************************************************************************************/
11 #include "gfx_debug.h"
13 #include <aros/debug.h>
14 #include <proto/exec.h>
15 #include <proto/utility.h>
16 #include <proto/oop.h>
17 #include <exec/memory.h>
18 #include <utility/tagitem.h>
19 #include <oop/oop.h>
20 #include <oop/static_mid.h>
21 #include <graphics/text.h>
22 #include <graphics/scale.h>
23 #include <hidd/gfx.h>
25 #include <string.h>
26 #include <stdlib.h>
28 #include "gfx_intern.h"
30 /****************************************************************************************/
32 #define POINT_OUTSIDE_CLIP(gc, x, y) \
33 ( (x) < GC_CLIPX1(gc) \
34 || (x) > GC_CLIPX2(gc) \
35 || (y) < GC_CLIPY1(gc) \
36 || (y) > GC_CLIPY2(gc) )
38 /*****************************************************************************************
40 NAME
41 --background_bitmap--
43 LOCATION
44 hidd.gfx.bitmap
46 NOTES
47 Every display driver should implement at least one bitmap class for displayable
48 bitmaps.
50 Normally this class doesn't need to have public ID. In order to use it the driver
51 should pass class pointer as aoHidd_BitMap_ClassPtr value to the graphics base class
52 in its moHidd_Gfx_CreateObject implementation.
54 BitMap base class is in C++ terminology a pure virtual
55 baseclass. It will not allocate any bitmap data at all;
56 that is up to the subclass to do.
58 The main task of the BitMap baseclass is to store some information about the bitmap
59 like its size and pixelformat. A pixelformat is an object of private class which
60 stores the actual information about the format.
62 There are two ways that we can find out the pixfmt in our moHidd_Gfx_CreateObject
63 implementation:
65 Displayable bitmap -
66 The tags will contain a modeid.
67 One can use this modeid to get a pointer to an
68 already registered pixfmt.
70 Non-displayable bitmap -
71 The aoHidd_BitMap_StdPixFmt or aoHidd_BitMap_Friend attribute will always be
72 passed.
74 *****************************************************************************************/
76 #define PIXBUFBYTES 16384
78 static BOOL DoBufferedOperation(OOP_Class *cl, OOP_Object *o, UWORD startx, UWORD starty, UWORD width, UWORD height,
79 BOOL getimage, HIDDT_StdPixFmt stdpf, VOID_FUNC operation, void *userdata)
81 struct HIDDBitMapData *data = OOP_INST_DATA(cl, o);
82 ULONG bytesperline = width * sizeof(ULONG);
83 UWORD buflines = PIXBUFBYTES / 4; /* Remove slow division */
84 ULONG bufsize;
85 UWORD endy = starty + height;
86 UWORD y;
87 UBYTE *buf;
89 if (buflines == 0)
90 buflines = 1;
91 else if (buflines > height)
92 buflines = height;
94 bufsize = buflines * bytesperline;
95 buf = AllocMem(bufsize, MEMF_PUBLIC);
96 if (!buf && (buflines > 1))
98 /* Try to allocate single-line buffer */
99 buflines = 1;
100 bufsize = bytesperline;
101 buf = AllocMem(bufsize, MEMF_PUBLIC);
103 if (!buf)
104 return FALSE;
106 for (y = starty; y < endy; y += buflines)
108 if (y + buflines > endy)
110 /* This prevents overflow on last pass, buffer may be used only partially */
111 buflines = endy - y;
114 if (getimage)
116 /* For some operations this can be optimized away */
117 HIDD_BM_GetImage(o, buf, bytesperline, startx, y, width, buflines, stdpf);
120 operation(buf, y, width, buflines, userdata);
122 HIDD_BM_PutImage(o, data->gc, buf, bytesperline, startx, y, width, buflines, stdpf);
125 FreeMem(buf, bufsize);
126 return TRUE;
129 /*****************************************************************************************
131 NAME
132 aoHidd_BitMap_Width
134 SYNOPSIS
135 [ISG], UWORD
137 LOCATION
138 hidd.gfx.bitmap
140 FUNCTION
141 Specifies bitmap width in pixels.
143 Setting this attribute does not cause actual bitmap resize, just updates the information
144 about it. Use this only from within subclasses only if you know what you do. For example
145 SDL hosted driver sets it when framebufer changes the resolution.
147 NOTES
149 EXAMPLE
151 BUGS
153 SEE ALSO
154 aoHidd_BitMap_Height
156 INTERNALS
158 *****************************************************************************************/
160 /*****************************************************************************************
162 NAME
163 aoHidd_BitMap_Height
165 SYNOPSIS
166 [ISG], UWORD
168 LOCATION
169 hidd.gfx.bitmap
171 FUNCTION
172 Specifies bitmap height in pixels.
174 Setting this attribute does not cause actual bitmap resize, just updates the information
175 about it. Use this only from within subclasses only if you know what you do. For example
176 SDL hosted driver sets it when framebufer changes the resolution.
178 NOTES
180 EXAMPLE
182 BUGS
184 SEE ALSO
185 aoHidd_BitMap_Width
187 INTERNALS
189 *****************************************************************************************/
191 /*****************************************************************************************
193 NAME
194 aoHidd_BitMap_Displayable
196 SYNOPSIS
197 [I.G], BOOL
199 LOCATION
200 hidd.gfx.bitmap
202 FUNCTION
203 The bitmap is displayable. A displayable bitmap is always managed by a display
204 driver and must have valid display mode ID specification.
206 If this attribute is not supplied during bitmap creation, its value defaults
207 to FALSE.
209 NOTES
211 EXAMPLE
213 BUGS
215 SEE ALSO
216 aoHidd_BitMap_ModeID
218 INTERNALS
220 *****************************************************************************************/
222 /*****************************************************************************************
224 NAME
225 aoHidd_BitMap_Visible
227 SYNOPSIS
228 [..G], BOOL
230 LOCATION
231 hidd.gfx.bitmap
233 FUNCTION
234 Check if the bitmap is currently visible on screen
236 NOTES
238 EXAMPLE
240 BUGS
241 Not all display drivers implement this attribute. No AROS components currently rely
242 on its value.
244 SEE ALSO
246 INTERNALS
247 Some drivers may choose to have this attribute internally setable. Do not rely on it
248 in any way and do not attempt to set it manually from within applications, this will
249 not do any nice things.
251 *****************************************************************************************/
253 /*****************************************************************************************
255 NAME
256 aoHidd_BitMap_IsLinearMem
258 SYNOPSIS
259 [..G], BOOL
261 LOCATION
262 hidd.gfx.bitmap
264 FUNCTION
265 Check if the bitmap provides linear memory access. This means that bitmap's
266 pixelbuffer is directly addressable by the CPU.
268 Bitmaps with no linear memory may implement moHidd_BitMap_ObtainDirectAccess,
269 but this means that this method will rely on mirrored buffer. In such a case
270 the user must call moHidd_BitMap_UpdateRect after modifying bitmap's contents.
272 NOTES
273 Used by cybergraphics.library/GetCyberMapAttr() for providing CYBRMATTR_ISLINEARMEM
274 value.
276 EXAMPLE
278 BUGS
279 Currently no display drivers implement this attribute despite many native mode
280 drivers actually provide linear memory.
282 SEE ALSO
283 moHidd_BitMap_ObtainDirectAccess, moHidd_BitMap_ReleaseDirectAccess,
284 moHidd_BitMap_UpdateRect
286 INTERNALS
288 *****************************************************************************************/
290 /*****************************************************************************************
292 NAME
293 aoHidd_BitMap_BytesPerRow
295 SYNOPSIS
296 [ISG], ULONG
298 LOCATION
299 hidd.gfx.bitmap
301 FUNCTION
302 Specify or query number of bytes per row in the bitmap storage buffer.
304 Setting this attribute doesn't actually cause changing buffer layout, just updates
305 the information about it. Use this only from within subclasses and only if you
306 exactly know why you do this.
308 Specifying this attribute during object creation overrides the value calculated
309 based on aoHidd_BitMap_Width and aoHidd_BitMap_Align values. Useful for wrapping
310 own buffers into bitmap objects, for example, in conjunction with
311 aoHidd_ChunkyBM_Buffer.
313 NOTES
314 The returned value includes possible padding needed for alignment.
316 EXAMPLE
318 BUGS
320 SEE ALSO
321 aoHidd_BitMap_Align
323 INTERNALS
325 *****************************************************************************************/
327 /*****************************************************************************************
329 NAME
330 aoHidd_BitMap_ColorMap
332 SYNOPSIS
333 [..G], OOP_Object *
335 LOCATION
336 hidd.gfx.bitmap
338 FUNCTION
339 Return associated colormap (palette) object.
341 By default only displayable bitmaps have colormaps. However a colormap can be attached
342 to any bitmap using moHidd_BitMap_SetColors or moHidd_BitMap_SetColorMap.
344 Note that manual attaching of a colormap to a nondisplayable bitmap may cause undesired
345 side-effects on graphics.library behavior. It's better not to do this at all. The system
346 knows what it does better than you.
348 NOTES
350 EXAMPLE
352 BUGS
354 SEE ALSO
355 moHidd_BitMap_SetColorMap, moHidd_BitMap_SetColors.
357 INTERNALS
359 *****************************************************************************************/
361 /*****************************************************************************************
363 NAME
364 aoHidd_BitMap_Friend
366 SYNOPSIS
367 [I.G], OOP_Object *
369 LOCATION
370 hidd.gfx.bitmap
372 FUNCTION
373 Specify a friend bitmap. The bitmap will be allocated so that it
374 is optimized for blitting to this bitmap.
376 Display drivers may query this attribute and then query friend bitmap
377 for anything they want (like pixelformat, mode ID, etc).
379 Note that explicit specification of mode ID and/or standard pixelformat
380 should override defaults provided by friend bitmap (i.e. actually breaking
381 the friendship).
383 NOTES
385 EXAMPLE
387 BUGS
389 SEE ALSO
391 INTERNALS
393 *****************************************************************************************/
395 /*****************************************************************************************
397 NAME
398 aoHidd_BitMap_GfxHidd
400 SYNOPSIS
401 [I.G], OOP_Object *
403 LOCATION
404 hidd.gfx.bitmap
406 FUNCTION
407 Specify display driver object this bitmap was created with.
409 Normally the user doesn't have to supply this attribute. Instead you should use
410 driver's moHidd_Gfx_CreateObject method in order to create bitmaps. In this case
411 aoHidd_BitMap_GfxHidd attribute will be provided by graphics driver base class
412 with the correct value.
414 It is illegal to manually create bitmap objects with no driver associated.
415 graphics.library maintains at least a memory driver for nondisplayable
416 bitmaps in system RAM without any acceleration.
418 NOTES
420 EXAMPLE
422 BUGS
424 SEE ALSO
425 CLID_Hidd_Gfx/moHidd_Gfx_CreateObject
427 INTERNALS
429 *****************************************************************************************/
431 /*****************************************************************************************
433 NAME
434 aoHidd_BitMap_StdPixFmt
436 SYNOPSIS
437 [I..], HIDDT_StdPixFmt
439 LOCATION
440 hidd.gfx.bitmap
442 FUNCTION
443 Specify standard pixelformat code (one of vHidd_StdPixFmt_... values) for the
444 bitmap.
446 Values less than num_Hidd_PseudoStdPixFmt are illegal for this attribute.
448 The bitmap class itself ignores this attribute. It is processed by
449 CLID_Hidd_Gfx/moHidd_Gfx_CreateObject method in order to look up a corresponding
450 pixelformat object in the system's database.
452 NOTES
453 Bitmaps with this attribute set should be created as RAM bitmaps with direct CPU
454 access. It is not recommended to replace them with, for example, virtual surfaces on
455 hosted AROS. Such bitmaps are expected to be directly addressable and breaking
456 this may cause undesired side effects.
458 EXAMPLE
460 BUGS
462 SEE ALSO
463 aoHidd_BitMap_PixFmt, CLID_Hidd_Gfx/moHidd_Gfx_CreateObject
465 INTERNALS
466 Currently all display drivers omit specifying own bitmap class for bitmaps with this
467 attribute set, letting base class (actually memory driver) to select an appropriate
468 class for it. This way it ends up in a bitmap of CLID_Hidd_ChunkyBM or CLID_Hidd_PlanarBM
469 class. It is recommended to follow this rule. It's not prohibited, however, to do some
470 adjustments to the bitmap (like alignment) in order to optimize blitting to/from it.
471 In fact if the display driver was asked to create such a bitmap, this means that
472 the standard bitmap is being created as a friend of some bitmap which was allocated
473 using this driver. This way the bitmap is expected to be friendly to this driver.
475 *****************************************************************************************/
477 /*****************************************************************************************
479 NAME
480 aoHidd_BitMap_PixFmt
482 SYNOPSIS
483 [I.G], OOP_Object *
485 LOCATION
486 hidd.gfx.bitmap
488 FUNCTION
489 Specify or query pixelformat descriptor object associated with the bitmap.
491 Every bitmap has some associated pixelformat object. Pixelformat objects are
492 shared data storages, so many bitmaps may refer to the same pixelformat objects.
494 NOTES
495 This attribute is internally specified during bitmap creation, but it's illegal
496 to do this for the user. CreateObject method of graphics driver performs an explicit
497 check against this. It's up to graphics base classes to figure out its value.
499 EXAMPLE
501 BUGS
503 SEE ALSO
505 INTERNALS
507 *****************************************************************************************/
509 /*****************************************************************************************
511 NAME
512 aoHidd_BitMap_ModeID
514 SYNOPSIS
515 [ISG], HIDDT_ModeID
517 LOCATION
518 hidd.gfx.bitmap
520 FUNCTION
521 Specify display mode ID for displayable bitmap.
523 A displayable bitmap must have this attribute supplied with valid value. A nondisplayable
524 one may miss it, however it may remember it if it was created as a friend of displayable
525 one. This way you may create another displayable bitmap as a friend of nondisplayable
526 one which in turn is a friend of displayable one.
528 This attribute can be set on a framebuffer bitmap. Doing so means an explicit request
529 for the driver to change current display mode on the hardware. Dependent parameters
530 (width, height and pixelformat) will be automatically adjusted, if not explicitly
531 specified in the attributes list.
533 NOTES
534 If the given ModeID is not supported, the operation causes an error. You can check
535 for this by checking return value of OOP_SetAttrs() function. It will be TRUE in
536 case of success and FALSE upon failure. In case of failure none of bitmap attributes
537 will be changed.
539 EXAMPLE
541 BUGS
543 SEE ALSO
545 INTERNALS
547 *****************************************************************************************/
549 /*****************************************************************************************
551 NAME
552 aoHidd_BitMap_ClassPtr
554 SYNOPSIS
555 [I..], OOP_Class *
557 LOCATION
558 hidd.gfx.bitmap
560 FUNCTION
561 Explicitly specify bitmap's class pointer.
563 This attribute is not actually a bitmap's attribute. Your display driver class can
564 supply it to base class' moHidd_Gfx_CreateObject method in order to select a class on
565 which to call OOP_NewObject().
567 If neither this attribute nor aoHidd_BitMap_ClassID attribute is provided for
568 moHidd_Gfx_CreateObject, graphics base class will do its best in order to find out the
569 correct class based on aoHidd_StdPixFmt attribute value or friend bitmap.
571 NOTES
572 If a friend bitmap is given, the new bitmap will have the same class, if your driver
573 doesn't override it by supplying explicit class specification (using either
574 aoHidd_BitMap_ClassPtr or aoHidd_BitMap_ClassID attribute).
576 EXAMPLE
578 BUGS
580 SEE ALSO
581 aoHidd_BitMap_ClassID, CLID_Hidd_Gfx/moHidd_Gfx_CreateObject
583 INTERNALS
585 *****************************************************************************************/
587 /*****************************************************************************************
589 NAME
590 aoHidd_BitMap_ClassID
592 SYNOPSIS
593 [I..]
595 LOCATION
596 hidd.gfx.bitmap
598 FUNCTION
599 Explicitly specify bitmap's class ID.
601 The purpose of this attribute is to let graphics driver base class to select a class
602 on which to call OOP_NewObject() in its moHidd_Gfx_CreateObject implementation.
604 If neither this attribute nor aoHidd_BitMap_ClassPtr attribute is provided for
605 moHidd_Gfx_CreateObject, graphics base class will do its best in order to find out the
606 correct class based on aoHidd_StdPixFmt attribute value or aoHidd_BitMap_ClassPtr value
607 of friend bitmap.
609 NOTES
611 EXAMPLE
613 BUGS
614 The pointer to a given class will not be remembered as aoHidd_BitMap_ClassPtr value.
616 SEE ALSO
617 aoHidd_BitMap_ClassPtr, CLID_Hidd_Gfx/moHidd_Gfx_CreateObject
619 INTERNALS
621 *****************************************************************************************/
623 /*****************************************************************************************
625 NAME
626 aoHidd_BitMap_PixFmtTags
628 SYNOPSIS
629 [...]
631 LOCATION
632 hidd.gfx.bitmap
634 FUNCTION
635 Private, very obsolete and currently has no function. Considered reserved.
637 NOTES
639 EXAMPLE
641 BUGS
643 SEE ALSO
645 INTERNALS
647 *****************************************************************************************/
649 /*****************************************************************************************
651 NAME
652 aoHidd_BitMap_FrameBuffer
654 SYNOPSIS
655 [I.G], BOOL
657 LOCATION
658 hidd.gfx.bitmap
660 FUNCTION
661 Specifies that the bitmap is a framebuffer bitmap.
663 A detailed description of a framebuffer is given in CLID_Hidd_Gfx/moHidd_Gfx_CreateObject
664 and in CLID_Hidd_Gfx/moHidd_Gfx_Show documentation.
666 Specifying this attribute causes also implicit setting of aoHidd_BitMap_Displayable
667 to TRUE.
669 NOTES
671 EXAMPLE
673 BUGS
675 SEE ALSO
677 INTERNALS
679 *****************************************************************************************/
681 /*****************************************************************************************
683 NAME
684 aoHidd_BitMap_LeftEdge
686 SYNOPSIS
687 [.SG]
689 LOCATION
690 hidd.gfx.bitmap
692 FUNCTION
693 Controls horizontal position of a scrollable screen bitmap.
695 Size of displayable bitmaps may differ from actual screen size. In this case the
696 bitmap can be scrolled around the whole display area. If the bitmap is larger than
697 the display, only its part can be visible.
699 Setting this attribute causes changing left origin point of the bitmap. The value
700 of this attribute represents an offset from the physical edge of the display to the
701 logical edge of the bitmap. This means that if a large bitmap scrolls to the left in
702 order to reveal its right part, the offset will be negative. If the bitmap scrolls
703 to the left (possibly revealing another bitmap behind it), the offset will be positive.
705 It's up to the display driver to set scroll limits. If the value of the attribute
706 becomes unacceptable for any reason, the driver should adjust it and provide the real
707 resulting value back.
709 NOTES
710 Implementing screen scrolling does not enforce to implement screen composition, despite
711 the composition is really based on scrolling (in case of composition scrolling a bitmap
712 off-display is expected to reveal another bitmap behind it instead of empty space).
714 EXAMPLE
716 BUGS
718 SEE ALSO
719 aoHidd_BitMap_TopEdge
721 INTERNALS
722 Base class will always provide zero value for this attribute and ignore all attempts
723 to set it. This means that by default bitmaps don't scroll and this needs explicit
724 implementation in the display driver.
726 *****************************************************************************************/
728 /*****************************************************************************************
730 NAME
731 aoHidd_BitMap_TopEdge
733 SYNOPSIS
734 [.SG]
736 LOCATION
737 hidd.gfx.bitmap
739 FUNCTION
740 Controls vertical position of a scrollable screen bitmap.
742 Size of displayable bitmaps may differ from actual screen size. In this case the
743 bitmap can be scrolled around the whole display area. If the bitmap is larger than
744 the display, only its part can be visible.
746 Setting this attribute causes changing top origin point of the bitmap. The value
747 of this attribute represents an offset from the physical edge of the display to the
748 logical edge of the bitmap. This means that if a large bitmap scrolls upwards in
749 order to reveal its bottom part, the offset will be negative. If the bitmap scrolls
750 downwards (possibly revealing another bitmap behind it), the offset will be positive.
752 It's up to the display driver to set scroll limits. If the value of the attribute
753 becomes unacceptable for any reason, the driver should adjust it and provide the real
754 resulting value back.
756 NOTES
757 Implementing screen scrolling does not enforce to implement screen composition, despite
758 the composition is really based on scrolling (in case of composition scrolling a bitmap
759 off-display is expected to reveal another bitmap behind it instead of empty space).
761 EXAMPLE
763 BUGS
765 SEE ALSO
767 INTERNALS
769 *****************************************************************************************/
771 /*****************************************************************************************
773 NAME
774 aoHidd_BitMap_Align
776 SYNOPSIS
777 [I.G]
779 LOCATION
780 hidd.gfx.bitmap
782 FUNCTION
783 Specify number of pixels to align bitmap data width to.
785 This attribute can be added in order to enforce alignment needed for example by
786 blitting hardware. It will have an impact on default aoHidd_BitMap_BytesPerRow
787 value.
789 Direct specification of aoHidd_BitMap_BytesPerRow attribute overrides any value
790 of this attribute.
792 NOTES
793 Default value of this attribute is 16. This alignment is required by graphics.library
794 for AmigaOS(tm) compatibility reasons.
796 EXAMPLE
798 BUGS
800 SEE ALSO
801 aoHidd_BitMap_BytesPerRow
803 INTERNALS
805 *****************************************************************************************/
807 /*****************************************************************************************
809 NAME
810 aoHidd_BitMap_Depth
812 SYNOPSIS
813 [G.I]
815 LOCATION
816 hidd.gfx.bitmap
818 FUNCTION
819 Specify or query the actual bitmap depth.
821 This a convenience attribute to simplify handling planar bitmaps, whose actual depth
822 may vary. Default implementation in base class simply returns depth of bitmap's
823 pixelformat, and is ignored during initialization. Planar bitmap class returns the
824 actual depth here. If your specific bitmap class also operates on bitmaps with variable
825 depths, you need to implement this attribute in it.
827 NOTES
829 EXAMPLE
831 BUGS
833 SEE ALSO
835 INTERNALS
837 *****************************************************************************************/
839 /****************************************************************************************/
841 #undef csd
844 * Calculate suggested bytes per row value based on bitmap's default alignment
845 * and pixelformat's bytes per pixel value.
847 static ULONG GetBytesPerRow(struct HIDDBitMapData *data, struct class_static_data *csd)
849 struct Library *OOPBase = csd->cs_OOPBase;
850 UWORD align = data->align - 1;
851 UWORD width = (data->width + align) & ~align;
852 IPTR bytesperpixel, stdpf;
854 OOP_GetAttr(data->prot.pixfmt, aHidd_PixFmt_BytesPerPixel, &bytesperpixel);
855 OOP_GetAttr(data->prot.pixfmt, aHidd_PixFmt_StdPixFmt, &stdpf);
857 if (stdpf == vHidd_StdPixFmt_Plane)
860 * Planar format actually have 8 pixels per one byte.
861 * However bytesperpixel == 1 for them. Perhaps this should
862 * be changed to 0 ?
864 return width >> 3;
866 else
868 return width * bytesperpixel;
872 #define csd CSD(cl)
874 OOP_Object *BM__Root__New(OOP_Class *cl, OOP_Object *obj, struct pRoot_New *msg)
876 struct Library *OOPBase = CSD(cl)->cs_OOPBase;
877 struct Library *UtilityBase = CSD(cl)->cs_UtilityBase;
879 EnterFunc(bug("BitMap::New()\n"));
881 obj = (OOP_Object *)OOP_DoSuperMethod(cl, obj, (OOP_Msg) msg);
883 if (NULL != obj)
885 struct TagItem colmap_tags[] =
887 { aHidd_ColorMap_NumEntries , 16 },
888 { TAG_DONE }
890 struct TagItem *tag, *tstate;
891 BOOL ok = TRUE;
892 struct HIDDBitMapData *data = OOP_INST_DATA(cl, obj);
894 /* Set some default values */
895 data->modeid = vHidd_ModeID_Invalid;
896 data->align = 16;
898 data->compositable = FALSE;
900 tstate = msg->attrList;
901 while ((tag = NextTagItem(&tstate)))
903 ULONG idx;
905 if (IS_BITMAP_ATTR(tag->ti_Tag, idx))
907 switch (idx)
909 case aoHidd_BitMap_BMStruct:
910 data->bmstruct = (struct BitMap *)tag->ti_Data;
911 break;
913 case aoHidd_BitMap_Width:
914 data->width = tag->ti_Data;
915 break;
917 case aoHidd_BitMap_Height:
918 data->height = tag->ti_Data;
919 break;
921 case aoHidd_BitMap_Align:
922 data->align = tag->ti_Data;
923 break;
925 case aoHidd_BitMap_BytesPerRow:
926 data->bytesPerRow = tag->ti_Data;
927 break;
929 case aoHidd_BitMap_GfxHidd:
930 data->gfxhidd = (OOP_Object *)tag->ti_Data;
931 break;
933 case aoHidd_BitMap_Friend:
934 data->friend = (OOP_Object *)tag->ti_Data;
935 break;
937 case aoHidd_BitMap_Displayable:
938 data->displayable = tag->ti_Data;
939 break;
941 case aoHidd_BitMap_Compositable:
942 data->compositable = tag->ti_Data;
943 break;
945 case aoHidd_BitMap_FrameBuffer:
946 data->framebuffer = tag->ti_Data;
947 break;
949 case aoHidd_BitMap_ModeID:
950 data->modeid = tag->ti_Data;
951 break;
953 case aoHidd_BitMap_PixFmt:
954 data->prot.pixfmt = (OOP_Object *)tag->ti_Data;
955 break;
960 /* aoHidd_BitMap_GfxHidd is mandatory */
961 if (!data->gfxhidd)
963 D(bug("!!!! BM CLASS DID NOT GET GFX HIDD !!!\n"));
964 D(bug("!!!! The reason for this is that the gfxhidd subclass CreateObject() method\n"));
965 D(bug("!!!! has not left it to the baseclass to actually create the object,\n"));
966 D(bug("!!!! but rather done it itself. This MUST be corrected in the gfxhidd subclass\n"));
968 ok = FALSE;
971 /* FrameBuffer implies Displayable */
972 if (data->framebuffer)
973 data->displayable = TRUE;
975 if (ok && (data->displayable || data->compositable))
977 HIDDT_ModeID bmmodeid = data->modeid;
979 /* We should always get modeid, but we check anyway */
980 if ((data->compositable) && (data->friend))
982 OOP_GetAttr(data->friend, aHidd_BitMap_ModeID, &bmmodeid);
983 D(bug("!!! BitMap:New() Using Friends ModeID - 0x%08X !!!\n", bmmodeid));
986 if (bmmodeid == vHidd_ModeID_Invalid)
988 D(bug("!!! BitMap:New() NO VALID MODEID SPECIFIED FOR DISPLAYABLE BITMAP !!!\n"));
989 data->compositable = ok = FALSE;
991 else
993 OOP_Object *sync, *pf;
995 if (!HIDD_Gfx_GetMode(data->gfxhidd, bmmodeid, &sync, &pf))
997 D(bug("!!! BitMap::New() RECEIVED INVALID MODEID 0x%08X\n", bmmodeid));
998 data->compositable = ok = FALSE;
1000 else
1002 /* Get display size from the modeid */
1003 OOP_GetAttr(sync, aHidd_Sync_HDisp, &data->displayWidth);
1004 OOP_GetAttr(sync, aHidd_Sync_VDisp, &data->displayHeight);
1005 data->display.MaxX = data->displayWidth;
1006 data->display.MaxY = data->displayHeight;
1008 /* Update the missing bitmap data */
1009 if (!data->width)
1010 data->width = data->displayWidth;
1011 if (!data->height)
1012 data->height = data->displayHeight;
1014 D(bug("[BitMap] Bitmap %dx%d, display %dx%d\n",
1015 data->width, data->height,
1016 data->displayWidth, data->displayHeight));
1018 if (!data->prot.pixfmt)
1020 /* The PixFmt is allready registered and locked in the PixFmt database */
1021 data->prot.pixfmt = pf;
1025 } /* if (ok) */
1027 if (ok)
1029 /* * PixFmt will be NULL in case of e.g. planarbm late initialization. */
1030 if (data->prot.pixfmt)
1032 ULONG bytesPerRow = GetBytesPerRow(data, CSD(cl));
1034 if (data->bytesPerRow)
1036 /* If we have user-supplied BytesPerRow value, make sure it's suitable */
1037 if (data->bytesPerRow < bytesPerRow)
1038 ok = FALSE;
1040 else
1042 /* Otherwise we have what we calculated */
1043 data->bytesPerRow = bytesPerRow;
1048 if (ok)
1050 InitSemaphore(&data->lock);
1052 /* Cache default GC */
1053 OOP_GetAttr(data->gfxhidd, aHidd_Gfx_DefaultGC, (IPTR *)&data->gc);
1056 * Initialize the direct method calling.
1057 * We don't check against errors because our base class contains all
1058 * these functions.
1060 #if USE_FAST_PUTPIXEL
1061 data->putpixel = OOP_GetMethod(obj, HiddBitMapBase + moHidd_BitMap_PutPixel, &data->putpixel_Class);
1062 #endif
1063 #if USE_FAST_GETPIXEL
1064 data->getpixel = OOP_GetMethod(obj, HiddBitMapBase + moHidd_BitMap_GetPixel, &data->getpixel_Class);
1065 #endif
1066 #if USE_FAST_DRAWPIXEL
1067 data->drawpixel = OOP_GetMethod(obj, HiddBitMapBase + moHidd_BitMap_DrawPixel, &data->drawpixel_Class);
1068 #endif
1071 * Try to create the colormap.
1073 * stegerg: Only add a ColorMap for a visible bitmap (screen). This
1074 * is important because one can create for example a bitmap
1075 * in PIXFMT_LUT8 without friend bitmap and then copy this
1076 * bitmap to a 16 bit screen. During copy the screen bitmap
1077 * CLUT must be used, which would not happen if our PIXFMT_LUT8
1078 * also had a colormap itself because then bltbitmap would use the
1079 * colormap of the PIXFMT_LUT8 bitmap as lookup, which in this
1080 * case would just cause everything to become black in the
1081 * destination (screen) bitmap, because noone ever sets up the
1082 * colormap of the PIXFMT_LUT8 bitmap
1084 * sonic: CHECKME: Why does the colormap always have 16 colors? May be calculate this
1085 * based on depth ? The colormap auto-enlarges itself if SetColors method requests
1086 * missing entries, but is it so good?
1089 if (data->displayable)
1091 data->colmap = OOP_NewObject(NULL, CLID_Hidd_ColorMap, colmap_tags);
1092 if (NULL == data->colmap)
1093 ok = FALSE;
1098 if (!ok)
1100 ULONG dispose_mid = OOP_GetMethodID(IID_Root, moRoot_Dispose);
1102 OOP_CoerceMethod(cl, obj, &dispose_mid);
1103 obj = NULL;
1105 } /* if(obj) */
1107 } /* if (NULL != obj) */
1109 ReturnPtr("BitMap::New", OOP_Object *, obj);
1112 /****************************************************************************************/
1114 void BM__Root__Dispose(OOP_Class *cl, OOP_Object *obj, OOP_Msg *msg)
1116 struct Library *OOPBase = CSD(cl)->cs_OOPBase;
1117 struct HIDDBitMapData *data = OOP_INST_DATA(cl, obj);
1119 EnterFunc(bug("BitMap::Dispose()\n"));
1121 if (NULL != data->colmap)
1122 OOP_DisposeObject(data->colmap);
1124 D(bug("Calling super\n"));
1126 /* Release the previously registered pixel format */
1127 if (data->pf_registered)
1128 GFXHIDD__Hidd_Gfx__ReleasePixFmt(CSD(cl)->gfxhiddclass, data->prot.pixfmt);
1130 OOP_DoSuperMethod(cl, obj, (OOP_Msg) msg);
1132 ReturnVoid("BitMap::Dispose");
1135 /****************************************************************************************/
1137 VOID BM__Root__Get(OOP_Class *cl, OOP_Object *obj, struct pRoot_Get *msg)
1139 struct HIDDBitMapData *data = OOP_INST_DATA(cl, obj);
1140 ULONG idx;
1142 EnterFunc(bug("BitMap::Get() attrID: %i storage: %p\n", msg->attrID, msg->storage));
1144 if (IS_BITMAP_ATTR(msg->attrID, idx))
1146 switch(idx)
1148 case aoHidd_BitMap_BMStruct:
1149 *msg->storage = (IPTR)data->bmstruct;
1150 return;
1152 case aoHidd_BitMap_Width:
1153 *msg->storage = data->width;
1154 D(bug(" width: %i\n", data->width));
1155 return;
1157 case aoHidd_BitMap_Height:
1158 *msg->storage = data->height;
1159 return;
1161 case aoHidd_BitMap_Depth:
1163 * Generally our bitmaps have a fixed depth, which depends on pixelformat.
1164 * If this is not true for your bitmap, overload aoHidd_BitMap_Depth in your class.
1166 *msg->storage = ((HIDDT_PixelFormat *)data->prot.pixfmt)->depth;
1167 return;
1169 case aoHidd_BitMap_Displayable:
1170 *msg->storage = data->displayable;
1171 return;
1173 case aoHidd_BitMap_FrameBuffer:
1174 *msg->storage = data->framebuffer;
1175 return;
1177 case aoHidd_BitMap_PixFmt:
1178 *msg->storage = (IPTR)data->prot.pixfmt;
1179 return;
1181 case aoHidd_BitMap_Friend:
1182 *msg->storage = (IPTR)data->friend;
1183 return;
1185 case aoHidd_BitMap_ColorMap:
1186 *msg->storage = (IPTR)data->colmap;
1187 return;
1189 case aoHidd_BitMap_GfxHidd:
1190 *msg->storage = (IPTR)data->gfxhidd;
1191 return;
1193 case aoHidd_BitMap_ModeID:
1194 *msg->storage = data->modeid;
1195 return;
1197 case aoHidd_BitMap_Align:
1198 *msg->storage = data->align;
1199 return;
1201 case aoHidd_BitMap_BytesPerRow:
1202 *msg->storage = data->bytesPerRow;
1203 return;
1205 case aoHidd_BitMap_Visible:
1206 /* Framebuffer is always visible */
1207 *msg->storage = data->framebuffer ? TRUE : data->visible;
1208 return;
1210 case aoHidd_BitMap_Compositable:
1211 *msg->storage = (IPTR)data->compositable;
1212 return;
1215 * The following two are stored with inverted sign!
1216 * Verbose explanation is in Set method.
1218 case aoHidd_BitMap_LeftEdge:
1219 *msg->storage = -data->display.MinX;
1220 return;
1222 case aoHidd_BitMap_TopEdge:
1223 *msg->storage = -data->display.MinY;
1224 return;
1226 D(default: bug("UNKNOWN ATTR IN BITMAP BASECLASS: %d\n", idx);)
1230 OOP_DoSuperMethod(cl, obj, &msg->mID);
1231 ReturnVoid("BitMap::Get");
1234 /****************************************************************************************/
1236 #define UB(x) ((UBYTE *)x)
1238 /*****************************************************************************************
1240 NAME
1241 moHidd_BitMap_SetColors
1243 SYNOPSIS
1244 BOOL OOP_DoMethod(OOP_Object *obj, struct pHidd_BitMap_SetColors *msg);
1246 BOOL HIDD_BM_SetColors (OOP_Object *obj, HIDDT_Color *colors,
1247 UWORD firstColor, UWORD numColors);
1249 LOCATION
1250 hidd.gfx.bitmap
1252 FUNCTION
1253 Sets values for one or more colors in the colormap object associated with the
1254 bitmap.
1256 The colormap will be created if it does not exist.
1258 Only ARGB values from the source array are taken into account. pixval member is
1259 updated with the real pixel value for every color.
1261 INPUTS
1262 obj - A bitmap object whose colormap needs to be set
1263 colors - A pointer to source data array
1264 firstColor - Number of the first color to set
1265 numColors - Number of subsequent colors to set
1267 RESULT
1268 TRUE on success, FALSE in case of some error (like out of memory)
1270 NOTES
1272 EXAMPLE
1274 BUGS
1276 SEE ALSO
1277 CLID_Hidd_ColorMap/moHidd_ColorMap_SetColors
1279 INTERNALS
1281 *****************************************************************************************/
1283 BOOL BM__Hidd_BitMap__SetColors(OOP_Class *cl, OOP_Object *o, struct pHidd_BitMap_SetColors *msg)
1285 /* Copy the colors into the internal buffer */
1286 struct Library *OOPBase = CSD(cl)->cs_OOPBase;
1287 struct HIDDBitMapData *data = OOP_INST_DATA(cl, o);
1288 BOOL ret = TRUE;
1290 /* Subclass has initialized HIDDT_Color->pixelVal field and such.
1291 Just copy it into the colortab.
1294 if (NULL == data->colmap)
1296 struct TagItem colmap_tags[] =
1298 { aHidd_ColorMap_NumEntries, 0 },
1299 { TAG_DONE }
1302 colmap_tags[0].ti_Data = msg->firstColor + msg->numColors;
1303 data->colmap = OOP_NewObject(NULL, CLID_Hidd_ColorMap, colmap_tags);
1306 if (NULL == data->colmap)
1308 return FALSE;
1311 /* Use the colormap class to set the colors */
1312 if (!HIDD_CM_SetColors(data->colmap, msg->colors,
1313 msg->firstColor, msg->numColors,
1314 data->prot.pixfmt))
1316 return FALSE;
1319 /* We may need to duplicate changes on framebuffer if running in mirrored mode */
1320 if (data->visible)
1322 ObtainSemaphoreShared(&data->lock);
1324 if (data->visible)
1326 ret = GFXHIDD__Hidd_Gfx__SetFBColors(CSD(cl)->gfxhiddclass, data->gfxhidd, msg);
1329 ReleaseSemaphore(&data->lock);
1332 return ret;
1335 /*******************************************************************************
1337 NAME
1338 moHidd_BitMap_PutPixel
1340 SYNOPSIS
1341 VOID OOP_DoMethod(OOP_Object *obj, struct pHidd_BitMap_PutPixel *msg);
1343 VOID HIDD_BM_PutPixel(OOP_Object *obj, WORD x, WORD y,
1344 HIDDT_Pixel pixel);
1346 LOCATION
1347 hidd.gfx.bitmap
1349 FUNCTION
1350 Sets a new color value for the pixel at (x,y). The actual color stored
1351 may be an approximation, due to the limited color depth or palette size
1352 of the bitmap. This function does not check the coordinates.
1354 INPUTS
1355 obj - bitmap to write to.
1356 x, y - coordinates of the pixel to write.
1357 pixel - the pixel's new color value.
1359 RESULT
1360 None.
1362 NOTES
1364 EXAMPLE
1366 BUGS
1368 SEE ALSO
1370 INTERNALS
1372 *******************************************************************************/
1374 /* PutPixel must be implemented in a subclass */
1376 /*****************************************************************************************
1378 NAME
1379 moHidd_BitMap_DrawPixel
1381 SYNOPSIS
1382 VOID OOP_DoMethod(OOP_Object *obj, struct pHidd_BitMap_DrawPixel *msg);
1384 VOID HIDD_BM_DrawPixel(OOP_Object *obj, OOP_Object *gc, WORD x, WORD y);
1386 LOCATION
1387 hidd.gfx.bitmap
1389 FUNCTION
1390 Changes the pixel at (x,y). The color of the pixel depends on the
1391 attributes of gc, eg. colors, drawmode, colormask etc.
1392 This function does not check the coordinates.
1394 INPUTS
1395 obj - A bitmap to draw on
1396 gc - A GC (graphics context) object to use for drawing
1397 x, y - Coordinates of the pixel to draw
1399 RESULT
1400 None.
1402 NOTES
1404 EXAMPLE
1406 BUGS
1408 SEE ALSO
1410 INTERNALS
1412 TODO
1413 - Support for shapeplane.
1414 - Optimize
1416 *****************************************************************************************/
1418 VOID BM__Hidd_BitMap__DrawPixel(OOP_Class *cl, OOP_Object *obj,
1419 struct pHidd_BitMap_DrawPixel *msg)
1421 HIDDT_Pixel src, dest, val;
1422 HIDDT_DrawMode mode;
1423 HIDDT_Pixel writeMask;
1424 OOP_Object *gc;
1426 /* EnterFunc(bug("BitMap::DrawPixel() x: %i, y: %i\n", msg->x, msg->y));
1429 Example: Pixels whose bits are set to 0 in the colMask must be
1430 unchanged
1432 data->colMask = 001111
1433 dest = 101100
1436 writeMask = ~data->colMask & dest
1437 = 110000 & 101100
1438 = 100000
1440 dest = data->fg && dest = 010100
1443 dest = dest & (writeMask | data->ColMask)
1444 = 010100 & (100000 | 001111)
1445 = 010100 & (101111)
1446 = 000100
1449 dest = dest | writeMask;
1450 = 000100 100000
1451 = 100100
1455 gc = msg->gc;
1457 src = GC_FG(gc);
1458 mode = GC_DRMD(gc);
1460 #if OPTIMIZE_DRAWPIXEL_FOR_COPY
1461 if (vHidd_GC_DrawMode_Copy == mode && GC_COLMASK(gc) == ~0)
1463 val = src;
1465 else
1466 #endif
1468 dest = GETPIXEL(cl, obj, msg->x, msg->y);
1469 writeMask = ~GC_COLMASK(gc) & dest;
1471 val = 0;
1473 if(mode & 1) val = ( src & dest);
1474 if(mode & 2) val = ( src & ~dest) | val;
1475 if(mode & 4) val = (~src & dest) | val;
1476 if(mode & 8) val = (~src & ~dest) | val;
1478 val = (val & (writeMask | GC_COLMASK(gc) )) | writeMask;
1482 PUTPIXEL(cl, obj, msg->x, msg->y, val);
1485 /*****************************************************************************************
1487 NAME
1488 moHidd_BitMap_DrawLine
1490 SYNOPSIS
1491 VOID OOP_DoMethod(OOP_Object *obj, struct pHidd_BitMap_DrawPixel *msg);
1493 VOID HIDD_BM_DrawLine(OOP_Object *obj, OOP_Object *gc, WORD x1, WORD y1,
1494 WORD x2, WORD y2);
1496 LOCATION
1497 hidd.gfx.bitmap
1499 FUNCTION
1500 Draws a line from (x1,y1) to (x2,y2) in the specified gc.
1501 The function does not clip the line against the drawing area.
1503 INPUTS
1504 obj - A bitmap to draw on
1505 gc - A graphics context object to use
1506 x1,y1 - start point of the line in pixels
1507 x2,y2 - end point of the line in pixels
1509 RESULT
1510 None.
1512 NOTES
1514 EXAMPLE
1516 BUGS
1518 SEE ALSO
1520 INTERNALS
1521 Uses midpoint line ("Bresenham") algorithm([FOL90] 3.2.2)
1523 TODO Support for line pattern
1524 Optimize remove if t == 1 ...
1525 Implement better clipping: Should be no reason to calculate
1526 more than the part of the line that is inside the cliprect
1528 *****************************************************************************************/
1530 VOID BM__Hidd_BitMap__DrawLine
1532 OOP_Class *cl, OOP_Object *obj, struct pHidd_BitMap_DrawLine *msg
1535 WORD dx, dy, incrE, incrNE, d, x, y, s1, s2, t, i;
1536 WORD x1, y1, x2, y2;
1537 UWORD maskLine; /* for line pattern */
1538 ULONG fg; /* foreground pen */
1539 APTR doclip;
1540 BOOL opaque;
1541 OOP_Object *gc;
1544 /* bug("BitMap::DrawLine()\n");
1545 */ EnterFunc(bug("BitMap::DrawLine() x1: %i, y1: %i x2: %i, y2: %i\n", msg->x1, msg->y1, msg->x2, msg->y2));
1547 gc = msg->gc;
1548 doclip = GC_DOCLIP(gc);
1549 opaque = (GC_COLEXP(gc) & vHidd_GC_ColExp_Opaque) ? TRUE : FALSE;
1550 fg = GC_FG(gc);
1552 maskLine = 1 << GC_LINEPATCNT(gc);
1554 if (doclip)
1556 /* If line is not inside cliprect, then just return */
1557 /* Normalize coords */
1558 if (msg->x1 > msg->x2)
1560 x1 = msg->x2; x2 = msg->x1;
1562 else
1564 x1 = msg->x1; x2 = msg->x2;
1567 if (msg->y1 > msg->y2)
1569 y1 = msg->y2; y2 = msg->y1;
1571 else
1573 y1 = msg->y1; y2 = msg->y2;
1576 if ( x1 > GC_CLIPX2(gc)
1577 || x2 < GC_CLIPX1(gc)
1578 || y1 > GC_CLIPY2(gc)
1579 || y2 < GC_CLIPY1(gc) )
1582 /* Line is not inside cliprect, so just return */
1583 return;
1588 x1 = msg->x1;
1589 y1 = msg->y1;
1590 x2 = msg->x2;
1591 y2 = msg->y2;
1593 if (y1 == y2)
1596 Horizontal line drawing code.
1598 y = y1;
1600 /* Don't swap coordinates if x2 < x1! Because of linepattern! */
1602 if (x1 < x2)
1604 x2++;
1605 dx = 1;
1607 else
1609 x2--;
1610 dx = -1;
1613 for(i = x1; i != x2; i += dx)
1615 /* Pixel inside ? */
1617 if (!doclip || !POINT_OUTSIDE_CLIP(gc, i, y ))
1619 if(GC_LINEPAT(gc) & maskLine)
1621 HIDD_BM_DrawPixel(obj, gc, i, y);
1623 else if (opaque)
1625 GC_FG(gc) = GC_BG(gc);
1626 HIDD_BM_DrawPixel(obj, gc, i, y);
1627 GC_FG(gc) = fg;
1631 maskLine = maskLine >> 1;
1632 if (!maskLine) maskLine = 1L << 15;
1635 else if (x1 == x2)
1638 Vertical line drawing code.
1640 x = x1;
1642 /* Don't swap coordinates if y2 < y1! Because of linepattern! */
1644 if (y1 < y2)
1646 y2++;
1647 dy = 1;
1649 else
1651 y2--;
1652 dy = -1;
1655 for(i = y1; i != y2; i += dy)
1657 /* Pixel inside ? */
1658 if (!doclip || !POINT_OUTSIDE_CLIP(gc, x, i ))
1660 if(GC_LINEPAT(gc) & maskLine)
1662 HIDD_BM_DrawPixel(obj, gc, x, i);
1664 else if (opaque)
1666 GC_FG(gc) = GC_BG(gc);
1667 HIDD_BM_DrawPixel(obj, gc, x, i);
1668 GC_FG(gc) = fg;
1672 maskLine = maskLine >> 1;
1673 if (!maskLine) maskLine = 1L << 15;
1677 else
1680 Generic line drawing code.
1682 /* Calculate slope */
1683 dx = abs(x2 - x1);
1684 dy = abs(y2 - y1);
1686 /* which direction? */
1687 if((x2 - x1) > 0) s1 = 1; else s1 = - 1;
1688 if((y2 - y1) > 0) s2 = 1; else s2 = - 1;
1690 /* change axes if dx < dy */
1691 if(dx < dy)
1693 d = dx;
1694 dx = dy;
1695 dy = d;
1696 t = 0;
1698 else
1700 t = 1;
1703 d = 2 * dy - dx; /* initial value of d */
1705 incrE = 2 * dy; /* Increment use for move to E */
1706 incrNE = 2 * (dy - dx); /* Increment use for move to NE */
1708 x = x1; y = y1;
1710 for(i = 0; i <= dx; i++)
1712 /* Pixel inside ? */
1713 if (!doclip || !POINT_OUTSIDE_CLIP(gc, x, y ))
1715 if(GC_LINEPAT(gc) & maskLine)
1717 HIDD_BM_DrawPixel(obj, gc, x, y);
1719 else if (opaque)
1721 GC_FG(gc) = GC_BG(gc);
1722 HIDD_BM_DrawPixel(obj, gc, x, y);
1723 GC_FG(gc) = fg;
1727 if(d <= 0)
1729 if(t == 1)
1731 x = x + s1;
1733 else
1735 y = y + s2;
1738 d = d + incrE;
1740 else
1742 x = x + s1;
1743 y = y + s2;
1744 d = d + incrNE;
1747 maskLine = maskLine >> 1;
1748 if (!maskLine) maskLine = 1L << 15;
1753 ReturnVoid("BitMap::DrawLine ");
1756 /*****************************************************************************************
1758 NAME
1759 moHidd_BitMap_DrawRect
1761 SYNOPSIS
1762 OOP_DoMethod(OOP_Object *obj, struct pHidd_BitMap_DrawRect *msg);
1764 VOID HIDD_BM_DrawRect (OOP_Object *obj, OOP_Object *gc, WORD minX, WORD minY,
1765 WORD maxX, WORD maxY);
1767 LOCATION
1768 hidd.gfx.bitmap
1770 FUNCTION
1771 Draws a hollow rectangle. minX and minY specifies the upper
1772 left corner of the rectangle. minY and maxY specifies the lower
1773 right corner of the rectangle.
1774 The function does not clip the rectangle against the drawing area.
1776 INPUTS
1777 obj - A bitmap to draw on
1778 gc - A GC object to use for drawing
1779 minX, minY - upper left corner of the rectangle in pixels
1780 maxX, maxY - lower right corner of the rectangle in pixels
1782 RESULT
1783 None.
1785 NOTES
1786 This method is not used by the system and considered reserved.
1788 EXAMPLE
1790 BUGS
1792 SEE ALSO
1794 INTERNALS
1796 TODO
1798 *****************************************************************************************/
1800 VOID BM__Hidd_BitMap__DrawRect(OOP_Class *cl, OOP_Object *obj,
1801 struct pHidd_BitMap_DrawRect *msg)
1803 #ifdef __RESERVED__
1804 OOP_Object *gc = msg->gc;
1805 WORD addX, addY;
1807 EnterFunc(bug("BitMap::DrawRect()"));
1809 if(msg->minX == msg->maxX) addX = 0; else addX = 1;
1810 if(msg->minY == msg->maxY) addY = 0; else addY = 1;
1812 HIDD_BM_DrawLine(obj, gc, msg->minX, msg->minY , msg->maxX, msg->minY);
1813 HIDD_BM_DrawLine(obj, gc, msg->maxX, msg->minY + addY, msg->maxX, msg->maxY);
1814 HIDD_BM_DrawLine(obj, gc, msg->maxX - addX, msg->maxY, msg->minX, msg->maxY);
1815 HIDD_BM_DrawLine(obj, gc, msg->minX, msg->maxY - addY, msg->minX, msg->minY + addY);
1816 #endif
1818 ReturnVoid("BitMap::DrawRect");
1821 /*****************************************************************************************
1823 NAME
1824 moHidd_BitMap_FillRect
1826 SYNOPSIS
1827 VOID OOP_DoMethod(OOP_Object *obj, struct pHidd_BitMap_DrawRect *msg);
1829 VOID HIDD_BM_FillRect (OOP_Object *obj, OOP_Object *gc, WORD minX, WORD minY,
1830 WORD maxX, WORD maxY);
1832 LOCATION
1833 hidd.gfx.bitmap
1835 FUNCTION
1837 Draws a solid rectangle. minX and minY specifies the upper
1838 left corner of the rectangle. maxX and maxY specifies the lower
1839 right corner of the rectangle.
1840 The function does not clip the rectangle against the drawing area.
1842 INPUTS
1843 obj - A bitmap to draw on
1844 gc - A GC object to use for drawing
1845 minX, minY - upper left corner of the rectangle in pixels
1846 maxX, maxY - lower right corner of the rectangle in pixels
1848 RESULT
1849 None.
1851 NOTES
1853 EXAMPLE
1855 BUGS
1857 SEE ALSO
1859 INTERNALS
1861 TODO
1862 Fill with pattern
1864 *****************************************************************************************/
1866 VOID BM__Hidd_BitMap__FillRect(OOP_Class *cl, OOP_Object *obj,
1867 struct pHidd_BitMap_DrawRect *msg)
1869 OOP_Object *gc = msg->gc;
1870 WORD y = msg->minY;
1871 UWORD linepat;
1873 EnterFunc(bug("BitMap::FillRect()"));
1875 linepat = GC_LINEPAT(gc);
1876 GC_LINEPAT(gc) = ~0;
1878 for(; y <= msg->maxY; y++)
1880 HIDD_BM_DrawLine(obj, gc, msg->minX, y, msg->maxX, y);
1883 GC_LINEPAT(gc) = linepat;
1885 ReturnVoid("BitMap::FillRect");
1888 /*****************************************************************************************
1890 NAME
1891 moHidd_BitMap_DrawEllipse
1893 SYNOPSIS
1894 VOID OOP_DoMethod(OOP_Object *obj, struct pHidd_BitMap_DrawEllipse *msg);
1896 VOID HIDD_BM_DrawEllipse (OOP_Object *obj, OOP_Object *gc, WORD x, WORD y,
1897 WORD rx, WORD ry);
1899 LOCATION
1900 hidd.gfx.bitmap
1902 FUNCTION
1903 Draws a hollow ellipse from the center point (x,y) with the radii
1904 rx and ry in the specified bitmap.
1905 The function does not clip the ellipse against the drawing area.
1907 INPUTS
1908 obj - A bitmap to draw on
1909 gc - A GC object to use for drawing
1910 x,y - Coordinates of center point in pixels
1911 rx,ry - ry and ry radius in pixels
1913 RESULT
1914 None.
1916 NOTES
1918 EXAMPLE
1920 BUGS
1921 Because of overflow the current code do not work with big
1922 values of rx and ry.
1924 SEE ALSO
1926 INTERNALS
1928 TODO
1929 Bugfix
1931 *****************************************************************************************/
1933 /* TODO: Try to opimize clipping here */
1935 VOID BM__Hidd_BitMap__DrawEllipse(OOP_Class *cl, OOP_Object *obj,
1936 struct pHidd_BitMap_DrawEllipse *msg)
1938 OOP_Object *gc = msg->gc;
1939 WORD x = msg->rx, y = 0; /* ellipse points */
1941 /* intermediate terms to speed up loop */
1942 LONG t1 = msg->rx * msg->rx, t2 = t1 << 1, t3 = t2 << 1;
1943 LONG t4 = msg->ry * msg->ry, t5 = t4 << 1, t6 = t5 << 1;
1944 LONG t7 = msg->rx * t5, t8 = t7 << 1, t9 = 0L;
1945 LONG d1 = t2 - t7 + (t4 >> 1); /* error terms */
1946 LONG d2 = (t1 >> 1) - t8 + t5;
1948 APTR doclip = GC_DOCLIP(gc);
1951 EnterFunc(bug("BitMap::DrawEllipse()"));
1953 while (d2 < 0) /* till slope = -1 */
1955 /* draw 4 points using symmetry */
1957 if (doclip)
1960 if (!POINT_OUTSIDE_CLIP(gc, msg->x + x, msg->y + y))
1961 HIDD_BM_DrawPixel(obj, gc, msg->x + x, msg->y + y);
1963 if (!POINT_OUTSIDE_CLIP(gc, msg->x + x, msg->y - y))
1964 HIDD_BM_DrawPixel(obj, gc, msg->x + x, msg->y - y);
1966 if (!POINT_OUTSIDE_CLIP(gc, msg->x - x, msg->y + y))
1967 HIDD_BM_DrawPixel(obj, gc, msg->x - x, msg->y + y);
1969 if (!POINT_OUTSIDE_CLIP(gc, msg->x - x, msg->y - y))
1970 HIDD_BM_DrawPixel(obj, gc, msg->x - x, msg->y - y);
1973 else
1975 HIDD_BM_DrawPixel(obj, gc, msg->x + x, msg->y + y);
1976 HIDD_BM_DrawPixel(obj, gc, msg->x + x, msg->y - y);
1977 HIDD_BM_DrawPixel(obj, gc, msg->x - x, msg->y + y);
1978 HIDD_BM_DrawPixel(obj, gc, msg->x - x, msg->y - y);
1981 y++; /* always move up here */
1982 t9 = t9 + t3;
1983 if (d1 < 0) /* move straight up */
1985 d1 = d1 + t9 + t2;
1986 d2 = d2 + t9;
1988 else /* move up and left */
1990 x--;
1991 t8 = t8 - t6;
1992 d1 = d1 + t9 + t2 - t8;
1993 d2 = d2 + t9 + t5 - t8;
1997 do /* rest of top right quadrant */
1999 /* draw 4 points using symmetry */
2000 #if 1
2001 if (doclip)
2004 if (!POINT_OUTSIDE_CLIP(gc, msg->x + x, msg->y + y))
2005 HIDD_BM_DrawPixel(obj, gc, msg->x + x, msg->y + y);
2007 if (!POINT_OUTSIDE_CLIP(gc, msg->x + x, msg->y - y))
2008 HIDD_BM_DrawPixel(obj, gc, msg->x + x, msg->y - y);
2010 if (!POINT_OUTSIDE_CLIP(gc, msg->x - x, msg->y + y))
2011 HIDD_BM_DrawPixel(obj, gc, msg->x - x, msg->y + y);
2013 if (!POINT_OUTSIDE_CLIP(gc, msg->x - x, msg->y - y))
2014 HIDD_BM_DrawPixel(obj, gc, msg->x - x, msg->y - y);
2017 else
2020 HIDD_BM_DrawPixel(obj, gc, msg->x + x, msg->y + y);
2021 HIDD_BM_DrawPixel(obj, gc, msg->x + x, msg->y - y);
2022 HIDD_BM_DrawPixel(obj, gc, msg->x - x, msg->y + y);
2023 HIDD_BM_DrawPixel(obj, gc, msg->x - x, msg->y - y);
2025 #else
2027 HIDD_BM_DrawPixel(obj, gc, msg->x + x, msg->y + y);
2028 HIDD_BM_DrawPixel(obj, gc, msg->x + x, msg->y - y);
2029 HIDD_BM_DrawPixel(obj, gc, msg->x - x, msg->y + y);
2030 HIDD_BM_DrawPixel(obj, gc, msg->x - x, msg->y - y);
2031 #endif
2032 x--; /* always move left here */
2033 t8 = t8 - t6;
2034 if (d2 < 0) /* move up and left */
2036 y++;
2037 t9 = t9 + t3;
2038 d2 = d2 + t9 + t5 - t8;
2040 else /* move straight left */
2042 d2 = d2 + t5 - t8;
2045 } while (x >= 0);
2048 ReturnVoid("BitMap::DrawEllipse");
2051 /*****************************************************************************************
2053 NAME
2054 moHidd_BitMap_FillEllipse
2056 SYNOPSIS
2057 VOID OOP_DoMethod(OOP_Object *obj, struct pHidd_BitMap_DrawEllipse *msg);
2059 VOID HIDD_BM_FillEllipse (OOP_Object *obj, OOP_Object *gc, WORD x, WORD y,
2060 WORD ry, WORD rx);
2062 LOCATION
2063 hidd.gfx.bitmap
2065 FUNCTION
2066 Draws a solid ellipse from the center point (x,y) with the radii
2067 rx and ry in the specified bitmap.
2068 The function does not clip the ellipse against the drawing area.
2070 INPUTS
2071 obj - A bitmap to draw on
2072 gc - A GC object to use for drawing
2073 x,y - Coordinates of center point in pixels
2074 rx,ry - ry and ry radius in pixels
2076 RESULT
2077 None.
2079 NOTES
2080 This method is not used by the system and considered reserved.
2082 EXAMPLE
2084 Because of overflow the current code do not work with big
2085 values of rx and ry.
2087 SEE ALSO
2089 INTERNALS
2091 TODO
2092 Bugfix
2094 *****************************************************************************************/
2096 VOID BM__Hidd_BitMap__FillEllipse(OOP_Class *cl, OOP_Object *obj,
2097 struct pHidd_BitMap_DrawEllipse *msg)
2099 #ifdef __RESERVED__
2100 OOP_Object *gc = msg->gc;
2101 WORD x = msg->rx, y = 0; /* ellipse points */
2103 /* intermediate terms to speed up loop */
2104 LONG t1 = msg->rx * msg->rx, t2 = t1 << 1, t3 = t2 << 1;
2105 LONG t4 = msg->ry * msg->ry, t5 = t4 << 1, t6 = t5 << 1;
2106 LONG t7 = msg->rx * t5, t8 = t7 << 1, t9 = 0L;
2107 LONG d1 = t2 - t7 + (t4 >> 1); /* error terms */
2108 LONG d2 = (t1 >> 1) - t8 + t5;
2110 EnterFunc(bug("BitMap::FillEllipse()"));
2112 while (d2 < 0) /* till slope = -1 */
2114 /* draw 4 points using symmetry */
2115 HIDD_BM_DrawLine(obj, gc, msg->x - x, msg->y + y, msg->x + x, msg->y + y);
2116 HIDD_BM_DrawLine(obj, gc, msg->x - x, msg->y - y, msg->x + x, msg->y - y);
2118 y++; /* always move up here */
2119 t9 = t9 + t3;
2120 if (d1 < 0) /* move straight up */
2122 d1 = d1 + t9 + t2;
2123 d2 = d2 + t9;
2125 else /* move up and left */
2127 x--;
2128 t8 = t8 - t6;
2129 d1 = d1 + t9 + t2 - t8;
2130 d2 = d2 + t9 + t5 - t8;
2134 do /* rest of top right quadrant */
2136 /* draw 4 points using symmetry */
2137 HIDD_BM_DrawLine(obj, gc, msg->x - x, msg->y + y, msg->x + x, msg->y + y);
2138 HIDD_BM_DrawLine(obj, gc, msg->x - x, msg->y - y, msg->x + x, msg->y - y);
2140 x--; /* always move left here */
2141 t8 = t8 - t6;
2142 if (d2 < 0) /* move up and left */
2144 y++;
2145 t9 = t9 + t3;
2146 d2 = d2 + t9 + t5 - t8;
2148 else /* move straight left */
2150 d2 = d2 + t5 - t8;
2153 } while (x >= 0);
2154 #endif
2156 ReturnVoid("BitMap::FillEllipse");
2159 /*****************************************************************************************
2161 NAME
2162 moHidd_BitMap_DrawPolygon
2164 SYNOPSIS
2165 VOID OOP_DoMethod(OOP_Object *obj, struct pHidd_BitMap_DrawPolygon *msg);
2167 VOID HIDD_BM_DrawPolygon (OOP_Object *obj, OOP_Object *gc, UWORD n, WORD *coords);
2169 LOCATION
2170 hidd.gfx.bitmap
2172 FUNCTION
2173 Draws a hollow polygon from the list of coordinates in coords[].
2174 The function does not clip the polygon against the drawing area.
2176 INPUTS
2177 obj - A bitmap to draw on
2178 gc - A GC object to use for drawing
2179 n - number of coordinate pairs
2180 coords - array of n (x, y) coordinates in pixels
2182 RESULT
2183 None.
2185 NOTES
2186 This method is not used by the system and considered reserved.
2188 EXAMPLE
2190 BUGS
2192 SEE ALSO
2194 INTERNALS
2196 TODO
2198 *****************************************************************************************/
2200 VOID BM__Hidd_BitMap__DrawPolygon(OOP_Class *cl, OOP_Object *obj,
2201 struct pHidd_BitMap_DrawPolygon *msg)
2203 #ifdef __RESERVED__
2204 OOP_Object *gc = msg->gc;
2205 WORD i;
2207 EnterFunc(bug("BitMap::DrawPolygon()"));
2209 for(i = 2; i < (2 * msg->n); i = i + 2)
2211 HIDD_BM_DrawLine(obj, gc, msg->coords[i - 2], msg->coords[i - 1],
2212 msg->coords[i], msg->coords[i + 1]);
2214 #endif
2216 ReturnVoid("BitMap::DrawPolygon");
2219 /*****************************************************************************************
2221 NAME
2222 moHidd_BitMap_FillPolygon
2224 SYNOPSIS
2225 VOID OOP_DoMethod(OOP_Object *obj, struct pHidd_BitMap_DrawPolygon *msg);
2227 VOID HIDD_BM_FillPolygon (OOP_Object *obj, OOP_Object *gc, UWORD n, WORD *coords);
2229 LOCATION
2230 hidd.gfx.bitmap
2232 FUNCTION
2233 This method was initially designed for drawing solid polygons, however it was never
2234 used and implemented. At the moment it is considered reserved, its synopsis and
2235 semantics may change in future.
2237 INPUTS
2238 obj - A bitmap to draw on
2239 gc - A GC object to use for drawing
2240 n - number of coordinate pairs
2241 coords - array of n (x, y) coordinates in pixels
2243 RESULT
2244 None
2246 NOTES
2248 EXAMPLE
2250 BUGS
2251 Never used and implemented
2253 SEE ALSO
2255 INTERNALS
2257 TODO
2259 *****************************************************************************************/
2261 VOID BM__Hidd_BitMap__FillPolygon(OOP_Class *cl, OOP_Object *obj, struct pHidd_BitMap_DrawPolygon *msg)
2263 D(bug("Sorry, FillPolygon() not implemented yet in bitmap baseclass\n"));
2266 /*****************************************************************************************
2268 NAME
2269 moHidd_BitMap_DrawText
2271 SYNOPSIS
2272 OOP_DoMethod(OOP_Object *obj, struct pHidd_BitMap_DrawText *msg);
2274 VOID HIDD_BM_DrawText (OOP_Object *obj, OOP_Object *gc, WORD x, WORD y,
2275 STRPTR text, UWORD length);
2277 LOCATION
2278 hidd.gfx.bitmap
2280 FUNCTION
2281 Draws the first length characters of text at (x, y).
2282 The function does not clip the text against the drawing area.
2284 INPUTS
2285 obj - A bitmap to draw on
2286 gc - A GC object to use for drawing and font specification
2287 x, y - Position to start drawing in pixels. The x
2288 coordinate is relativ to the left side of the
2289 first character.
2290 The y coordinate is relative to the baseline of the font.
2291 text - Pointer to a Latin 1 string
2292 length - Number of characters to draw
2294 RESULT
2295 None.
2297 NOTES
2298 At the moment text drawing is processed entirely by graphics.library
2299 using BltTemplate(), which in turn uses moHodd_BitMap_PutTemplate.
2300 This method is considered obsolete.
2302 EXAMPLE
2304 BUGS
2305 The default implementation in the base class does not process styles,
2306 color and alpha-blended fonts.
2308 SEE ALSO
2310 INTERNALS
2312 TODO
2314 *****************************************************************************************/
2316 VOID BM__Hidd_BitMap__DrawText(OOP_Class *cl, OOP_Object *obj,
2317 struct pHidd_BitMap_DrawText *msg)
2319 #ifdef __RESERVED__
2320 OOP_Object *gc = msg->gc;
2321 struct TextFont *font = GC_FONT(gc);
2322 UBYTE *charPatternPtr = font->tf_CharData;
2323 UWORD modulo = font->tf_Modulo;
2324 ULONG charLog;
2325 UBYTE ch; /* current character to print */
2326 WORD fx, fx2, fy, fw; /* position and length of character in the */
2327 /* character bitmap */
2328 WORD xMem = msg->x; /* position in bitmap */
2329 WORD yMem = msg->y - font->tf_Baseline;
2330 WORD x, y, i;
2333 EnterFunc(bug("BitMap::DrawText()"));
2335 for(i = 0; i < msg->length; i++)
2337 ch = msg->text[i];
2339 if((ch < font->tf_LoChar) || (ch > font->tf_HiChar))
2341 ch = font->tf_HiChar - font->tf_LoChar + 1;
2343 else
2345 ch = ch - font->tf_LoChar;
2348 if(font->tf_Flags & FPF_PROPORTIONAL)
2350 xMem = xMem + ((UWORD *) font->tf_CharKern)[ch];
2353 charLog = ((ULONG *) font->tf_CharLoc)[ch];
2354 fx2 = charLog >> 16; /* x position of character pattern in character bitmap */
2355 fw = (UWORD) charLog; /* width of character pattern in character bitmap */
2357 y = yMem;
2359 for(fy = 0; fy < font->tf_YSize; fy ++)
2361 x = xMem;
2363 for(fx = fx2; fx < fw + fx2; fx++)
2365 if(*(charPatternPtr + fx / 8 + fy * modulo) & (128 >> (fx % 8)))
2367 HIDD_BM_DrawPixel(obj, msg->gc, x, y);
2369 x++;
2372 y++;
2375 if(font->tf_Flags & FPF_PROPORTIONAL)
2377 xMem = xMem + ((UWORD *) font->tf_CharSpace)[ch];
2379 else
2381 xMem = xMem + font->tf_XSize;
2384 #endif
2385 ReturnVoid("BitMap::DrawText");
2388 /*****************************************************************************************
2390 NAME
2391 moHidd_BitMap_FillText
2393 SYNOPSIS
2394 VOID OOP_DoMethod(OOP_Object *obj, struct pHidd_BitMap_DrawText *msg);
2396 VOID HIDD_BM_FillText (OOP_Object *obj, OOP_Object *gc, WORD x, WORD y,
2397 STRPTR text, UWORD length);
2399 LOCATION
2400 hidd.gfx.bitmap
2402 FUNCTION
2403 Historically this method was designed to draw a text with background.
2404 It was never implemented.
2406 Currently this method is considered reserved. Its synopsis and semantics
2407 may change in future.
2409 INPUTS
2410 obj - A bitmap to draw on
2411 gc - A GC object to use for drawing
2412 x, y - Position to start drawing in pixels. The x
2413 coordinate is relative to the left side of the
2414 first character.
2415 The y coordinate is relative to the baseline of the font.
2416 text - Pointer to a Latin 1 string
2417 length - Number of characters to draw
2419 RESULT
2421 NOTES
2423 EXAMPLE
2425 BUGS
2427 SEE ALSO
2429 INTERNALS
2431 TODO
2433 *****************************************************************************************/
2435 VOID BM__Hidd_BitMap__FillText(OOP_Class *cl, OOP_Object *obj, struct pHidd_BitMap_DrawText *msg)
2437 D(bug("Sorry, FillText() not implemented yet in bitmap baseclass\n"));
2440 /*****************************************************************************************
2442 NAME
2443 moHidd_BitMap_FillSpan
2445 SYNOPSIS
2446 VOID OOP_DoMethod(OOP_Object *obj, struct pHidd_BitMap_DrawText *msg);
2448 LOCATION
2449 hidd.gfx.bitmap
2451 FUNCTION
2452 Reserved, never implemented method. The definition will change in future.
2454 INPUTS
2456 RESULT
2457 None.
2459 NOTES
2461 EXAMPLE
2463 BUGS
2465 SEE ALSO
2467 INTERNALS
2469 TODO
2471 *****************************************************************************************/
2473 VOID BM__Hidd_BitMap__FillSpan(OOP_Class *cl, OOP_Object *obj, struct pHidd_BitMap_DrawText *msg)
2475 D(bug("Sorry, FillSpan() not implemented yet\n"));
2478 /*****************************************************************************************
2480 NAME
2481 moHidd_BitMap_Clear
2483 SYNOPSIS
2484 OOP_DoMethod(OOP_Object *obj, struct pHidd_BitMap_Clear *msg);
2486 VOID HIDD_BM_Clear (OOP_Object *obj, OOP_Object *gc);
2488 LOCATION
2489 hidd.gfx.bitmap
2491 FUNCTION
2492 Sets all pixels of the drawing area to the background color.
2494 INPUTS
2495 obj - A bitmap to clear.
2496 gc - A GC object, specifies background color value
2498 RESULT
2500 NOTES
2501 This method is not used by the system and considered reserved. However it can
2502 be useful for display driver's own needs.
2504 EXAMPLE
2506 BUGS
2507 Default implementation in the base class sets all pixels to zero color instead of
2508 the background color from GC
2510 SEE ALSO
2512 INTERNALS
2514 TODO
2516 *****************************************************************************************/
2518 VOID BM__Hidd_BitMap__Clear(OOP_Class *cl, OOP_Object *obj, struct pHidd_BitMap_Clear *msg)
2520 struct Library *OOPBase = CSD(cl)->cs_OOPBase;
2521 WORD x, y;
2522 IPTR width, height;
2524 EnterFunc(bug("BitMap::Clear()\n"));
2526 OOP_GetAttr(obj, aHidd_BitMap_Width, &width);
2527 OOP_GetAttr(obj, aHidd_BitMap_Height, &height);
2529 for(y = 0; y < height; y++)
2531 for(x = 0; x < width; x++)
2533 HIDD_BM_PutPixel(obj, x, y, 0);
2537 ReturnVoid("BitMap::Clear");
2540 /****************************************************************************************/
2542 static LONG inline getpixfmtbpp(OOP_Class *cl, OOP_Object *o, HIDDT_StdPixFmt stdpf)
2544 struct Library *OOPBase = CSD(cl)->cs_OOPBase;
2545 OOP_Object *pf;
2546 struct HIDDBitMapData *data;
2547 SIPTR bpp = -1;
2549 data = OOP_INST_DATA(cl, o);
2551 switch (stdpf)
2553 case vHidd_StdPixFmt_Native:
2554 OOP_GetAttr(data->prot.pixfmt, aHidd_PixFmt_BytesPerPixel, &bpp);
2555 break;
2557 case vHidd_StdPixFmt_Native32:
2558 bpp = sizeof (HIDDT_Pixel);
2559 break;
2561 default:
2562 pf = HIDD_Gfx_GetPixFmt(data->gfxhidd, stdpf);
2564 if (NULL == pf)
2566 D(bug("!!! INVALID PIXFMT IN BitMap::PutImage(): %d !!!\n", stdpf));
2568 else
2570 OOP_GetAttr(pf, aHidd_PixFmt_BytesPerPixel, &bpp);
2572 break;
2575 return bpp;
2578 /*****************************************************************************************
2580 NAME
2581 moHidd_BitMap_GetImage
2583 SYNOPSIS
2584 VOID OOP_DoMethod(OOP_Object *obj, struct pHidd_BitMap_GetImage *msg);
2586 VOID HIDD_BM_GetImage (OOP_Object *obj, UBYTE *pixels, ULONG modulo, WORD x, WORD y,
2587 WORD width, WORD height, HIDDT_StdPixFmt pixFmt);
2589 LOCATION
2590 hidd.gfx.bitmap
2592 FUNCTION
2594 INPUTS
2595 obj -
2596 pixels -
2597 modulo -
2598 x, y -
2599 width -
2600 height -
2601 pixFmt -
2603 RESULT
2605 NOTES
2607 EXAMPLE
2609 BUGS
2611 SEE ALSO
2613 INTERNALS
2615 *****************************************************************************************/
2617 VOID BM__Hidd_BitMap__GetImage(OOP_Class *cl, OOP_Object *o,
2618 struct pHidd_BitMap_GetImage *msg)
2620 WORD x, y;
2621 UBYTE *pixarray = (UBYTE *)msg->pixels;
2622 APTR ppixarray = &pixarray;
2623 WORD bpp;
2624 struct HIDDBitMapData *data;
2626 data = OOP_INST_DATA(cl, o);
2628 EnterFunc(bug("BitMap::GetImage(x=%d, y=%d, width=%d, height=%d)\n"
2629 , msg->x, msg->y, msg->width, msg->height));
2632 bpp = getpixfmtbpp(cl, o, msg->pixFmt);
2633 if (-1 == bpp)
2635 D(bug("!!! INVALID PIXFMT IN BitMap::GetImage(): %d !!!\n", msg->pixFmt));
2636 return;
2640 switch(msg->pixFmt)
2642 case vHidd_StdPixFmt_Native:
2643 case vHidd_StdPixFmt_Native32:
2644 for (y = 0; y < msg->height; y ++)
2646 for (x = 0; x < msg->width; x ++)
2648 register HIDDT_Pixel pix;
2650 pix = HIDD_BM_GetPixel(o, x + msg->x , y + msg->y);
2652 switch (bpp)
2654 case 1:
2655 *pixarray++ = pix;
2656 break;
2658 case 2:
2659 *((UWORD *)pixarray) = pix;
2660 pixarray += 2;
2661 break;
2663 case 3:
2664 #if AROS_BIG_ENDIAN
2665 pixarray[0] = (pix >> 16) & 0xFF;
2666 pixarray[1] = (pix >> 8) & 0xFF;
2667 pixarray[2] = pix & 0xFF;
2668 #else
2669 pixarray[0] = pix & 0xFF;
2670 pixarray[1] = (pix >> 8) & 0xFF;
2671 pixarray[2] = (pix >> 16) & 0xFF;
2672 #endif
2673 pixarray += 3;
2674 break;
2676 case 4:
2677 *(ULONG *)pixarray = pix;
2678 pixarray += 4;
2679 break;
2684 pixarray += (msg->modulo - msg->width * bpp);
2687 break;
2689 default:
2691 OOP_Object *dstpf;
2692 APTR buf, srcPixels;
2694 dstpf = HIDD_Gfx_GetPixFmt(data->gfxhidd, msg->pixFmt);
2696 buf = srcPixels = AllocVec(msg->width * sizeof(HIDDT_Pixel), MEMF_PUBLIC);
2697 if (buf)
2699 for(y = 0; y < msg->height; y++)
2701 HIDD_BM_GetImage(o,
2702 buf,
2704 msg->x,
2705 msg->y + y,
2706 msg->width,
2708 vHidd_StdPixFmt_Native);
2710 HIDD_BM_ConvertPixels(o,
2711 &srcPixels,
2712 (HIDDT_PixelFormat *)data->prot.pixfmt,
2714 (APTR *)ppixarray,
2715 (HIDDT_PixelFormat *)dstpf,
2716 msg->modulo,
2717 msg->width,
2719 NULL);
2722 FreeVec(buf);
2725 break;
2727 } /* switch(msg->pixFmt) */
2729 ReturnVoid("BitMap::GetImage");
2732 /*****************************************************************************************
2734 NAME
2735 moHidd_BitMap_PutImage
2737 SYNOPSIS
2738 VOID OOP_DoMethod(OOP_Object *obj, struct pHidd_BitMap_PutImage *msg);
2740 VOID HIDD_BM_PutImage (OOP_Object *obj, OOP_Object *gc, UBYTE *pixels, ULONG modulo,
2741 WORD x, WORD y, WORD width, WORD height, HIDDT_StdPixFmt pixFmt);
2743 LOCATION
2744 hidd.gfx.bitmap
2746 FUNCTION
2748 INPUTS
2749 obj -
2750 gc -
2751 pixels -
2752 modulo -
2753 x, y -
2754 width -
2755 height -
2756 pixFmt -
2758 RESULT
2760 NOTES
2762 EXAMPLE
2764 BUGS
2766 SEE ALSO
2768 INTERNALS
2770 *****************************************************************************************/
2772 VOID BM__Hidd_BitMap__PutImage(OOP_Class *cl, OOP_Object *o,
2773 struct pHidd_BitMap_PutImage *msg)
2775 WORD x, y;
2776 UBYTE *pixarray = (UBYTE *)msg->pixels;
2777 APTR ppixarray = &pixarray;
2778 ULONG old_fg;
2779 WORD bpp;
2780 struct HIDDBitMapData *data;
2781 OOP_Object *gc = msg->gc;
2783 data = OOP_INST_DATA(cl, o);
2785 EnterFunc(bug("BitMap::PutImage(x=%d, y=%d, width=%d, height=%d)\n"
2786 , msg->x, msg->y, msg->width, msg->height));
2788 if (msg->width <= 0 || msg->height <= 0)
2789 return;
2791 bpp = getpixfmtbpp(cl, o, msg->pixFmt);
2792 if (-1 == bpp)
2794 D(bug("!!! INVALID PIXFMT IN BitMap::PutImage(): %d !!!\n", msg->pixFmt));
2795 return;
2798 switch(msg->pixFmt)
2800 case vHidd_StdPixFmt_Native:
2801 case vHidd_StdPixFmt_Native32:
2803 /* Preserve old fg pen */
2804 old_fg = GC_FG(gc);
2806 for (y = 0; y < msg->height; y ++)
2808 for (x = 0; x < msg->width; x ++)
2810 register HIDDT_Pixel pix = 0;
2812 switch (bpp)
2814 case 1:
2815 pix = *((UBYTE *)pixarray);
2816 pixarray ++;
2817 break;
2819 case 2:
2820 pix = *((UWORD *)pixarray);
2821 pixarray += 2;
2822 break;
2824 case 3:
2825 #if AROS_BIG_ENDIAN
2826 pix = ((UBYTE *)pixarray)[0] << 16;
2827 pix |= ((UBYTE *)pixarray)[1] << 8;
2828 pix |= ((UBYTE *)pixarray)[2];
2829 #else
2830 pix = ((UBYTE *)pixarray)[2] << 16;
2831 pix |= ((UBYTE *)pixarray)[1] << 8;
2832 pix |= ((UBYTE *)pixarray)[0];
2833 #endif
2834 pixarray += 3;
2835 break;
2837 case 4:
2838 pix = *((ULONG *)pixarray); pixarray += 4;
2839 break;
2843 GC_FG(gc) = pix;
2845 HIDD_BM_DrawPixel(o, gc, x + msg->x , y + msg->y);
2847 pixarray += (msg->modulo - msg->width * bpp);
2850 GC_FG(gc) = old_fg;
2851 break;
2853 default:
2855 OOP_Object *srcpf;
2856 APTR buf, destPixels;
2858 srcpf = HIDD_Gfx_GetPixFmt(data->gfxhidd, msg->pixFmt);
2860 buf = destPixels = AllocVec(msg->width * sizeof(HIDDT_Pixel), MEMF_PUBLIC);
2861 if (buf)
2863 for(y = 0; y < msg->height; y++)
2865 HIDD_BM_ConvertPixels(o,
2866 (APTR *)ppixarray,
2867 (HIDDT_PixelFormat *)srcpf,
2868 msg->modulo,
2869 &destPixels,
2870 (HIDDT_PixelFormat *)data->prot.pixfmt,
2872 msg->width,
2874 NULL);
2876 HIDD_BM_PutImage(o,
2877 msg->gc,
2878 buf,
2880 msg->x,
2881 msg->y + y,
2882 msg->width,
2884 vHidd_StdPixFmt_Native);
2886 FreeVec(buf);
2889 break;
2891 } /* switch(msg->pixFmt) */
2893 ReturnVoid("BitMap::PutImage");
2896 /****************************************************************************************/
2898 int static inline
2899 __attribute__((always_inline, const)) do_alpha(int a, int v)
2901 int tmp = (a*v);
2902 return ((tmp<<8) + tmp + 32768)>>16;
2905 #if AROS_BIG_ENDIAN
2907 #define RGB32_DECOMPOSE(red, green, blue, pix) \
2908 red = ((pix) & 0x00FF0000) >> 16; \
2909 green = ((pix) & 0x0000FF00) >> 8; \
2910 blue = ((pix) & 0x000000FF);
2912 #define ARGB32_ALPHA(pix) ((pix) & 0xFF000000)
2914 #define ARGB32_DECOMPOSE(alpha, red, green, blue, pix) \
2915 alpha = ((pix) & 0xFF000000) >> 24; \
2916 red = ((pix) & 0x00FF0000) >> 16; \
2917 green = ((pix) & 0x0000FF00) >> 8; \
2918 blue = ((pix) & 0x000000FF);
2920 #define ARGB32_COMPOSE(red, green, blue, old) (((old) & 0xFF000000) + ((red) << 16) + ((green) << 8) + (blue))
2922 #else
2924 #define RGB32_DECOMPOSE(red, green, blue, pix) \
2925 red = (pix & 0x0000FF00) >> 8; \
2926 green = (pix & 0x00FF0000) >> 16; \
2927 blue = (pix & 0xFF000000) >> 24
2929 #define ARGB32_ALPHA(pix) ((pix) & 0x000000FF)
2931 #define ARGB32_DECOMPOSE(alpha, red, green, blue, pix) \
2932 alpha = (pix & 0x000000FF); \
2933 red = (pix & 0x0000FF00) >> 8; \
2934 green = (pix & 0x00FF0000) >> 16; \
2935 blue = (pix & 0xFF000000) >> 24
2937 #define ARGB32_COMPOSE(red, green, blue, old) (((blue) << 24) + ((green) << 16) + ((red) << 8) + ((old) & 0x000000FF))
2939 #endif
2941 /*****************************************************************************************
2943 NAME
2944 moHidd_BitMap_PutAlphaImage
2946 SYNOPSIS
2947 VOID OOP_DoMethod(OOP_Object *obj, struct pHidd_BitMap_PutAlphaImage *msg);
2949 VOID HIDD_BM_PutAlphaImage (OOP_Object *obj, OOP_Object *gc, UBYTE *pixels, ULONG modulo,
2950 WORD x, WORD y, WORD width, WORD height);
2952 LOCATION
2953 hidd.gfx.bitmap
2955 FUNCTION
2956 Perform an alpha-blending operation between a bitmap and ARGB pixel array.
2958 INPUTS
2959 obj - A bitmap to operate on
2960 gc - A GC object, internally needed to perform the operation. All its attributes
2961 are ignored.
2962 pixels - A pointer to an array of pixels
2963 modulo - Number of bytes per row in pixel array
2964 x, y - Top-left corner of affected bitmap's region
2965 width - Width of the modified rectangle.
2966 height - Height of the modified rectangle.
2968 RESULT
2969 None.
2971 NOTES
2972 Do not rely on 'gc' parameter being valid when implementing this method in own
2973 display driver. This parameter is actually obsolete, and will be set to NULL in
2974 future AROS versions. Current base class implementation ignores it.
2976 EXAMPLE
2978 BUGS
2980 SEE ALSO
2982 INTERNALS
2984 *****************************************************************************************/
2986 struct paib_data
2988 void *pixels;
2989 ULONG modulo;
2993 * TODOs:
2994 * 1. Merge buffered and slow versions of PutAlphaImage(), use the same processing algorithm
2995 * (convert array's pixels to bitmap's format, not vice versa)
2996 * 2. Make DoBufferedOperation() public, to be used for cybergraphics.library/ProcessPixelArray()
2997 * implementation, and for some other functions in graphics.library and cybergraphics.library,
2998 * currently using own implementation of pixel buffer.
2999 * 3. Reuse the new code for other buffered operations (currently using old macros).
3002 static void PutAlphaImageBuffered(ULONG *xbuf, UWORD starty, UWORD width, UWORD height, struct paib_data *data)
3004 UWORD x, y;
3006 for (y = 0; y < height; y++)
3008 ULONG *pixarray = data->pixels;
3010 for (x = 0; x < width; x++)
3012 ULONG destpix;
3013 ULONG srcpix;
3014 ULONG src_red, src_green, src_blue, src_alpha;
3015 ULONG dst_red, dst_green, dst_blue;
3017 srcpix = *pixarray++;
3019 if (ARGB32_ALPHA(srcpix) == ARGB32_ALPHA(0xFFFFFFFF))
3021 xbuf[x] = srcpix;
3023 else if (ARGB32_ALPHA(srcpix) != 0)
3025 ARGB32_DECOMPOSE(src_alpha, src_red, src_green, src_blue, srcpix);
3027 destpix = xbuf[x];
3028 RGB32_DECOMPOSE(dst_red, dst_green, dst_blue, destpix);
3030 dst_red += do_alpha(src_alpha, src_red - dst_red);
3031 dst_green += do_alpha(src_alpha, src_green - dst_green);
3032 dst_blue += do_alpha(src_alpha, src_blue - dst_blue);
3034 xbuf[x] = ARGB32_COMPOSE(dst_red, dst_green, dst_blue, destpix);
3038 xbuf += width;
3039 data->pixels += data->modulo;
3043 VOID BM__Hidd_BitMap__PutAlphaImage(OOP_Class *cl, OOP_Object *o,
3044 struct pHidd_BitMap_PutAlphaImage *msg)
3046 WORD x, y;
3047 struct paib_data data = {msg->pixels, msg->modulo};
3049 EnterFunc(bug("BitMap::PutAlphaImage(x=%d, y=%d, width=%d, height=%d)\n"
3050 , msg->x, msg->y, msg->width, msg->height));
3052 if (msg->width <= 0 || msg->height <= 0)
3053 return;
3055 if (!DoBufferedOperation(cl, o, msg->x, msg->y, msg->width, msg->height, TRUE, vHidd_StdPixFmt_ARGB32,
3056 (VOID_FUNC)PutAlphaImageBuffered, &data))
3058 /* Buffered method failed, use slow pixel-by-pixel method */
3059 for (y = msg->y; y < msg->y + msg->height; y++)
3061 ULONG *pixarray = data.pixels;
3063 for (x = msg->x; x < msg->x + msg->width; x++)
3065 HIDDT_Pixel destpix;
3066 HIDDT_Color col;
3067 ULONG srcpix;
3068 LONG src_red, src_green, src_blue, src_alpha;
3069 LONG dst_red, dst_green, dst_blue;
3071 destpix = HIDD_BM_GetPixel(o, x, y);
3072 HIDD_BM_UnmapPixel(o, destpix, &col);
3074 srcpix = *pixarray++;
3075 ARGB32_DECOMPOSE(src_alpha, src_red, src_green, src_blue, srcpix);
3077 dst_red = col.red >> 8;
3078 dst_green = col.green >> 8;
3079 dst_blue = col.blue >> 8;
3081 dst_red += do_alpha(src_alpha, src_red - dst_red);
3082 dst_green += do_alpha(src_alpha, src_green - dst_green);
3083 dst_blue += do_alpha(src_alpha, src_blue - dst_blue);
3085 col.red = dst_red << 8;
3086 col.green = dst_green << 8;
3087 col.blue = dst_blue << 8;
3089 HIDD_BM_PutPixel(o, x, y, HIDD_BM_MapColor(o, &col));
3091 } /* for(x = msg->x; x < msg->x + msg->width; x++) */
3093 data.pixels += msg->modulo;
3095 } /* for(y = msg->y; y < msg->y + msg->height; y++) */
3097 ReturnVoid("BitMap::PutAlphaImage");
3100 /*****************************************************************************************
3102 NAME
3103 moHidd_BitMap_PutTemplate
3105 SYNOPSIS
3106 VOID OOP_DoMethod(OOP_Object *obj, struct pHidd_BitMap_PutTemplate *msg);
3108 VOID HIDD_BM_PutTemplate (OOP_Object *obj, OOP_Object *gc, UBYTE *masktemplate, ULONG modulo,
3109 WORD srcx, WORD x, WORD y, WORD width, WORD height, BOOL inverttemplate);
3111 LOCATION
3112 hidd.gfx.bitmap
3114 FUNCTION
3115 Apply a single-bit mask to the given portion of the bitmap. Pixels set to 1 in the mask will be filled
3116 by foreground color. Pixels set to 0 in the mask will be filled by background color or left unchanged,
3117 according to the following GC attributes:
3118 Foreground - a foreground color
3119 Background - a background color
3120 DrawMode - if set to Invert, foreground and background colors will be ignored. Instead,
3121 pixels which are set to 1 in the mask, will be inverted. Other pixels will be
3122 left unchanged.
3123 ColorExpansion - if set to Transparent, only pixels which are set to 1 in the mask, will be modified.
3124 Other pixels will not be changed (background color will be ignored).
3126 INPUTS
3127 obj - A bitmap to draw on
3128 gc - A GC object, holding operation parameters
3129 masktemplate - A pointer to a bit mask
3130 modulo - Number of bytes per line in the mask
3131 srcx - Horizontal offset of the mask
3132 x, y - Top-left corner of the bitmap's region to affect
3133 width - Width of the affected region
3134 height - Height of the affected region
3135 inverttemplate - If set to TRUE, bit mask will be interpreted in inverted form
3137 RESULT
3138 None
3140 NOTES
3142 EXAMPLE
3144 BUGS
3146 SEE ALSO
3148 INTERNALS
3150 *****************************************************************************************/
3152 struct ptb_data
3154 void *bitarray;
3155 ULONG bitmask;
3156 ULONG modulo;
3157 ULONG fg;
3158 ULONG bg;
3159 UWORD invert;
3162 static void JAM1TemplateBuffered(ULONG *xbuf, UWORD starty, UWORD width, UWORD height, struct ptb_data *data)
3164 UWORD x, y;
3166 for (y = 0; y < height; y++)
3168 ULONG mask = data->bitmask;
3169 UWORD *array = data->bitarray;
3170 UWORD bitword = AROS_BE2WORD(*array);
3172 for (x = 0; x < width; x++)
3174 if ((bitword & mask) == (data->invert & mask))
3175 xbuf[x] = data->fg;
3177 mask >>= 1;
3178 if (!mask)
3180 mask = 0x8000;
3181 array++;
3182 bitword = AROS_BE2WORD(*array);
3186 xbuf += width;
3187 data->bitarray += data->modulo;
3191 static void ComplementTemplateBuffered(ULONG *xbuf, UWORD starty, UWORD width, UWORD height, struct ptb_data *data)
3193 UWORD x, y;
3195 for (y = 0; y < height; y++)
3197 ULONG mask = data->bitmask;
3198 UWORD *array = data->bitarray;
3199 UWORD bitword = AROS_BE2WORD(*array);
3201 for (x = 0; x < width; x++)
3203 if ((bitword & mask) == (data->invert & mask))
3204 xbuf[x] = ~xbuf[x];
3206 mask >>= 1;
3207 if (!mask)
3209 mask = 0x8000;
3210 array++;
3211 bitword = AROS_BE2WORD(*array);
3215 xbuf += width;
3216 data->bitarray += data->modulo;
3220 static void JAM2TemplateBuffered(ULONG *xbuf, UWORD starty, UWORD width, UWORD height, struct ptb_data *data)
3222 UWORD x, y;
3224 for (y = 0; y < height; y++)
3226 ULONG mask = data->bitmask;
3227 UWORD *array = data->bitarray;
3228 UWORD bitword = AROS_BE2WORD(*array);
3230 for (x = 0; x < width; x++)
3232 if ((bitword & mask) == (data->invert & mask))
3233 xbuf[x] = data->fg;
3234 else
3235 xbuf[x] = data->bg;
3237 mask >>= 1;
3238 if (!mask)
3240 mask = 0x8000;
3241 array++;
3242 bitword = AROS_BE2WORD(*array);
3246 xbuf += width;
3247 data->bitarray += data->modulo;
3251 VOID BM__Hidd_BitMap__PutTemplate(OOP_Class *cl, OOP_Object *o, struct pHidd_BitMap_PutTemplate *msg)
3253 OOP_Object *gc = msg->gc;
3254 BOOL get = TRUE;
3255 void (*op)(ULONG *, UWORD, UWORD, UWORD, struct ptb_data *);
3256 struct ptb_data data;
3258 EnterFunc(bug("BitMap::PutTemplate(x=%d, y=%d, width=%d, height=%d)\n"
3259 , msg->x, msg->y, msg->width, msg->height));
3261 if (msg->width <= 0 || msg->height <= 0)
3262 return;
3264 if (GC_COLEXP(gc) == vHidd_GC_ColExp_Transparent)
3266 op = JAM1TemplateBuffered;
3268 else if (GC_DRMD(gc) == vHidd_GC_DrawMode_Invert)
3270 op = ComplementTemplateBuffered;
3272 else
3274 op = JAM2TemplateBuffered;
3275 get = FALSE;
3278 data.bitarray = msg->masktemplate + ((msg->srcx / 16) * 2);
3279 data.bitmask = 0x8000 >> (msg->srcx & 0xF);
3280 data.modulo = msg->modulo;
3281 data.fg = GC_FG(msg->gc);
3282 data.bg = GC_BG(msg->gc);
3283 data.invert = msg->inverttemplate ? 0 : 0xFFFF;
3285 DoBufferedOperation(cl, o, msg->x, msg->y, msg->width, msg->height, get, vHidd_StdPixFmt_Native32, (VOID_FUNC)op, &data);
3287 /* TODO: write fallback */
3289 ReturnVoid("BitMap::PutTemplate");
3292 /*****************************************************************************************
3294 NAME
3295 moHidd_BitMap_PutAlphaTemplate
3297 SYNOPSIS
3298 VOID OOP_DoMethod(OOP_Object *obj, struct pHidd_BitMap_PutAlphaTemplate *msg);
3300 VOID HIDD_BM_PutAlphaTemplate (OOP_Object *obj, OOP_Object *gc, UBYTE *alpha, ULONG modulo,
3301 WORD x, WORD y, WORD width, WORD height, BOOL invertalpha);
3303 LOCATION
3304 hidd.gfx.bitmap
3306 FUNCTION
3307 Perform a drawing with current foreground color, using 8-bit alpha channel mask. The following
3308 GC attributes are considered:
3309 Foreground - a foreground color
3310 Background - a background color
3311 DrawMode - if set to Invert, foreground and background colors will be ignored. Instead,
3312 pixels, for which alpha channel value is greater than 127, will be inverted.
3313 Other pixels will be left unchanged.
3314 ColorExpansion - if set to Opaque, alpha blending will happen between foreground and background
3315 colors, instead of between foreground color and old bitmap contents.
3317 INPUTS
3318 obj - A bitmap to draw on
3319 gc - A GC object specifying drawing parameters
3320 alpha - A pointer to an 8-bit per pixel alpha channel mask
3321 modulo - Number of bytes per line in the mask
3322 x, y - Top-left corner of the affected bitmap's region
3323 width - Width of the affected bitmap's region
3324 height - Height of the affected bitmap's region
3325 invertalpha - If set to TRUE, alpha mask values will be treated in inverted form
3327 RESULT
3328 None
3330 NOTES
3332 EXAMPLE
3334 BUGS
3336 SEE ALSO
3338 INTERNALS
3340 *****************************************************************************************/
3342 struct patb_data
3344 UBYTE *pixarray;
3345 ULONG modulo;
3346 LONG a_red, a_green, a_blue;
3347 LONG b_red, b_green, b_blue;
3348 UBYTE invert;
3351 static void JAM1AlphaTemplateBuffered(ULONG *xbuf, UWORD starty, UWORD width, UWORD height, struct patb_data *data)
3353 UWORD x, y;
3355 for (y = 0; y < height; y++)
3357 UBYTE *pixarray = data->pixarray;
3359 for (x = 0; x < width; x++)
3361 LONG dst_red, dst_green, dst_blue, alpha;
3363 alpha = (*pixarray++) ^ data->invert;
3364 RGB32_DECOMPOSE(dst_red, dst_green, dst_blue, xbuf[x]);
3366 dst_red += do_alpha(alpha, data->a_red - dst_red);
3367 dst_green += do_alpha(alpha, data->a_green - dst_green);
3368 dst_blue += do_alpha(alpha, data->a_blue - dst_blue);
3370 xbuf[x] = ARGB32_COMPOSE(dst_red, dst_green, dst_blue, 0);
3373 xbuf += width;
3374 data->pixarray += data->modulo;
3378 static void ComplementAlphaTemplateBuffered(ULONG *xbuf, UWORD starty, UWORD width, UWORD height, struct patb_data *data)
3380 UWORD x, y;
3382 for (y = 0; y < height; y++)
3384 UBYTE *pixarray = data->pixarray;
3386 for (x = 0; x < width; x++)
3388 UBYTE alpha = (*pixarray++) ^ data->invert;
3390 if (alpha >= 0x80)
3391 xbuf[x] = ~xbuf[x];
3394 xbuf += width;
3395 data->pixarray += data->modulo;
3399 static void JAM2AlphaTemplateBuffered(ULONG *xbuf, UWORD starty, UWORD width, UWORD height, struct patb_data *data)
3401 UWORD x, y;
3403 for (y = 0; y < height; y++)
3405 UBYTE *pixarray = data->pixarray;
3407 for (x = 0; x < width; x++)
3409 LONG dst_red, dst_green, dst_blue, alpha;
3411 alpha = (*pixarray++) ^ data->invert;
3413 dst_red = data->b_red + ((data->a_red - data->b_red) * alpha) / 256;
3414 dst_green = data->b_green + ((data->a_green - data->b_green) * alpha) / 256;
3415 dst_blue = data->b_blue + ((data->a_blue - data->b_blue) * alpha) / 256;
3417 xbuf[x] = ARGB32_COMPOSE(dst_red, dst_green, dst_blue, 0);
3420 xbuf += width;
3421 data->pixarray += data->modulo;
3425 VOID BM__Hidd_BitMap__PutAlphaTemplate(OOP_Class *cl, OOP_Object *o,
3426 struct pHidd_BitMap_PutAlphaTemplate *msg)
3428 OOP_Object *gc = msg->gc;
3429 BOOL get = TRUE;
3430 void (*op)(ULONG *, UWORD, UWORD, UWORD, struct patb_data *);
3431 struct patb_data data;
3432 HIDDT_Color color;
3434 EnterFunc(bug("BitMap::PutAlphaTemplate(x=%d, y=%d, width=%d, height=%d)\n"
3435 , msg->x, msg->y, msg->width, msg->height));
3437 if (msg->width <= 0 || msg->height <= 0)
3438 return;
3440 HIDD_BM_UnmapPixel(o, GC_FG(gc), &color);
3441 data.a_red = color.red >> 8;
3442 data.a_green = color.green >> 8;
3443 data.a_blue = color.blue >> 8;
3445 if (GC_COLEXP(gc) == vHidd_GC_ColExp_Transparent)
3447 op = JAM1AlphaTemplateBuffered;
3449 else if (GC_DRMD(gc) == vHidd_GC_DrawMode_Invert)
3451 op = ComplementAlphaTemplateBuffered;
3453 else
3455 op = JAM2AlphaTemplateBuffered;
3456 get = FALSE;
3458 HIDD_BM_UnmapPixel(o, GC_BG(gc), &color);
3459 data.b_red = color.red >> 8;
3460 data.b_green = color.green >> 8;
3461 data.b_blue = color.blue >> 8;
3464 data.pixarray = msg->alpha;
3465 data.modulo = msg->modulo;
3466 data.invert = msg->invertalpha ? 255 : 0;
3468 DoBufferedOperation(cl, o, msg->x, msg->y, msg->width, msg->height, get, vHidd_StdPixFmt_ARGB32, (VOID_FUNC)op, &data);
3470 /* TODO: write fallback */
3472 ReturnVoid("BitMap::PutAlphaTemplate");
3475 /*****************************************************************************************
3477 NAME
3478 moHidd_BitMap_PutPattern
3480 SYNOPSIS
3481 VOID OOP_DoMethod(OOP_Object *o, struct pHidd_BitMap_PutPattern *msg);
3483 VOID HIDD_BM_PutPattern(OOP_Object *obj, OOP_Object *gc, UBYTE *pattern,
3484 WORD patternsrcx, WORD patternsrcy, WORD patternheight, WORD patterndepth,
3485 HIDDT_PixelLUT *patternlut, BOOL invertpattern, UBYTE *mask,
3486 ULONG maskmodulo, WORD masksrcx, WORD x, WORD y,
3487 WORD width, WORD height);
3489 LOCATION
3490 hidd.gfx.bitmap
3492 FUNCTION
3494 INPUTS
3495 obj - A bitmap to draw on
3496 gc - A GC object to use for drawing
3497 pattern -
3498 patternsrcx -
3499 patternsrcy -
3500 patternheight -
3501 patterndepth -
3502 patternlut -
3503 invertpattern -
3504 mask -
3505 maskmodulo -
3506 masksrcx -
3507 x, y -
3508 width -
3509 height -
3511 RESULT
3512 None
3514 NOTES
3516 EXAMPLE
3518 BUGS
3520 SEE ALSO
3522 INTERNALS
3524 *****************************************************************************************/
3526 struct ppb_data
3528 UWORD *patarray;
3529 void *maskarray;
3530 ULONG *patternlut;
3531 UWORD patternsrcy;
3532 UWORD desty;
3533 UWORD patternheight;
3534 ULONG maskmodulo;
3535 ULONG fg;
3536 ULONG bg;
3537 UWORD patmask;
3538 UWORD maskmask;
3539 UWORD patterndepth;
3540 UWORD invert;
3543 static void JAM1PatternBuffered(ULONG *xbuf, UWORD starty, UWORD width, UWORD height, struct ppb_data *data)
3545 UWORD x, y;
3547 for (y = 0; y < height; y++)
3549 UWORD pmask = data->patmask;
3550 UWORD mmask = data->maskmask;
3551 UWORD *parray = data->patarray + ((y + starty + data->patternsrcy - data->desty) % data->patternheight);
3552 UWORD patword = AROS_BE2WORD(*parray);
3553 UWORD *marray = data->maskarray;
3554 UWORD maskword = marray ? AROS_BE2WORD(*marray) : 0xFFFF;
3556 for (x = 0; x < width; x++)
3558 if (maskword & mmask)
3560 if ((patword & pmask) == (data->invert & pmask))
3561 xbuf[x] = data->fg;
3564 if (marray)
3566 mmask >>= 1;
3567 if (!mmask)
3569 mmask = 0x8000;
3570 marray++;
3571 maskword = AROS_BE2WORD(*marray);
3575 pmask >>= 1;
3576 if (!pmask)
3577 pmask = 0x8000;
3579 } /* for (x) */
3581 xbuf += width;
3582 if (data->maskarray)
3583 data->maskarray += data->maskmodulo;
3585 } /* for (y) */
3588 static void ComplementPatternBuffered(ULONG *xbuf, UWORD starty, UWORD width, UWORD height, struct ppb_data *data)
3590 UWORD x, y;
3592 for (y = 0; y < height; y++)
3594 UWORD pmask = data->patmask;
3595 UWORD mmask = data->maskmask;
3596 UWORD *parray = data->patarray + ((y + starty + data->patternsrcy - data->desty) % data->patternheight);
3597 UWORD patword = AROS_BE2WORD(*parray);
3598 UWORD *marray = data->maskarray;
3599 UWORD maskword = marray ? AROS_BE2WORD(*marray) : 0xFFFF;
3601 for (x = 0; x < width; x++)
3603 if (maskword & mmask)
3605 if ((patword & pmask) == (data->invert & pmask))
3606 xbuf[x] = ~xbuf[x];
3609 if (marray)
3611 mmask >>= 1;
3612 if (!mmask)
3614 mmask = 0x8000;
3615 marray++;
3616 maskword = AROS_BE2WORD(*marray);
3620 pmask >>= 1;
3621 if (!pmask)
3622 pmask = 0x8000;
3624 } /* for (x) */
3626 xbuf += width;
3627 if (data->maskarray)
3628 data->maskarray += data->maskmodulo;
3630 } /* for (y) */
3633 static void JAM2PatternBuffered(ULONG *xbuf, UWORD starty, UWORD width, UWORD height, struct ppb_data *data)
3635 UWORD x, y;
3637 for (y = 0; y < height; y++)
3639 UWORD pmask = data->patmask;
3640 UWORD mmask = data->maskmask;
3641 UWORD *parray = data->patarray + ((y + starty + data->patternsrcy - data->desty) % data->patternheight);
3642 UWORD patword = AROS_BE2WORD(*parray);
3643 UWORD *marray = data->maskarray;
3644 UWORD maskword = marray ? AROS_BE2WORD(*marray) : 0xFFFF;
3646 for (x = 0; x < width; x++)
3648 if (maskword & mmask)
3650 if ((patword & pmask) == (data->invert & pmask))
3651 xbuf[x] = data->fg;
3652 else
3653 xbuf[x] = data->bg;
3656 if (marray)
3658 mmask >>= 1;
3659 if (!mmask)
3661 mmask = 0x8000;
3662 marray++;
3663 maskword = AROS_BE2WORD(*marray);
3667 pmask >>= 1;
3668 if (!pmask)
3669 pmask = 0x8000;
3671 } /* for (x) */
3673 xbuf += width;
3674 if (data->maskarray)
3675 data->maskarray += data->maskmodulo;
3677 } /* for (y) */
3680 static void ColorPatternBuffered(ULONG *xbuf, UWORD starty, UWORD width, UWORD height, struct ppb_data *data)
3682 UWORD x, y;
3684 for (y = 0; y < height; y++)
3686 UWORD pmask = data->patmask;
3687 UWORD mmask = data->maskmask;
3688 UWORD *parray = data->patarray + ((y + starty + data->patternsrcy - data->desty) % data->patternheight);
3689 UWORD patword = AROS_BE2WORD(*parray);
3690 UWORD *marray = data->maskarray;
3691 UWORD maskword = marray ? AROS_BE2WORD(*marray) : 0xFFFF;
3693 for (x = 0; x < width; x++)
3695 if (maskword & mmask)
3697 UWORD plane;
3698 ULONG pixel = (patword & pmask) ? 1 : 0; /* CHECKME: Shouldn't we handle INVERSVID here too ? */
3700 for (plane = 1; plane < data->patterndepth; plane++)
3702 UWORD *_parray = parray + plane * data->patternheight;
3703 UWORD _patword = AROS_BE2WORD(*_parray);
3705 if (_patword & pmask)
3706 pixel |= 1L << plane;
3709 if (data->patternlut)
3710 pixel = data->patternlut[pixel];
3712 xbuf[x] = pixel;
3715 if (marray)
3717 mmask >>= 1;
3718 if (!mmask)
3720 mmask = 0x8000;
3721 marray++;
3722 maskword = AROS_BE2WORD(*marray);
3726 pmask >>= 1;
3727 if (!pmask)
3728 pmask = 0x8000;
3730 } /* for (x) */
3732 xbuf += width;
3733 if (data->maskarray)
3734 data->maskarray += data->maskmodulo;
3736 } /* for (y) */
3739 VOID BM__Hidd_BitMap__PutPattern(OOP_Class *cl, OOP_Object *o,
3740 struct pHidd_BitMap_PutPattern *msg)
3742 void (*op)(ULONG *xbuf, UWORD starty, UWORD width, UWORD height, struct ppb_data *data);
3743 BOOL get = TRUE;
3744 struct ppb_data data;
3746 DPUTPATTERN(bug("BitMap::PutPattern(x=%d, y=%d, width=%d, height=%d)\n",
3747 msg->x, msg->y, msg->width, msg->height));
3749 if (msg->width <= 0 || msg->height <= 0)
3750 return;
3752 if (msg->patterndepth > 1)
3754 DPUTPATTERN(bug("[PutPattern] Color\n"));
3755 op = ColorPatternBuffered;
3756 get = FALSE;
3758 else if (GC_COLEXP(msg->gc) == vHidd_GC_ColExp_Transparent)
3760 DPUTPATTERN(bug("[PutPattern] JAM1\n"));
3761 op = JAM1PatternBuffered;
3763 else if (GC_DRMD(msg->gc) == vHidd_GC_DrawMode_Invert)
3765 DPUTPATTERN(bug("[PutPattern] Complement\n"));
3766 op = ComplementPatternBuffered;
3768 else
3770 DPUTPATTERN(bug("[PutPattern] JAM2\n"));
3771 op = JAM2PatternBuffered;
3772 get = FALSE;
3775 data.patarray = (UWORD *)msg->pattern;
3776 data.patmask = 0x8000 >> (msg->patternsrcx & 0xF);
3777 data.maskarray = msg->mask;
3778 data.patternlut = msg->patternlut ? msg->patternlut->pixels : NULL;
3779 data.patternsrcy = msg->patternsrcy;
3780 data.desty = msg->y;
3781 data.patternheight = msg->patternheight;
3782 data.patterndepth = msg->patterndepth;
3783 data.maskmodulo = msg->maskmodulo;
3784 data.fg = GC_FG(msg->gc);
3785 data.bg = GC_BG(msg->gc);
3786 data.invert = msg->invertpattern ? 0 : 0xFFFF;
3788 if (data.maskarray)
3790 data.maskarray += (msg->masksrcx / 16) * 2;
3791 data.maskmask = 0x8000 >> (msg->masksrcx & 0xF);
3792 get = TRUE;
3794 else
3795 data.maskmask = 0xFFFF;
3797 DPUTPATTERN(bug("[PutPattern] MaskArray 0x%p, MaskMask 0x%04X\n", data.maskarray, data.maskmask));
3799 DoBufferedOperation(cl, o, msg->x, msg->y, msg->width, msg->height, get, vHidd_StdPixFmt_Native32, (VOID_FUNC)op, &data);
3801 /* TODO: Write fallback */
3803 ReturnVoid("BitMap::PutPattern");
3806 /*****************************************************************************************
3808 NAME
3809 moHidd_BitMap_PutImageLUT
3811 SYNOPSIS
3812 VOID OOP_DoMethod(OOP_Object *o, struct pHidd_BitMap_PutImageLUT *msg);
3814 VOID HIDD_BM_PutImageLUT (OOP_Object *obj, OOP_Object *gc, UBYTE *pixels, ULONG modulo,
3815 WORD x, WORD y, WORD width, WORD height, HIDDT_PixelLUT *pixlut);
3817 LOCATION
3818 hidd.gfx.bitmap
3820 FUNCTION
3822 INPUTS
3823 obj -
3824 gc -
3825 pixels -
3826 modulo -
3827 x, y -
3828 width -
3829 height -
3830 pixlut -
3832 RESULT
3834 NOTES
3836 EXAMPLE
3838 BUGS
3840 SEE ALSO
3842 INTERNALS
3844 *****************************************************************************************/
3846 VOID BM__Hidd_BitMap__PutImageLUT(OOP_Class *cl, OOP_Object *o,
3847 struct pHidd_BitMap_PutImageLUT *msg)
3849 WORD x, y;
3850 UBYTE *pixarray = (UBYTE *)msg->pixels;
3851 HIDDT_PixelLUT *pixlut = msg->pixlut;
3852 HIDDT_Pixel *lut = pixlut ? pixlut->pixels : NULL;
3853 HIDDT_Pixel *linebuf;
3854 OOP_Object *gc = msg->gc;
3856 EnterFunc(bug("BitMap::PutImageLUT(x=%d, y=%d, width=%d, height=%d)\n"
3857 , msg->x, msg->y, msg->width, msg->height));
3859 if (msg->width <= 0 || msg->height <= 0)
3860 return;
3862 linebuf = AllocVec(msg->width * sizeof(HIDDT_Pixel), MEMF_PUBLIC);
3864 for(y = 0; y < msg->height; y++)
3866 if (linebuf)
3868 if (lut)
3870 for(x = 0; x < msg->width; x++)
3872 linebuf[x] = lut[pixarray[x]];
3875 else
3877 for(x = 0; x < msg->width; x++)
3879 linebuf[x] = pixarray[x];
3882 pixarray += msg->modulo;
3884 HIDD_BM_PutImage(o,
3885 msg->gc,
3886 (UBYTE *)linebuf,
3888 msg->x,
3889 msg->y + y,
3890 msg->width,
3892 vHidd_StdPixFmt_Native32);
3894 } /* if (linebuf) */
3895 else
3897 ULONG old_fg;
3899 /* Preserve old fg pen */
3900 old_fg = GC_FG(gc);
3902 if (lut)
3904 for(x = 0; x < msg->width; x++)
3906 GC_FG(gc) = lut[pixarray[x]];
3907 HIDD_BM_DrawPixel(o, gc, msg->x + x, msg->y + y);
3910 else
3912 for(x = 0; x < msg->width; x++)
3914 GC_FG(gc) = pixarray[x];
3915 HIDD_BM_DrawPixel(o, gc, msg->x + x, msg->y + y);
3918 GC_FG(gc) = old_fg;
3920 pixarray += msg->modulo;
3922 } /* if (linebuf) else ... */
3924 } /* for(y = 0; y < msg->height; y++) */
3926 FreeVec(linebuf);
3928 ReturnVoid("BitMap::PutImageLUT");
3930 /*****************************************************************************************
3932 NAME
3933 moHidd_BitMap_PutTranspImageLUT
3935 SYNOPSIS
3936 VOID OOP_DoMethod(OOP_Object *obj, struct pHidd_BitMap_PutTranspImageLUT *msg);
3938 VOID HIDD_BM_PutTranspImageLUT (OOP_Object *obj, OOP_Object *gc, UBYTE *pixels,
3939 ULONG modulo, WORD x, WORD y, WORD width, WORD height,
3940 HIDDT_PixelLUT *pixlut, UBYTE transparent);
3942 LOCATION
3943 hidd.gfx.bitmap
3945 FUNCTION
3946 Copy an array of 8-bit LUT pixels to the bitmap at the specified position making
3947 one of colors transparent.
3949 Pixels are converted to bitmap's native format using either user-supplied LUT (if
3950 given) or bitmap's own colormap.
3952 Draw mode of the supplied GC is ignored, the operation is always bulk copy.
3954 INPUTS
3955 obj - A bitmap to draw image on
3956 gc - A GC used for drawing
3957 pixels - A pointer to source pixel array
3958 modulo - Total number of bytes per line in the source array
3959 x, y - Top-left corner of the destination rectangle
3960 width - Width of the image to draw
3961 height - Height of the image to draw
3962 pixlut - An optional pointer to a LUT to use. NULL means using bitmap's
3963 own colormap (if available)
3964 transparent - Value of pixels in the source array which will be made
3965 transparent
3967 RESULT
3968 None
3970 NOTES
3972 EXAMPLE
3974 BUGS
3976 SEE ALSO
3978 INTERNALS
3980 *****************************************************************************************/
3982 #undef csd /* Bad hack, but there's no other way */
3984 struct ptilb_data
3986 UBYTE *pixarray;
3987 ULONG *lut;
3988 OOP_Object *colmap;
3989 struct class_static_data *csd;
3990 ULONG modulo;
3991 UBYTE transparent;
3994 static void PutTranspImageLUTBuffered(ULONG *xbuf, UWORD starty, UWORD width, UWORD height, struct ptilb_data *data)
3996 struct class_static_data *csd = data->csd;
3997 UWORD x, y;
3999 for (y = 0; y < height; y++)
4001 UBYTE *pixarray = data->pixarray;
4003 if (data->lut)
4005 for (x = 0; x < width; x++)
4007 UBYTE pix = *pixarray++;
4009 if (pix != data->transparent)
4010 xbuf[x] = data->lut[pix];
4012 } /* for (x) */
4014 else
4016 for (x = 0; x < width; x++)
4018 UBYTE pix = *pixarray++;
4020 if (pix != data->transparent)
4022 if (data->colmap)
4023 pix = HIDD_CM_GetPixel(data->colmap, pix);
4025 xbuf[x] = pix;
4028 } /* for (x) */
4031 xbuf += width;
4032 data->pixarray += data->modulo;
4033 } /* for (y) */
4036 VOID BM__Hidd_BitMap__PutTranspImageLUT(OOP_Class *cl, OOP_Object *o,
4037 struct pHidd_BitMap_PutTranspImageLUT *msg)
4039 struct HIDDBitMapData *data = OOP_INST_DATA(cl, o);
4040 struct ptilb_data userdata =
4042 msg->pixels,
4043 NULL,
4044 data->colmap,
4045 CSD(cl),
4046 msg->modulo,
4047 msg->transparent
4050 EnterFunc(bug("BitMap::PutTranspImageLUT(x=%d, y=%d, width=%d, height=%d)\n"
4051 , msg->x, msg->y, msg->width, msg->height));
4053 if (msg->width <= 0 || msg->height <= 0)
4054 return;
4056 if (msg->pixlut)
4057 userdata.lut = msg->pixlut->pixels;
4059 DoBufferedOperation(cl, o, msg->x, msg->y, msg->width, msg->height, TRUE, vHidd_StdPixFmt_Native32,
4060 (VOID_FUNC)PutTranspImageLUTBuffered, &userdata);
4062 /* TODO: Write fallback */
4064 ReturnVoid("BitMap::PutTranspImageLUT");
4067 #define csd CSD(cl)
4069 /*****************************************************************************************
4071 NAME
4072 moHidd_BitMap_GetImageLUT
4074 SYNOPSIS
4075 VOID OOP_DoMethod(OOP_Object *obj, struct pHidd_BitMap_GetImageLUT *msg);
4077 VOID HIDD_BM_GetImageLUT (OOP_Object *obj, UBYTE *pixels, ULONG modulo, WORD x, WORD y,
4078 WORD width, WORD height, HIDDT_PixelLUT *pixlut);
4080 LOCATION
4081 hidd.gfx.bitmap
4083 FUNCTION
4085 INPUTS
4086 obj -
4087 pixels -
4088 modulo -
4089 x, y -
4090 width -
4091 height -
4092 pixlut -
4094 RESULT
4096 NOTES
4098 EXAMPLE
4100 BUGS
4102 SEE ALSO
4104 INTERNALS
4106 *****************************************************************************************/
4108 VOID BM__Hidd_BitMap__GetImageLUT(OOP_Class *cl, OOP_Object *o,
4109 struct pHidd_BitMap_GetImageLUT *msg)
4111 WORD x, y;
4112 UBYTE *pixarray = (UBYTE *)msg->pixels;
4113 HIDDT_PixelLUT *pixlut = msg->pixlut;
4114 HIDDT_Pixel *lut = pixlut ? pixlut->pixels : NULL;
4115 HIDDT_Pixel *linebuf;
4117 EnterFunc(bug("BitMap::GetImageLUT(x=%d, y=%d, width=%d, height=%d)\n"
4118 , msg->x, msg->y, msg->width, msg->height));
4120 linebuf = AllocVec(msg->width * sizeof(HIDDT_Pixel), MEMF_PUBLIC);
4122 for(y = 0; y < msg->height; y++)
4124 if (linebuf)
4126 HIDD_BM_GetImage(o,
4127 (UBYTE *)linebuf,
4129 msg->x,
4130 msg->y + y,
4131 msg->width,
4133 vHidd_StdPixFmt_Native32);
4134 if (lut)
4136 /* FIXME: This is wrong, but HIDD_BM_GetImageLUT on hi/truecolor screens does not really make sense anyway */
4137 for(x = 0; x < msg->width; x++)
4139 pixarray[x] = (UBYTE)linebuf[x];
4142 else
4144 for(x = 0; x < msg->width; x++)
4146 pixarray[x] = (UBYTE)linebuf[x];
4149 pixarray += msg->modulo;
4151 } /* if (linebuf) */
4152 else
4154 if (lut)
4156 /* FIXME: This is wrong, but HIDD_BM_GetImageLUT on hi/truecolor screens does not really make sense anyway */
4157 for(x = 0; x < msg->width; x++)
4159 pixarray[x] = (UBYTE)HIDD_BM_GetPixel(o, msg->x + x, msg->y + y);
4162 else
4164 for(x = 0; x < msg->width; x++)
4166 pixarray[x] = (UBYTE)HIDD_BM_GetPixel(o, msg->x + x, msg->y + y);
4170 pixarray += msg->modulo;
4172 } /* if (linebuf) else ... */
4174 } /* for(y = 0; y < msg->height; y++) */
4176 FreeVec(linebuf);
4178 ReturnVoid("BitMap::GetImageLUT");
4181 /*****************************************************************************************
4183 NAME
4184 moHidd_BitMap_BlitColorExpansion
4186 SYNOPSIS
4187 VOID OOP_DoMethod(OOP_Object *obj, struct pHidd_BitMap_BlitColorExpansion *msg);
4189 VOID HIDD_BM_BlitColorExpansion (OOP_Object *obj, OOP_Object *gc, OOP_Object *srcBitMap,
4190 WORD srcX, WORD srcY, WORD destX, WORD destY,
4191 UWORD width, UWORD height);
4193 LOCATION
4194 hidd.gfx.bitmap
4196 FUNCTION
4197 Perform a color expansion of the mask in srcBitMap according to foreground and background
4198 colors and expansion mode specified by the supplied GC. Pixels which are set to zero in
4199 the mask bitmap will be either painted by background (in opaque mode) or left without
4200 change (in transparent mode). Pixels which are set to nonzero in the mask will be painted
4201 by foreground color.
4203 The result of expansion is blitted onto the destination bitmap accorging to GC's draw mode.
4205 INPUTS
4206 obj - A bitmap to draw on
4207 gc - A GC object to use for drawing
4208 srcBitMap - A bitmap object containing mask image.
4209 srcX, srcY - A top-left coordinate of the used rectangle in the source bitmap
4210 destX, destY - A top-left coordinate of the destination rectangle to draw in
4211 width, height - A size of the rectangle to blit
4213 RESULT
4214 None.
4216 NOTES
4217 This method was previously used by graphics.library/Text() to draw fonts with no
4218 styles specified. Currently graphics.library always uses BltTemplate() and this
4219 method is considered obsolete.
4221 EXAMPLE
4223 BUGS
4225 SEE ALSO
4227 INTERNALS
4229 *****************************************************************************************/
4231 VOID BM__Hidd_BitMap__BlitColorExpansion(OOP_Class *cl, OOP_Object *o,
4232 struct pHidd_BitMap_BlitColorExpansion *msg)
4234 #ifdef __RESERVED__
4235 ULONG cemd;
4236 ULONG fg, bg;
4237 WORD x, y;
4239 OOP_Object *gc = msg->gc;
4241 EnterFunc(bug("BitMap::BlitColorExpansion(srcBM=%p, srcX=%d, srcY=%d, destX=%d, destY=%d, width=%d, height=%d)\n",
4242 msg->srcBitMap, msg->srcX, msg->srcY, msg->destX, msg->destY, msg->width, msg->height));
4244 cemd = GC_COLEXP(gc);
4245 fg = GC_FG(gc);
4246 bg = GC_BG(gc);
4248 /* bug("------------- Blit_ColExp: (%d, %d, %d, %d, %d, %d) cemd=%d, fg=%p, bg=%p -------------\n"
4249 , msg->srcX, msg->srcY, msg->destX, msg->destY, msg->width, msg->height
4250 , cemd, fg, bg);
4252 for (y = 0; y < msg->height; y ++)
4254 for (x = 0; x < msg->width; x ++)
4256 ULONG is_set;
4258 /* Pixel value is either 0 or 1 for BM of depth 1 */
4259 is_set = HIDD_BM_GetPixel(msg->srcBitMap, x + msg->srcX, y + msg->srcY);
4262 if (is_set)
4263 bug("#");
4264 else
4265 bug(" ");
4267 if (is_set)
4269 HIDD_BM_DrawPixel(o, gc, x + msg->destX, y + msg->destY);
4271 else
4273 if (cemd & vHidd_GC_ColExp_Opaque)
4275 /* Write bixel with BG pen */
4276 GC_FG(gc) = bg;
4277 HIDD_BM_DrawPixel(o, gc, x + msg->destX, y + msg->destY);
4278 /* Reset to FG pen */
4279 GC_FG(gc) = fg;
4282 } /* if () */
4284 } /* for (each x) */
4286 bug("\n");
4288 } /* for ( each y ) */
4289 #endif
4291 ReturnVoid("BitMap::BlitColorExpansion");
4294 /*****************************************************************************************
4296 NAME
4297 moHidd_BitMap_BytesPerLine
4299 SYNOPSIS
4300 ULONG OOP_DoMethod(OOP_Object *obj, struct pHidd_BitMap_BytesPerLine *msg);
4302 ULONG HIDD_BM_BytesPerLine(OOP_Object *obj, HIDDT_StdPixFmt pixFmt, UWORD width);
4304 LOCATION
4305 hidd.gfx.bitmap
4307 FUNCTION
4308 This method is currently not used and reserved.
4310 INPUTS
4311 obj -
4312 pixFmt -
4313 width -
4315 RESULT
4317 NOTES
4319 EXAMPLE
4321 BUGS
4323 SEE ALSO
4325 INTERNALS
4327 *****************************************************************************************/
4329 ULONG BM__Hidd_BitMap__BytesPerLine(OOP_Class *cl, OOP_Object *o, struct pHidd_BitMap_BytesPerLine *msg)
4331 #ifdef __RESERVED__
4332 ULONG bpl;
4334 switch (msg->pixFmt)
4336 case vHidd_StdPixFmt_Native32:
4337 bpl = sizeof (HIDDT_Pixel) * msg->width;
4338 break;
4340 case vHidd_StdPixFmt_Native:
4342 struct HIDDBitMapData *data;
4344 data = OOP_INST_DATA(cl, o);
4346 bpl = ((HIDDT_PixelFormat *)data->prot.pixfmt)->bytes_per_pixel * msg->width;
4347 break;
4350 default:
4352 OOP_Object *pf;
4353 struct HIDDBitMapData *data;
4355 data = OOP_INST_DATA(cl, o);
4357 pf = HIDD_Gfx_GetPixFmt(data->gfxhidd, msg->pixFmt);
4359 if (NULL == pf)
4361 D(bug("!!! COULD NOT GET STD PIXFMT IN BitMap::BytesPerLine() !!!\n"));
4362 return 0;
4365 bpl = ((HIDDT_PixelFormat *)pf)->bytes_per_pixel * msg->width;
4366 break;
4370 return bpl;
4371 #else
4372 return 0;
4373 #endif
4377 /****************************************************************************************/
4380 This makes it easier to create a subclass of the graphics hidd.
4381 It is only allowed to use this method in the p_RootNew method of a
4382 bitmap subclass.
4385 /****************************************************************************************/
4387 IPTR BM__Root__Set(OOP_Class *cl, OOP_Object *obj, struct pRoot_Set *msg)
4389 struct Library *UtilityBase = CSD(cl)->cs_UtilityBase;
4390 struct Library *OOPBase = CSD(cl)->cs_OOPBase;
4391 struct HIDDBitMapData *data = OOP_INST_DATA(cl, obj);
4392 struct TagItem *tag, *tstate;
4393 ULONG idx;
4394 WORD xoffset, yoffset;
4396 if (data->framebuffer)
4399 * If this is a framebuffer, we can process ModeID change.
4400 * We do it before parsing the rest of tags, because here we retrieve
4401 * defaults for new bitmap parameters (size and pixelformat).
4402 * They can be overridden by other tags. For example we can imagine
4403 * a hardware scrollable framebuffer whose width and height are larger
4404 * than visible part.
4406 HIDDT_ModeID modeid = GetTagData(aHidd_BitMap_ModeID, vHidd_ModeID_Invalid, msg->attrList);
4407 OOP_Object *sync, *pixfmt;
4409 if (HIDD_Gfx_GetMode(data->gfxhidd, modeid, &sync, &pixfmt))
4411 data->modeid = modeid;
4413 * Set defaults based on the ModeID.
4414 * They can be overriden lated, in SetBitMapTags.
4416 data->width = OOP_GET(sync, aHidd_Sync_HDisp);
4417 data->height = OOP_GET(sync, aHidd_Sync_VDisp);
4418 data->bytesPerRow = GetBytesPerRow(data, CSD(cl));
4419 data->prot.pixfmt = pixfmt;
4421 else
4423 /* Bad ModeID given, request rejected */
4424 return FALSE;
4427 /* Process the rest of tags. */
4428 BM__Hidd_BitMap__SetBitMapTags(cl, obj, msg->attrList);
4430 else
4433 * This is not a framebuffer.
4434 * We can modify size data (CHECKME: is it really used anywhere ?)
4435 * and also we can scroll (makes sense only if this is displayable
4436 * bitmap in mirrored framebuffer mode.
4438 BM__Hidd_BitMap__SetBitMapTags(cl, obj, msg->attrList);
4441 * And now we process position change.
4442 * One trick: we store our 'display' rectangle in bitmap's coordinates.
4443 * In other words, these are screen coordinates relative to bitmap, not
4444 * bitmap's ones relative to screen. As a result, we have to invert the sign.
4445 * This is done in order to simplify calculations in UpdateBitMap method of
4446 * graphics base class. It needs to perform intersection of update rectangle
4447 * with display rectangle, and they need to be in the same coordinate system
4448 * in order to be able to do this.
4449 * Update operation is performance-critical, so we perform this conversion
4450 * for display rectangle here.
4452 xoffset = data->display.MinX;
4453 yoffset = data->display.MinY;
4454 tstate = msg->attrList;
4455 while ((tag = NextTagItem(&tstate)))
4457 Hidd_BitMap_Switch(tag->ti_Tag, idx)
4459 case aoHidd_BitMap_LeftEdge:
4460 xoffset = tag->ti_Data;
4462 * FIXME:
4463 * Our bitmap cannot be smaller than display size because of fakegfx.hidd
4464 * limitations (it can't place cursor beyond bitmap edges). Otherwise Intuition
4465 * will provide strange user experience (mouse cursor will disappear)
4467 if (xoffset >= (WORD)data->displayWidth)
4468 xoffset = data->displayWidth - 1;
4469 else if (xoffset <= (WORD)-data->width)
4470 xoffset = -(data->width - 1);
4471 xoffset = -xoffset;
4472 D(bug("[BitMap] xoffset requested %ld, got %d\n", -tag->ti_Data, xoffset));
4473 break;
4475 case aoHidd_BitMap_TopEdge:
4476 /* Only offsets that ensure at least some of the bitmap is
4477 seen are valid */
4478 yoffset = tag->ti_Data;
4479 if (yoffset >= (WORD)data->displayHeight)
4480 yoffset = data->displayHeight - 1;
4481 else if (yoffset <= (WORD)-data->height)
4482 yoffset = -(data->height - 1);
4483 yoffset = -yoffset;
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 GFXHIDD__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.gfx.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.gfx.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.gfx.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.gfx.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.gfx.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.gfx.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.gfx.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.gfx.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 GFXHIDD__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",
5170 data->width, data->height,
5171 data->displayWidth, data->displayHeight));
5181 * Updates bitmap's pixelformat.
5182 * Used from within planarbm subclass, and would be extremely dangerous to expose
5183 * as setable aHidd_BitMap_PixFmt, so implemented as a separate method.
5185 void BM__Hidd_BitMap__SetPixFmt(OOP_Class *cl, OOP_Object *o, OOP_Object *pf)
5187 struct HIDDBitMapData *data = OOP_INST_DATA(cl, o);
5189 /* Already a pixfmt registered? */
5190 if (data->pf_registered)
5191 GFXHIDD__Hidd_Gfx__ReleasePixFmt(CSD(cl)->gfxhiddclass, data->prot.pixfmt);
5193 /* Remember the new pixelformat */
5194 data->prot.pixfmt = pf;
5197 * This pixelformat was obtained using GFXHIDD__Hidd_Gfx__RegisterPixFmt().
5198 * It increases number of pixfmt users, so we'll need to release it when
5199 * not used any more.
5201 data->pf_registered = TRUE;
5205 * Change visible state of the bitmap.
5206 * Used in mirrored framebuffer mode. Actually needed because
5207 * of semaphore barrier, which makes sure that bitmap state does
5208 * not change during scrolling or updating operation. Prevents possibilities
5209 * of screen corruption during concurrently running scrolling with Show.
5211 void BM__Hidd_BitMap__SetVisible(OOP_Class *cl, OOP_Object *o, BOOL val)
5213 struct HIDDBitMapData *data = OOP_INST_DATA(cl, o);
5215 ObtainSemaphore(&data->lock);
5216 data->visible = val;
5217 ReleaseSemaphore(&data->lock);