nr-pixblock.cpp
Go to the documentation of this file.
00001 #define __NR_PIXBLOCK_C__ 00002 00013 #include <cstring> 00014 #include <string> 00015 #include <string.h> 00016 #include <glib/gmem.h> 00017 #include "nr-pixblock.h" 00018 00020 #define NR_TINY_MAX sizeof (unsigned char *) 00021 00034 void 00035 nr_pixblock_setup_fast (NRPixBlock *pb, NR_PIXBLOCK_MODE mode, int x0, int y0, int x1, int y1, bool clear) 00036 { 00037 int w, h, bpp; 00038 size_t size; 00039 00040 w = x1 - x0; 00041 h = y1 - y0; 00042 bpp = (mode == NR_PIXBLOCK_MODE_A8) ? 1 : (mode == NR_PIXBLOCK_MODE_R8G8B8) ? 3 : 4; 00043 00044 size = bpp * w * h; 00045 00046 if (size <= NR_TINY_MAX) { 00047 pb->size = NR_PIXBLOCK_SIZE_TINY; 00048 if (clear) memset (pb->data.p, 0x0, size); 00049 } else if (size <= 4096) { 00050 pb->size = NR_PIXBLOCK_SIZE_4K; 00051 pb->data.px = nr_pixelstore_4K_new (clear, 0x0); 00052 } else if (size <= 16384) { 00053 pb->size = NR_PIXBLOCK_SIZE_16K; 00054 pb->data.px = nr_pixelstore_16K_new (clear, 0x0); 00055 } else if (size <= 65536) { 00056 pb->size = NR_PIXBLOCK_SIZE_64K; 00057 pb->data.px = nr_pixelstore_64K_new (clear, 0x0); 00058 } else if (size <= 262144) { 00059 pb->size = NR_PIXBLOCK_SIZE_256K; 00060 pb->data.px = nr_pixelstore_256K_new (clear, 0x0); 00061 } else if (size <= 1048576) { 00062 pb->size = NR_PIXBLOCK_SIZE_1M; 00063 pb->data.px = nr_pixelstore_1M_new (clear, 0x0); 00064 } else { 00065 pb->size = NR_PIXBLOCK_SIZE_BIG; 00066 pb->data.px = NULL; 00067 if (size > 100000000) { // Don't even try to allocate more than 100Mb (5000x5000 RGBA 00068 // pixels). It'll just bog the system down even if successful. FIXME: 00069 // Can anyone suggest something better than the magic number? 00070 g_warning ("%lu bytes requested for pixel buffer, I won't try to allocate that.", (long unsigned) size); 00071 return; 00072 } 00073 pb->data.px = g_try_new (unsigned char, size); 00074 if (pb->data.px == NULL) { // memory allocation failed 00075 g_warning ("Could not allocate %lu bytes for pixel buffer!", (long unsigned) size); 00076 return; 00077 } 00078 if (clear) memset (pb->data.px, 0x0, size); 00079 } 00080 00081 pb->mode = mode; 00082 pb->empty = 1; 00083 pb->visible_area.x0 = pb->area.x0 = x0; 00084 pb->visible_area.y0 = pb->area.y0 = y0; 00085 pb->visible_area.x1 = pb->area.x1 = x1; 00086 pb->visible_area.y1 = pb->area.y1 = y1; 00087 pb->rs = bpp * w; 00088 } 00089 00100 void 00101 nr_pixblock_setup (NRPixBlock *pb, NR_PIXBLOCK_MODE mode, int x0, int y0, int x1, int y1, bool clear) 00102 { 00103 int w, h, bpp; 00104 size_t size; 00105 00106 w = x1 - x0; 00107 h = y1 - y0; 00108 bpp = (mode == NR_PIXBLOCK_MODE_A8) ? 1 : (mode == NR_PIXBLOCK_MODE_R8G8B8) ? 3 : 4; 00109 00110 size = bpp * w * h; 00111 00112 if (size <= NR_TINY_MAX) { 00113 pb->size = NR_PIXBLOCK_SIZE_TINY; 00114 if (clear) memset (pb->data.p, 0x0, size); 00115 } else { 00116 pb->size = NR_PIXBLOCK_SIZE_BIG; 00117 pb->data.px = g_new (unsigned char, size); 00118 if (clear) memset (pb->data.px, 0x0, size); 00119 } 00120 00121 pb->mode = mode; 00122 pb->empty = 1; 00123 pb->visible_area.x0 = pb->area.x0 = x0; 00124 pb->visible_area.y0 = pb->area.y0 = y0; 00125 pb->visible_area.x1 = pb->area.x1 = x1; 00126 pb->visible_area.y1 = pb->area.y1 = y1; 00127 pb->rs = bpp * w; 00128 } 00129 00139 void 00140 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) 00141 { 00142 int w, bpp; 00143 00144 w = x1 - x0; 00145 bpp = (mode == NR_PIXBLOCK_MODE_A8) ? 1 : (mode == NR_PIXBLOCK_MODE_R8G8B8) ? 3 : 4; 00146 00147 pb->size = NR_PIXBLOCK_SIZE_STATIC; 00148 pb->mode = mode; 00149 pb->empty = empty; 00150 pb->visible_area.x0 = pb->area.x0 = x0; 00151 pb->visible_area.y0 = pb->area.y0 = y0; 00152 pb->visible_area.x1 = pb->area.x1 = x1; 00153 pb->visible_area.y1 = pb->area.y1 = y1; 00154 pb->data.px = px; 00155 pb->rs = rs; 00156 00157 g_assert (pb->data.px != NULL); 00158 if (clear) { 00159 if (rs == bpp * w) { 00162 if (pb->data.px) 00163 memset (pb->data.px, 0x0, bpp * (y1 - y0) * w); 00164 } else { 00165 int y; 00166 for (y = y0; y < y1; y++) { 00167 memset (pb->data.px + (y - y0) * rs, 0x0, bpp * w); 00168 } 00169 } 00170 } 00171 } 00172 00181 void 00182 nr_pixblock_release (NRPixBlock *pb) 00183 { 00184 switch (pb->size) { 00185 case NR_PIXBLOCK_SIZE_TINY: 00186 break; 00187 case NR_PIXBLOCK_SIZE_4K: 00188 nr_pixelstore_4K_free (pb->data.px); 00189 break; 00190 case NR_PIXBLOCK_SIZE_16K: 00191 nr_pixelstore_16K_free (pb->data.px); 00192 break; 00193 case NR_PIXBLOCK_SIZE_64K: 00194 nr_pixelstore_64K_free (pb->data.px); 00195 break; 00196 case NR_PIXBLOCK_SIZE_256K: 00197 nr_pixelstore_256K_free (pb->data.px); 00198 break; 00199 case NR_PIXBLOCK_SIZE_1M: 00200 nr_pixelstore_1M_free (pb->data.px); 00201 break; 00202 case NR_PIXBLOCK_SIZE_BIG: 00203 g_free (pb->data.px); 00204 break; 00205 case NR_PIXBLOCK_SIZE_STATIC: 00206 break; 00207 default: 00208 break; 00209 } 00210 } 00211 00219 NRPixBlock * 00220 nr_pixblock_new (NR_PIXBLOCK_MODE mode, int x0, int y0, int x1, int y1, bool clear) 00221 { 00222 NRPixBlock *pb; 00223 00224 pb = g_new (NRPixBlock, 1); 00225 if (!pb) return 0; 00226 00227 nr_pixblock_setup (pb, mode, x0, y0, x1, y1, clear); 00228 if (pb->size!=NR_PIXBLOCK_SIZE_TINY && !pb->data.px) { 00229 g_free(pb); 00230 return 0; 00231 } 00232 00233 return pb; 00234 } 00235 00242 NRPixBlock * 00243 nr_pixblock_new_fast (NR_PIXBLOCK_MODE mode, int x0, int y0, int x1, int y1, bool clear) 00244 { 00245 NRPixBlock *pb; 00246 00247 pb = g_new (NRPixBlock, 1); 00248 if (!pb) return 0; 00249 00250 nr_pixblock_setup_fast (pb, mode, x0, y0, x1, y1, clear); 00251 if (pb->size!=NR_PIXBLOCK_SIZE_TINY && !pb->data.px) { 00252 g_free(pb); 00253 return 0; 00254 } 00255 00256 return pb; 00257 } 00258 00264 NRPixBlock * 00265 nr_pixblock_free (NRPixBlock *pb) 00266 { 00267 nr_pixblock_release (pb); 00268 00269 g_free (pb); 00270 00271 return NULL; 00272 } 00273 00274 /* PixelStore operations */ 00275 00276 #define NR_4K_BLOCK 32 00277 static unsigned char **nr_4K_px = NULL; 00278 static unsigned int nr_4K_len = 0; 00279 static unsigned int nr_4K_size = 0; 00280 00281 unsigned char * 00282 nr_pixelstore_4K_new (bool clear, unsigned char val) 00283 { 00284 unsigned char *px; 00285 00286 if (nr_4K_len != 0) { 00287 nr_4K_len -= 1; 00288 px = nr_4K_px[nr_4K_len]; 00289 } else { 00290 px = g_new (unsigned char, 4096); 00291 } 00292 00293 if (clear) memset (px, val, 4096); 00294 00295 return px; 00296 } 00297 00298 void 00299 nr_pixelstore_4K_free (unsigned char *px) 00300 { 00301 if (nr_4K_len == nr_4K_size) { 00302 nr_4K_size += NR_4K_BLOCK; 00303 nr_4K_px = g_renew (unsigned char *, nr_4K_px, nr_4K_size); 00304 } 00305 00306 nr_4K_px[nr_4K_len] = px; 00307 nr_4K_len += 1; 00308 } 00309 00310 #define NR_16K_BLOCK 32 00311 static unsigned char **nr_16K_px = NULL; 00312 static unsigned int nr_16K_len = 0; 00313 static unsigned int nr_16K_size = 0; 00314 00315 unsigned char * 00316 nr_pixelstore_16K_new (bool clear, unsigned char val) 00317 { 00318 unsigned char *px; 00319 00320 if (nr_16K_len != 0) { 00321 nr_16K_len -= 1; 00322 px = nr_16K_px[nr_16K_len]; 00323 } else { 00324 px = g_new (unsigned char, 16384); 00325 } 00326 00327 if (clear) memset (px, val, 16384); 00328 00329 return px; 00330 } 00331 00332 void 00333 nr_pixelstore_16K_free (unsigned char *px) 00334 { 00335 if (nr_16K_len == nr_16K_size) { 00336 nr_16K_size += NR_16K_BLOCK; 00337 nr_16K_px = g_renew (unsigned char *, nr_16K_px, nr_16K_size); 00338 } 00339 00340 nr_16K_px[nr_16K_len] = px; 00341 nr_16K_len += 1; 00342 } 00343 00344 #define NR_64K_BLOCK 32 00345 static unsigned char **nr_64K_px = NULL; 00346 static unsigned int nr_64K_len = 0; 00347 static unsigned int nr_64K_size = 0; 00348 00349 unsigned char * 00350 nr_pixelstore_64K_new (bool clear, unsigned char val) 00351 { 00352 unsigned char *px; 00353 00354 if (nr_64K_len != 0) { 00355 nr_64K_len -= 1; 00356 px = nr_64K_px[nr_64K_len]; 00357 } else { 00358 px = g_new (unsigned char, 65536); 00359 } 00360 00361 if (clear) memset (px, val, 65536); 00362 00363 return px; 00364 } 00365 00366 void 00367 nr_pixelstore_64K_free (unsigned char *px) 00368 { 00369 if (nr_64K_len == nr_64K_size) { 00370 nr_64K_size += NR_64K_BLOCK; 00371 nr_64K_px = g_renew (unsigned char *, nr_64K_px, nr_64K_size); 00372 } 00373 00374 nr_64K_px[nr_64K_len] = px; 00375 nr_64K_len += 1; 00376 } 00377 00378 #define NR_256K_BLOCK 32 00379 #define NR_256K 262144 00380 static unsigned char **nr_256K_px = NULL; 00381 static unsigned int nr_256K_len = 0; 00382 static unsigned int nr_256K_size = 0; 00383 00384 unsigned char * 00385 nr_pixelstore_256K_new (bool clear, unsigned char val) 00386 { 00387 unsigned char *px; 00388 00389 if (nr_256K_len != 0) { 00390 nr_256K_len -= 1; 00391 px = nr_256K_px[nr_256K_len]; 00392 } else { 00393 px = g_new (unsigned char, NR_256K); 00394 } 00395 00396 if (clear) memset (px, val, NR_256K); 00397 00398 return px; 00399 } 00400 00401 void 00402 nr_pixelstore_256K_free (unsigned char *px) 00403 { 00404 if (nr_256K_len == nr_256K_size) { 00405 nr_256K_size += NR_256K_BLOCK; 00406 nr_256K_px = g_renew (unsigned char *, nr_256K_px, nr_256K_size); 00407 } 00408 00409 nr_256K_px[nr_256K_len] = px; 00410 nr_256K_len += 1; 00411 } 00412 00413 #define NR_1M_BLOCK 32 00414 #define NR_1M 1048576 00415 static unsigned char **nr_1M_px = NULL; 00416 static unsigned int nr_1M_len = 0; 00417 static unsigned int nr_1M_size = 0; 00418 00419 unsigned char * 00420 nr_pixelstore_1M_new (bool clear, unsigned char val) 00421 { 00422 unsigned char *px; 00423 00424 if (nr_1M_len != 0) { 00425 nr_1M_len -= 1; 00426 px = nr_1M_px[nr_1M_len]; 00427 } else { 00428 px = g_new (unsigned char, NR_1M); 00429 } 00430 00431 if (clear) memset (px, val, NR_1M); 00432 00433 return px; 00434 } 00435 00436 void 00437 nr_pixelstore_1M_free (unsigned char *px) 00438 { 00439 if (nr_1M_len == nr_1M_size) { 00440 nr_1M_size += NR_1M_BLOCK; 00441 nr_1M_px = g_renew (unsigned char *, nr_1M_px, nr_1M_size); 00442 } 00443 00444 nr_1M_px[nr_1M_len] = px; 00445 nr_1M_len += 1; 00446 } 00447 00448 /* 00449 Local Variables: 00450 mode:c++ 00451 c-file-style:"stroustrup" 00452 c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +)) 00453 indent-tabs-mode:nil 00454 fill-column:99 00455 End: 00456 */ 00457 // vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :
