logo

Inkscape

  • Main Page
  • Related Pages
  • Namespaces
  • Classes
  • Files
  • File List
  • File Members

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 :