diff options
author | Sebastian Geerken <devnull@localhost> | 2014-07-01 14:33:05 +0200 |
---|---|---|
committer | Sebastian Geerken <devnull@localhost> | 2014-07-01 14:33:05 +0200 |
commit | 732d5e480bec103be3faf4d351b652d156a0de23 (patch) | |
tree | dc5e439b8789bfe1028d87497f905c948ca11842 | |
parent | 8fe775ea0f01393b7691f1bffb81d30e6dce39c0 (diff) | |
parent | d4b1ef469fa0362035e55365923916a40998dc84 (diff) |
Merge with main repo.
-rw-r--r-- | src/cache.c | 2 | ||||
-rw-r--r-- | src/dicache.c | 236 | ||||
-rw-r--r-- | src/dicache.h | 13 | ||||
-rw-r--r-- | src/gif.c | 15 | ||||
-rw-r--r-- | src/jpeg.c | 1 | ||||
-rw-r--r-- | src/png.c | 9 |
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); @@ -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); } @@ -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; @@ -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; |