revert between 56095 -> 55830 in arch
[AROS.git] / rom / hidds / gfx / gfx_bitmapclass.c
blob665efe68f209403408f239a01a11d462088cea4e
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 GETIMAGE(cl, o, buf, bytesperline, startx, y, width, buflines, stdpf);
120 operation(buf, y, width, buflines, userdata);
122 PUTIMAGE(cl, 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
1069 #if USE_FAST_DRAWLINE
1070 data->drawline = OOP_GetMethod(obj, HiddBitMapBase + moHidd_BitMap_DrawLine, &data->drawline_Class);
1071 #endif
1072 #if USE_FAST_GETIMAGE
1073 data->getimage = OOP_GetMethod(obj, HiddBitMapBase + moHidd_BitMap_GetImage, &data->getimage_Class);
1074 #endif
1075 #if USE_FAST_PUTIMAGE
1076 data->putimage = OOP_GetMethod(obj, HiddBitMapBase + moHidd_BitMap_PutImage, &data->putimage_Class);
1077 #endif
1078 #if USE_FAST_CONVERTPIXELS
1079 data->convertpixels = OOP_GetMethod(obj, HiddBitMapBase + moHidd_BitMap_ConvertPixels, &data->convertpixels_Class);
1080 #endif
1081 #if USE_FAST_UNMAPPIXEL
1082 data->unmappixel = OOP_GetMethod(obj, HiddBitMapBase + moHidd_BitMap_UnmapPixel, &data->unmappixel_Class);
1083 #endif
1084 #if USE_FAST_MAPCOLOR
1085 data->mapcolor = OOP_GetMethod(obj, HiddBitMapBase + moHidd_BitMap_MapColor, &data->mapcolor_Class);
1086 #endif
1088 * Try to create the colormap.
1090 * stegerg: Only add a ColorMap for a visible bitmap (screen). This
1091 * is important because one can create for example a bitmap
1092 * in PIXFMT_LUT8 without friend bitmap and then copy this
1093 * bitmap to a 16 bit screen. During copy the screen bitmap
1094 * CLUT must be used, which would not happen if our PIXFMT_LUT8
1095 * also had a colormap itself because then bltbitmap would use the
1096 * colormap of the PIXFMT_LUT8 bitmap as lookup, which in this
1097 * case would just cause everything to become black in the
1098 * destination (screen) bitmap, because noone ever sets up the
1099 * colormap of the PIXFMT_LUT8 bitmap
1101 * sonic: CHECKME: Why does the colormap always have 16 colors? May be calculate this
1102 * based on depth ? The colormap auto-enlarges itself if SetColors method requests
1103 * missing entries, but is it so good?
1106 if (data->displayable)
1108 data->colmap = OOP_NewObject(NULL, CLID_Hidd_ColorMap, colmap_tags);
1109 if (NULL == data->colmap)
1110 ok = FALSE;
1115 if (!ok)
1117 ULONG dispose_mid = OOP_GetMethodID(IID_Root, moRoot_Dispose);
1119 OOP_CoerceMethod(cl, obj, &dispose_mid);
1120 obj = NULL;
1122 } /* if(obj) */
1124 } /* if (NULL != obj) */
1126 ReturnPtr("BitMap::New", OOP_Object *, obj);
1129 /****************************************************************************************/
1131 void BM__Root__Dispose(OOP_Class *cl, OOP_Object *obj, OOP_Msg *msg)
1133 struct Library *OOPBase = CSD(cl)->cs_OOPBase;
1134 struct HIDDBitMapData *data = OOP_INST_DATA(cl, obj);
1136 EnterFunc(bug("BitMap::Dispose()\n"));
1138 if (NULL != data->colmap)
1139 OOP_DisposeObject(data->colmap);
1141 D(bug("Calling super\n"));
1143 /* Release the previously registered pixel format */
1144 if (data->pf_registered)
1145 GFXHIDD__Hidd_Gfx__ReleasePixFmt(CSD(cl)->gfxhiddclass, data->prot.pixfmt);
1147 OOP_DoSuperMethod(cl, obj, (OOP_Msg) msg);
1149 ReturnVoid("BitMap::Dispose");
1152 /****************************************************************************************/
1154 VOID BM__Root__Get(OOP_Class *cl, OOP_Object *obj, struct pRoot_Get *msg)
1156 struct HIDDBitMapData *data = OOP_INST_DATA(cl, obj);
1157 ULONG idx;
1159 EnterFunc(bug("BitMap::Get() attrID: %i storage: %p\n", msg->attrID, msg->storage));
1161 if (IS_BITMAP_ATTR(msg->attrID, idx))
1163 switch(idx)
1165 case aoHidd_BitMap_BMStruct:
1166 *msg->storage = (IPTR)data->bmstruct;
1167 return;
1169 case aoHidd_BitMap_Width:
1170 *msg->storage = data->width;
1171 D(bug(" width: %i\n", data->width));
1172 return;
1174 case aoHidd_BitMap_Height:
1175 *msg->storage = data->height;
1176 return;
1178 case aoHidd_BitMap_Depth:
1180 * Generally our bitmaps have a fixed depth, which depends on pixelformat.
1181 * If this is not true for your bitmap, overload aoHidd_BitMap_Depth in your class.
1183 *msg->storage = ((HIDDT_PixelFormat *)data->prot.pixfmt)->depth;
1184 return;
1186 case aoHidd_BitMap_Displayable:
1187 *msg->storage = data->displayable;
1188 return;
1190 case aoHidd_BitMap_FrameBuffer:
1191 *msg->storage = data->framebuffer;
1192 return;
1194 case aoHidd_BitMap_PixFmt:
1195 *msg->storage = (IPTR)data->prot.pixfmt;
1196 return;
1198 case aoHidd_BitMap_Friend:
1199 *msg->storage = (IPTR)data->friend;
1200 return;
1202 case aoHidd_BitMap_ColorMap:
1203 *msg->storage = (IPTR)data->colmap;
1204 return;
1206 case aoHidd_BitMap_GfxHidd:
1207 *msg->storage = (IPTR)data->gfxhidd;
1208 return;
1210 case aoHidd_BitMap_ModeID:
1211 *msg->storage = data->modeid;
1212 return;
1214 case aoHidd_BitMap_Align:
1215 *msg->storage = data->align;
1216 return;
1218 case aoHidd_BitMap_BytesPerRow:
1219 *msg->storage = data->bytesPerRow;
1220 return;
1222 case aoHidd_BitMap_Visible:
1223 /* Framebuffer is always visible */
1224 *msg->storage = data->framebuffer ? TRUE : data->visible;
1225 return;
1227 case aoHidd_BitMap_Compositable:
1228 *msg->storage = (IPTR)data->compositable;
1229 return;
1232 * The following two are stored with inverted sign!
1233 * Verbose explanation is in Set method.
1235 case aoHidd_BitMap_LeftEdge:
1236 *msg->storage = -data->display.MinX;
1237 return;
1239 case aoHidd_BitMap_TopEdge:
1240 *msg->storage = -data->display.MinY;
1241 return;
1243 D(default: bug("UNKNOWN ATTR IN BITMAP BASECLASS: %d\n", idx);)
1247 OOP_DoSuperMethod(cl, obj, &msg->mID);
1248 ReturnVoid("BitMap::Get");
1251 /****************************************************************************************/
1253 #define UB(x) ((UBYTE *)x)
1255 /*****************************************************************************************
1257 NAME
1258 moHidd_BitMap_SetColors
1260 SYNOPSIS
1261 BOOL OOP_DoMethod(OOP_Object *obj, struct pHidd_BitMap_SetColors *msg);
1263 BOOL HIDD_BM_SetColors (OOP_Object *obj, HIDDT_Color *colors,
1264 UWORD firstColor, UWORD numColors);
1266 LOCATION
1267 hidd.gfx.bitmap
1269 FUNCTION
1270 Sets values for one or more colors in the colormap object associated with the
1271 bitmap.
1273 The colormap will be created if it does not exist.
1275 Only ARGB values from the source array are taken into account. pixval member is
1276 updated with the real pixel value for every color.
1278 INPUTS
1279 obj - A bitmap object whose colormap needs to be set
1280 colors - A pointer to source data array
1281 firstColor - Number of the first color to set
1282 numColors - Number of subsequent colors to set
1284 RESULT
1285 TRUE on success, FALSE in case of some error (like out of memory)
1287 NOTES
1289 EXAMPLE
1291 BUGS
1293 SEE ALSO
1294 CLID_Hidd_ColorMap/moHidd_ColorMap_SetColors
1296 INTERNALS
1298 *****************************************************************************************/
1300 BOOL BM__Hidd_BitMap__SetColors(OOP_Class *cl, OOP_Object *o, struct pHidd_BitMap_SetColors *msg)
1302 /* Copy the colors into the internal buffer */
1303 struct Library *OOPBase = CSD(cl)->cs_OOPBase;
1304 struct HIDDBitMapData *data = OOP_INST_DATA(cl, o);
1305 BOOL ret = TRUE;
1307 /* Subclass has initialized HIDDT_Color->pixelVal field and such.
1308 Just copy it into the colortab.
1311 if (NULL == data->colmap)
1313 struct TagItem colmap_tags[] =
1315 { aHidd_ColorMap_NumEntries, 0 },
1316 { TAG_DONE }
1319 colmap_tags[0].ti_Data = msg->firstColor + msg->numColors;
1320 data->colmap = OOP_NewObject(NULL, CLID_Hidd_ColorMap, colmap_tags);
1323 if (NULL == data->colmap)
1325 return FALSE;
1328 /* Use the colormap class to set the colors */
1329 if (!HIDD_CM_SetColors(data->colmap, msg->colors,
1330 msg->firstColor, msg->numColors,
1331 data->prot.pixfmt))
1333 return FALSE;
1336 /* We may need to duplicate changes on framebuffer if running in mirrored mode */
1337 if (data->visible)
1339 ObtainSemaphoreShared(&data->lock);
1341 if (data->visible)
1343 ret = GFXHIDD__Hidd_Gfx__SetFBColors(CSD(cl)->gfxhiddclass, data->gfxhidd, msg);
1346 ReleaseSemaphore(&data->lock);
1349 return ret;
1352 /*******************************************************************************
1354 NAME
1355 moHidd_BitMap_PutPixel
1357 SYNOPSIS
1358 VOID OOP_DoMethod(OOP_Object *obj, struct pHidd_BitMap_PutPixel *msg);
1360 VOID HIDD_BM_PutPixel(OOP_Object *obj, WORD x, WORD y,
1361 HIDDT_Pixel pixel);
1363 LOCATION
1364 hidd.gfx.bitmap
1366 FUNCTION
1367 Sets a new color value for the pixel at (x,y). The actual color stored
1368 may be an approximation, due to the limited color depth or palette size
1369 of the bitmap. This function does not check the coordinates.
1371 INPUTS
1372 obj - bitmap to write to.
1373 x, y - coordinates of the pixel to write.
1374 pixel - the pixel's new color value.
1376 RESULT
1377 None.
1379 NOTES
1381 EXAMPLE
1383 BUGS
1385 SEE ALSO
1387 INTERNALS
1389 *******************************************************************************/
1391 /* PutPixel must be implemented in a subclass */
1393 /*****************************************************************************************
1395 NAME
1396 moHidd_BitMap_DrawPixel
1398 SYNOPSIS
1399 VOID OOP_DoMethod(OOP_Object *obj, struct pHidd_BitMap_DrawPixel *msg);
1401 VOID HIDD_BM_DrawPixel(OOP_Object *obj, OOP_Object *gc, WORD x, WORD y);
1403 LOCATION
1404 hidd.gfx.bitmap
1406 FUNCTION
1407 Changes the pixel at (x,y). The color of the pixel depends on the
1408 attributes of gc, eg. colors, drawmode, colormask etc.
1409 This function does not check the coordinates.
1411 INPUTS
1412 obj - A bitmap to draw on
1413 gc - A GC (graphics context) object to use for drawing
1414 x, y - Coordinates of the pixel to draw
1416 RESULT
1417 None.
1419 NOTES
1421 EXAMPLE
1423 BUGS
1425 SEE ALSO
1427 INTERNALS
1429 TODO
1430 - Support for shapeplane.
1431 - Optimize
1433 *****************************************************************************************/
1435 VOID BM__Hidd_BitMap__DrawPixel(OOP_Class *cl, OOP_Object *obj,
1436 struct pHidd_BitMap_DrawPixel *msg)
1438 HIDDT_Pixel src, dest, val;
1439 HIDDT_DrawMode mode;
1440 HIDDT_Pixel writeMask;
1441 OOP_Object *gc;
1443 /* EnterFunc(bug("BitMap::DrawPixel() x: %i, y: %i\n", msg->x, msg->y));
1446 Example: Pixels whose bits are set to 0 in the colMask must be
1447 unchanged
1449 data->colMask = 001111
1450 dest = 101100
1453 writeMask = ~data->colMask & dest
1454 = 110000 & 101100
1455 = 100000
1457 dest = data->fg && dest = 010100
1460 dest = dest & (writeMask | data->ColMask)
1461 = 010100 & (100000 | 001111)
1462 = 010100 & (101111)
1463 = 000100
1466 dest = dest | writeMask;
1467 = 000100 100000
1468 = 100100
1472 gc = msg->gc;
1474 src = GC_FG(gc);
1475 mode = GC_DRMD(gc);
1477 #if OPTIMIZE_DRAWPIXEL_FOR_COPY
1478 if (vHidd_GC_DrawMode_Copy == mode && GC_COLMASK(gc) == ~0)
1480 val = src;
1482 else
1483 #endif
1485 dest = GETPIXEL(cl, obj, msg->x, msg->y);
1486 writeMask = ~GC_COLMASK(gc) & dest;
1488 val = 0;
1490 if(mode & 1) val = ( src & dest);
1491 if(mode & 2) val = ( src & ~dest) | val;
1492 if(mode & 4) val = (~src & dest) | val;
1493 if(mode & 8) val = (~src & ~dest) | val;
1495 val = (val & (writeMask | GC_COLMASK(gc) )) | writeMask;
1499 PUTPIXEL(cl, obj, msg->x, msg->y, val);
1502 /*****************************************************************************************
1504 NAME
1505 moHidd_BitMap_DrawLine
1507 SYNOPSIS
1508 VOID OOP_DoMethod(OOP_Object *obj, struct pHidd_BitMap_DrawPixel *msg);
1510 VOID HIDD_BM_DrawLine(OOP_Object *obj, OOP_Object *gc, WORD x1, WORD y1,
1511 WORD x2, WORD y2);
1513 LOCATION
1514 hidd.gfx.bitmap
1516 FUNCTION
1517 Draws a line from (x1,y1) to (x2,y2) in the specified gc.
1518 The function does not clip the line against the drawing area.
1520 INPUTS
1521 obj - A bitmap to draw on
1522 gc - A graphics context object to use
1523 x1,y1 - start point of the line in pixels
1524 x2,y2 - end point of the line in pixels
1526 RESULT
1527 None.
1529 NOTES
1531 EXAMPLE
1533 BUGS
1535 SEE ALSO
1537 INTERNALS
1538 Uses midpoint line ("Bresenham") algorithm([FOL90] 3.2.2)
1540 TODO Support for line pattern
1541 Optimize remove if t == 1 ...
1542 Implement better clipping: Should be no reason to calculate
1543 more than the part of the line that is inside the cliprect
1545 *****************************************************************************************/
1547 VOID BM__Hidd_BitMap__DrawLine
1549 OOP_Class *cl, OOP_Object *obj, struct pHidd_BitMap_DrawLine *msg
1552 WORD dx, dy, incrE, incrNE, d, x, y, s1, s2, t, i;
1553 WORD x1, y1, x2, y2;
1554 UWORD maskLine; /* for line pattern */
1555 ULONG fg; /* foreground pen */
1556 APTR doclip;
1557 BOOL opaque;
1558 OOP_Object *gc;
1561 /* bug("BitMap::DrawLine()\n");
1562 */ EnterFunc(bug("BitMap::DrawLine() x1: %i, y1: %i x2: %i, y2: %i\n", msg->x1, msg->y1, msg->x2, msg->y2));
1564 gc = msg->gc;
1565 doclip = GC_DOCLIP(gc);
1566 opaque = (GC_COLEXP(gc) & vHidd_GC_ColExp_Opaque) ? TRUE : FALSE;
1567 fg = GC_FG(gc);
1569 maskLine = 1 << GC_LINEPATCNT(gc);
1571 if (doclip)
1573 /* If line is not inside cliprect, then just return */
1574 /* Normalize coords */
1575 if (msg->x1 > msg->x2)
1577 x1 = msg->x2; x2 = msg->x1;
1579 else
1581 x1 = msg->x1; x2 = msg->x2;
1584 if (msg->y1 > msg->y2)
1586 y1 = msg->y2; y2 = msg->y1;
1588 else
1590 y1 = msg->y1; y2 = msg->y2;
1593 if ( x1 > GC_CLIPX2(gc)
1594 || x2 < GC_CLIPX1(gc)
1595 || y1 > GC_CLIPY2(gc)
1596 || y2 < GC_CLIPY1(gc) )
1599 /* Line is not inside cliprect, so just return */
1600 return;
1605 x1 = msg->x1;
1606 y1 = msg->y1;
1607 x2 = msg->x2;
1608 y2 = msg->y2;
1610 if (y1 == y2)
1613 Horizontal line drawing code.
1615 y = y1;
1617 /* Don't swap coordinates if x2 < x1! Because of linepattern! */
1619 if (x1 < x2)
1621 x2++;
1622 dx = 1;
1624 else
1626 x2--;
1627 dx = -1;
1630 for(i = x1; i != x2; i += dx)
1632 /* Pixel inside ? */
1634 if (!doclip || !POINT_OUTSIDE_CLIP(gc, i, y ))
1636 if(GC_LINEPAT(gc) & maskLine)
1638 DRAWPIXEL(cl, obj, gc, i, y);
1640 else if (opaque)
1642 GC_FG(gc) = GC_BG(gc);
1643 DRAWPIXEL(cl, obj, gc, i, y);
1644 GC_FG(gc) = fg;
1648 maskLine = maskLine >> 1;
1649 if (!maskLine) maskLine = 1L << 15;
1652 else if (x1 == x2)
1655 Vertical line drawing code.
1657 x = x1;
1659 /* Don't swap coordinates if y2 < y1! Because of linepattern! */
1661 if (y1 < y2)
1663 y2++;
1664 dy = 1;
1666 else
1668 y2--;
1669 dy = -1;
1672 for(i = y1; i != y2; i += dy)
1674 /* Pixel inside ? */
1675 if (!doclip || !POINT_OUTSIDE_CLIP(gc, x, i ))
1677 if(GC_LINEPAT(gc) & maskLine)
1679 DRAWPIXEL(cl, obj, gc, x, i);
1681 else if (opaque)
1683 GC_FG(gc) = GC_BG(gc);
1684 DRAWPIXEL(cl, obj, gc, x, i);
1685 GC_FG(gc) = fg;
1689 maskLine = maskLine >> 1;
1690 if (!maskLine) maskLine = 1L << 15;
1694 else
1697 Generic line drawing code.
1699 /* Calculate slope */
1700 dx = abs(x2 - x1);
1701 dy = abs(y2 - y1);
1703 /* which direction? */
1704 if((x2 - x1) > 0) s1 = 1; else s1 = - 1;
1705 if((y2 - y1) > 0) s2 = 1; else s2 = - 1;
1707 /* change axes if dx < dy */
1708 if(dx < dy)
1710 d = dx;
1711 dx = dy;
1712 dy = d;
1713 t = 0;
1715 else
1717 t = 1;
1720 d = 2 * dy - dx; /* initial value of d */
1722 incrE = 2 * dy; /* Increment use for move to E */
1723 incrNE = 2 * (dy - dx); /* Increment use for move to NE */
1725 x = x1; y = y1;
1727 for(i = 0; i <= dx; i++)
1729 /* Pixel inside ? */
1730 if (!doclip || !POINT_OUTSIDE_CLIP(gc, x, y ))
1732 if(GC_LINEPAT(gc) & maskLine)
1734 DRAWPIXEL(cl, obj, gc, x, y);
1736 else if (opaque)
1738 GC_FG(gc) = GC_BG(gc);
1739 DRAWPIXEL(cl, obj, gc, x, y);
1740 GC_FG(gc) = fg;
1744 if(d <= 0)
1746 if(t == 1)
1748 x = x + s1;
1750 else
1752 y = y + s2;
1755 d = d + incrE;
1757 else
1759 x = x + s1;
1760 y = y + s2;
1761 d = d + incrNE;
1764 maskLine = maskLine >> 1;
1765 if (!maskLine) maskLine = 1L << 15;
1770 ReturnVoid("BitMap::DrawLine ");
1773 /*****************************************************************************************
1775 NAME
1776 moHidd_BitMap_DrawRect
1778 SYNOPSIS
1779 OOP_DoMethod(OOP_Object *obj, struct pHidd_BitMap_DrawRect *msg);
1781 VOID HIDD_BM_DrawRect (OOP_Object *obj, OOP_Object *gc, WORD minX, WORD minY,
1782 WORD maxX, WORD maxY);
1784 LOCATION
1785 hidd.gfx.bitmap
1787 FUNCTION
1788 Draws a hollow rectangle. minX and minY specifies the upper
1789 left corner of the rectangle. minY and maxY specifies the lower
1790 right corner of the rectangle.
1791 The function does not clip the rectangle against the drawing area.
1793 INPUTS
1794 obj - A bitmap to draw on
1795 gc - A GC object to use for drawing
1796 minX, minY - upper left corner of the rectangle in pixels
1797 maxX, maxY - lower right corner of the rectangle in pixels
1799 RESULT
1800 None.
1802 NOTES
1803 This method is not used by the system and considered reserved.
1805 EXAMPLE
1807 BUGS
1809 SEE ALSO
1811 INTERNALS
1813 TODO
1815 *****************************************************************************************/
1817 VOID BM__Hidd_BitMap__DrawRect(OOP_Class *cl, OOP_Object *obj,
1818 struct pHidd_BitMap_DrawRect *msg)
1820 #ifdef __RESERVED__
1821 OOP_Object *gc = msg->gc;
1822 WORD addX, addY;
1824 EnterFunc(bug("BitMap::DrawRect()"));
1826 if(msg->minX == msg->maxX) addX = 0; else addX = 1;
1827 if(msg->minY == msg->maxY) addY = 0; else addY = 1;
1829 DRAWLINE(cl, obj, gc, msg->minX, msg->minY , msg->maxX, msg->minY);
1830 DRAWLINE(cl, obj, gc, msg->maxX, msg->minY + addY, msg->maxX, msg->maxY);
1831 DRAWLINE(cl, obj, gc, msg->maxX - addX, msg->maxY, msg->minX, msg->maxY);
1832 DRAWLINE(cl, obj, gc, msg->minX, msg->maxY - addY, msg->minX, msg->minY + addY);
1833 #endif
1835 ReturnVoid("BitMap::DrawRect");
1838 /*****************************************************************************************
1840 NAME
1841 moHidd_BitMap_FillRect
1843 SYNOPSIS
1844 VOID OOP_DoMethod(OOP_Object *obj, struct pHidd_BitMap_DrawRect *msg);
1846 VOID HIDD_BM_FillRect (OOP_Object *obj, OOP_Object *gc, WORD minX, WORD minY,
1847 WORD maxX, WORD maxY);
1849 LOCATION
1850 hidd.gfx.bitmap
1852 FUNCTION
1854 Draws a solid rectangle. minX and minY specifies the upper
1855 left corner of the rectangle. maxX and maxY specifies the lower
1856 right corner of the rectangle.
1857 The function does not clip the rectangle against the drawing area.
1859 INPUTS
1860 obj - A bitmap to draw on
1861 gc - A GC object to use for drawing
1862 minX, minY - upper left corner of the rectangle in pixels
1863 maxX, maxY - lower right corner of the rectangle in pixels
1865 RESULT
1866 None.
1868 NOTES
1870 EXAMPLE
1872 BUGS
1874 SEE ALSO
1876 INTERNALS
1878 TODO
1879 Fill with pattern
1881 *****************************************************************************************/
1883 VOID BM__Hidd_BitMap__FillRect(OOP_Class *cl, OOP_Object *obj,
1884 struct pHidd_BitMap_DrawRect *msg)
1886 OOP_Object *gc = msg->gc;
1887 WORD y = msg->minY;
1888 UWORD linepat;
1890 EnterFunc(bug("BitMap::FillRect()"));
1892 linepat = GC_LINEPAT(gc);
1893 GC_LINEPAT(gc) = ~0;
1895 for(; y <= msg->maxY; y++)
1897 DRAWLINE(cl, obj, gc, msg->minX, y, msg->maxX, y);
1900 GC_LINEPAT(gc) = linepat;
1902 ReturnVoid("BitMap::FillRect");
1905 /*****************************************************************************************
1907 NAME
1908 moHidd_BitMap_DrawEllipse
1910 SYNOPSIS
1911 VOID OOP_DoMethod(OOP_Object *obj, struct pHidd_BitMap_DrawEllipse *msg);
1913 VOID HIDD_BM_DrawEllipse (OOP_Object *obj, OOP_Object *gc, WORD x, WORD y,
1914 WORD rx, WORD ry);
1916 LOCATION
1917 hidd.gfx.bitmap
1919 FUNCTION
1920 Draws a hollow ellipse from the center point (x,y) with the radii
1921 rx and ry in the specified bitmap.
1922 The function does not clip the ellipse against the drawing area.
1924 INPUTS
1925 obj - A bitmap to draw on
1926 gc - A GC object to use for drawing
1927 x,y - Coordinates of center point in pixels
1928 rx,ry - ry and ry radius in pixels
1930 RESULT
1931 None.
1933 NOTES
1935 EXAMPLE
1937 BUGS
1938 Because of overflow the current code do not work with big
1939 values of rx and ry.
1941 SEE ALSO
1943 INTERNALS
1945 TODO
1946 Bugfix
1948 *****************************************************************************************/
1950 /* TODO: Try to opimize clipping here */
1952 VOID BM__Hidd_BitMap__DrawEllipse(OOP_Class *cl, OOP_Object *obj,
1953 struct pHidd_BitMap_DrawEllipse *msg)
1955 OOP_Object *gc = msg->gc;
1956 WORD x = msg->rx, y = 0; /* ellipse points */
1958 /* intermediate terms to speed up loop */
1959 LONG t1 = msg->rx * msg->rx, t2 = t1 << 1, t3 = t2 << 1;
1960 LONG t4 = msg->ry * msg->ry, t5 = t4 << 1, t6 = t5 << 1;
1961 LONG t7 = msg->rx * t5, t8 = t7 << 1, t9 = 0L;
1962 LONG d1 = t2 - t7 + (t4 >> 1); /* error terms */
1963 LONG d2 = (t1 >> 1) - t8 + t5;
1965 APTR doclip = GC_DOCLIP(gc);
1968 EnterFunc(bug("BitMap::DrawEllipse()"));
1970 while (d2 < 0) /* till slope = -1 */
1972 /* draw 4 points using symmetry */
1974 if (doclip)
1977 if (!POINT_OUTSIDE_CLIP(gc, msg->x + x, msg->y + y))
1979 DRAWPIXEL(cl, obj, gc, msg->x + x, msg->y + y);
1982 if (!POINT_OUTSIDE_CLIP(gc, msg->x + x, msg->y - y))
1984 DRAWPIXEL(cl, obj, gc, msg->x + x, msg->y - y);
1987 if (!POINT_OUTSIDE_CLIP(gc, msg->x - x, msg->y + y))
1989 DRAWPIXEL(cl, obj, gc, msg->x - x, msg->y + y);
1992 if (!POINT_OUTSIDE_CLIP(gc, msg->x - x, msg->y - y))
1994 DRAWPIXEL(cl, obj, gc, msg->x - x, msg->y - y);
1998 else
2000 DRAWPIXEL(cl, obj, gc, msg->x + x, msg->y + y);
2001 DRAWPIXEL(cl, obj, gc, msg->x + x, msg->y - y);
2002 DRAWPIXEL(cl, obj, gc, msg->x - x, msg->y + y);
2003 DRAWPIXEL(cl, obj, gc, msg->x - x, msg->y - y);
2006 y++; /* always move up here */
2007 t9 = t9 + t3;
2008 if (d1 < 0) /* move straight up */
2010 d1 = d1 + t9 + t2;
2011 d2 = d2 + t9;
2013 else /* move up and left */
2015 x--;
2016 t8 = t8 - t6;
2017 d1 = d1 + t9 + t2 - t8;
2018 d2 = d2 + t9 + t5 - t8;
2022 do /* rest of top right quadrant */
2024 /* draw 4 points using symmetry */
2025 #if 1
2026 if (doclip)
2029 if (!POINT_OUTSIDE_CLIP(gc, msg->x + x, msg->y + y))
2031 DRAWPIXEL(cl, obj, gc, msg->x + x, msg->y + y);
2034 if (!POINT_OUTSIDE_CLIP(gc, msg->x + x, msg->y - y))
2036 DRAWPIXEL(cl, obj, gc, msg->x + x, msg->y - y);
2039 if (!POINT_OUTSIDE_CLIP(gc, msg->x - x, msg->y + y))
2041 DRAWPIXEL(cl, obj, gc, msg->x - x, msg->y + y);
2044 if (!POINT_OUTSIDE_CLIP(gc, msg->x - x, msg->y - y))
2046 DRAWPIXEL(cl, obj, gc, msg->x - x, msg->y - y);
2050 else
2052 DRAWPIXEL(cl, obj, gc, msg->x + x, msg->y + y);
2053 DRAWPIXEL(cl, obj, gc, msg->x + x, msg->y - y);
2054 DRAWPIXEL(cl, obj, gc, msg->x - x, msg->y + y);
2055 DRAWPIXEL(cl, obj, gc, msg->x - x, msg->y - y);
2057 #else
2058 DRAWPIXEL(cl, obj, gc, msg->x + x, msg->y + y);
2059 DRAWPIXEL(cl, obj, gc, msg->x + x, msg->y - y);
2060 DRAWPIXEL(cl, obj, gc, msg->x - x, msg->y + y);
2061 DRAWPIXEL(cl, obj, gc, msg->x - x, msg->y - y);
2062 #endif
2063 x--; /* always move left here */
2064 t8 = t8 - t6;
2065 if (d2 < 0) /* move up and left */
2067 y++;
2068 t9 = t9 + t3;
2069 d2 = d2 + t9 + t5 - t8;
2071 else /* move straight left */
2073 d2 = d2 + t5 - t8;
2076 } while (x >= 0);
2079 ReturnVoid("BitMap::DrawEllipse");
2082 /*****************************************************************************************
2084 NAME
2085 moHidd_BitMap_FillEllipse
2087 SYNOPSIS
2088 VOID OOP_DoMethod(OOP_Object *obj, struct pHidd_BitMap_DrawEllipse *msg);
2090 VOID HIDD_BM_FillEllipse (OOP_Object *obj, OOP_Object *gc, WORD x, WORD y,
2091 WORD ry, WORD rx);
2093 LOCATION
2094 hidd.gfx.bitmap
2096 FUNCTION
2097 Draws a solid ellipse from the center point (x,y) with the radii
2098 rx and ry in the specified bitmap.
2099 The function does not clip the ellipse against the drawing area.
2101 INPUTS
2102 obj - A bitmap to draw on
2103 gc - A GC object to use for drawing
2104 x,y - Coordinates of center point in pixels
2105 rx,ry - ry and ry radius in pixels
2107 RESULT
2108 None.
2110 NOTES
2111 This method is not used by the system and considered reserved.
2113 EXAMPLE
2115 Because of overflow the current code do not work with big
2116 values of rx and ry.
2118 SEE ALSO
2120 INTERNALS
2122 TODO
2123 Bugfix
2125 *****************************************************************************************/
2127 VOID BM__Hidd_BitMap__FillEllipse(OOP_Class *cl, OOP_Object *obj,
2128 struct pHidd_BitMap_DrawEllipse *msg)
2130 #ifdef __RESERVED__
2131 OOP_Object *gc = msg->gc;
2132 WORD x = msg->rx, y = 0; /* ellipse points */
2134 /* intermediate terms to speed up loop */
2135 LONG t1 = msg->rx * msg->rx, t2 = t1 << 1, t3 = t2 << 1;
2136 LONG t4 = msg->ry * msg->ry, t5 = t4 << 1, t6 = t5 << 1;
2137 LONG t7 = msg->rx * t5, t8 = t7 << 1, t9 = 0L;
2138 LONG d1 = t2 - t7 + (t4 >> 1); /* error terms */
2139 LONG d2 = (t1 >> 1) - t8 + t5;
2141 EnterFunc(bug("BitMap::FillEllipse()"));
2143 while (d2 < 0) /* till slope = -1 */
2145 /* draw 4 points using symmetry */
2146 DRAWLINE(cl, obj, gc, msg->x - x, msg->y + y, msg->x + x, msg->y + y);
2147 DRAWLINE(cl, obj, gc, msg->x - x, msg->y - y, msg->x + x, msg->y - y);
2149 y++; /* always move up here */
2150 t9 = t9 + t3;
2151 if (d1 < 0) /* move straight up */
2153 d1 = d1 + t9 + t2;
2154 d2 = d2 + t9;
2156 else /* move up and left */
2158 x--;
2159 t8 = t8 - t6;
2160 d1 = d1 + t9 + t2 - t8;
2161 d2 = d2 + t9 + t5 - t8;
2165 do /* rest of top right quadrant */
2167 /* draw 4 points using symmetry */
2168 DRAWLINE(cl, obj, gc, msg->x - x, msg->y + y, msg->x + x, msg->y + y);
2169 DRAWLINE(cl, obj, gc, msg->x - x, msg->y - y, msg->x + x, msg->y - y);
2171 x--; /* always move left here */
2172 t8 = t8 - t6;
2173 if (d2 < 0) /* move up and left */
2175 y++;
2176 t9 = t9 + t3;
2177 d2 = d2 + t9 + t5 - t8;
2179 else /* move straight left */
2181 d2 = d2 + t5 - t8;
2184 } while (x >= 0);
2185 #endif
2187 ReturnVoid("BitMap::FillEllipse");
2190 /*****************************************************************************************
2192 NAME
2193 moHidd_BitMap_DrawPolygon
2195 SYNOPSIS
2196 VOID OOP_DoMethod(OOP_Object *obj, struct pHidd_BitMap_DrawPolygon *msg);
2198 VOID HIDD_BM_DrawPolygon (OOP_Object *obj, OOP_Object *gc, UWORD n, WORD *coords);
2200 LOCATION
2201 hidd.gfx.bitmap
2203 FUNCTION
2204 Draws a hollow polygon from the list of coordinates in coords[].
2205 The function does not clip the polygon against the drawing area.
2207 INPUTS
2208 obj - A bitmap to draw on
2209 gc - A GC object to use for drawing
2210 n - number of coordinate pairs
2211 coords - array of n (x, y) coordinates in pixels
2213 RESULT
2214 None.
2216 NOTES
2217 This method is not used by the system and considered reserved.
2219 EXAMPLE
2221 BUGS
2223 SEE ALSO
2225 INTERNALS
2227 TODO
2229 *****************************************************************************************/
2231 VOID BM__Hidd_BitMap__DrawPolygon(OOP_Class *cl, OOP_Object *obj,
2232 struct pHidd_BitMap_DrawPolygon *msg)
2234 #ifdef __RESERVED__
2235 OOP_Object *gc = msg->gc;
2236 WORD i;
2238 EnterFunc(bug("BitMap::DrawPolygon()"));
2240 for(i = 2; i < (2 * msg->n); i = i + 2)
2242 DRAWLINE(cl, obj, gc, msg->coords[i - 2], msg->coords[i - 1],
2243 msg->coords[i], msg->coords[i + 1]);
2245 #endif
2247 ReturnVoid("BitMap::DrawPolygon");
2250 /*****************************************************************************************
2252 NAME
2253 moHidd_BitMap_FillPolygon
2255 SYNOPSIS
2256 VOID OOP_DoMethod(OOP_Object *obj, struct pHidd_BitMap_DrawPolygon *msg);
2258 VOID HIDD_BM_FillPolygon (OOP_Object *obj, OOP_Object *gc, UWORD n, WORD *coords);
2260 LOCATION
2261 hidd.gfx.bitmap
2263 FUNCTION
2264 This method was initially designed for drawing solid polygons, however it was never
2265 used and implemented. At the moment it is considered reserved, its synopsis and
2266 semantics may change in future.
2268 INPUTS
2269 obj - A bitmap to draw on
2270 gc - A GC object to use for drawing
2271 n - number of coordinate pairs
2272 coords - array of n (x, y) coordinates in pixels
2274 RESULT
2275 None
2277 NOTES
2279 EXAMPLE
2281 BUGS
2282 Never used and implemented
2284 SEE ALSO
2286 INTERNALS
2288 TODO
2290 *****************************************************************************************/
2292 VOID BM__Hidd_BitMap__FillPolygon(OOP_Class *cl, OOP_Object *obj, struct pHidd_BitMap_DrawPolygon *msg)
2294 D(bug("Sorry, FillPolygon() not implemented yet in bitmap baseclass\n"));
2297 /*****************************************************************************************
2299 NAME
2300 moHidd_BitMap_DrawText
2302 SYNOPSIS
2303 OOP_DoMethod(OOP_Object *obj, struct pHidd_BitMap_DrawText *msg);
2305 VOID HIDD_BM_DrawText (OOP_Object *obj, OOP_Object *gc, WORD x, WORD y,
2306 STRPTR text, UWORD length);
2308 LOCATION
2309 hidd.gfx.bitmap
2311 FUNCTION
2312 Draws the first length characters of text at (x, y).
2313 The function does not clip the text against the drawing area.
2315 INPUTS
2316 obj - A bitmap to draw on
2317 gc - A GC object to use for drawing and font specification
2318 x, y - Position to start drawing in pixels. The x
2319 coordinate is relativ to the left side of the
2320 first character.
2321 The y coordinate is relative to the baseline of the font.
2322 text - Pointer to a Latin 1 string
2323 length - Number of characters to draw
2325 RESULT
2326 None.
2328 NOTES
2329 At the moment text drawing is processed entirely by graphics.library
2330 using BltTemplate(), which in turn uses moHodd_BitMap_PutTemplate.
2331 This method is considered obsolete.
2333 EXAMPLE
2335 BUGS
2336 The default implementation in the base class does not process styles,
2337 color and alpha-blended fonts.
2339 SEE ALSO
2341 INTERNALS
2343 TODO
2345 *****************************************************************************************/
2347 VOID BM__Hidd_BitMap__DrawText(OOP_Class *cl, OOP_Object *obj,
2348 struct pHidd_BitMap_DrawText *msg)
2350 #ifdef __RESERVED__
2351 OOP_Object *gc = msg->gc;
2352 struct TextFont *font = GC_FONT(gc);
2353 UBYTE *charPatternPtr = font->tf_CharData;
2354 UWORD modulo = font->tf_Modulo;
2355 ULONG charLog;
2356 UBYTE ch; /* current character to print */
2357 WORD fx, fx2, fy, fw; /* position and length of character in the */
2358 /* character bitmap */
2359 WORD xMem = msg->x; /* position in bitmap */
2360 WORD yMem = msg->y - font->tf_Baseline;
2361 WORD x, y, i;
2364 EnterFunc(bug("BitMap::DrawText()"));
2366 for(i = 0; i < msg->length; i++)
2368 ch = msg->text[i];
2370 if((ch < font->tf_LoChar) || (ch > font->tf_HiChar))
2372 ch = font->tf_HiChar - font->tf_LoChar + 1;
2374 else
2376 ch = ch - font->tf_LoChar;
2379 if(font->tf_Flags & FPF_PROPORTIONAL)
2381 xMem = xMem + ((UWORD *) font->tf_CharKern)[ch];
2384 charLog = ((ULONG *) font->tf_CharLoc)[ch];
2385 fx2 = charLog >> 16; /* x position of character pattern in character bitmap */
2386 fw = (UWORD) charLog; /* width of character pattern in character bitmap */
2388 y = yMem;
2390 for(fy = 0; fy < font->tf_YSize; fy ++)
2392 x = xMem;
2394 for(fx = fx2; fx < fw + fx2; fx++)
2396 if(*(charPatternPtr + fx / 8 + fy * modulo) & (128 >> (fx % 8)))
2398 DRAWPIXEL(cl, obj, msg->gc, x, y);
2400 x++;
2403 y++;
2406 if(font->tf_Flags & FPF_PROPORTIONAL)
2408 xMem = xMem + ((UWORD *) font->tf_CharSpace)[ch];
2410 else
2412 xMem = xMem + font->tf_XSize;
2415 #endif
2416 ReturnVoid("BitMap::DrawText");
2419 /*****************************************************************************************
2421 NAME
2422 moHidd_BitMap_FillText
2424 SYNOPSIS
2425 VOID OOP_DoMethod(OOP_Object *obj, struct pHidd_BitMap_DrawText *msg);
2427 VOID HIDD_BM_FillText (OOP_Object *obj, OOP_Object *gc, WORD x, WORD y,
2428 STRPTR text, UWORD length);
2430 LOCATION
2431 hidd.gfx.bitmap
2433 FUNCTION
2434 Historically this method was designed to draw a text with background.
2435 It was never implemented.
2437 Currently this method is considered reserved. Its synopsis and semantics
2438 may change in future.
2440 INPUTS
2441 obj - A bitmap to draw on
2442 gc - A GC object to use for drawing
2443 x, y - Position to start drawing in pixels. The x
2444 coordinate is relative to the left side of the
2445 first character.
2446 The y coordinate is relative to the baseline of the font.
2447 text - Pointer to a Latin 1 string
2448 length - Number of characters to draw
2450 RESULT
2452 NOTES
2454 EXAMPLE
2456 BUGS
2458 SEE ALSO
2460 INTERNALS
2462 TODO
2464 *****************************************************************************************/
2466 VOID BM__Hidd_BitMap__FillText(OOP_Class *cl, OOP_Object *obj, struct pHidd_BitMap_DrawText *msg)
2468 D(bug("Sorry, FillText() not implemented yet in bitmap baseclass\n"));
2471 /*****************************************************************************************
2473 NAME
2474 moHidd_BitMap_FillSpan
2476 SYNOPSIS
2477 VOID OOP_DoMethod(OOP_Object *obj, struct pHidd_BitMap_DrawText *msg);
2479 LOCATION
2480 hidd.gfx.bitmap
2482 FUNCTION
2483 Reserved, never implemented method. The definition will change in future.
2485 INPUTS
2487 RESULT
2488 None.
2490 NOTES
2492 EXAMPLE
2494 BUGS
2496 SEE ALSO
2498 INTERNALS
2500 TODO
2502 *****************************************************************************************/
2504 VOID BM__Hidd_BitMap__FillSpan(OOP_Class *cl, OOP_Object *obj, struct pHidd_BitMap_DrawText *msg)
2506 D(bug("Sorry, FillSpan() not implemented yet\n"));
2509 /*****************************************************************************************
2511 NAME
2512 moHidd_BitMap_Clear
2514 SYNOPSIS
2515 OOP_DoMethod(OOP_Object *obj, struct pHidd_BitMap_Clear *msg);
2517 VOID HIDD_BM_Clear (OOP_Object *obj, OOP_Object *gc);
2519 LOCATION
2520 hidd.gfx.bitmap
2522 FUNCTION
2523 Sets all pixels of the drawing area to the background color.
2525 INPUTS
2526 obj - A bitmap to clear.
2527 gc - A GC object, specifies background color value
2529 RESULT
2531 NOTES
2532 This method is not used by the system and considered reserved. However it can
2533 be useful for display driver's own needs.
2535 EXAMPLE
2537 BUGS
2538 Default implementation in the base class sets all pixels to zero color instead of
2539 the background color from GC
2541 SEE ALSO
2543 INTERNALS
2545 TODO
2547 *****************************************************************************************/
2549 VOID BM__Hidd_BitMap__Clear(OOP_Class *cl, OOP_Object *obj, struct pHidd_BitMap_Clear *msg)
2551 struct Library *OOPBase = CSD(cl)->cs_OOPBase;
2552 WORD x, y;
2553 IPTR width, height;
2555 EnterFunc(bug("BitMap::Clear()\n"));
2557 OOP_GetAttr(obj, aHidd_BitMap_Width, &width);
2558 OOP_GetAttr(obj, aHidd_BitMap_Height, &height);
2560 for(y = 0; y < height; y++)
2562 for(x = 0; x < width; x++)
2564 PUTPIXEL(cl, obj, x, y, 0);
2568 ReturnVoid("BitMap::Clear");
2571 /****************************************************************************************/
2573 static LONG inline getpixfmtbpp(OOP_Class *cl, OOP_Object *o, HIDDT_StdPixFmt stdpf)
2575 struct Library *OOPBase = CSD(cl)->cs_OOPBase;
2576 OOP_Object *pf;
2577 struct HIDDBitMapData *data;
2578 SIPTR bpp = -1;
2580 data = OOP_INST_DATA(cl, o);
2582 switch (stdpf)
2584 case vHidd_StdPixFmt_Native:
2585 OOP_GetAttr(data->prot.pixfmt, aHidd_PixFmt_BytesPerPixel, &bpp);
2586 break;
2588 case vHidd_StdPixFmt_Native32:
2589 bpp = sizeof (HIDDT_Pixel);
2590 break;
2592 default:
2593 pf = HIDD_Gfx_GetPixFmt(data->gfxhidd, stdpf);
2595 if (NULL == pf)
2597 D(bug("!!! INVALID PIXFMT IN BitMap::PutImage(): %d !!!\n", stdpf));
2599 else
2601 OOP_GetAttr(pf, aHidd_PixFmt_BytesPerPixel, &bpp);
2603 break;
2606 return bpp;
2609 /*****************************************************************************************
2611 NAME
2612 moHidd_BitMap_GetImage
2614 SYNOPSIS
2615 VOID OOP_DoMethod(OOP_Object *obj, struct pHidd_BitMap_GetImage *msg);
2617 VOID HIDD_BM_GetImage (OOP_Object *obj, UBYTE *pixels, ULONG modulo, WORD x, WORD y,
2618 WORD width, WORD height, HIDDT_StdPixFmt pixFmt);
2620 LOCATION
2621 hidd.gfx.bitmap
2623 FUNCTION
2625 INPUTS
2626 obj -
2627 pixels -
2628 modulo -
2629 x, y -
2630 width -
2631 height -
2632 pixFmt -
2634 RESULT
2636 NOTES
2638 EXAMPLE
2640 BUGS
2642 SEE ALSO
2644 INTERNALS
2646 *****************************************************************************************/
2648 VOID BM__Hidd_BitMap__GetImage(OOP_Class *cl, OOP_Object *o,
2649 struct pHidd_BitMap_GetImage *msg)
2651 WORD x, y;
2652 UBYTE *pixarray = (UBYTE *)msg->pixels;
2653 APTR ppixarray = &pixarray;
2654 WORD bpp;
2655 struct HIDDBitMapData *data;
2657 data = OOP_INST_DATA(cl, o);
2659 EnterFunc(bug("BitMap::GetImage(x=%d, y=%d, width=%d, height=%d)\n"
2660 , msg->x, msg->y, msg->width, msg->height));
2663 bpp = getpixfmtbpp(cl, o, msg->pixFmt);
2664 if (-1 == bpp)
2666 D(bug("!!! INVALID PIXFMT IN BitMap::GetImage(): %d !!!\n", msg->pixFmt));
2667 return;
2671 switch(msg->pixFmt)
2673 case vHidd_StdPixFmt_Native:
2674 case vHidd_StdPixFmt_Native32:
2675 for (y = 0; y < msg->height; y ++)
2677 for (x = 0; x < msg->width; x ++)
2679 register HIDDT_Pixel pix;
2681 pix = GETPIXEL(cl, o, x + msg->x , y + msg->y);
2683 switch (bpp)
2685 case 1:
2686 *pixarray++ = pix;
2687 break;
2689 case 2:
2690 *((UWORD *)pixarray) = pix;
2691 pixarray += 2;
2692 break;
2694 case 3:
2695 #if AROS_BIG_ENDIAN
2696 pixarray[0] = (pix >> 16) & 0xFF;
2697 pixarray[1] = (pix >> 8) & 0xFF;
2698 pixarray[2] = pix & 0xFF;
2699 #else
2700 pixarray[0] = pix & 0xFF;
2701 pixarray[1] = (pix >> 8) & 0xFF;
2702 pixarray[2] = (pix >> 16) & 0xFF;
2703 #endif
2704 pixarray += 3;
2705 break;
2707 case 4:
2708 *(ULONG *)pixarray = pix;
2709 pixarray += 4;
2710 break;
2715 pixarray += (msg->modulo - msg->width * bpp);
2718 break;
2720 default:
2722 OOP_Object *dstpf;
2723 APTR buf, srcPixels;
2725 dstpf = HIDD_Gfx_GetPixFmt(data->gfxhidd, msg->pixFmt);
2727 buf = srcPixels = AllocVec(msg->width * sizeof(HIDDT_Pixel), MEMF_PUBLIC);
2728 if (buf)
2730 for(y = 0; y < msg->height; y++)
2732 GETIMAGE(cl, o,
2733 buf,
2735 msg->x,
2736 msg->y + y,
2737 msg->width,
2739 vHidd_StdPixFmt_Native);
2741 CONVERTPIXELS(cl, o,
2742 &srcPixels,
2743 (HIDDT_PixelFormat *)data->prot.pixfmt,
2745 (APTR *)ppixarray,
2746 (HIDDT_PixelFormat *)dstpf,
2747 msg->modulo,
2748 msg->width,
2750 NULL);
2753 FreeVec(buf);
2756 break;
2758 } /* switch(msg->pixFmt) */
2760 ReturnVoid("BitMap::GetImage");
2763 /*****************************************************************************************
2765 NAME
2766 moHidd_BitMap_PutImage
2768 SYNOPSIS
2769 VOID OOP_DoMethod(OOP_Object *obj, struct pHidd_BitMap_PutImage *msg);
2771 VOID HIDD_BM_PutImage (OOP_Object *obj, OOP_Object *gc, UBYTE *pixels, ULONG modulo,
2772 WORD x, WORD y, WORD width, WORD height, HIDDT_StdPixFmt pixFmt);
2774 LOCATION
2775 hidd.gfx.bitmap
2777 FUNCTION
2779 INPUTS
2780 obj -
2781 gc -
2782 pixels -
2783 modulo -
2784 x, y -
2785 width -
2786 height -
2787 pixFmt -
2789 RESULT
2791 NOTES
2793 EXAMPLE
2795 BUGS
2797 SEE ALSO
2799 INTERNALS
2801 *****************************************************************************************/
2803 VOID BM__Hidd_BitMap__PutImage(OOP_Class *cl, OOP_Object *o,
2804 struct pHidd_BitMap_PutImage *msg)
2806 WORD x, y;
2807 UBYTE *pixarray = (UBYTE *)msg->pixels;
2808 APTR ppixarray = &pixarray;
2809 ULONG old_fg;
2810 WORD bpp;
2811 struct HIDDBitMapData *data;
2812 OOP_Object *gc = msg->gc;
2814 data = OOP_INST_DATA(cl, o);
2816 EnterFunc(bug("BitMap::PutImage(x=%d, y=%d, width=%d, height=%d)\n"
2817 , msg->x, msg->y, msg->width, msg->height));
2819 if (msg->width <= 0 || msg->height <= 0)
2820 return;
2822 bpp = getpixfmtbpp(cl, o, msg->pixFmt);
2823 if (-1 == bpp)
2825 D(bug("!!! INVALID PIXFMT IN BitMap::PutImage(): %d !!!\n", msg->pixFmt));
2826 return;
2829 switch(msg->pixFmt)
2831 case vHidd_StdPixFmt_Native:
2832 case vHidd_StdPixFmt_Native32:
2834 /* Preserve old fg pen */
2835 old_fg = GC_FG(gc);
2837 for (y = 0; y < msg->height; y ++)
2839 for (x = 0; x < msg->width; x ++)
2841 register HIDDT_Pixel pix = 0;
2843 switch (bpp)
2845 case 1:
2846 pix = *((UBYTE *)pixarray);
2847 pixarray ++;
2848 break;
2850 case 2:
2851 pix = *((UWORD *)pixarray);
2852 pixarray += 2;
2853 break;
2855 case 3:
2856 #if AROS_BIG_ENDIAN
2857 pix = ((UBYTE *)pixarray)[0] << 16;
2858 pix |= ((UBYTE *)pixarray)[1] << 8;
2859 pix |= ((UBYTE *)pixarray)[2];
2860 #else
2861 pix = ((UBYTE *)pixarray)[2] << 16;
2862 pix |= ((UBYTE *)pixarray)[1] << 8;
2863 pix |= ((UBYTE *)pixarray)[0];
2864 #endif
2865 pixarray += 3;
2866 break;
2868 case 4:
2869 pix = *((ULONG *)pixarray); pixarray += 4;
2870 break;
2874 GC_FG(gc) = pix;
2876 DRAWPIXEL(cl, o, gc, x + msg->x , y + msg->y);
2878 pixarray += (msg->modulo - msg->width * bpp);
2881 GC_FG(gc) = old_fg;
2882 break;
2884 default:
2886 OOP_Object *srcpf;
2887 APTR buf, destPixels;
2889 srcpf = HIDD_Gfx_GetPixFmt(data->gfxhidd, msg->pixFmt);
2891 buf = destPixels = AllocVec(msg->width * sizeof(HIDDT_Pixel), MEMF_PUBLIC);
2892 if (buf)
2894 for(y = 0; y < msg->height; y++)
2896 CONVERTPIXELS(cl, o,
2897 (APTR *)ppixarray,
2898 (HIDDT_PixelFormat *)srcpf,
2899 msg->modulo,
2900 &destPixels,
2901 (HIDDT_PixelFormat *)data->prot.pixfmt,
2903 msg->width,
2905 NULL);
2907 PUTIMAGE(cl, o,
2908 msg->gc,
2909 buf,
2911 msg->x,
2912 msg->y + y,
2913 msg->width,
2915 vHidd_StdPixFmt_Native);
2917 FreeVec(buf);
2920 break;
2922 } /* switch(msg->pixFmt) */
2924 ReturnVoid("BitMap::PutImage");
2927 /****************************************************************************************/
2929 #if defined(EXACT_ALPHA)
2930 int static inline
2931 __attribute__((always_inline, const)) do_alpha(int a, int f, int b)
2933 int tmp = ((f)*(a) + (b)*(255 - (a)) + 128);
2934 return ((tmp + (tmp >> 8)) >> 8);
2936 #else
2937 int static inline
2938 __attribute__((always_inline, const)) do_alpha(int a, int f, int b)
2940 int tmp = (a*(f-b));
2941 return ((tmp<<8) + tmp + 32768)>>16;
2943 #endif
2945 #if AROS_BIG_ENDIAN
2947 #define RGB32_DECOMPOSE(red, green, blue, pix) \
2948 red = ((pix) & 0x00FF0000) >> 16; \
2949 green = ((pix) & 0x0000FF00) >> 8; \
2950 blue = ((pix) & 0x000000FF);
2952 #define ARGB32_ALPHA(pix) ((pix) & 0xFF000000)
2954 #define ARGB32_DECOMPOSE(alpha, red, green, blue, pix) \
2955 alpha = ((pix) & 0xFF000000) >> 24; \
2956 red = ((pix) & 0x00FF0000) >> 16; \
2957 green = ((pix) & 0x0000FF00) >> 8; \
2958 blue = ((pix) & 0x000000FF);
2960 #define ARGB32_COMPOSE(red, green, blue, old) (((old) & 0xFF000000) + ((red) << 16) + ((green) << 8) + (blue))
2962 #else
2964 #define RGB32_DECOMPOSE(red, green, blue, pix) \
2965 red = (pix & 0x0000FF00) >> 8; \
2966 green = (pix & 0x00FF0000) >> 16; \
2967 blue = (pix & 0xFF000000) >> 24
2969 #define ARGB32_ALPHA(pix) ((pix) & 0x000000FF)
2971 #define ARGB32_DECOMPOSE(alpha, red, green, blue, pix) \
2972 alpha = (pix & 0x000000FF); \
2973 red = (pix & 0x0000FF00) >> 8; \
2974 green = (pix & 0x00FF0000) >> 16; \
2975 blue = (pix & 0xFF000000) >> 24
2977 #define ARGB32_COMPOSE(red, green, blue, old) (((blue) << 24) + ((green) << 16) + ((red) << 8) + ((old) & 0x000000FF))
2979 #endif
2981 /*****************************************************************************************
2983 NAME
2984 moHidd_BitMap_PutAlphaImage
2986 SYNOPSIS
2987 VOID OOP_DoMethod(OOP_Object *obj, struct pHidd_BitMap_PutAlphaImage *msg);
2989 VOID HIDD_BM_PutAlphaImage (OOP_Object *obj, OOP_Object *gc, UBYTE *pixels, ULONG modulo,
2990 WORD x, WORD y, WORD width, WORD height);
2992 LOCATION
2993 hidd.gfx.bitmap
2995 FUNCTION
2996 Perform an alpha-blending operation between a bitmap and ARGB pixel array.
2998 INPUTS
2999 obj - A bitmap to operate on
3000 gc - A GC object, internally needed to perform the operation. All its attributes
3001 are ignored.
3002 pixels - A pointer to an array of pixels
3003 modulo - Number of bytes per row in pixel array
3004 x, y - Top-left corner of affected bitmap's region
3005 width - Width of the modified rectangle.
3006 height - Height of the modified rectangle.
3008 RESULT
3009 None.
3011 NOTES
3012 Do not rely on 'gc' parameter being valid when implementing this method in own
3013 display driver. This parameter is actually obsolete, and will be set to NULL in
3014 future AROS versions. Current base class implementation ignores it.
3016 EXAMPLE
3018 BUGS
3020 SEE ALSO
3022 INTERNALS
3024 *****************************************************************************************/
3026 struct paib_data
3028 void *pixels;
3029 ULONG modulo;
3033 * TODOs:
3034 * 1. Merge buffered and slow versions of PutAlphaImage(), use the same processing algorithm
3035 * (convert array's pixels to bitmap's format, not vice versa)
3036 * 2. Make DoBufferedOperation() public, to be used for cybergraphics.library/ProcessPixelArray()
3037 * implementation, and for some other functions in graphics.library and cybergraphics.library,
3038 * currently using own implementation of pixel buffer.
3039 * 3. Reuse the new code for other buffered operations (currently using old macros).
3042 static void PutAlphaImageBuffered(ULONG *xbuf, UWORD starty, UWORD width, UWORD height, struct paib_data *data)
3044 UWORD x, y;
3046 for (y = 0; y < height; y++)
3048 ULONG *pixarray = data->pixels;
3050 for (x = 0; x < width; x++)
3052 ULONG destpix;
3053 ULONG srcpix;
3054 ULONG src_red, src_green, src_blue, src_alpha;
3055 ULONG dst_red, dst_green, dst_blue;
3057 srcpix = *pixarray++;
3059 if (ARGB32_ALPHA(srcpix) == ARGB32_ALPHA(0xFFFFFFFF))
3061 xbuf[x] = srcpix;
3063 else if (ARGB32_ALPHA(srcpix) != 0)
3065 ARGB32_DECOMPOSE(src_alpha, src_red, src_green, src_blue, srcpix);
3067 destpix = xbuf[x];
3068 RGB32_DECOMPOSE(dst_red, dst_green, dst_blue, destpix);
3070 dst_red += do_alpha(src_alpha, src_red, dst_red);
3071 dst_green += do_alpha(src_alpha, src_green, dst_green);
3072 dst_blue += do_alpha(src_alpha, src_blue, dst_blue);
3074 xbuf[x] = ARGB32_COMPOSE(dst_red, dst_green, dst_blue, destpix);
3078 xbuf += width;
3079 data->pixels += data->modulo;
3083 VOID BM__Hidd_BitMap__PutAlphaImage(OOP_Class *cl, OOP_Object *o,
3084 struct pHidd_BitMap_PutAlphaImage *msg)
3086 WORD x, y;
3087 struct paib_data data = {msg->pixels, msg->modulo};
3089 EnterFunc(bug("BitMap::PutAlphaImage(x=%d, y=%d, width=%d, height=%d)\n"
3090 , msg->x, msg->y, msg->width, msg->height));
3092 if (msg->width <= 0 || msg->height <= 0)
3093 return;
3095 if (!DoBufferedOperation(cl, o, msg->x, msg->y, msg->width, msg->height, TRUE, vHidd_StdPixFmt_ARGB32,
3096 (VOID_FUNC)PutAlphaImageBuffered, &data))
3098 /* Buffered method failed, use slow pixel-by-pixel method */
3099 for (y = msg->y; y < msg->y + msg->height; y++)
3101 ULONG *pixarray = data.pixels;
3103 for (x = msg->x; x < msg->x + msg->width; x++)
3105 HIDDT_Pixel destpix;
3106 HIDDT_Color col;
3107 ULONG srcpix;
3108 LONG src_red, src_green, src_blue, src_alpha;
3109 LONG dst_red, dst_green, dst_blue;
3111 destpix = GETPIXEL(cl, o, x, y);
3112 UNMAPPIXEL(cl, o, destpix, &col);
3114 srcpix = *pixarray++;
3115 ARGB32_DECOMPOSE(src_alpha, src_red, src_green, src_blue, srcpix);
3117 dst_red = col.red >> 8;
3118 dst_green = col.green >> 8;
3119 dst_blue = col.blue >> 8;
3121 dst_red += do_alpha(src_alpha, src_red, dst_red);
3122 dst_green += do_alpha(src_alpha, src_green, dst_green);
3123 dst_blue += do_alpha(src_alpha, src_blue, dst_blue);
3125 col.red = dst_red << 8;
3126 col.green = dst_green << 8;
3127 col.blue = dst_blue << 8;
3129 PUTPIXEL(cl, o, x, y, MAPCOLOR(cl, o, &col));
3130 } /* for(x = msg->x; x < msg->x + msg->width; x++) */
3132 data.pixels += msg->modulo;
3134 } /* for(y = msg->y; y < msg->y + msg->height; y++) */
3136 ReturnVoid("BitMap::PutAlphaImage");
3139 /*****************************************************************************************
3141 NAME
3142 moHidd_BitMap_PutTemplate
3144 SYNOPSIS
3145 VOID OOP_DoMethod(OOP_Object *obj, struct pHidd_BitMap_PutTemplate *msg);
3147 VOID HIDD_BM_PutTemplate (OOP_Object *obj, OOP_Object *gc, UBYTE *masktemplate, ULONG modulo,
3148 WORD srcx, WORD x, WORD y, WORD width, WORD height, BOOL inverttemplate);
3150 LOCATION
3151 hidd.gfx.bitmap
3153 FUNCTION
3154 Apply a single-bit mask to the given portion of the bitmap. Pixels set to 1 in the mask will be filled
3155 by foreground color. Pixels set to 0 in the mask will be filled by background color or left unchanged,
3156 according to the following GC attributes:
3157 Foreground - a foreground color
3158 Background - a background color
3159 DrawMode - if set to Invert, foreground and background colors will be ignored. Instead,
3160 pixels which are set to 1 in the mask, will be inverted. Other pixels will be
3161 left unchanged.
3162 ColorExpansion - if set to Transparent, only pixels which are set to 1 in the mask, will be modified.
3163 Other pixels will not be changed (background color will be ignored).
3165 INPUTS
3166 obj - A bitmap to draw on
3167 gc - A GC object, holding operation parameters
3168 masktemplate - A pointer to a bit mask
3169 modulo - Number of bytes per line in the mask
3170 srcx - Horizontal offset of the mask
3171 x, y - Top-left corner of the bitmap's region to affect
3172 width - Width of the affected region
3173 height - Height of the affected region
3174 inverttemplate - If set to TRUE, bit mask will be interpreted in inverted form
3176 RESULT
3177 None
3179 NOTES
3181 EXAMPLE
3183 BUGS
3185 SEE ALSO
3187 INTERNALS
3189 *****************************************************************************************/
3191 struct ptb_data
3193 void *bitarray;
3194 ULONG bitmask;
3195 ULONG modulo;
3196 ULONG fg;
3197 ULONG bg;
3198 UWORD invert;
3201 static void JAM1TemplateBuffered(ULONG *xbuf, UWORD starty, UWORD width, UWORD height, struct ptb_data *data)
3203 UWORD x, y;
3205 for (y = 0; y < height; y++)
3207 ULONG mask = data->bitmask;
3208 UWORD *array = data->bitarray;
3209 UWORD bitword = AROS_BE2WORD(*array);
3211 for (x = 0; x < width; x++)
3213 if ((bitword & mask) == (data->invert & mask))
3214 xbuf[x] = data->fg;
3216 mask >>= 1;
3217 if (!mask)
3219 mask = 0x8000;
3220 array++;
3221 bitword = AROS_BE2WORD(*array);
3225 xbuf += width;
3226 data->bitarray += data->modulo;
3230 static void ComplementTemplateBuffered(ULONG *xbuf, UWORD starty, UWORD width, UWORD height, struct ptb_data *data)
3232 UWORD x, y;
3234 for (y = 0; y < height; y++)
3236 ULONG mask = data->bitmask;
3237 UWORD *array = data->bitarray;
3238 UWORD bitword = AROS_BE2WORD(*array);
3240 for (x = 0; x < width; x++)
3242 if ((bitword & mask) == (data->invert & mask))
3243 xbuf[x] = ~xbuf[x];
3245 mask >>= 1;
3246 if (!mask)
3248 mask = 0x8000;
3249 array++;
3250 bitword = AROS_BE2WORD(*array);
3254 xbuf += width;
3255 data->bitarray += data->modulo;
3259 static void JAM2TemplateBuffered(ULONG *xbuf, UWORD starty, UWORD width, UWORD height, struct ptb_data *data)
3261 UWORD x, y;
3263 for (y = 0; y < height; y++)
3265 ULONG mask = data->bitmask;
3266 UWORD *array = data->bitarray;
3267 UWORD bitword = AROS_BE2WORD(*array);
3269 for (x = 0; x < width; x++)
3271 if ((bitword & mask) == (data->invert & mask))
3272 xbuf[x] = data->fg;
3273 else
3274 xbuf[x] = data->bg;
3276 mask >>= 1;
3277 if (!mask)
3279 mask = 0x8000;
3280 array++;
3281 bitword = AROS_BE2WORD(*array);
3285 xbuf += width;
3286 data->bitarray += data->modulo;
3290 VOID BM__Hidd_BitMap__PutTemplate(OOP_Class *cl, OOP_Object *o, struct pHidd_BitMap_PutTemplate *msg)
3292 OOP_Object *gc = msg->gc;
3293 BOOL get = TRUE;
3294 void (*op)(ULONG *, UWORD, UWORD, UWORD, struct ptb_data *);
3295 struct ptb_data data;
3297 EnterFunc(bug("BitMap::PutTemplate(x=%d, y=%d, width=%d, height=%d)\n"
3298 , msg->x, msg->y, msg->width, msg->height));
3300 if (msg->width <= 0 || msg->height <= 0)
3301 return;
3303 if (GC_COLEXP(gc) == vHidd_GC_ColExp_Transparent)
3305 op = JAM1TemplateBuffered;
3307 else if (GC_DRMD(gc) == vHidd_GC_DrawMode_Invert)
3309 op = ComplementTemplateBuffered;
3311 else
3313 op = JAM2TemplateBuffered;
3314 get = FALSE;
3317 data.bitarray = msg->masktemplate + ((msg->srcx / 16) * 2);
3318 data.bitmask = 0x8000 >> (msg->srcx & 0xF);
3319 data.modulo = msg->modulo;
3320 data.fg = GC_FG(msg->gc);
3321 data.bg = GC_BG(msg->gc);
3322 data.invert = msg->inverttemplate ? 0 : 0xFFFF;
3324 DoBufferedOperation(cl, o, msg->x, msg->y, msg->width, msg->height, get, vHidd_StdPixFmt_Native32, (VOID_FUNC)op, &data);
3326 /* TODO: write fallback */
3328 ReturnVoid("BitMap::PutTemplate");
3331 /*****************************************************************************************
3333 NAME
3334 moHidd_BitMap_PutAlphaTemplate
3336 SYNOPSIS
3337 VOID OOP_DoMethod(OOP_Object *obj, struct pHidd_BitMap_PutAlphaTemplate *msg);
3339 VOID HIDD_BM_PutAlphaTemplate (OOP_Object *obj, OOP_Object *gc, UBYTE *alpha, ULONG modulo,
3340 WORD x, WORD y, WORD width, WORD height, BOOL invertalpha);
3342 LOCATION
3343 hidd.gfx.bitmap
3345 FUNCTION
3346 Perform a drawing with current foreground color, using 8-bit alpha channel mask. The following
3347 GC attributes are considered:
3348 Foreground - a foreground color
3349 Background - a background color
3350 DrawMode - if set to Invert, foreground and background colors will be ignored. Instead,
3351 pixels, for which alpha channel value is greater than 127, will be inverted.
3352 Other pixels will be left unchanged.
3353 ColorExpansion - if set to Opaque, alpha blending will happen between foreground and background
3354 colors, instead of between foreground color and old bitmap contents.
3356 INPUTS
3357 obj - A bitmap to draw on
3358 gc - A GC object specifying drawing parameters
3359 alpha - A pointer to an 8-bit per pixel alpha channel mask
3360 modulo - Number of bytes per line in the mask
3361 x, y - Top-left corner of the affected bitmap's region
3362 width - Width of the affected bitmap's region
3363 height - Height of the affected bitmap's region
3364 invertalpha - If set to TRUE, alpha mask values will be treated in inverted form
3366 RESULT
3367 None
3369 NOTES
3371 EXAMPLE
3373 BUGS
3375 SEE ALSO
3377 INTERNALS
3379 *****************************************************************************************/
3381 struct patb_data
3383 UBYTE *pixarray;
3384 ULONG modulo;
3385 LONG a_red, a_green, a_blue;
3386 LONG b_red, b_green, b_blue;
3387 UBYTE invert;
3390 static void JAM1AlphaTemplateBuffered(ULONG *xbuf, UWORD starty, UWORD width, UWORD height, struct patb_data *data)
3392 UWORD x, y;
3394 for (y = 0; y < height; y++)
3396 UBYTE *pixarray = data->pixarray;
3398 for (x = 0; x < width; x++)
3400 LONG dst_red, dst_green, dst_blue, alpha;
3402 alpha = (*pixarray++) ^ data->invert;
3403 RGB32_DECOMPOSE(dst_red, dst_green, dst_blue, xbuf[x]);
3405 dst_red += do_alpha(alpha, data->a_red, dst_red);
3406 dst_green += do_alpha(alpha, data->a_green, dst_green);
3407 dst_blue += do_alpha(alpha, data->a_blue, dst_blue);
3409 xbuf[x] = ARGB32_COMPOSE(dst_red, dst_green, dst_blue, 0);
3412 xbuf += width;
3413 data->pixarray += data->modulo;
3417 static void ComplementAlphaTemplateBuffered(ULONG *xbuf, UWORD starty, UWORD width, UWORD height, struct patb_data *data)
3419 UWORD x, y;
3421 for (y = 0; y < height; y++)
3423 UBYTE *pixarray = data->pixarray;
3425 for (x = 0; x < width; x++)
3427 UBYTE alpha = (*pixarray++) ^ data->invert;
3429 if (alpha >= 0x80)
3430 xbuf[x] = ~xbuf[x];
3433 xbuf += width;
3434 data->pixarray += data->modulo;
3438 static void JAM2AlphaTemplateBuffered(ULONG *xbuf, UWORD starty, UWORD width, UWORD height, struct patb_data *data)
3440 UWORD x, y;
3442 for (y = 0; y < height; y++)
3444 UBYTE *pixarray = data->pixarray;
3446 for (x = 0; x < width; x++)
3448 LONG dst_red, dst_green, dst_blue, alpha;
3450 alpha = (*pixarray++) ^ data->invert;
3452 dst_red = data->b_red + ((data->a_red - data->b_red) * alpha) / 256;
3453 dst_green = data->b_green + ((data->a_green - data->b_green) * alpha) / 256;
3454 dst_blue = data->b_blue + ((data->a_blue - data->b_blue) * alpha) / 256;
3456 xbuf[x] = ARGB32_COMPOSE(dst_red, dst_green, dst_blue, 0);
3459 xbuf += width;
3460 data->pixarray += data->modulo;
3464 VOID BM__Hidd_BitMap__PutAlphaTemplate(OOP_Class *cl, OOP_Object *o,
3465 struct pHidd_BitMap_PutAlphaTemplate *msg)
3467 OOP_Object *gc = msg->gc;
3468 BOOL get = TRUE;
3469 void (*op)(ULONG *, UWORD, UWORD, UWORD, struct patb_data *);
3470 struct patb_data data;
3471 HIDDT_Color color;
3473 EnterFunc(bug("BitMap::PutAlphaTemplate(x=%d, y=%d, width=%d, height=%d)\n"
3474 , msg->x, msg->y, msg->width, msg->height));
3476 if (msg->width <= 0 || msg->height <= 0)
3477 return;
3479 UNMAPPIXEL(cl, o, GC_FG(gc), &color);
3480 data.a_red = color.red >> 8;
3481 data.a_green = color.green >> 8;
3482 data.a_blue = color.blue >> 8;
3484 if (GC_COLEXP(gc) == vHidd_GC_ColExp_Transparent)
3486 op = JAM1AlphaTemplateBuffered;
3488 else if (GC_DRMD(gc) == vHidd_GC_DrawMode_Invert)
3490 op = ComplementAlphaTemplateBuffered;
3492 else
3494 op = JAM2AlphaTemplateBuffered;
3495 get = FALSE;
3497 UNMAPPIXEL(cl, o, GC_BG(gc), &color);
3498 data.b_red = color.red >> 8;
3499 data.b_green = color.green >> 8;
3500 data.b_blue = color.blue >> 8;
3503 data.pixarray = msg->alpha;
3504 data.modulo = msg->modulo;
3505 data.invert = msg->invertalpha ? 255 : 0;
3507 DoBufferedOperation(cl, o, msg->x, msg->y, msg->width, msg->height, get, vHidd_StdPixFmt_ARGB32, (VOID_FUNC)op, &data);
3509 /* TODO: write fallback */
3511 ReturnVoid("BitMap::PutAlphaTemplate");
3514 /*****************************************************************************************
3516 NAME
3517 moHidd_BitMap_PutPattern
3519 SYNOPSIS
3520 VOID OOP_DoMethod(OOP_Object *o, struct pHidd_BitMap_PutPattern *msg);
3522 VOID HIDD_BM_PutPattern(OOP_Object *obj, OOP_Object *gc, UBYTE *pattern,
3523 WORD patternsrcx, WORD patternsrcy, WORD patternheight, WORD patterndepth,
3524 HIDDT_PixelLUT *patternlut, BOOL invertpattern, UBYTE *mask,
3525 ULONG maskmodulo, WORD masksrcx, WORD x, WORD y,
3526 WORD width, WORD height);
3528 LOCATION
3529 hidd.gfx.bitmap
3531 FUNCTION
3533 INPUTS
3534 obj - A bitmap to draw on
3535 gc - A GC object to use for drawing
3536 pattern -
3537 patternsrcx -
3538 patternsrcy -
3539 patternheight -
3540 patterndepth -
3541 patternlut -
3542 invertpattern -
3543 mask -
3544 maskmodulo -
3545 masksrcx -
3546 x, y -
3547 width -
3548 height -
3550 RESULT
3551 None
3553 NOTES
3555 EXAMPLE
3557 BUGS
3559 SEE ALSO
3561 INTERNALS
3563 *****************************************************************************************/
3565 struct ppb_data
3567 UWORD *patarray;
3568 void *maskarray;
3569 ULONG *patternlut;
3570 UWORD patternsrcy;
3571 UWORD desty;
3572 UWORD patternheight;
3573 ULONG maskmodulo;
3574 ULONG fg;
3575 ULONG bg;
3576 UWORD patmask;
3577 UWORD maskmask;
3578 UWORD patterndepth;
3579 UWORD invert;
3582 static void JAM1PatternBuffered(ULONG *xbuf, UWORD starty, UWORD width, UWORD height, struct ppb_data *data)
3584 UWORD x, y;
3586 for (y = 0; y < height; y++)
3588 UWORD pmask = data->patmask;
3589 UWORD mmask = data->maskmask;
3590 UWORD *parray = data->patarray + ((y + starty + data->patternsrcy - data->desty) % data->patternheight);
3591 UWORD patword = AROS_BE2WORD(*parray);
3592 UWORD *marray = data->maskarray;
3593 UWORD maskword = marray ? AROS_BE2WORD(*marray) : 0xFFFF;
3595 for (x = 0; x < width; x++)
3597 if (maskword & mmask)
3599 if ((patword & pmask) == (data->invert & pmask))
3600 xbuf[x] = data->fg;
3603 if (marray)
3605 mmask >>= 1;
3606 if (!mmask)
3608 mmask = 0x8000;
3609 marray++;
3610 maskword = AROS_BE2WORD(*marray);
3614 pmask >>= 1;
3615 if (!pmask)
3616 pmask = 0x8000;
3618 } /* for (x) */
3620 xbuf += width;
3621 if (data->maskarray)
3622 data->maskarray += data->maskmodulo;
3624 } /* for (y) */
3627 static void ComplementPatternBuffered(ULONG *xbuf, UWORD starty, UWORD width, UWORD height, struct ppb_data *data)
3629 UWORD x, y;
3631 for (y = 0; y < height; y++)
3633 UWORD pmask = data->patmask;
3634 UWORD mmask = data->maskmask;
3635 UWORD *parray = data->patarray + ((y + starty + data->patternsrcy - data->desty) % data->patternheight);
3636 UWORD patword = AROS_BE2WORD(*parray);
3637 UWORD *marray = data->maskarray;
3638 UWORD maskword = marray ? AROS_BE2WORD(*marray) : 0xFFFF;
3640 for (x = 0; x < width; x++)
3642 if (maskword & mmask)
3644 if ((patword & pmask) == (data->invert & pmask))
3645 xbuf[x] = ~xbuf[x];
3648 if (marray)
3650 mmask >>= 1;
3651 if (!mmask)
3653 mmask = 0x8000;
3654 marray++;
3655 maskword = AROS_BE2WORD(*marray);
3659 pmask >>= 1;
3660 if (!pmask)
3661 pmask = 0x8000;
3663 } /* for (x) */
3665 xbuf += width;
3666 if (data->maskarray)
3667 data->maskarray += data->maskmodulo;
3669 } /* for (y) */
3672 static void JAM2PatternBuffered(ULONG *xbuf, UWORD starty, UWORD width, UWORD height, struct ppb_data *data)
3674 UWORD x, y;
3676 for (y = 0; y < height; y++)
3678 UWORD pmask = data->patmask;
3679 UWORD mmask = data->maskmask;
3680 UWORD *parray = data->patarray + ((y + starty + data->patternsrcy - data->desty) % data->patternheight);
3681 UWORD patword = AROS_BE2WORD(*parray);
3682 UWORD *marray = data->maskarray;
3683 UWORD maskword = marray ? AROS_BE2WORD(*marray) : 0xFFFF;
3685 for (x = 0; x < width; x++)
3687 if (maskword & mmask)
3689 if ((patword & pmask) == (data->invert & pmask))
3690 xbuf[x] = data->fg;
3691 else
3692 xbuf[x] = data->bg;
3695 if (marray)
3697 mmask >>= 1;
3698 if (!mmask)
3700 mmask = 0x8000;
3701 marray++;
3702 maskword = AROS_BE2WORD(*marray);
3706 pmask >>= 1;
3707 if (!pmask)
3708 pmask = 0x8000;
3710 } /* for (x) */
3712 xbuf += width;
3713 if (data->maskarray)
3714 data->maskarray += data->maskmodulo;
3716 } /* for (y) */
3719 static void ColorPatternBuffered(ULONG *xbuf, UWORD starty, UWORD width, UWORD height, struct ppb_data *data)
3721 UWORD x, y;
3723 for (y = 0; y < height; y++)
3725 UWORD pmask = data->patmask;
3726 UWORD mmask = data->maskmask;
3727 UWORD *parray = data->patarray + ((y + starty + data->patternsrcy - data->desty) % data->patternheight);
3728 UWORD patword = AROS_BE2WORD(*parray);
3729 UWORD *marray = data->maskarray;
3730 UWORD maskword = marray ? AROS_BE2WORD(*marray) : 0xFFFF;
3732 for (x = 0; x < width; x++)
3734 if (maskword & mmask)
3736 UWORD plane;
3737 ULONG pixel = (patword & pmask) ? 1 : 0; /* CHECKME: Shouldn't we handle INVERSVID here too ? */
3739 for (plane = 1; plane < data->patterndepth; plane++)
3741 UWORD *_parray = parray + plane * data->patternheight;
3742 UWORD _patword = AROS_BE2WORD(*_parray);
3744 if (_patword & pmask)
3745 pixel |= 1L << plane;
3748 if (data->patternlut)
3749 pixel = data->patternlut[pixel];
3751 xbuf[x] = pixel;
3754 if (marray)
3756 mmask >>= 1;
3757 if (!mmask)
3759 mmask = 0x8000;
3760 marray++;
3761 maskword = AROS_BE2WORD(*marray);
3765 pmask >>= 1;
3766 if (!pmask)
3767 pmask = 0x8000;
3769 } /* for (x) */
3771 xbuf += width;
3772 if (data->maskarray)
3773 data->maskarray += data->maskmodulo;
3775 } /* for (y) */
3778 VOID BM__Hidd_BitMap__PutPattern(OOP_Class *cl, OOP_Object *o,
3779 struct pHidd_BitMap_PutPattern *msg)
3781 void (*op)(ULONG *xbuf, UWORD starty, UWORD width, UWORD height, struct ppb_data *data);
3782 BOOL get = TRUE;
3783 struct ppb_data data;
3785 DPUTPATTERN(bug("BitMap::PutPattern(x=%d, y=%d, width=%d, height=%d)\n",
3786 msg->x, msg->y, msg->width, msg->height));
3788 if (msg->width <= 0 || msg->height <= 0)
3789 return;
3791 if (msg->patterndepth > 1)
3793 DPUTPATTERN(bug("[PutPattern] Color\n"));
3794 op = ColorPatternBuffered;
3795 get = FALSE;
3797 else if (GC_COLEXP(msg->gc) == vHidd_GC_ColExp_Transparent)
3799 DPUTPATTERN(bug("[PutPattern] JAM1\n"));
3800 op = JAM1PatternBuffered;
3802 else if (GC_DRMD(msg->gc) == vHidd_GC_DrawMode_Invert)
3804 DPUTPATTERN(bug("[PutPattern] Complement\n"));
3805 op = ComplementPatternBuffered;
3807 else
3809 DPUTPATTERN(bug("[PutPattern] JAM2\n"));
3810 op = JAM2PatternBuffered;
3811 get = FALSE;
3814 data.patarray = (UWORD *)msg->pattern;
3815 data.patmask = 0x8000 >> (msg->patternsrcx & 0xF);
3816 data.maskarray = msg->mask;
3817 data.patternlut = msg->patternlut ? msg->patternlut->pixels : NULL;
3818 data.patternsrcy = msg->patternsrcy;
3819 data.desty = msg->y;
3820 data.patternheight = msg->patternheight;
3821 data.patterndepth = msg->patterndepth;
3822 data.maskmodulo = msg->maskmodulo;
3823 data.fg = GC_FG(msg->gc);
3824 data.bg = GC_BG(msg->gc);
3825 data.invert = msg->invertpattern ? 0 : 0xFFFF;
3827 if (data.maskarray)
3829 data.maskarray += (msg->masksrcx / 16) * 2;
3830 data.maskmask = 0x8000 >> (msg->masksrcx & 0xF);
3831 get = TRUE;
3833 else
3834 data.maskmask = 0xFFFF;
3836 DPUTPATTERN(bug("[PutPattern] MaskArray 0x%p, MaskMask 0x%04X\n", data.maskarray, data.maskmask));
3838 DoBufferedOperation(cl, o, msg->x, msg->y, msg->width, msg->height, get, vHidd_StdPixFmt_Native32, (VOID_FUNC)op, &data);
3840 /* TODO: Write fallback */
3842 ReturnVoid("BitMap::PutPattern");
3845 /*****************************************************************************************
3847 NAME
3848 moHidd_BitMap_PutImageLUT
3850 SYNOPSIS
3851 VOID OOP_DoMethod(OOP_Object *o, struct pHidd_BitMap_PutImageLUT *msg);
3853 VOID HIDD_BM_PutImageLUT (OOP_Object *obj, OOP_Object *gc, UBYTE *pixels, ULONG modulo,
3854 WORD x, WORD y, WORD width, WORD height, HIDDT_PixelLUT *pixlut);
3856 LOCATION
3857 hidd.gfx.bitmap
3859 FUNCTION
3861 INPUTS
3862 obj -
3863 gc -
3864 pixels -
3865 modulo -
3866 x, y -
3867 width -
3868 height -
3869 pixlut -
3871 RESULT
3873 NOTES
3875 EXAMPLE
3877 BUGS
3879 SEE ALSO
3881 INTERNALS
3883 *****************************************************************************************/
3885 VOID BM__Hidd_BitMap__PutImageLUT(OOP_Class *cl, OOP_Object *o,
3886 struct pHidd_BitMap_PutImageLUT *msg)
3888 WORD x, y;
3889 UBYTE *pixarray = (UBYTE *)msg->pixels;
3890 HIDDT_PixelLUT *pixlut = msg->pixlut;
3891 HIDDT_Pixel *lut = pixlut ? pixlut->pixels : NULL;
3892 HIDDT_Pixel *linebuf;
3893 OOP_Object *gc = msg->gc;
3895 EnterFunc(bug("BitMap::PutImageLUT(x=%d, y=%d, width=%d, height=%d)\n"
3896 , msg->x, msg->y, msg->width, msg->height));
3898 if (msg->width <= 0 || msg->height <= 0)
3899 return;
3901 linebuf = AllocVec(msg->width * sizeof(HIDDT_Pixel), MEMF_PUBLIC);
3903 for(y = 0; y < msg->height; y++)
3905 if (linebuf)
3907 if (lut)
3909 for(x = 0; x < msg->width; x++)
3911 linebuf[x] = lut[pixarray[x]];
3914 else
3916 for(x = 0; x < msg->width; x++)
3918 linebuf[x] = pixarray[x];
3921 pixarray += msg->modulo;
3923 PUTIMAGE(cl, o,
3924 msg->gc,
3925 (UBYTE *)linebuf,
3927 msg->x,
3928 msg->y + y,
3929 msg->width,
3931 vHidd_StdPixFmt_Native32);
3933 } /* if (linebuf) */
3934 else
3936 ULONG old_fg;
3938 /* Preserve old fg pen */
3939 old_fg = GC_FG(gc);
3941 if (lut)
3943 for(x = 0; x < msg->width; x++)
3945 GC_FG(gc) = lut[pixarray[x]];
3946 DRAWPIXEL(cl, o, gc, msg->x + x, msg->y + y);
3949 else
3951 for(x = 0; x < msg->width; x++)
3953 GC_FG(gc) = pixarray[x];
3954 DRAWPIXEL(cl, o, gc, msg->x + x, msg->y + y);
3957 GC_FG(gc) = old_fg;
3959 pixarray += msg->modulo;
3961 } /* if (linebuf) else ... */
3963 } /* for(y = 0; y < msg->height; y++) */
3965 FreeVec(linebuf);
3967 ReturnVoid("BitMap::PutImageLUT");
3969 /*****************************************************************************************
3971 NAME
3972 moHidd_BitMap_PutTranspImageLUT
3974 SYNOPSIS
3975 VOID OOP_DoMethod(OOP_Object *obj, struct pHidd_BitMap_PutTranspImageLUT *msg);
3977 VOID HIDD_BM_PutTranspImageLUT (OOP_Object *obj, OOP_Object *gc, UBYTE *pixels,
3978 ULONG modulo, WORD x, WORD y, WORD width, WORD height,
3979 HIDDT_PixelLUT *pixlut, UBYTE transparent);
3981 LOCATION
3982 hidd.gfx.bitmap
3984 FUNCTION
3985 Copy an array of 8-bit LUT pixels to the bitmap at the specified position making
3986 one of colors transparent.
3988 Pixels are converted to bitmap's native format using either user-supplied LUT (if
3989 given) or bitmap's own colormap.
3991 Draw mode of the supplied GC is ignored, the operation is always bulk copy.
3993 INPUTS
3994 obj - A bitmap to draw image on
3995 gc - A GC used for drawing
3996 pixels - A pointer to source pixel array
3997 modulo - Total number of bytes per line in the source array
3998 x, y - Top-left corner of the destination rectangle
3999 width - Width of the image to draw
4000 height - Height of the image to draw
4001 pixlut - An optional pointer to a LUT to use. NULL means using bitmap's
4002 own colormap (if available)
4003 transparent - Value of pixels in the source array which will be made
4004 transparent
4006 RESULT
4007 None
4009 NOTES
4011 EXAMPLE
4013 BUGS
4015 SEE ALSO
4017 INTERNALS
4019 *****************************************************************************************/
4021 #undef csd /* Bad hack, but there's no other way */
4023 struct ptilb_data
4025 UBYTE *pixarray;
4026 ULONG *lut;
4027 OOP_Object *colmap;
4028 struct class_static_data *csd;
4029 ULONG modulo;
4030 UBYTE transparent;
4033 static void PutTranspImageLUTBuffered(ULONG *xbuf, UWORD starty, UWORD width, UWORD height, struct ptilb_data *data)
4035 struct class_static_data *csd = data->csd;
4036 UWORD x, y;
4038 for (y = 0; y < height; y++)
4040 UBYTE *pixarray = data->pixarray;
4042 if (data->lut)
4044 for (x = 0; x < width; x++)
4046 UBYTE pix = *pixarray++;
4048 if (pix != data->transparent)
4049 xbuf[x] = data->lut[pix];
4051 } /* for (x) */
4053 else
4055 for (x = 0; x < width; x++)
4057 UBYTE pix = *pixarray++;
4059 if (pix != data->transparent)
4061 if (data->colmap)
4062 pix = HIDD_CM_GetPixel(data->colmap, pix);
4064 xbuf[x] = pix;
4067 } /* for (x) */
4070 xbuf += width;
4071 data->pixarray += data->modulo;
4072 } /* for (y) */
4075 VOID BM__Hidd_BitMap__PutTranspImageLUT(OOP_Class *cl, OOP_Object *o,
4076 struct pHidd_BitMap_PutTranspImageLUT *msg)
4078 struct HIDDBitMapData *data = OOP_INST_DATA(cl, o);
4079 struct ptilb_data userdata =
4081 msg->pixels,
4082 NULL,
4083 data->colmap,
4084 CSD(cl),
4085 msg->modulo,
4086 msg->transparent
4089 EnterFunc(bug("BitMap::PutTranspImageLUT(x=%d, y=%d, width=%d, height=%d)\n"
4090 , msg->x, msg->y, msg->width, msg->height));
4092 if (msg->width <= 0 || msg->height <= 0)
4093 return;
4095 if (msg->pixlut)
4096 userdata.lut = msg->pixlut->pixels;
4098 DoBufferedOperation(cl, o, msg->x, msg->y, msg->width, msg->height, TRUE, vHidd_StdPixFmt_Native32,
4099 (VOID_FUNC)PutTranspImageLUTBuffered, &userdata);
4101 /* TODO: Write fallback */
4103 ReturnVoid("BitMap::PutTranspImageLUT");
4106 #define csd CSD(cl)
4108 /*****************************************************************************************
4110 NAME
4111 moHidd_BitMap_GetImageLUT
4113 SYNOPSIS
4114 VOID OOP_DoMethod(OOP_Object *obj, struct pHidd_BitMap_GetImageLUT *msg);
4116 VOID HIDD_BM_GetImageLUT (OOP_Object *obj, UBYTE *pixels, ULONG modulo, WORD x, WORD y,
4117 WORD width, WORD height, HIDDT_PixelLUT *pixlut);
4119 LOCATION
4120 hidd.gfx.bitmap
4122 FUNCTION
4124 INPUTS
4125 obj -
4126 pixels -
4127 modulo -
4128 x, y -
4129 width -
4130 height -
4131 pixlut -
4133 RESULT
4135 NOTES
4137 EXAMPLE
4139 BUGS
4141 SEE ALSO
4143 INTERNALS
4145 *****************************************************************************************/
4147 VOID BM__Hidd_BitMap__GetImageLUT(OOP_Class *cl, OOP_Object *o,
4148 struct pHidd_BitMap_GetImageLUT *msg)
4150 WORD x, y;
4151 UBYTE *pixarray = (UBYTE *)msg->pixels;
4152 HIDDT_PixelLUT *pixlut = msg->pixlut;
4153 HIDDT_Pixel *lut = pixlut ? pixlut->pixels : NULL;
4154 HIDDT_Pixel *linebuf;
4156 EnterFunc(bug("BitMap::GetImageLUT(x=%d, y=%d, width=%d, height=%d)\n"
4157 , msg->x, msg->y, msg->width, msg->height));
4159 linebuf = AllocVec(msg->width * sizeof(HIDDT_Pixel), MEMF_PUBLIC);
4161 for(y = 0; y < msg->height; y++)
4163 if (linebuf)
4165 GETIMAGE(cl, o,
4166 (UBYTE *)linebuf,
4168 msg->x,
4169 msg->y + y,
4170 msg->width,
4172 vHidd_StdPixFmt_Native32);
4173 if (lut)
4175 /* FIXME: This is wrong, but HIDD_BM_GetImageLUT on hi/truecolor screens does not really make sense anyway */
4176 for(x = 0; x < msg->width; x++)
4178 pixarray[x] = (UBYTE)linebuf[x];
4181 else
4183 for(x = 0; x < msg->width; x++)
4185 pixarray[x] = (UBYTE)linebuf[x];
4188 pixarray += msg->modulo;
4190 } /* if (linebuf) */
4191 else
4193 if (lut)
4195 /* FIXME: This is wrong, but HIDD_BM_GetImageLUT on hi/truecolor screens does not really make sense anyway */
4196 for(x = 0; x < msg->width; x++)
4198 pixarray[x] = (UBYTE)GETPIXEL(cl, o, msg->x + x, msg->y + y);
4201 else
4203 for(x = 0; x < msg->width; x++)
4205 pixarray[x] = (UBYTE)GETPIXEL(cl, o, msg->x + x, msg->y + y);
4209 pixarray += msg->modulo;
4211 } /* if (linebuf) else ... */
4213 } /* for(y = 0; y < msg->height; y++) */
4215 FreeVec(linebuf);
4217 ReturnVoid("BitMap::GetImageLUT");
4220 /*****************************************************************************************
4222 NAME
4223 moHidd_BitMap_BlitColorExpansion
4225 SYNOPSIS
4226 VOID OOP_DoMethod(OOP_Object *obj, struct pHidd_BitMap_BlitColorExpansion *msg);
4228 VOID HIDD_BM_BlitColorExpansion (OOP_Object *obj, OOP_Object *gc, OOP_Object *srcBitMap,
4229 WORD srcX, WORD srcY, WORD destX, WORD destY,
4230 UWORD width, UWORD height);
4232 LOCATION
4233 hidd.gfx.bitmap
4235 FUNCTION
4236 Perform a color expansion of the mask in srcBitMap according to foreground and background
4237 colors and expansion mode specified by the supplied GC. Pixels which are set to zero in
4238 the mask bitmap will be either painted by background (in opaque mode) or left without
4239 change (in transparent mode). Pixels which are set to nonzero in the mask will be painted
4240 by foreground color.
4242 The result of expansion is blitted onto the destination bitmap accorging to GC's draw mode.
4244 INPUTS
4245 obj - A bitmap to draw on
4246 gc - A GC object to use for drawing
4247 srcBitMap - A bitmap object containing mask image.
4248 srcX, srcY - A top-left coordinate of the used rectangle in the source bitmap
4249 destX, destY - A top-left coordinate of the destination rectangle to draw in
4250 width, height - A size of the rectangle to blit
4252 RESULT
4253 None.
4255 NOTES
4256 This method was previously used by graphics.library/Text() to draw fonts with no
4257 styles specified. Currently graphics.library always uses BltTemplate() and this
4258 method is considered obsolete.
4260 EXAMPLE
4262 BUGS
4264 SEE ALSO
4266 INTERNALS
4268 *****************************************************************************************/
4270 VOID BM__Hidd_BitMap__BlitColorExpansion(OOP_Class *cl, OOP_Object *o,
4271 struct pHidd_BitMap_BlitColorExpansion *msg)
4273 #ifdef __RESERVED__
4274 ULONG cemd;
4275 ULONG fg, bg;
4276 WORD x, y;
4278 OOP_Object *gc = msg->gc;
4280 EnterFunc(bug("BitMap::BlitColorExpansion(srcBM=%p, srcX=%d, srcY=%d, destX=%d, destY=%d, width=%d, height=%d)\n",
4281 msg->srcBitMap, msg->srcX, msg->srcY, msg->destX, msg->destY, msg->width, msg->height));
4283 cemd = GC_COLEXP(gc);
4284 fg = GC_FG(gc);
4285 bg = GC_BG(gc);
4287 /* bug("------------- Blit_ColExp: (%d, %d, %d, %d, %d, %d) cemd=%d, fg=%p, bg=%p -------------\n"
4288 , msg->srcX, msg->srcY, msg->destX, msg->destY, msg->width, msg->height
4289 , cemd, fg, bg);
4291 for (y = 0; y < msg->height; y ++)
4293 for (x = 0; x < msg->width; x ++)
4295 ULONG is_set;
4297 /* Pixel value is either 0 or 1 for BM of depth 1 */
4299 #if USE_FAST_GETPIXEL
4300 if (cl==()) is_set = GETPIXEL(cl, msg->srcBitMap, x + msg->srcX, y + msg->srcY);
4301 else
4302 #endif
4304 is_set = HIDD_BM_GetPixel(msg->srcBitMap, x + msg->srcX, y + msg->srcY);
4307 if (is_set)
4308 bug("#");
4309 else
4310 bug(" ");
4312 if (is_set)
4314 DRAWPIXEL(cl, o, gc, x + msg->destX, y + msg->destY);
4316 else
4318 if (cemd & vHidd_GC_ColExp_Opaque)
4320 /* Write bixel with BG pen */
4321 GC_FG(gc) = bg;
4322 DRAWPIXEL(cl, o, gc, x + msg->destX, y + msg->destY);
4323 /* Reset to FG pen */
4324 GC_FG(gc) = fg;
4327 } /* if () */
4329 } /* for (each x) */
4331 bug("\n");
4333 } /* for ( each y ) */
4334 #endif
4336 ReturnVoid("BitMap::BlitColorExpansion");
4339 /*****************************************************************************************
4341 NAME
4342 moHidd_BitMap_BytesPerLine
4344 SYNOPSIS
4345 ULONG OOP_DoMethod(OOP_Object *obj, struct pHidd_BitMap_BytesPerLine *msg);
4347 ULONG HIDD_BM_BytesPerLine(OOP_Object *obj, HIDDT_StdPixFmt pixFmt, UWORD width);
4349 LOCATION
4350 hidd.gfx.bitmap
4352 FUNCTION
4353 This method is currently not used and reserved.
4355 INPUTS
4356 obj -
4357 pixFmt -
4358 width -
4360 RESULT
4362 NOTES
4364 EXAMPLE
4366 BUGS
4368 SEE ALSO
4370 INTERNALS
4372 *****************************************************************************************/
4374 ULONG BM__Hidd_BitMap__BytesPerLine(OOP_Class *cl, OOP_Object *o, struct pHidd_BitMap_BytesPerLine *msg)
4376 #ifdef __RESERVED__
4377 ULONG bpl;
4379 switch (msg->pixFmt)
4381 case vHidd_StdPixFmt_Native32:
4382 bpl = sizeof (HIDDT_Pixel) * msg->width;
4383 break;
4385 case vHidd_StdPixFmt_Native:
4387 struct HIDDBitMapData *data;
4389 data = OOP_INST_DATA(cl, o);
4391 bpl = ((HIDDT_PixelFormat *)data->prot.pixfmt)->bytes_per_pixel * msg->width;
4392 break;
4395 default:
4397 OOP_Object *pf;
4398 struct HIDDBitMapData *data;
4400 data = OOP_INST_DATA(cl, o);
4402 pf = HIDD_Gfx_GetPixFmt(data->gfxhidd, msg->pixFmt);
4404 if (NULL == pf)
4406 D(bug("!!! COULD NOT GET STD PIXFMT IN BitMap::BytesPerLine() !!!\n"));
4407 return 0;
4410 bpl = ((HIDDT_PixelFormat *)pf)->bytes_per_pixel * msg->width;
4411 break;
4415 return bpl;
4416 #else
4417 return 0;
4418 #endif
4422 /****************************************************************************************/
4425 This makes it easier to create a subclass of the graphics hidd.
4426 It is only allowed to use this method in the p_RootNew method of a
4427 bitmap subclass.
4430 /****************************************************************************************/
4432 IPTR BM__Root__Set(OOP_Class *cl, OOP_Object *obj, struct pRoot_Set *msg)
4434 struct Library *UtilityBase = CSD(cl)->cs_UtilityBase;
4435 struct Library *OOPBase = CSD(cl)->cs_OOPBase;
4436 struct HIDDBitMapData *data = OOP_INST_DATA(cl, obj);
4437 struct TagItem *tag, *tstate;
4438 ULONG idx;
4439 WORD xoffset, yoffset;
4441 if (data->framebuffer)
4444 * If this is a framebuffer, we can process ModeID change.
4445 * We do it before parsing the rest of tags, because here we retrieve
4446 * defaults for new bitmap parameters (size and pixelformat).
4447 * They can be overridden by other tags. For example we can imagine
4448 * a hardware scrollable framebuffer whose width and height are larger
4449 * than visible part.
4451 HIDDT_ModeID modeid = GetTagData(aHidd_BitMap_ModeID, vHidd_ModeID_Invalid, msg->attrList);
4452 OOP_Object *sync, *pixfmt;
4454 if (HIDD_Gfx_GetMode(data->gfxhidd, modeid, &sync, &pixfmt))
4456 data->modeid = modeid;
4458 * Set defaults based on the ModeID.
4459 * They can be overriden lated, in SetBitMapTags.
4461 data->width = OOP_GET(sync, aHidd_Sync_HDisp);
4462 data->height = OOP_GET(sync, aHidd_Sync_VDisp);
4463 data->bytesPerRow = GetBytesPerRow(data, CSD(cl));
4464 data->prot.pixfmt = pixfmt;
4466 else
4468 /* Bad ModeID given, request rejected */
4469 return FALSE;
4472 /* Process the rest of tags. */
4473 BM__Hidd_BitMap__SetBitMapTags(cl, obj, msg->attrList);
4475 else
4478 * This is not a framebuffer.
4479 * We can modify size data (CHECKME: is it really used anywhere ?)
4480 * and also we can scroll (makes sense only if this is displayable
4481 * bitmap in mirrored framebuffer mode.
4483 BM__Hidd_BitMap__SetBitMapTags(cl, obj, msg->attrList);
4486 * And now we process position change.
4487 * One trick: we store our 'display' rectangle in bitmap's coordinates.
4488 * In other words, these are screen coordinates relative to bitmap, not
4489 * bitmap's ones relative to screen. As a result, we have to invert the sign.
4490 * This is done in order to simplify calculations in UpdateBitMap method of
4491 * graphics base class. It needs to perform intersection of update rectangle
4492 * with display rectangle, and they need to be in the same coordinate system
4493 * in order to be able to do this.
4494 * Update operation is performance-critical, so we perform this conversion
4495 * for display rectangle here.
4497 xoffset = data->display.MinX;
4498 yoffset = data->display.MinY;
4499 tstate = msg->attrList;
4500 while ((tag = NextTagItem(&tstate)))
4502 Hidd_BitMap_Switch(tag->ti_Tag, idx)
4504 case aoHidd_BitMap_LeftEdge:
4505 xoffset = tag->ti_Data;
4507 * FIXME:
4508 * Our bitmap cannot be smaller than display size because of fakegfx.hidd
4509 * limitations (it can't place cursor beyond bitmap edges). Otherwise Intuition
4510 * will provide strange user experience (mouse cursor will disappear)
4512 if (xoffset >= (WORD)data->displayWidth)
4513 xoffset = data->displayWidth - 1;
4514 else if (xoffset <= (WORD)-data->width)
4515 xoffset = -(data->width - 1);
4516 xoffset = -xoffset;
4517 D(bug("[BitMap] xoffset requested %ld, got %d\n", -tag->ti_Data, xoffset));
4518 break;
4520 case aoHidd_BitMap_TopEdge:
4521 /* Only offsets that ensure at least some of the bitmap is
4522 seen are valid */
4523 yoffset = tag->ti_Data;
4524 if (yoffset >= (WORD)data->displayHeight)
4525 yoffset = data->displayHeight - 1;
4526 else if (yoffset <= (WORD)-data->height)
4527 yoffset = -(data->height - 1);
4528 yoffset = -yoffset;
4529 D(bug("[BitMap] yoffset requested %ld, got %d\n", -tag->ti_Data, yoffset));
4530 break;
4534 if ((xoffset != data->display.MinX) || (yoffset != data->display.MinY))
4536 ObtainSemaphore(&data->lock);
4538 data->display.MinX = xoffset;
4539 data->display.MinY = yoffset;
4540 data->display.MaxX = xoffset + data->displayWidth;
4541 data->display.MaxY = yoffset + data->displayHeight;
4543 if (data->visible)
4545 GFXHIDD__Hidd_Gfx__UpdateFB(CSD(cl)->gfxhiddclass, data->gfxhidd,
4546 obj, data->display.MinX, data->display.MinY,
4547 0, 0, data->displayWidth, data->displayHeight);
4550 ReleaseSemaphore(&data->lock);
4554 /* There's no superclass above us */
4555 return TRUE;
4558 /*****************************************************************************************
4560 NAME
4561 moHidd_BitMap_SetColorMap
4563 SYNOPSIS
4564 OOP_Object * OOP_DoMethod(OOP_Object *obj, struct pHidd_BitMap_SetColorMap *msg);
4566 OOP_Object * HIDD_BM_SetColorMap(OOP_Object *obj, OOP_Object *colorMap);
4568 LOCATION
4569 hidd.gfx.bitmap
4571 FUNCTION
4573 INPUTS
4574 obj -
4575 colorMap -
4577 RESULT
4579 NOTES
4581 EXAMPLE
4583 BUGS
4585 SEE ALSO
4587 INTERNALS
4589 *****************************************************************************************/
4591 OOP_Object *BM__Hidd_BitMap__SetColorMap(OOP_Class *cl, OOP_Object *o,
4592 struct pHidd_BitMap_SetColorMap *msg)
4594 struct HIDDBitMapData *data;
4595 OOP_Object *old;
4597 data = OOP_INST_DATA(cl, o);
4599 old = data->colmap;
4600 data->colmap = msg->colorMap;
4602 return old;
4605 /*****************************************************************************************
4607 NAME
4608 moHidd_BitMap_MapColor
4610 SYNOPSIS
4611 HIDDT_Pixel OOP_DoMethod(OOP_Object *obj, struct pHidd_BitMap_MapColor *msg);
4613 HIDDT_Pixel HIDD_BM_MapColor(OOP_Object *obj, HIDDT_Color *color);
4615 LOCATION
4616 hidd.gfx.bitmap
4618 FUNCTION
4620 INPUTS
4621 obj -
4622 color -
4624 RESULT
4626 NOTES
4628 EXAMPLE
4630 BUGS
4632 SEE ALSO
4634 INTERNALS
4636 *****************************************************************************************/
4638 /* We only care about magnitudes here, so we don't
4639 * have to perform the square root operation to get
4640 * the real distance.
4642 static ULONG colorDistance(HIDDT_Color *a, HIDDT_Color *b)
4644 #define SQR(x) ((x) * (x))
4645 return SQR((int)a->red - (int)b->red) +
4646 SQR((int)a->blue - (int)b->blue) +
4647 SQR((int)a->green - (int)b->green) +
4648 SQR((int)a->alpha - (int)b->alpha);
4649 #undef SQR
4652 HIDDT_Pixel BM__Hidd_BitMap__MapColor(OOP_Class *cl, OOP_Object *o,
4653 struct pHidd_BitMap_MapColor *msg)
4655 HIDDT_PixelFormat *pf = BM_PIXFMT(o);
4657 HIDDT_Pixel red = msg->color->red;
4658 HIDDT_Pixel green = msg->color->green;
4659 HIDDT_Pixel blue = msg->color->blue;
4660 HIDDT_Pixel alpha = msg->color->alpha;
4662 /* This code assumes that sizeof(HIDDT_Pixel) is a multiple of sizeof(col->#?),
4663 which should be true for most (all?) systems. I have never heard
4664 of any system with for example 3 byte types.
4667 if (IS_TRUECOLOR(pf))
4669 if (HIDD_PF_SWAPPIXELBYTES(pf))
4671 /* FIXME: BM__Hidd_BitMap__MapColor assuming that SwapPixelBytes flag only set for 2-byte/16-bit pixel formats */
4673 HIDDT_Pixel pixel = MAP_RGBA(red, green, blue, alpha, pf);
4675 msg->color->pixval = SWAPBYTES_WORD(pixel);
4677 else
4679 msg->color->pixval = MAP_RGBA(red, green, blue, alpha, pf);
4682 else
4684 struct HIDDBitMapData *data = OOP_INST_DATA(cl, o);
4685 HIDDT_Color *ctab;
4686 HIDDT_ColorLUT *cmap;
4687 UWORD i;
4688 ULONG best_ndx = ~0, best_dist = ~0;
4690 cmap = (HIDDT_ColorLUT *)data->colmap;
4691 ctab = cmap->colors;
4692 /* Search for the best match in the color table */
4693 for (i = 0; i < cmap->entries; i++) {
4694 ULONG dist;
4696 dist = colorDistance(&ctab[i], msg->color);
4697 if (dist < best_dist) {
4698 best_dist = dist;
4699 best_ndx = i;
4703 if (best_dist != ~0)
4704 msg->color->pixval = ctab[best_ndx].pixval;
4707 return msg->color->pixval;
4710 /*****************************************************************************************
4712 NAME
4713 moHidd_BitMap_UnmapPixel
4715 SYNOPSIS
4716 VOID OOP_DoMethod(OOP_Object *obj, struct pHidd_BitMap_UnmapPixel *msg);
4718 VOID HIDD_BM_UnmapPixel(OOP_Object *obj, HIDDT_Pixel pixel, HIDDT_Color *color);
4720 LOCATION
4721 hidd.gfx.bitmap
4723 FUNCTION
4725 INPUTS
4726 obj -
4727 pixel -
4728 color -
4730 RESULT
4732 NOTES
4734 EXAMPLE
4736 BUGS
4738 SEE ALSO
4740 INTERNALS
4742 *****************************************************************************************/
4744 VOID BM__Hidd_BitMap__UnmapPixel(OOP_Class *cl, OOP_Object *o, struct pHidd_BitMap_UnmapPixel *msg)
4747 HIDDT_PixelFormat *pf = BM_PIXFMT(o);
4749 if (IS_TRUECOLOR(pf))
4751 HIDDT_Pixel pixel = msg->pixel;
4753 if (HIDD_PF_SWAPPIXELBYTES(pf))
4755 /* FIXME: bitmap_unmappixel assuming that SwapPixelBytes flag only set for 2-byte/16-bit pixel formats */
4756 pixel = SWAPBYTES_WORD(pixel);
4759 msg->color->red = RED_COMP (pixel, pf);
4760 msg->color->green = GREEN_COMP (pixel, pf);
4761 msg->color->blue = BLUE_COMP (pixel, pf);
4762 msg->color->alpha = ALPHA_COMP (pixel, pf);
4764 else
4766 struct HIDDBitMapData *data = OOP_INST_DATA(cl, o);
4767 HIDDT_ColorLUT *clut;
4769 clut = (HIDDT_ColorLUT *)data->colmap;
4773 /* FIXME: Use CLUT shift and CLUT mask here */
4774 if (msg->pixel < 0 || msg->pixel >= clut->entries)
4775 return;
4777 *msg->color = clut->colors[msg->pixel];
4781 /* Unnecessary, but... */
4782 msg->color->pixval = msg->pixel;
4785 /*****************************************************************************************
4787 NAME
4788 moHidd_BitMap_ObtainDirectAccess
4790 SYNOPSIS
4791 BOOL OOP_DoMethod(OOP_Object *obj, struct pHidd_BitMap_ObtainDirectAccess *msg);
4793 BOOL HIDD_BM_ObtainDirectAccess(OOP_Object *obj, UBYTE **addressReturn,
4794 ULONG *widthReturn, ULONG *heightReturn,
4795 ULONG *bankSizeReturn, ULONG *memSizeReturn);
4797 LOCATION
4798 hidd.gfx.bitmap
4800 FUNCTION
4802 INPUTS
4803 obj -
4804 addressReturn -
4805 widthReturn -
4806 heightReturn -
4807 bankSizeReturn -
4808 memSizeReturn -
4810 RESULT
4811 BOOL
4813 NOTES
4815 EXAMPLE
4817 BUGS
4819 SEE ALSO
4821 INTERNALS
4823 *****************************************************************************************/
4825 BOOL BM__Hidd_BitMap__ObtainDirectAccess(OOP_Class *cl, OOP_Object *o,
4826 struct pHidd_BitMap_ObtainDirectAccess *msg)
4828 /* Default implementation of direct access funcs. Just return FALSE */
4829 return FALSE;
4832 /*****************************************************************************************
4834 NAME
4835 moHidd_BitMap_ReleaseDirectAccess
4837 SYNOPSIS
4838 VOID OOP_DoMethod(OOP_Object *obj, struct pHidd_BitMap_ReleaseDirectAccess *msg);
4840 VOID HIDD_BM_ReleaseDirectAccess(OOP_Object *obj);
4842 LOCATION
4843 hidd.gfx.bitmap
4845 FUNCTION
4847 INPUTS
4848 obj -
4850 RESULT
4852 NOTES
4854 EXAMPLE
4856 BUGS
4858 SEE ALSO
4860 INTERNALS
4862 *****************************************************************************************/
4864 VOID BM__Hidd_BitMap__ReleaseDirectAccess(OOP_Class *cl, OOP_Object *o,
4865 struct pHidd_BitMap_ReleaseDirectAccess *msg)
4867 D(bug("!!! BitMap BaseClasse ReleaseDirectAccess() called !!!\n"));
4868 D(bug("!!! This should never happen and is probably due to a buggy implementation in the subclass !!!\n"));
4870 return;
4873 /*****************************************************************************************
4875 NAME
4876 moHidd_BitMap_BitMapScale
4878 SYNOPSIS
4879 VOID OOP_DoMethod(OOP_Object *obj, struct pHidd_BitMap_BitMapScale * msg);
4881 VOID HIDD_BM_BitMapScale(OOP_Object *obj, OOP_Object *src, OOP_Object *dest,
4882 struct BitScaleArgs * bsa, OOP_Object *gc);
4884 LOCATION
4885 hidd.gfx.bitmap
4887 FUNCTION
4889 INPUTS
4890 obj -
4891 src -
4892 dest -
4893 bsa -
4894 gc -
4896 RESULT
4898 NOTES
4900 EXAMPLE
4902 BUGS
4904 SEE ALSO
4906 INTERNALS
4908 *****************************************************************************************/
4910 VOID BM__Hidd_BitMap__BitMapScale(OOP_Class * cl, OOP_Object *o,
4911 struct pHidd_BitMap_BitMapScale * msg)
4913 struct BitScaleArgs *bsa = msg->bsa;
4914 ULONG *srcbuf, *dstbuf;
4915 WORD srcline = -1;
4916 UWORD *linepattern;
4917 UWORD count;
4918 UWORD ys = bsa->bsa_SrcY;
4919 UWORD xs = bsa->bsa_SrcX;
4920 UWORD dyd = bsa->bsa_DestHeight;
4921 UWORD dxd = bsa->bsa_DestWidth;
4922 LONG accuys = dyd;
4923 LONG accuxs = dxd;
4924 UWORD dxs = bsa->bsa_SrcWidth;
4925 UWORD dys = bsa->bsa_SrcHeight;
4926 LONG accuyd = - (dys >> 1);
4927 LONG accuxd = - (dxs >> 1);
4928 UWORD x;
4930 if ((srcbuf = AllocVec(bsa->bsa_SrcWidth * sizeof(ULONG), 0)) == NULL)
4931 return;
4933 if ((dstbuf = AllocVec(bsa->bsa_DestWidth * sizeof(ULONG), 0)) == NULL) {
4934 FreeVec(srcbuf);
4935 return;
4938 if ((linepattern = (UWORD *) AllocVec(bsa->bsa_DestWidth * sizeof(UWORD), 0)) == NULL) {
4939 FreeVec(dstbuf);
4940 FreeVec(srcbuf);
4941 return;
4944 count = 0;
4945 while (count < bsa->bsa_DestWidth) {
4946 accuxd += dxs;
4947 while (accuxd > accuxs) {
4948 xs++;
4949 accuxs += dxd;
4952 linepattern[count] = xs;
4954 count++;
4957 count = bsa->bsa_DestY;
4958 while (count < bsa->bsa_DestHeight + bsa->bsa_DestY) {
4959 accuyd += dys;
4960 while (accuyd > accuys) {
4961 ys++;
4962 accuys += dyd;
4965 if (srcline != ys) {
4966 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);
4967 srcline = ys;
4969 for (x = 0; x < bsa->bsa_DestWidth; x++)
4970 dstbuf[x] = srcbuf[linepattern[x]];
4973 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);
4975 count++;
4978 FreeVec(linepattern);
4980 FreeVec(dstbuf);
4981 FreeVec(srcbuf);
4984 /*****************************************************************************************
4986 NAME
4987 moHidd_BitMap_SetRGBConversionFunction
4989 SYNOPSIS
4990 HIDDT_RGBConversionFunction
4991 OOP_DoMethod(OOP_Object *obj, struct pHidd_BitMap_SetRGBConversionFunction *msg);
4993 HIDDT_RGBConversionFunction
4994 HIDD_BM_SetRGBConversionFunction(OOP_Object *obj, HIDDT_StdPixFmt srcPixFmt,
4995 HIDDT_StdPixFmt dstPixFmt,
4996 HIDDT_RGBConversionFunction function);
4998 LOCATION
4999 hidd.gfx.bitmap
5001 FUNCTION
5003 INPUTS
5005 RESULT
5007 NOTES
5009 EXAMPLE
5011 BUGS
5013 SEE ALSO
5015 INTERNALS
5017 *****************************************************************************************/
5019 HIDDT_RGBConversionFunction BM__Hidd_BitMap__SetRGBConversionFunction(OOP_Class * cl, OOP_Object *o,
5020 struct pHidd_BitMap_SetRGBConversionFunction * msg)
5022 HIDDT_RGBConversionFunction old;
5024 if ((msg->srcPixFmt < FIRST_RGB_STDPIXFMT) ||
5025 (msg->dstPixFmt < FIRST_RGB_STDPIXFMT) ||
5026 (msg->srcPixFmt > LAST_RGB_STDPIXFMT) ||
5027 (msg->dstPixFmt > LAST_RGB_STDPIXFMT))
5029 return (HIDDT_RGBConversionFunction)-1;
5031 else
5033 ObtainSemaphore(&CSD(cl)->rgbconvertfuncs_sem);
5034 old = CSD(cl)->rgbconvertfuncs[msg->srcPixFmt - FIRST_RGB_STDPIXFMT][msg->dstPixFmt - FIRST_RGB_STDPIXFMT];
5035 CSD(cl)->rgbconvertfuncs[msg->srcPixFmt - FIRST_RGB_STDPIXFMT][msg->dstPixFmt - FIRST_RGB_STDPIXFMT] = msg->function;
5036 ReleaseSemaphore(&CSD(cl)->rgbconvertfuncs_sem);
5038 return old;
5042 /*****************************************************************************************
5044 NAME
5045 moHidd_BitMap_UpdateRect
5047 SYNOPSIS
5048 VOID OOP_DoMethod(OOP_Object *obj, struct pHidd_BitMap_UpdateRect *msg);
5050 VOID HIDD_BM_UpdateRect(OOP_Object *obj, WORD x, WORD y, WORD width, WORD height);
5052 LOCATION
5053 hidd.gfx.bitmap
5055 FUNCTION
5056 Update displayed image of the given rectangle.
5058 Some drivers (like VGA and VESA) may work not with VRAM directly, but with a mirrored
5059 copy of it. Usually it is done in case if VRAM reading is slow. This method is called
5060 by the system after it completes any drawing operation, in order to make sure that
5061 changes made are visible on the actual screen. If your driver uses mirroring, this method
5062 should copy the given rectangle (at least) from the mirror buffer to the actual VRAM.
5064 This method is also called after changing currently visible bitmap (after moHidd_Gfx_Show
5065 method call) in order to allow the mirroring driver to refresh the screen after current bitmap
5066 changed. Note that moHidd_Gfx_ShowViewPorts is very different and moHidd_BitMap_UpdateRect
5067 will not be called if it succeeded!
5069 INPUTS
5070 obj - an object whose image to refresh
5071 x, y - A top-left edge of the rectangle to refresh
5072 width - Width of the rectangle to refresh
5073 height - Height of the rectangle to refresh
5075 RESULT
5076 None.
5078 NOTES
5079 This method is called also on offscreen bitmaps. You should track visible state of your bitmap
5080 and ignore these calls if it's not currently visible on the screen.
5082 EXAMPLE
5084 BUGS
5086 SEE ALSO
5088 INTERNALS
5090 *****************************************************************************************/
5092 VOID BM__Hidd_BitMap__UpdateRect(OOP_Class *cl, OOP_Object *o, struct pHidd_BitMap_UpdateRect *msg)
5094 struct HIDDBitMapData *data = OOP_INST_DATA(cl, o);
5096 DUPDATE(bug("[BitMap] UpdateRect(0x%p, %d, %d, %d, %d)\n", o, msg->x, msg->y, msg->width, msg->height));
5099 * We check data->visible twice in order to avoid unnecessary locking
5100 * when our bitmap is not on display (it may be not displayable at all).
5101 * However the second check is still needed in order to make sure that
5102 * this bitmap is still on display, because we could be preempted between
5103 * the test and ObtainSemaphoreShared() by concurrently running Show() call.
5104 * We use shared lock because it's safe to have two concurrently running
5105 * updates even on the same region.
5107 if (data->visible)
5109 ObtainSemaphoreShared(&data->lock);
5111 if (data->visible)
5114 * Complete update rectangle.
5115 * Display rectangle is already in bitmap's coordinates.
5117 UWORD srcX = msg->x;
5118 UWORD srcY = msg->y;
5119 UWORD xLimit = srcX + msg->width;
5120 UWORD yLimit = srcY + msg->height;
5122 /* Intersect rectangles */
5123 if (data->display.MinX > srcX)
5124 srcX = data->display.MinX;
5125 if (data->display.MinY > srcY)
5126 srcY = data->display.MinY;
5127 if (data->display.MaxX < xLimit)
5128 xLimit = data->display.MaxX;
5129 if (data->display.MaxY < yLimit)
5130 yLimit = data->display.MaxY;
5132 /* Update the intersection region, if any */
5133 if ((xLimit > srcX) && (yLimit > srcY))
5135 GFXHIDD__Hidd_Gfx__UpdateFB(CSD(cl)->gfxhiddclass, data->gfxhidd,
5136 o, srcX, srcY,
5137 srcX - data->display.MinX, srcY - data->display.MinY,
5138 xLimit - srcX, yLimit - srcY);
5142 ReleaseSemaphore(&data->lock);
5146 /****************************************************************************************/
5149 * Private methods follow.
5150 * They are implemented as non-virtual, for speed up.
5153 /* This is a private form of Set method. Doesn't need a standard message. */
5154 void BM__Hidd_BitMap__SetBitMapTags(OOP_Class *cl, OOP_Object *o, struct TagItem *bitMapTags)
5156 struct Library *UtilityBase = CSD(cl)->cs_UtilityBase;
5157 struct HIDDBitMapData *data = OOP_INST_DATA(cl, o);
5158 struct TagItem *tag;
5160 while ((tag = NextTagItem(&bitMapTags)))
5162 ULONG idx;
5164 if (IS_BITMAP_ATTR(tag->ti_Tag, idx))
5166 switch (idx)
5168 case aoHidd_BitMap_Width:
5169 data->width = tag->ti_Data;
5170 break;
5172 case aoHidd_BitMap_Height:
5173 data->height = tag->ti_Data;
5174 break;
5176 case aoHidd_BitMap_BytesPerRow:
5177 data->bytesPerRow = tag->ti_Data;
5178 break;
5180 case aoHidd_BitMap_Compositable:
5181 data->compositable = tag->ti_Data;
5182 if (data->compositable)
5184 HIDDT_ModeID compositmodeid;
5185 struct Library *OOPBase = csd->cs_OOPBase;
5187 if (data->friend)
5189 OOP_GetAttr(data->friend, aHidd_BitMap_ModeID, &compositmodeid);
5191 else
5192 compositmodeid = data->modeid;
5194 if (compositmodeid == vHidd_ModeID_Invalid)
5196 data->compositable = FALSE;
5198 else
5200 OOP_Object *sync, *pf;
5202 if (!HIDD_Gfx_GetMode(data->gfxhidd, compositmodeid, &sync, &pf))
5204 data->compositable = FALSE;
5206 else
5208 /* Get display size from the modeid */
5209 OOP_GetAttr(sync, aHidd_Sync_HDisp, &data->displayWidth);
5210 OOP_GetAttr(sync, aHidd_Sync_VDisp, &data->displayHeight);
5211 data->display.MaxX = data->displayWidth;
5212 data->display.MaxY = data->displayHeight;
5214 D(bug("[BitMap] Bitmap %dx%d, display %dx%d\n",
5215 data->width, data->height,
5216 data->displayWidth, data->displayHeight));
5226 * Updates bitmap's pixelformat.
5227 * Used from within planarbm subclass, and would be extremely dangerous to expose
5228 * as setable aHidd_BitMap_PixFmt, so implemented as a separate method.
5230 void BM__Hidd_BitMap__SetPixFmt(OOP_Class *cl, OOP_Object *o, OOP_Object *pf)
5232 struct HIDDBitMapData *data = OOP_INST_DATA(cl, o);
5234 /* Already a pixfmt registered? */
5235 if (data->pf_registered)
5236 GFXHIDD__Hidd_Gfx__ReleasePixFmt(CSD(cl)->gfxhiddclass, data->prot.pixfmt);
5238 /* Remember the new pixelformat */
5239 data->prot.pixfmt = pf;
5242 * This pixelformat was obtained using GFXHIDD__Hidd_Gfx__RegisterPixFmt().
5243 * It increases number of pixfmt users, so we'll need to release it when
5244 * not used any more.
5246 data->pf_registered = TRUE;
5250 * Change visible state of the bitmap.
5251 * Used in mirrored framebuffer mode. Actually needed because
5252 * of semaphore barrier, which makes sure that bitmap state does
5253 * not change during scrolling or updating operation. Prevents possibilities
5254 * of screen corruption during concurrently running scrolling with Show.
5256 void BM__Hidd_BitMap__SetVisible(OOP_Class *cl, OOP_Object *o, BOOL val)
5258 struct HIDDBitMapData *data = OOP_INST_DATA(cl, o);
5260 ObtainSemaphore(&data->lock);
5261 data->visible = val;
5262 ReleaseSemaphore(&data->lock);