aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSebastian Geerken <devnull@localhost>2014-07-01 14:33:05 +0200
committerSebastian Geerken <devnull@localhost>2014-07-01 14:33:05 +0200
commit732d5e480bec103be3faf4d351b652d156a0de23 (patch)
treedc5e439b8789bfe1028d87497f905c948ca11842
parent8fe775ea0f01393b7691f1bffb81d30e6dce39c0 (diff)
parentd4b1ef469fa0362035e55365923916a40998dc84 (diff)
Merge with main repo.
-rw-r--r--src/cache.c2
-rw-r--r--src/dicache.c236
-rw-r--r--src/dicache.h13
-rw-r--r--src/gif.c15
-rw-r--r--src/jpeg.c1
-rw-r--r--src/png.c9
6 files changed, 116 insertions, 160 deletions
diff --git a/src/cache.c b/src/cache.c
index 6a7d2748..c4bc1f9b 100644
--- a/src/cache.c
+++ b/src/cache.c
@@ -110,7 +110,7 @@ static int Cache_entry_by_url_cmp(const void *v1, const void *v2)
}
/*
- * Initialize dicache data
+ * Initialize cache data
*/
void a_Cache_init(void)
{
diff --git a/src/dicache.c b/src/dicache.c
index 7f4cac85..a2904c32 100644
--- a/src/dicache.c
+++ b/src/dicache.c
@@ -28,15 +28,10 @@ enum {
DIC_Jpeg
};
-typedef struct {
- int valid; /* flag */
- DilloUrl *url; /* primary "Key" for this dicache entry */
- DICacheEntry *first; /* pointer to the first dicache entry in this list */
-} DICacheNode;
/*
- * List of DICacheNode. One node per URL. Each node may have several
- * versions of the same image in a linked list.
+ * List of DICacheEntry. May hold several versions of the same image,
+ * although most of the time it holds just one.
*/
static Dlist *CachedIMGs = NULL;
@@ -45,24 +40,20 @@ static uint_t dicache_size_total; /* invariant: dicache_size_total is
* of all the images in the dicache. */
/*
- * Compare two dicache nodes
+ * Compare function for image entries
*/
-static int Dicache_node_cmp(const void *v1, const void *v2)
+static int Dicache_entry_cmp(const void *v1, const void *v2)
{
- const DICacheNode *n1 = v1, *n2 = v2;
-
- return a_Url_cmp(n1->url, n2->url);
-}
-
-/*
- * Compare function for searching a node by Url
- */
-static int Dicache_node_by_url_cmp(const void *v1, const void *v2)
-{
- const DICacheNode *node = v1;
- const DilloUrl *url = v2;
-
- return a_Url_cmp(node->url, url);
+ const DICacheEntry *e1 = v1, *e2 = v2;
+
+ int st = a_Url_cmp(e1->url, e2->url);
+ if (st == 0) {
+ if (e2->version == DIC_Last)
+ st = (e1->Flags & DIF_Last ? 0 : -1);
+ else
+ st = (e1->version - e2->version);
+ }
+ return st;
}
/*
@@ -83,6 +74,8 @@ static DICacheEntry *Dicache_entry_new(void)
entry->width = 0;
entry->height = 0;
+ entry->Flags = DIF_Valid;
+ entry->SurvCleanup = 0;
entry->type = DILLO_IMG_TYPE_NOTSET;
entry->cmap = NULL;
entry->v_imgbuf = NULL;
@@ -97,41 +90,29 @@ static DICacheEntry *Dicache_entry_new(void)
entry->DecoderData = NULL;
entry->DecodedSize = 0;
- entry->next = NULL;
-
return entry;
}
/*
* Add a new entry in the dicache
- * (a single node (URL) may have several entries)
+ * (a single URL may have several entries)
*/
static DICacheEntry *Dicache_add_entry(const DilloUrl *Url)
{
- DICacheEntry *entry;
- DICacheNode *node;
+ DICacheEntry e, *entry, *last;
entry = Dicache_entry_new();
-
- if ((node = dList_find_sorted(CachedIMGs, Url, Dicache_node_by_url_cmp))) {
- /* this URL is already in CachedIMGs, add entry at the END of the list */
- DICacheEntry *ptr = node->first;
-
- node->valid = 1;
- for ( ; ptr->next; ptr = ptr->next);
- ptr->next = entry;
- entry->version = ptr->version+1;
- entry->url = node->url;
-
- } else { /* no node yet, so create one */
- DICacheNode *node = dNew(DICacheNode, 1);
-
- node->url = a_Url_dup(Url);
- entry->url = node->url;
- node->first = entry;
- node->valid = 1;
- dList_insert_sorted(CachedIMGs, node, Dicache_node_cmp);
+ e.url = (DilloUrl*)Url;
+ e.version = DIC_Last;
+ last = dList_find_sorted(CachedIMGs, &e, Dicache_entry_cmp);
+ if (last) {
+ /* URL is already in CachedIMGs, make a new version */
+ last->Flags &= ~DIF_Last;
+ entry->version = last->version + 1;
}
+ entry->url = a_Url_dup(Url);
+ entry->Flags |= DIF_Last;
+ dList_insert_sorted(CachedIMGs, entry, Dicache_entry_cmp);
return entry;
}
@@ -145,23 +126,15 @@ static DICacheEntry *Dicache_add_entry(const DilloUrl *Url)
*/
DICacheEntry *a_Dicache_get_entry(const DilloUrl *Url, int version)
{
- DICacheNode *node;
+ DICacheEntry e;
DICacheEntry *entry = NULL;
dReturn_val_if_fail(version != 0, NULL);
-
- node = dList_find_sorted(CachedIMGs, Url, Dicache_node_by_url_cmp);
- if (node) {
- if (version == DIC_Last) {
- if (node->valid) {
- entry = node->first;
- for ( ; (entry && entry->next); entry = entry->next);
- }
- } else {
- entry = node->first;
- for ( ; entry && entry->version != version; entry = entry->next) ;
- }
- }
+ e.url = (DilloUrl*)Url;
+ e.version = version;
+ entry = dList_find_sorted(CachedIMGs, &e, Dicache_entry_cmp);
+ if (entry && !(entry->Flags & DIF_Valid) && version == DIC_Last)
+ entry = NULL;
return entry;
}
@@ -170,60 +143,47 @@ DICacheEntry *a_Dicache_get_entry(const DilloUrl *Url, int version)
*/
static void Dicache_remove(const DilloUrl *Url, int version)
{
- DICacheNode *node;
- DICacheEntry *entry, *prev;
- _MSG("Dicache_remove url=%s\n", URL_STR(Url));
- node = dList_find_sorted(CachedIMGs, Url, Dicache_node_by_url_cmp);
- prev = entry = (node) ? node->first : NULL;
-
- while (entry && (entry->version != version) ) {
- prev = entry;
- entry = entry->next;
- }
+ DICacheEntry e, *entry;
- if (entry) {
- _MSG("Dicache_remove Imgbuf=%p Decoder=%p DecoderData=%p\n",
- entry->v_imgbuf, entry->Decoder, entry->DecoderData);
- /* Eliminate this dicache entry */
- dFree(entry->cmap);
- a_Bitvec_free(entry->BitVec);
- a_Imgbuf_unref(entry->v_imgbuf);
- if (entry->Decoder) {
- entry->Decoder(CA_Abort, entry->DecoderData);
- }
- dicache_size_total -= entry->TotalSize;
-
- if (node->first == entry) {
- if (!entry->next) {
- /* last entry with this URL. Remove the node as well */
- dList_remove(CachedIMGs, node);
- a_Url_free(node->url);
- dFree(node);
- } else
- node->first = entry->next;
- } else {
- prev->next = entry->next;
- }
- dFree(entry);
+ _MSG("Dicache_remove url=%s\n", URL_STR(Url));
+ e.url = (DilloUrl*)Url;
+ e.version = version;
+ entry = dList_find_sorted(CachedIMGs, &e, Dicache_entry_cmp);
+ dReturn_if (entry == NULL);
+
+ _MSG("Dicache_remove Imgbuf=%p Decoder=%p DecoderData=%p\n",
+ entry->v_imgbuf, entry->Decoder, entry->DecoderData);
+ /* Eliminate this dicache entry */
+ dList_remove(CachedIMGs, entry);
+ dicache_size_total -= entry->TotalSize;
+
+ /* entry cleanup */
+ a_Url_free(entry->url);
+ dFree(entry->cmap);
+ a_Bitvec_free(entry->BitVec);
+ a_Imgbuf_unref(entry->v_imgbuf);
+ if (entry->Decoder) {
+ entry->Decoder(CA_Abort, entry->DecoderData);
}
+ dFree(entry);
}
/*
- * Unrefs the counter of a dicache entry, and _if_ no DwImage is acessing
- * this buffer, then we call Dicache_remove() to do the job.
+ * Unrefs the counter of a dicache entry (it counts cache clients).
+ * If there're no clients and no imgbuf, remove the entry.
+ * Otherwise, let a_Dicache_cleanup() do the job later
+ * (keeping it cached meanwhile for e.g. reload, repush, back/fwd).
*/
void a_Dicache_unref(const DilloUrl *Url, int version)
{
DICacheEntry *entry;
- _MSG("a_Dicache_unref\n");
if ((entry = a_Dicache_get_entry(Url, version))) {
- _MSG(" a_Dicache_unref: RefCount=%d\n", entry->RefCount);
- _MSG(" a_Dicache_unref: ImgbufLastRef=%d\n",
+ _MSG("a_Dicache_unref: RefCount=%d State=%d ImgbufLastRef=%d\n",
+ entry->RefCount, entry->State,
entry->v_imgbuf ? a_Imgbuf_last_reference(entry->v_imgbuf) : -1);
if (entry->RefCount > 0) --entry->RefCount;
- if (entry->v_imgbuf == NULL ||
- (entry->RefCount == 0 && a_Imgbuf_last_reference(entry->v_imgbuf)))
+ if (entry->RefCount == 0 && entry->v_imgbuf == NULL)
Dicache_remove(Url, version);
}
}
@@ -248,11 +208,9 @@ DICacheEntry* a_Dicache_ref(const DilloUrl *Url, int version)
*/
void a_Dicache_invalidate_entry(const DilloUrl *Url)
{
- DICacheNode *node;
-
- node = dList_find_sorted(CachedIMGs, Url, Dicache_node_by_url_cmp);
- if (node)
- node->valid = 0;
+ DICacheEntry *entry = a_Dicache_get_entry(Url, DIC_Last);
+ if (entry)
+ entry->Flags &= ~DIF_Valid;
}
@@ -298,7 +256,7 @@ void a_Dicache_set_parms(DilloUrl *url, int version, DilloImage *Image,
/*
* Implement the set_cmap method for the Image
*/
-void a_Dicache_set_cmap(DilloUrl *url, int version, DilloImage *Image,
+void a_Dicache_set_cmap(DilloUrl *url, int version, int bg_color,
const uchar_t *cmap, uint_t num_colors,
int num_colors_max, int bg_index)
{
@@ -311,9 +269,9 @@ void a_Dicache_set_cmap(DilloUrl *url, int version, DilloImage *Image,
DicEntry->cmap = dNew0(uchar_t, 3 * num_colors_max);
memcpy(DicEntry->cmap, cmap, 3 * num_colors);
if (bg_index >= 0 && (uint_t)bg_index < num_colors) {
- DicEntry->cmap[bg_index * 3] = (Image->bg_color >> 16) & 0xff;
- DicEntry->cmap[bg_index * 3 + 1] = (Image->bg_color >> 8) & 0xff;
- DicEntry->cmap[bg_index * 3 + 2] = (Image->bg_color) & 0xff;
+ DicEntry->cmap[bg_index * 3] = (bg_color >> 16) & 0xff;
+ DicEntry->cmap[bg_index * 3 + 1] = (bg_color >> 8) & 0xff;
+ DicEntry->cmap[bg_index * 3 + 2] = (bg_color) & 0xff;
}
DicEntry->State = DIC_SetCmap;
@@ -439,6 +397,8 @@ static void *Dicache_image(int ImgType, const char *MimeType, void *Ptr,
/* Repeated image */
a_Dicache_ref(DicEntry->url, DicEntry->version);
}
+ /* Survive three cleanup passes (set to zero = old behaviour). */
+ DicEntry->SurvCleanup = 3;
*Data = DicEntry->DecoderData;
*Call = (CA_Callback_t) a_Dicache_callback;
@@ -547,50 +507,42 @@ void a_Dicache_callback(int Op, CacheClient_t *Client)
void a_Dicache_cleanup(void)
{
int i;
- DICacheNode *node;
- DICacheEntry *entry, *next;
-
- _MSG("a_Dicache_cleanup\n");
- for (i = 0; i < dList_length(CachedIMGs); ++i) {
- node = dList_nth_data(CachedIMGs, i);
- /* iterate each entry of this node */
- for (entry = node->first; entry; entry = next) {
- next = entry->next;
- if (entry->v_imgbuf &&
- a_Imgbuf_last_reference(entry->v_imgbuf)) {
- /* free this unused entry */
- _MSG("a_Dicache_cleanup: removing entry...\n");
- Dicache_remove(node->url, entry->version);
- if (!next && node != dList_nth_data(CachedIMGs, i))
- --i; /* removed node, adjust counter */
- }
+ DICacheEntry *entry;
+
+ for (i = 0; (entry = dList_nth_data(CachedIMGs, i)); ++i) {
+ _MSG(" SurvCleanup = %d\n", entry->SurvCleanup);
+ if (entry->RefCount == 0 &&
+ (!entry->v_imgbuf || a_Imgbuf_last_reference(entry->v_imgbuf))) {
+ if (--entry->SurvCleanup >= 0)
+ continue; /* keep the entry one more pass */
+
+ /* free this unused entry */
+ Dicache_remove(entry->url, entry->version);
+ --i; /* adjust counter */
}
}
+ MSG("a_Dicache_cleanup: length = %d\n", dList_length(CachedIMGs));
}
/* ------------------------------------------------------------------------- */
/*
* Deallocate memory used by dicache module
- * (Call this one at exit time)
+ * (Call this one at exit time, with no cache clients queued)
*/
void a_Dicache_freeall(void)
{
- DICacheNode *node;
DICacheEntry *entry;
- /* Remove every dicache node and its entries */
- while ((node = dList_nth_data(CachedIMGs, 0))) {
- while ((entry = node->first)) {
- node->first = entry->next;
- dFree(entry->cmap);
- a_Bitvec_free(entry->BitVec);
- a_Imgbuf_unref(entry->v_imgbuf);
- dicache_size_total -= entry->TotalSize;
- }
- dList_remove_fast(CachedIMGs, node);
- a_Url_free(node->url);
- dFree(node);
+ /* Remove all the dicache entries */
+ while ((entry = dList_nth_data(CachedIMGs, dList_length(CachedIMGs)-1))) {
+ dList_remove_fast(CachedIMGs, entry);
+ a_Url_free(entry->url);
+ dFree(entry->cmap);
+ a_Bitvec_free(entry->BitVec);
+ a_Imgbuf_unref(entry->v_imgbuf);
+ dicache_size_total -= entry->TotalSize;
+ dFree(entry);
}
dList_free(CachedIMGs);
}
diff --git a/src/dicache.h b/src/dicache.h
index df8a8b89..7d5ef6ee 100644
--- a/src/dicache.h
+++ b/src/dicache.h
@@ -12,6 +12,9 @@ extern "C" {
/* Symbolic name to request the last version of an image */
#define DIC_Last -1
+/* Flags: Last version, Valid entry */
+#define DIF_Last 1
+#define DIF_Valid 2
/* These will reflect the entry's "state" */
@@ -26,8 +29,10 @@ typedef enum {
typedef struct DICacheEntry {
DilloUrl *url; /* Image URL for this entry */
- uint_t width, height; /* As taken from image data */
DilloImgType type; /* Image type */
+ uint_t width, height; /* As taken from image data */
+ short Flags; /* See Flags */
+ short SurvCleanup; /* Cleanup-pass survival for unused images */
uchar_t *cmap; /* Color map */
void *v_imgbuf; /* Void pointer to an Imgbuf object */
uint_t TotalSize; /* Amount of memory the image takes up */
@@ -38,11 +43,9 @@ typedef struct DICacheEntry {
int version; /* Version number, used for different
versions of the same URL image */
+ uint_t DecodedSize; /* Size of already decoded data */
CA_Callback_t Decoder; /* Client function */
void *DecoderData; /* Client function data */
- uint_t DecodedSize; /* Size of already decoded data */
-
- struct DICacheEntry *next; /* Link to the next "newer" version */
} DICacheEntry;
@@ -61,7 +64,7 @@ void a_Dicache_callback(int Op, CacheClient_t *Client);
void a_Dicache_set_parms(DilloUrl *url, int version, DilloImage *Image,
uint_t width, uint_t height, DilloImgType type,
double gamma);
-void a_Dicache_set_cmap(DilloUrl *url, int version, DilloImage *Image,
+void a_Dicache_set_cmap(DilloUrl *url, int version, int bg_color,
const uchar_t *cmap, uint_t num_colors,
int num_colors_max, int bg_index);
void a_Dicache_new_scan(const DilloUrl *url, int version);
diff --git a/src/gif.c b/src/gif.c
index 7ce1e110..34424d33 100644
--- a/src/gif.c
+++ b/src/gif.c
@@ -103,9 +103,7 @@ typedef struct {
size_t ColorMap_ofs;
uint_t ColorResolution;
uint_t NumColors;
-#if 0
- int Background;
-#endif
+ int Background;
uint_t spill_line_index;
#if 0
uint_t AspectRatio; /* AspectRatio (not used) */
@@ -165,9 +163,7 @@ void *a_Gif_new(DilloImage *Image, DilloUrl *url, int version)
gif->state = 0;
gif->Start_Ofs = 0;
gif->linebuf = NULL;
-#if 0
- gif->Background = -1;
-#endif
+ gif->Background = Image->bg_color;
gif->transparent = -1;
gif->num_spill_lines_max = 0;
gif->spill_lines = NULL;
@@ -222,7 +218,7 @@ static void Gif_write(DilloGif *gif, void *Buf, uint_t BufSize)
int bufsize, bytes_consumed;
/* Sanity checks */
- if (!Buf || !gif->Image || BufSize == 0)
+ if (!Buf || BufSize == 0)
return;
buf = ((uchar_t *) Buf) + gif->Start_Ofs;
@@ -820,6 +816,7 @@ static size_t Gif_do_img_desc(DilloGif *gif, void *Buf,
a_Dicache_set_parms(gif->url, gif->version, gif->Image,
gif->Width, gif->Height, DILLO_IMG_TYPE_INDEXED,
1 / 2.2);
+ gif->Image = NULL; /* safeguard: hereafter it may be freed by its owner */
Flags = buf[8];
@@ -850,8 +847,8 @@ static size_t Gif_do_img_desc(DilloGif *gif, void *Buf,
gif->spill_line_index = 0;
gif->linebuf = dMalloc(gif->Width);
gif->state = 3; /*Process the lzw data next */
- if (gif->Image && gif->ColorMap_ofs) {
- a_Dicache_set_cmap(gif->url, gif->version, gif->Image,
+ if (gif->ColorMap_ofs) {
+ a_Dicache_set_cmap(gif->url, gif->version, gif->Background,
(uchar_t *) Buf + gif->ColorMap_ofs,
gif->NumColors, 256, gif->transparent);
}
diff --git a/src/jpeg.c b/src/jpeg.c
index 625808fb..5652aa56 100644
--- a/src/jpeg.c
+++ b/src/jpeg.c
@@ -304,6 +304,7 @@ static void Jpeg_write(DilloJpeg *jpeg, void *Buf, uint_t BufSize)
(uint_t)jpeg->cinfo.image_width,
(uint_t)jpeg->cinfo.image_height,
type, 1 / 2.2);
+ jpeg->Image = NULL; /* safeguard: may be freed by its owner later */
/* decompression step 4 (see libjpeg.doc) */
jpeg->state = DILLO_JPEG_STARTING;
diff --git a/src/png.c b/src/png.c
index 4f5da1c2..093e2600 100644
--- a/src/png.c
+++ b/src/png.c
@@ -62,6 +62,7 @@ typedef struct {
DilloImage *Image; /* Image meta data */
DilloUrl *url; /* Primary Key for the dicache */
int version; /* Secondary Key for the dicache */
+ int bgcolor; /* Parent widget background color */
png_uint_32 width; /* png image width */
png_uint_32 height; /* png image height */
@@ -204,6 +205,7 @@ Png_datainfo_callback(png_structp png_ptr, png_infop info_ptr)
a_Dicache_set_parms(png->url, png->version, png->Image,
(uint_t)png->width, (uint_t)png->height,
DILLO_IMG_TYPE_RGB, file_gamma);
+ png->Image = NULL; /* safeguard: hereafter it may be freed by its owner */
}
static void
@@ -244,9 +246,9 @@ static void
/* TODO: maybe change prefs.bg_color to `a_Dw_widget_get_bg_color`,
* when background colors are correctly implementated */
- bg_blue = (png->Image->bg_color) & 0xFF;
- bg_green = (png->Image->bg_color>>8) & 0xFF;
- bg_red = (png->Image->bg_color>>16) & 0xFF;
+ bg_blue = (png->bgcolor) & 0xFF;
+ bg_green = (png->bgcolor>>8) & 0xFF;
+ bg_red = (png->bgcolor>>16) & 0xFF;
for (i = 0; i < png->width; i++) {
a = *(data+3);
@@ -433,6 +435,7 @@ void *a_Png_new(DilloImage *Image, DilloUrl *url, int version)
png->Image = Image;
png->url = url;
png->version = version;
+ png->bgcolor = Image->bg_color;
png->error = 0;
png->ipbuf = NULL;
png->ipbufstart = 0;