revert between 56095 -> 55830 in arch
[AROS.git] / workbench / devs / diskimage / png_image / class.c
blobeb5c964ed9a162c4f9cc4ba5028a5ab6428815a3
1 /* Copyright 2007-2012 Fredrik Wikstrom. All rights reserved.
2 **
3 ** Redistribution and use in source and binary forms, with or without
4 ** modification, are permitted provided that the following conditions
5 ** are met:
6 **
7 ** 1. Redistributions of source code must retain the above copyright
8 ** notice, this list of conditions and the following disclaimer.
9 **
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.
27 #include "class.h"
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>
38 #include <string.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)) {
50 IPTR res;
51 switch (msg->MethodID) {
52 case OM_NEW:
53 res = PNG_New(cl, o, (struct opSet *)msg);
54 break;
56 case OM_DISPOSE:
57 res = PNG_Dispose(cl, o, msg);
58 break;
60 case IM_DOMAINFRAME:
61 res = PNG_DomainFrame(cl, o, (struct impDomainFrame *)msg);
62 break;
64 case IM_DRAW:
65 res = PNG_Draw(cl, o, (struct impDraw *)msg);
66 break;
68 default:
69 res = DoSuperMethodA(cl, o, msg);
70 break;
72 return res;
75 static IPTR PNG_New (Class *cl, Object *o, struct opSet *ops) {
76 IPTR res;
77 res = DoSuperMethodA(cl, o, (Msg)ops);
78 if (res) {
79 struct ClassData *data = INST_DATA(cl, (Object *)res);
80 struct Screen *screen;
81 const char *filename;
82 int i;
83 memset(data, 0, sizeof(*data));
84 data->screen =
85 screen = (struct Screen *)GetTagData(PNG_Screen, (IPTR)NULL, ops->ops_AttrList);
86 if (!screen) {
87 CoerceMethod(cl, (Object *)res, OM_DISPOSE);
88 return (IPTR)NULL;
90 if (P96Base) {
91 if (p96GetBitMapAttr(screen->RastPort.BitMap, P96BMA_ISP96)) {
92 data->rtg = TRUE;
93 data->truecolor = IsSupportedRGBFormat_P96(
94 p96GetBitMapAttr(screen->RastPort.BitMap, P96BMA_RGBFORMAT)
97 } else if (CyberGfxBase) {
98 if (GetCyberMapAttr(screen->RastPort.BitMap, CYBRMATTR_ISCYBERGFX)) {
99 data->rtg = TRUE;
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);
108 return (IPTR)NULL;
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);
113 return (IPTR)NULL;
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);
118 return (IPTR)NULL;
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);
126 } else {
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);
133 return (IPTR)NULL;
135 FreeVec(data->image[i]);
136 data->image[i] = NULL;
140 IA(res)->Width = data->width;
141 IA(res)->Height = data->height;
143 return res;
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]);
152 } else {
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);
166 IPTR res = 0;
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;
173 res = 1;
174 break;
176 return res;
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;
182 LONG x, y;
183 LONG index;
184 x = IA(o)->LeftEdge + imp->imp_Offset.X;
185 y = IA(o)->TopEdge + imp->imp_Offset.Y;
186 index = IMG_NORMAL;
187 switch (imp->imp_State) {
188 case IDS_NORMAL:
189 break;
190 case IDS_SELECTED:
191 if (HAS_IMAGE(data, IMG_SELECTED)) {
192 index = IMG_SELECTED;
194 break;
195 case IDS_DISABLED:
196 case IDS_INACTIVEDISABLED:
197 case IDS_SELECTEDDISABLED:
198 if (HAS_IMAGE(data, IMG_DISABLED)) {
199 index = IMG_DISABLED;
201 break;
203 if (data->truecolor) {
204 WriteRGBAPixels(rp, data->image[index], x, y, data->width, data->height);
205 } else {
206 BltMaskBitMapRastPort(data->bm[index], 0, 0, rp, x, y, data->width, data->height,
207 ABC|ABNC|ANBC, data->mask[index]);
209 return 0;
212 static void PreMultiplyAlpha (UBYTE *rgba, WORD w, WORD h) {
213 WORD x, y;
214 UWORD a;
215 for (y = 0; y < h; y++) {
216 for (x = 0; x < w; x++) {
217 a = rgba[3];
218 rgba[3] = 255 - a;
219 if (a != 255) {
220 rgba[0] = (rgba[0] * a) >> 8;
221 rgba[1] = (rgba[1] * a) >> 8;
222 rgba[2] = (rgba[2] * a) >> 8;
224 rgba += 4;
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;
232 struct Hook hook;
233 data.x = x;
234 data.y = y;
235 data.w = w;
236 data.h = h;
237 data.image = image;
238 rect.MinX = x;
239 rect.MinY = y;
240 rect.MaxX = x + w - 1;
241 rect.MaxY = y + h - 1;
242 memset(&hook, 0, sizeof(hook));
243 hook.h_Data = &data;
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);