Code

moving trunk for module inkscape
[inkscape.git] / src / libnr / nr-pixblock.cpp
1 #define __NR_PIXBLOCK_C__
3 /** \file
4  * \brief Allocation/Setup of NRPixBlock objects. Pixel store functions.
5  *
6  * Authors:
7  *   (C) 1999-2002 Lauris Kaplinski <lauris@kaplinski.com>
8  *
9  * This code is in the Public Domain
10  */
12 #include "nr-pixblock.h"
14 /// Size of buffer that needs no allocation (default 4).
15 #define NR_TINY_MAX sizeof (unsigned char *)
17 /**
18  * Pixbuf initialisation using homegrown memory handling ("pixelstore").
19  *
20  * Pixbuf sizes are differentiated into tiny, <4K, <16K, <64K, and more,
21  * with each type having its own method of memory handling. After allocating
22  * memory, the buffer is cleared if the clear flag is set. Intended to
23  * reduce memory fragmentation.
24  * \param pb Pointer to the pixbuf struct.
25  * \param mode Indicates grayscale/RGB/RGBA.
26  * \param clear True if buffer should be cleared.
27  * \pre x1>=x0 && y1>=y0 && pb!=NULL
28  */
29 void
30 nr_pixblock_setup_fast (NRPixBlock *pb, NR_PIXBLOCK_MODE mode, int x0, int y0, int x1, int y1, bool clear)
31 {
32         int w, h, bpp;
33         size_t size;
35         w = x1 - x0;
36         h = y1 - y0;
37         bpp = (mode == NR_PIXBLOCK_MODE_A8) ? 1 : (mode == NR_PIXBLOCK_MODE_R8G8B8) ? 3 : 4;
39         size = bpp * w * h;
41         if (size <= NR_TINY_MAX) {
42                 pb->size = NR_PIXBLOCK_SIZE_TINY;
43                 if (clear) memset (pb->data.p, 0x0, size);
44         } else if (size <= 4096) {
45                 pb->size = NR_PIXBLOCK_SIZE_4K;
46                 pb->data.px = nr_pixelstore_4K_new (clear, 0x0);
47         } else if (size <= 16384) {
48                 pb->size = NR_PIXBLOCK_SIZE_16K;
49                 pb->data.px = nr_pixelstore_16K_new (clear, 0x0);
50         } else if (size <= 65536) {
51                 pb->size = NR_PIXBLOCK_SIZE_64K;
52                 pb->data.px = nr_pixelstore_64K_new (clear, 0x0);
53         } else if (size <= 262144) {
54                 pb->size = NR_PIXBLOCK_SIZE_256K;
55                 pb->data.px = nr_pixelstore_256K_new (clear, 0x0);
56         } else if (size <= 1048576) {
57                 pb->size = NR_PIXBLOCK_SIZE_1M;
58                 pb->data.px = nr_pixelstore_1M_new (clear, 0x0);
59         } else {
60                 pb->size = NR_PIXBLOCK_SIZE_BIG;
61                 pb->data.px = nr_new (unsigned char, size);
62                 if (clear) memset (pb->data.px, 0x0, size);
63         }
65         pb->mode = mode;
66         pb->empty = 1;
67         pb->area.x0 = x0;
68         pb->area.y0 = y0;
69         pb->area.x1 = x1;
70         pb->area.y1 = y1;
71         pb->rs = bpp * w;
72 }
74 /**
75  * Pixbuf initialisation using nr_new.
76  *
77  * After allocating memory, the buffer is cleared if the clear flag is set.
78  * \param pb Pointer to the pixbuf struct.
79  * \param mode Indicates grayscale/RGB/RGBA.
80  * \param clear True if buffer should be cleared.
81  * \pre x1>=x0 && y1>=y0 && pb!=NULL
82  */
83 void
84 nr_pixblock_setup (NRPixBlock *pb, NR_PIXBLOCK_MODE mode, int x0, int y0, int x1, int y1, bool clear)
85 {
86         int w, h, bpp;
87         size_t size;
89         w = x1 - x0;
90         h = y1 - y0;
91         bpp = (mode == NR_PIXBLOCK_MODE_A8) ? 1 : (mode == NR_PIXBLOCK_MODE_R8G8B8) ? 3 : 4;
93         size = bpp * w * h;
95         if (size <= NR_TINY_MAX) {
96                 pb->size = NR_PIXBLOCK_SIZE_TINY;
97                 if (clear) memset (pb->data.p, 0x0, size);
98         } else {
99                 pb->size = NR_PIXBLOCK_SIZE_BIG;
100                 pb->data.px = nr_new (unsigned char, size);
101                 if (clear) memset (pb->data.px, 0x0, size);
102         }
104         pb->mode = mode;
105         pb->empty = 1;
106         pb->area.x0 = x0;
107         pb->area.y0 = y0;
108         pb->area.x1 = x1;
109         pb->area.y1 = y1;
110         pb->rs = bpp * w;
113 /**
114  * Pixbuf initialisation with preset values.
115  *
116  * After copying all parameters into the NRPixBlock struct, the pixel buffer is cleared if the clear flag is set.
117  * \param pb Pointer to the pixbuf struct.
118  * \param mode Indicates grayscale/RGB/RGBA.
119  * \param clear True if buffer should be cleared.
120  * \pre x1>=x0 && y1>=y0 && pb!=NULL
121  */
122 void
123 nr_pixblock_setup_extern (NRPixBlock *pb, NR_PIXBLOCK_MODE mode, int x0, int y0, int x1, int y1, unsigned char *px, int rs, bool empty, bool clear)
125         int w, bpp;
127         w = x1 - x0;
128         bpp = (mode == NR_PIXBLOCK_MODE_A8) ? 1 : (mode == NR_PIXBLOCK_MODE_R8G8B8) ? 3 : 4;
130         pb->size = NR_PIXBLOCK_SIZE_STATIC; 
131         pb->mode = mode;
132         pb->empty = empty;
133         pb->area.x0 = x0;
134         pb->area.y0 = y0;
135         pb->area.x1 = x1;
136         pb->area.y1 = y1;
137         pb->data.px = px;
138         pb->rs = rs;
140         g_assert (pb->data.px != NULL);
141         if (clear) {
142                 if (rs == bpp * w) {
143                         /// \todo How do you recognise if 
144                         /// px was an uncleared tiny buffer? 
145                         if (pb->data.px) 
146                                 memset (pb->data.px, 0x0, bpp * (y1 - y0) * w);
147                 } else {
148                         int y;
149                         for (y = y0; y < y1; y++) {
150                                 memset (pb->data.px + (y - y0) * rs, 0x0, bpp * w);
151                         }
152                 }
153         }
156 /**
157  * Frees memory taken by pixel data in NRPixBlock.
158  * \param pb Pointer to pixblock.
159  * \pre pb and pb->data.px point to valid addresses.
160  *
161  * According to pb->size, one of the functions for freeing the pixelstore
162  * is called. May be called regardless of how pixbuf was set up.
163  */
164 void
165 nr_pixblock_release (NRPixBlock *pb)
167         switch (pb->size) {
168         case NR_PIXBLOCK_SIZE_TINY:
169                 break;
170         case NR_PIXBLOCK_SIZE_4K:
171                 nr_pixelstore_4K_free (pb->data.px);
172                 break;
173         case NR_PIXBLOCK_SIZE_16K:
174                 nr_pixelstore_16K_free (pb->data.px);
175                 break;
176         case NR_PIXBLOCK_SIZE_64K:
177                 nr_pixelstore_64K_free (pb->data.px);
178                 break;
179         case NR_PIXBLOCK_SIZE_256K:
180                 nr_pixelstore_256K_free (pb->data.px);
181                 break;
182         case NR_PIXBLOCK_SIZE_1M:
183                 nr_pixelstore_1M_free (pb->data.px);
184                 break;
185         case NR_PIXBLOCK_SIZE_BIG:
186                 nr_free (pb->data.px);
187                 break;
188         case NR_PIXBLOCK_SIZE_STATIC:
189                 break;
190         default:
191                 break;
192         }
195 /**
196  * Allocates NRPixBlock and sets it up.
197  *
198  * \return Pointer to fresh pixblock.
199  * Calls nr_new() and nr_pixblock_setup().
200  */
201 NRPixBlock *
202 nr_pixblock_new (NR_PIXBLOCK_MODE mode, int x0, int y0, int x1, int y1, bool clear)
204         NRPixBlock *pb;
206         pb = nr_new (NRPixBlock, 1);
208         nr_pixblock_setup (pb, mode, x0, y0, x1, y1, clear);
210         return pb;
213 /**
214  * Frees all memory taken by pixblock.
215  *
216  * \return NULL
217  */
218 NRPixBlock *
219 nr_pixblock_free (NRPixBlock *pb)
221         nr_pixblock_release (pb);
223         nr_free (pb);
225         return NULL;
228 /* PixelStore operations */
230 #define NR_4K_BLOCK 32
231 static unsigned char **nr_4K_px = NULL;
232 static unsigned int nr_4K_len = 0;
233 static unsigned int nr_4K_size = 0;
235 unsigned char *
236 nr_pixelstore_4K_new (bool clear, unsigned char val)
238         unsigned char *px;
240         if (nr_4K_len != 0) {
241                 nr_4K_len -= 1;
242                 px = nr_4K_px[nr_4K_len];
243         } else {
244                 px = nr_new (unsigned char, 4096);
245         }
246         
247         if (clear) memset (px, val, 4096);
249         return px;
252 void
253 nr_pixelstore_4K_free (unsigned char *px)
255         if (nr_4K_len == nr_4K_size) {
256                 nr_4K_size += NR_4K_BLOCK;
257                 nr_4K_px = nr_renew (nr_4K_px, unsigned char *, nr_4K_size);
258         }
260         nr_4K_px[nr_4K_len] = px;
261         nr_4K_len += 1;
264 #define NR_16K_BLOCK 32
265 static unsigned char **nr_16K_px = NULL;
266 static unsigned int nr_16K_len = 0;
267 static unsigned int nr_16K_size = 0;
269 unsigned char *
270 nr_pixelstore_16K_new (bool clear, unsigned char val)
272         unsigned char *px;
274         if (nr_16K_len != 0) {
275                 nr_16K_len -= 1;
276                 px = nr_16K_px[nr_16K_len];
277         } else {
278                 px = nr_new (unsigned char, 16384);
279         }
280         
281         if (clear) memset (px, val, 16384);
283         return px;
286 void
287 nr_pixelstore_16K_free (unsigned char *px)
289         if (nr_16K_len == nr_16K_size) {
290                 nr_16K_size += NR_16K_BLOCK;
291                 nr_16K_px = nr_renew (nr_16K_px, unsigned char *, nr_16K_size);
292         }
294         nr_16K_px[nr_16K_len] = px;
295         nr_16K_len += 1;
298 #define NR_64K_BLOCK 32
299 static unsigned char **nr_64K_px = NULL;
300 static unsigned int nr_64K_len = 0;
301 static unsigned int nr_64K_size = 0;
303 unsigned char *
304 nr_pixelstore_64K_new (bool clear, unsigned char val)
306         unsigned char *px;
308         if (nr_64K_len != 0) {
309                 nr_64K_len -= 1;
310                 px = nr_64K_px[nr_64K_len];
311         } else {
312                 px = nr_new (unsigned char, 65536);
313         }
315         if (clear) memset (px, val, 65536);
317         return px;
320 void
321 nr_pixelstore_64K_free (unsigned char *px)
323         if (nr_64K_len == nr_64K_size) {
324                 nr_64K_size += NR_64K_BLOCK;
325                 nr_64K_px = nr_renew (nr_64K_px, unsigned char *, nr_64K_size);
326         }
328         nr_64K_px[nr_64K_len] = px;
329         nr_64K_len += 1;
332 #define NR_256K_BLOCK 32
333 #define NR_256K 262144
334 static unsigned char **nr_256K_px = NULL;
335 static unsigned int nr_256K_len = 0;
336 static unsigned int nr_256K_size = 0;
338 unsigned char *
339 nr_pixelstore_256K_new (bool clear, unsigned char val)
341         unsigned char *px;
343         if (nr_256K_len != 0) {
344                 nr_256K_len -= 1;
345                 px = nr_256K_px[nr_256K_len];
346         } else {
347            px = nr_new (unsigned char, NR_256K);
348         }
350         if (clear) memset (px, val, NR_256K);
352         return px;
355 void
356 nr_pixelstore_256K_free (unsigned char *px)
358         if (nr_256K_len == nr_256K_size) {
359                 nr_256K_size += NR_256K_BLOCK;
360                 nr_256K_px = nr_renew (nr_256K_px, unsigned char *, nr_256K_size);
361         }
363         nr_256K_px[nr_256K_len] = px;
364         nr_256K_len += 1;
367 #define NR_1M_BLOCK 32
368 #define NR_1M 1048576
369 static unsigned char **nr_1M_px = NULL;
370 static unsigned int nr_1M_len = 0;
371 static unsigned int nr_1M_size = 0;
373 unsigned char *
374 nr_pixelstore_1M_new (bool clear, unsigned char val)
376         unsigned char *px;
378         if (nr_1M_len != 0) {
379                 nr_1M_len -= 1;
380                 px = nr_1M_px[nr_1M_len];
381         } else {
382            px = nr_new (unsigned char, NR_1M);
383         }
385         if (clear) memset (px, val, NR_1M);
387         return px;
390 void
391 nr_pixelstore_1M_free (unsigned char *px)
393         if (nr_1M_len == nr_1M_size) {
394                 nr_1M_size += NR_1M_BLOCK;
395                 nr_1M_px = nr_renew (nr_1M_px, unsigned char *, nr_1M_size);
396         }
398         nr_1M_px[nr_1M_len] = px;
399         nr_1M_len += 1;
402 /*
403   Local Variables:
404   mode:c++
405   c-file-style:"stroustrup"
406   c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
407   indent-tabs-mode:nil
408   fill-column:99
409   End:
410 */
411 // vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :