/* exported interface documented in image_cache.h */ nserror image_cache_add(struct content *content, struct bitmap *bitmap, image_cache_convert_fn *convert) { struct image_cache_entry_s *centry; /* bump the cache age by a ms to ensure multiple items are not * added at exactly the same time */ image_cache->current_age++; centry = image_cache__find(content); if (centry == NULL) { /* new cache entry, content not previously added */ centry = calloc(1, sizeof(struct image_cache_entry_s)); if (centry == NULL) { return NSERROR_NOMEM; } image_cache__link(centry); centry->content = content; centry->bitmap_size = content->width * content->height * 4; } LOG(("centry %p, content %p, bitmap %p", centry, content, bitmap)); centry->convert = convert; /* set bitmap entry if one is passed, free extant one if present */ if (bitmap != NULL) { if (centry->bitmap != NULL) { bitmap_destroy(centry->bitmap); } else { image_cache_stats_bitmap_add(centry); } centry->bitmap = bitmap; } else { /* no bitmap, check to see if we should speculatively convert */ if ((centry->convert != NULL) && (image_cache_speculate(content) == true)) { centry->bitmap = centry->convert(centry->content); if (centry->bitmap != NULL) { image_cache_stats_bitmap_add(centry); } else { image_cache->fail_count++; } } } return NSERROR_OK; }
/** * info_callback -- PNG header has been completely received, prepare to process * image data */ static void info_callback(png_structp png_s, png_infop info) { int interlace; png_uint_32 width, height; nspng_content *png_c = png_get_progressive_ptr(png_s); width = png_get_image_width(png_s, info); height = png_get_image_height(png_s, info); interlace = png_get_interlace_type(png_s, info); png_c->base.width = width; png_c->base.height = height; png_c->base.size += width * height * 4; /* see if progressive-conversion should continue */ if (image_cache_speculate((struct content *)png_c) == false) { longjmp(png_jmpbuf(png_s), CBERR_NOPRE); } /* Claim the required memory for the converted PNG */ png_c->bitmap = bitmap_create(width, height, BITMAP_NEW); if (png_c->bitmap == NULL) { /* Failed to create bitmap skip pre-conversion */ longjmp(png_jmpbuf(png_s), CBERR_NOPRE); } png_c->rowstride = bitmap_get_rowstride(png_c->bitmap); png_c->bpp = bitmap_get_bpp(png_c->bitmap); nspng_setup_transforms(png_s, info); png_c->rowbytes = png_get_rowbytes(png_s, info); png_c->interlace = (interlace == PNG_INTERLACE_ADAM7); LOG(("size %li * %li, rowbytes %zu", (unsigned long)width, (unsigned long)height, png_c->rowbytes)); }