1 /* Copyright 2007-2012 Fredrik Wikstrom. All rights reserved.
3 ** Redistribution and use in source and binary forms, with or without
4 ** modification, are permitted provided that the following conditions
7 ** 1. Redistributions of source code must retain the above copyright
8 ** notice, this list of conditions and the following disclaimer.
10 ** 2. Redistributions in binary form must reproduce the above copyright
11 ** notice, this list of conditions and the following disclaimer in the
12 ** documentation and/or other materials provided with the distribution.
14 ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS'
15 ** AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 ** IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 ** ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
18 ** LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
19 ** CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
20 ** SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
21 ** INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
22 ** CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
23 ** ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
24 ** POSSIBILITY OF SUCH DAMAGE.
28 #include <libraries/Picasso96.h>
29 #include <cybergraphx/cybergraphics.h>
30 #include <proto/exec.h>
31 #include <proto/utility.h>
32 #include <proto/intuition.h>
33 #include <proto/graphics.h>
34 #include <proto/layers.h>
35 #include <proto/Picasso96API.h>
36 #include <proto/cybergraphics.h>
37 #include <clib/alib_protos.h>
40 #define IA(x) ((struct Image *)x)
42 static IPTR
PNG_New (Class
*cl
, Object
*o
, struct opSet
*ops
);
43 static IPTR
PNG_Dispose (Class
*cl
, Object
*o
, Msg msg
);
44 static IPTR
PNG_DomainFrame (Class
*cl
, Object
*o
, struct impDomainFrame
*imp
);
45 static IPTR
PNG_Draw (Class
*cl
, Object
*o
, struct impDraw
*imp
);
46 static void PreMultiplyAlpha (UBYTE
*rgba
, WORD w
, WORD h
);
47 static void WriteRGBAPixels (struct RastPort
*rp
, UBYTE
*image
, WORD x
, WORD y
, WORD w
, WORD h
);
49 IPTR
ClassDispatch (REG(a0
, Class
*cl
), REG(a2
, Object
*o
), REG(a1
, Msg msg
)) {
51 switch (msg
->MethodID
) {
53 res
= PNG_New(cl
, o
, (struct opSet
*)msg
);
57 res
= PNG_Dispose(cl
, o
, msg
);
61 res
= PNG_DomainFrame(cl
, o
, (struct impDomainFrame
*)msg
);
65 res
= PNG_Draw(cl
, o
, (struct impDraw
*)msg
);
69 res
= DoSuperMethodA(cl
, o
, msg
);
75 static IPTR
PNG_New (Class
*cl
, Object
*o
, struct opSet
*ops
) {
77 res
= DoSuperMethodA(cl
, o
, (Msg
)ops
);
79 struct ClassData
*data
= INST_DATA(cl
, (Object
*)res
);
80 struct Screen
*screen
;
83 memset(data
, 0, sizeof(*data
));
85 screen
= (struct Screen
*)GetTagData(PNG_Screen
, (IPTR
)NULL
, ops
->ops_AttrList
);
87 CoerceMethod(cl
, (Object
*)res
, OM_DISPOSE
);
91 if (p96GetBitMapAttr(screen
->RastPort
.BitMap
, P96BMA_ISP96
)) {
93 data
->truecolor
= IsSupportedRGBFormat_P96(
94 p96GetBitMapAttr(screen
->RastPort
.BitMap
, P96BMA_RGBFORMAT
)
97 } else if (CyberGfxBase
) {
98 if (GetCyberMapAttr(screen
->RastPort
.BitMap
, CYBRMATTR_ISCYBERGFX
)) {
100 data
->truecolor
= IsSupportedRGBFormat_CGX(
101 GetCyberMapAttr(screen
->RastPort
.BitMap
, CYBRMATTR_PIXFMT
)
105 filename
= (const char *)GetTagData(PNG_SourceFile
, (IPTR
)NULL
, ops
->ops_AttrList
);
106 if (!filename
|| !LoadPNG(data
, filename
, IMG_NORMAL
)) {
107 CoerceMethod(cl
, (Object
*)res
, OM_DISPOSE
);
110 filename
= (const char *)GetTagData(PNG_SelectSourceFile
, (IPTR
)NULL
, ops
->ops_AttrList
);
111 if (filename
&& !LoadPNG(data
, filename
, IMG_SELECTED
)) {
112 CoerceMethod(cl
, (Object
*)res
, OM_DISPOSE
);
115 filename
= (const char *)GetTagData(PNG_DisabledSourceFile
, (IPTR
)NULL
, ops
->ops_AttrList
);
116 if (filename
&& !LoadPNG(data
, filename
, IMG_DISABLED
)) {
117 CoerceMethod(cl
, (Object
*)res
, OM_DISPOSE
);
120 if (data
->truecolor
) {
121 for (i
= 0; i
< 3; i
++) {
122 if (data
->image
[i
]) {
123 PreMultiplyAlpha(data
->image
[i
], data
->width
, data
->height
);
127 for (i
= 0; i
< 3; i
++) {
128 if (data
->image
[i
]) {
129 if (!RemapRGBAImage(screen
, data
->rtg
, data
->image
[i
], data
->width
, data
->height
,
130 data
->pen_map
, &data
->bm
[i
], &data
->mask
[i
]))
132 CoerceMethod(cl
, (Object
*)res
, OM_DISPOSE
);
135 FreeVec(data
->image
[i
]);
136 data
->image
[i
] = NULL
;
140 IA(res
)->Width
= data
->width
;
141 IA(res
)->Height
= data
->height
;
146 static IPTR
PNG_Dispose (Class
*cl
, Object
*o
, Msg msg
) {
147 struct ClassData
*data
= INST_DATA(cl
, o
);
148 if (data
->truecolor
) {
149 FreeVec(data
->image
[IMG_NORMAL
]);
150 FreeVec(data
->image
[IMG_SELECTED
]);
151 FreeVec(data
->image
[IMG_DISABLED
]);
153 FreeBitMap(data
->bm
[IMG_NORMAL
]);
154 FreeBitMap(data
->bm
[IMG_SELECTED
]);
155 FreeBitMap(data
->bm
[IMG_DISABLED
]);
156 FreeVec(data
->mask
[IMG_NORMAL
]);
157 FreeVec(data
->mask
[IMG_SELECTED
]);
158 FreeVec(data
->mask
[IMG_DISABLED
]);
159 PenMap_ReleasePens(data
->pen_map
, data
->screen
);
161 return DoSuperMethodA(cl
, o
, msg
);
164 static IPTR
PNG_DomainFrame (Class
*cl
, Object
*o
, struct impDomainFrame
*imp
) {
165 struct ClassData
*data
= INST_DATA(cl
, o
);
167 switch (imp
->imp_Which
) {
168 case IDOMAIN_MINIMUM
:
169 case IDOMAIN_NOMINAL
:
170 case IDOMAIN_MAXIMUM
:
171 imp
->imp_Domain
.Width
= data
->width
;
172 imp
->imp_Domain
.Height
= data
->height
;
179 static IPTR
PNG_Draw (Class
*cl
, Object
*o
, struct impDraw
*imp
) {
180 struct ClassData
*data
= INST_DATA(cl
, o
);
181 struct RastPort
*rp
= imp
->imp_RPort
;
184 x
= IA(o
)->LeftEdge
+ imp
->imp_Offset
.X
;
185 y
= IA(o
)->TopEdge
+ imp
->imp_Offset
.Y
;
187 switch (imp
->imp_State
) {
191 if (HAS_IMAGE(data
, IMG_SELECTED
)) {
192 index
= IMG_SELECTED
;
196 case IDS_INACTIVEDISABLED
:
197 case IDS_SELECTEDDISABLED
:
198 if (HAS_IMAGE(data
, IMG_DISABLED
)) {
199 index
= IMG_DISABLED
;
203 if (data
->truecolor
) {
204 WriteRGBAPixels(rp
, data
->image
[index
], x
, y
, data
->width
, data
->height
);
206 BltMaskBitMapRastPort(data
->bm
[index
], 0, 0, rp
, x
, y
, data
->width
, data
->height
,
207 ABC
|ABNC
|ANBC
, data
->mask
[index
]);
212 static void PreMultiplyAlpha (UBYTE
*rgba
, WORD w
, WORD h
) {
215 for (y
= 0; y
< h
; y
++) {
216 for (x
= 0; x
< w
; x
++) {
220 rgba
[0] = (rgba
[0] * a
) >> 8;
221 rgba
[1] = (rgba
[1] * a
) >> 8;
222 rgba
[2] = (rgba
[2] * a
) >> 8;
229 static void WriteRGBAPixels (struct RastPort
*rp
, UBYTE
*image
, WORD x
, WORD y
, WORD w
, WORD h
) {
230 struct HookData data
;
231 struct Rectangle rect
;
240 rect
.MaxX
= x
+ w
- 1;
241 rect
.MaxY
= y
+ h
- 1;
242 memset(&hook
, 0, sizeof(hook
));
244 if (P96Base
&& p96GetBitMapAttr(rp
->BitMap
, P96BMA_ISP96
)) {
245 hook
.h_Entry
= (HOOKFUNC
)WriteRGBAPixels_P96
;
246 DoHookClipRects(&hook
, rp
, &rect
);
247 } else if (CyberGfxBase
&& GetCyberMapAttr(rp
->BitMap
, CYBRMATTR_ISCYBERGFX
)) {
248 hook
.h_Entry
= (HOOKFUNC
)WriteRGBAPixels_CGX
;
249 DoHookClipRects(&hook
, rp
, &rect
);