Initial revision
[blender.git] / intern / img / intern / IMG_PixmapRGBA32.cpp
1 /**
2  * $Id$
3  * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
4  *
5  * This program is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU General Public License
7  * as published by the Free Software Foundation; either version 2
8  * of the License, or (at your option) any later version. The Blender
9  * Foundation also sells licenses for use in proprietary software under
10  * the Blender License.  See http://www.blender.org/BL/ for information
11  * about this.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, write to the Free Software Foundation,
20  * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
21  *
22  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
23  * All rights reserved.
24  *
25  * The Original Code is: all of this file.
26  *
27  * Contributor(s): none yet.
28  *
29  * ***** END GPL/BL DUAL LICENSE BLOCK *****
30  */
31
32 /**
33
34  * $Id$
35  * Copyright (C) 2001 NaN Technologies B.V.
36  * Base class for pixmaps.
37  * @author      Maarten Gribnau
38  * @date        March 6, 2001
39  */
40
41
42 #include "../extern/IMG_PixmapRGBA32.h"
43
44 IMG_PixmapRGBA32::IMG_PixmapRGBA32(GEN_TUns32 width, GEN_TUns32 height)
45         : IMG_Pixmap(), m_pixels(width * height)
46 {
47         m_pixelsBase = m_pixels;
48         m_width = width;
49         m_height = height;
50         m_rowBytes = width * sizeof(TPixelRGBA32);
51         m_pixelSize = 32;
52         m_pixelType = kPixelTypeRGBA32;
53 }
54
55
56 IMG_PixmapRGBA32::IMG_PixmapRGBA32(void* image, GEN_TUns32 width, GEN_TUns32 height, GEN_TUns32 rowBytes)
57         : IMG_Pixmap(), m_pixels(image, width * rowBytes)
58 {
59         m_pixelsBase = m_pixels;
60         m_width = width;
61         m_height = height;
62         m_rowBytes = rowBytes;
63         m_pixelSize = 32;
64         m_pixelType = kPixelTypeRGBA32;
65 }
66
67
68 void IMG_PixmapRGBA32::fillRect(const GEN_Rect& r, const IMG_ColorRGB& c)
69 {
70         GEN_Rect t_bnds (0, 0, m_width, m_height);      // Bounds of this pixmap
71         GEN_Rect r_bnds (r);                                            // Area to set
72
73         // Determine visibility
74         GEN_TVisibility v = t_bnds.getVisibility(r_bnds);
75         if (v == GEN_kNotVisible) return;
76         if (v == GEN_kPartiallyVisible) {
77                 // Clip the destination rectangle to the bounds of this pixmap
78                 t_bnds.clip(r_bnds);
79                 if (r_bnds.isEmpty()) {
80                         return;
81                 }
82         }
83
84 #if 0
85         // Set new pixels using shifting
86         // Prepare the pixel value to set
87         IMG_ColorRGBA ca (c);
88         TPixelRGBA32 pv = getPixelValue(c);
89         // Mask off the alpha bits
90         pv &= 0x00FFFFFF; //0xFFFFFF00;
91
92         // Set the pixels in the destination rectangle
93         for (GEN_TInt32 y = r.m_t; y < r.m_b; y++) {
94                 // Park pixel pointer at the start pixels
95                 TPixelPtr desPtr = getPixelPtr(r_bnds.m_l, y);
96                 for (GEN_TInt32 x = r.m_l; x < r.m_r; x++) {
97                         // Set the new pixel value (retain current alpha)
98                         *(desPtr++) = pv | ((*desPtr) & 0xFF000000); //0x000000FF);
99                 }
100         }
101 #else
102         // Set new values using byte indexing
103         //IMG_ColorRGBA ca (c);
104         TPixelRGBA32 src = getPixelValue(c);
105         TPixelPtr desPtr;
106         GEN_TUns8* srcBytes = (GEN_TUns8*) &src;
107         
108         // Set the pixels in the destination rectangle
109         for (GEN_TInt32 y = r.m_t; y < r.m_b; y++) {
110                 // Park pixel pointer at the start pixels
111                 desPtr = getPixelPtr(r_bnds.m_l, y);
112                 for (GEN_TInt32 x = r.m_l; x < r.m_r; x++) {
113                         // Set the new pixel value (retain current alpha)
114                         ((GEN_TUns8*)desPtr)[bi_r] = srcBytes[bi_r];
115                         ((GEN_TUns8*)desPtr)[bi_g] = srcBytes[bi_g];
116                         ((GEN_TUns8*)desPtr)[bi_b] = srcBytes[bi_b];
117                         desPtr++;
118                 }
119         }
120 #endif
121 }
122
123
124 void IMG_PixmapRGBA32::fillRect(const GEN_Rect& r, const IMG_ColorRGBA& c)
125 {
126         GEN_Rect t_bnds (0, 0, m_width, m_height);      // Bounds of this pixmap
127         GEN_Rect r_bnds (r);                                            // Area to set
128
129         // Determine visibility
130         GEN_TVisibility v = t_bnds.getVisibility(r_bnds);
131         if (v == GEN_kNotVisible) return;
132         if (v == GEN_kPartiallyVisible) {
133                 // Clip the destination rectangle to the bounds of this pixmap
134                 t_bnds.clip(r_bnds);
135                 if (r_bnds.isEmpty()) {
136                         return;
137                 }
138         }
139
140         // Set the pixels in the destination rectangle
141         TPixelRGBA32 pixel = getPixelValue(c);
142         for (GEN_TInt32 y = r.m_t; y < r.m_b; y++) {
143                 // Park pixel pointer at the start pixels
144                 TPixelPtr desPtr = getPixelPtr(r_bnds.m_l, y);
145                 for (GEN_TInt32 x = r.m_l; x < r.m_r; x++) {
146                         *(desPtr++) = pixel;
147                 }
148         }
149 }
150
151
152 void IMG_PixmapRGBA32::setPixmap(const IMG_PixmapRGBA32& src, const GEN_Rect& srcBnds, const GEN_Rect& destBnds)
153 {
154         GEN_Rect i_bnds (srcBnds);                                      // Bounds of input pixmap
155         GEN_Rect t_bnds (0, 0, m_width, m_height);      // Bounds of this pixmap
156         GEN_Rect p_bnds (destBnds);                                     // Bounds of the paste area
157         
158         // The next check could be removed if the caller is made responsible for handing us non-empty rectangles
159         if (i_bnds.isEmpty()) {
160                 // Nothing to do
161                 return;
162         }
163
164         // Determine visibility of the paste area
165         GEN_TVisibility v = t_bnds.getVisibility(p_bnds);
166         if (v == GEN_kNotVisible) return;
167         if (v == GEN_kPartiallyVisible) {
168                 // Clipping is needed
169                 if (p_bnds.m_l < 0) {
170                         i_bnds.m_l += -p_bnds.m_l;
171                         p_bnds.m_l = 0;
172                 }
173                 if (p_bnds.m_t < 0) {
174                         i_bnds.m_t += -p_bnds.m_t;
175                         p_bnds.m_t = 0;
176                 }
177                 GEN_TInt32 d = t_bnds.getWidth();
178                 if (p_bnds.m_r > d) {
179                         i_bnds.m_r -= d - p_bnds.m_r;
180                         p_bnds.m_r = d;
181                 }
182                 d = t_bnds.getHeight();
183                 if (p_bnds.m_b > d) {
184                         i_bnds.m_b -= d - p_bnds.m_b;
185                         p_bnds.m_b = d;
186                 }
187         }
188
189         // Iterate through the rows
190         for (GEN_TInt32 r = 0; r < p_bnds.getHeight(); r++) {
191                 // Park pixel pointers at the start pixels
192                 TPixelPtr srcPtr = src.getPixelPtr(i_bnds.m_l, i_bnds.m_t + r);
193                 TPixelPtr desPtr = getPixelPtr(p_bnds.m_l, p_bnds.m_t + r);
194                 // Iterate through the columns
195                 for (int c = 0; c < p_bnds.getWidth(); c++) {
196                         *(desPtr++) = *(srcPtr++);
197                 }
198         }
199 }
200
201
202 void IMG_PixmapRGBA32::blendPixmap(const IMG_PixmapRGBA32& src, const GEN_Rect& srcBnds, const GEN_Rect& destBnds)
203 {
204         GEN_Rect i_bnds (srcBnds);                                      // Bounds of input pixmap
205         GEN_Rect t_bnds (0, 0, m_width, m_height);      // Bounds of this pixmap
206         GEN_Rect p_bnds (destBnds);                                     // Bounds of the paste area
207         
208         // The next check could be removed if the caller is made responsible for handing us non-empty rectangles
209         if (i_bnds.isEmpty()) {
210                 // Nothing to do
211                 return;
212         }
213
214         // Determine visibility of the paste area
215         GEN_TVisibility v = t_bnds.getVisibility(p_bnds);
216         if (v == GEN_kNotVisible) return;
217         if (v == GEN_kPartiallyVisible) {
218                 // Clipping is needed
219                 if (p_bnds.m_l < 0) {
220                         i_bnds.m_l += -p_bnds.m_l;
221                         p_bnds.m_l = 0;
222                 }
223                 if (p_bnds.m_t < 0) {
224                         i_bnds.m_t += -p_bnds.m_t;
225                         p_bnds.m_t = 0;
226                 }
227                 GEN_TInt32 d = t_bnds.getWidth();
228                 if (p_bnds.m_r > d) {
229                         i_bnds.m_r -= p_bnds.m_r - d;
230                         p_bnds.m_r = d;
231                 }
232                 d = t_bnds.getHeight();
233                 if (p_bnds.m_b > d) {
234                         i_bnds.m_b -= p_bnds.m_b - d;
235                         p_bnds.m_b = d;
236                 }
237         }
238
239         IMG_ColorRGBA srcColor;
240         IMG_ColorRGBA desColor;
241
242         // Iterate through the rows
243         for (int r = 0; r < p_bnds.getHeight(); r++) {
244                 // Park pixel pointers at the start pixels
245                 TPixelPtr srcPtr = src.getPixelPtr(i_bnds.m_l, i_bnds.m_t + r);
246                 TPixelPtr desPtr = getPixelPtr(p_bnds.m_l, p_bnds.m_t + r);
247                 // Iterate through the columns
248                 for (int c = 0; c < p_bnds.getWidth(); c++) {
249                         // Retrieve colors from source and destination pixmaps
250                         getColor(*srcPtr, srcColor);
251                         getColor(*desPtr, desColor);
252                         // Blend the colors
253                         desColor.blendColor(srcColor);
254                         // Write color back to destination pixmap
255                         *desPtr = getPixelValue(desColor);
256                         srcPtr++;
257                         desPtr++;
258                 }
259         }
260 }