Bug Summary

File:content/handlers/image/image_cache.c
Warning:line 449, column 3
Use of memory after it is freed

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-pc-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name image_cache.c -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -pic-is-pie -mframe-pointer=none -fmath-errno -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/var/lib/jenkins/workspace/scan-build-netsurf -resource-dir /usr/lib/llvm-14/lib/clang/14.0.6 -I . -I include -I build/Linux-framebuffer -I frontends -I content/handlers -D WITH_JPEG -U WITH_PDF_EXPORT -D LIBICONV_PLUG -I /var/lib/jenkins/artifacts-x86_64-linux-gnu/include -I /var/lib/jenkins/artifacts-x86_64-linux-gnu/include -I /var/lib/jenkins/artifacts-x86_64-linux-gnu/include -I /usr/include/x86_64-linux-gnu -D WITH_CURL -D WITH_OPENSSL -I /var/lib/jenkins/artifacts-x86_64-linux-gnu/include -D UTF8PROC_EXPORTS -D WITH_UTF8PROC -D WITH_WEBP -I /usr/include/libpng16 -D WITH_PNG -I /var/lib/jenkins/artifacts-x86_64-linux-gnu/include/ -D WITH_BMP -I /var/lib/jenkins/artifacts-x86_64-linux-gnu/include -D WITH_GIF -I /var/lib/jenkins/artifacts-x86_64-linux-gnu/include -D WITH_NS_SVG -I /var/lib/jenkins/artifacts-x86_64-linux-gnu/include -D WITH_NSSPRITE -I /var/lib/jenkins/artifacts-x86_64-linux-gnu/include -D WITH_NSPSL -I /var/lib/jenkins/artifacts-x86_64-linux-gnu/include -D WITH_NSLOG -D NETSURF_UA_FORMAT_STRING="Mozilla/5.0 (%s) NetSurf/%d.%d" -D NETSURF_HOMEPAGE="about:welcome" -D NETSURF_LOG_LEVEL=VERBOSE -D NETSURF_BUILTIN_LOG_FILTER="(level:WARNING || cat:jserrors)" -D NETSURF_BUILTIN_VERBOSE_FILTER="(level:VERBOSE || cat:jserrors)" -D STMTEXPR=1 -D nsframebuffer -D small -D NETSURF_FB_RESPATH="${HOME}/.netsurf/:${NETSURFRES}:/var/lib/jenkins/artifacts-x86_64-linux-gnu/share/netsurf:./frontends/framebuffer/res" -D NETSURF_FB_FONTPATH="/usr/share/fonts/truetype/dejavu:/usr/share/fonts/truetype/msttcorefonts" -D NETSURF_FB_FONT_SANS_SERIF="DejaVuSans.ttf" -D NETSURF_FB_FONT_SANS_SERIF_BOLD="DejaVuSans-Bold.ttf" -D NETSURF_FB_FONT_SANS_SERIF_ITALIC="DejaVuSans-Oblique.ttf" -D NETSURF_FB_FONT_SANS_SERIF_ITALIC_BOLD="DejaVuSans-BoldOblique.ttf" -D NETSURF_FB_FONT_SERIF="DejaVuSerif.ttf" -D NETSURF_FB_FONT_SERIF_BOLD="DejaVuSerif-Bold.ttf" -D NETSURF_FB_FONT_MONOSPACE="DejaVuSansMono.ttf" -D NETSURF_FB_FONT_MONOSPACE_BOLD="DejaVuSansMono-Bold.ttf" -D NETSURF_FB_FONT_CURSIVE="Comic_Sans_MS.ttf" -D NETSURF_FB_FONT_FANTASY="Impact.ttf" -I /var/lib/jenkins/artifacts-x86_64-linux-gnu/include -D _POSIX_C_SOURCE=200809L -D _XOPEN_SOURCE=700 -D _BSD_SOURCE -D _DEFAULT_SOURCE -D _NETBSD_SOURCE -D DUK_OPT_HAVE_CUSTOM_H -internal-isystem /usr/lib/llvm-14/lib/clang/14.0.6/include -internal-isystem /usr/local/include -internal-isystem /usr/bin/../lib/gcc/x86_64-linux-gnu/12/../../../../x86_64-linux-gnu/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -O2 -Wwrite-strings -Wno-unused-parameter -Wno-unused-but-set-variable -std=c99 -fconst-strings -fdebug-compilation-dir=/var/lib/jenkins/workspace/scan-build-netsurf -ferror-limit 19 -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -analyzer-display-progress -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /var/lib/jenkins/workspace/scan-build-netsurf/clangScanBuildReports/2024-12-17-120558-2788052-1 -x c content/handlers/image/image_cache.c
1/*
2 * Copyright 2011 Vincent Sanders <vince@netsurf-browser.org>
3 *
4 * This file is part of NetSurf, http://www.netsurf-browser.org/
5 *
6 * NetSurf is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; version 2 of the License.
9 *
10 * NetSurf is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 */
18
19/**
20 * \file
21 * Cache implementation for bitmap images decoded into frontend format.
22 */
23
24#include <assert.h>
25#include <stdint.h>
26#include <stdbool.h>
27#include <string.h>
28#include <stdlib.h>
29
30#include "netsurf/inttypes.h"
31#include "utils/utils.h"
32#include "utils/log.h"
33#include "netsurf/misc.h"
34#include "netsurf/bitmap.h"
35#include "content/llcache.h"
36#include "content/content_protected.h"
37#include "desktop/gui_internal.h"
38
39#include "image/image_cache.h"
40#include "image/image.h"
41
42/**
43 * Age of an entry within the cache
44 *
45 * type deffed away so it can be readily changed later perhaps to a
46 * wallclock time structure.
47 */
48typedef unsigned int cache_age;
49
50/**
51 * Image cache entry
52 */
53struct image_cache_entry_s {
54 struct image_cache_entry_s *next; /**< next cache entry in list */
55 struct image_cache_entry_s *prev; /**< previous cache entry in list */
56
57 /** content is used as a key */
58 struct content *content;
59 /** associated bitmap entry */
60 struct bitmap *bitmap;
61 /** routine to convert content into bitmap */
62 image_cache_convert_fn *convert;
63
64 /* Statistics for replacement algorithm */
65
66 unsigned int redraw_count; /**< number of times object has been drawn */
67 cache_age redraw_age; /**< Age of last redraw */
68 size_t bitmap_size; /**< size if storage occupied by bitmap */
69 cache_age bitmap_age; /**< Age of last conversion to a bitmap by cache*/
70
71 int conversion_count; /**< Number of times image has been converted */
72};
73
74/**
75 * Current state of the cache.
76 *
77 * Global state of the cache. entries "age" is determined based on a
78 * monotonically incrementing operation count. This avoids issues with
79 * using wall clock time while allowing the LRU algorithm to work
80 * sensibly.
81 */
82struct image_cache_s {
83 /** Cache parameters */
84 struct image_cache_parameters params;
85
86 /** The "age" of the current operation */
87 cache_age current_age;
88
89 /* The objects the cache holds */
90 struct image_cache_entry_s *entries;
91
92
93 /* Statistics for management algorithm */
94
95 /** total size of bitmaps currently allocated */
96 size_t total_bitmap_size;
97
98 /** Total count of bitmaps currently allocated */
99 int bitmap_count;
100
101 /** Maximum size of bitmaps allocated at any one time */
102 size_t max_bitmap_size;
103 /** The number of objects when maximum bitmap usage occurred */
104 int max_bitmap_size_count;
105
106 /** Maximum count of bitmaps allocated at any one time */
107 int max_bitmap_count;
108 /** The size of the bitmaps when the max count occurred */
109 size_t max_bitmap_count_size;
110
111 /** Bitmap was not available at plot time required conversion */
112 int miss_count;
113 uint64_t miss_size;
114 /** Bitmap was available at plot time required no conversion */
115 int hit_count;
116 uint64_t hit_size;
117 /** Bitmap was not available at plot time and required
118 * conversion which failed.
119 */
120 int fail_count;
121 uint64_t fail_size;
122
123 /* Cache entry freed without ever being redrawn */
124 int total_unrendered;
125 /** Bitmap was available but never required - wasted conversions */
126 int specultive_miss_count;
127
128 /** Total number of additional (after the first) conversions */
129 int total_extra_conversions;
130 /** counts total number of images with more than one conversion */
131 int total_extra_conversions_count;
132
133 /** Bitmap with most conversions was converted this many times */
134 int peak_conversions;
135 /** Size of bitmap with most conversions */
136 unsigned int peak_conversions_size;
137};
138
139/** image cache state */
140static struct image_cache_s *image_cache = NULL((void*)0);
141
142
143/**
144 * Find a cache entry by index.
145 *
146 * \param entryn index of cache entry
147 * \return cache entry at index or NULL if not found.
148 */
149static struct image_cache_entry_s *image_cache__findn(int entryn)
150{
151 struct image_cache_entry_s *found;
152
153 found = image_cache->entries;
154 while ((found != NULL((void*)0)) && (entryn > 0)) {
155 entryn--;
156 found = found->next;
157 }
158 return found;
159}
160
161
162/**
163 * Find the cache entry for a content
164 *
165 * \param c The content to get an entry for
166 * \return The image cache entry or NULL if not found.
167 */
168static struct image_cache_entry_s *image_cache__find(const struct content *c)
169{
170 struct image_cache_entry_s *found;
171
172 found = image_cache->entries;
173 while ((found != NULL((void*)0)) && (found->content != c)) {
174 found = found->next;
175 }
176 return found;
177}
178
179/**
180 * Update the image cache statistics with an entry.
181 *
182 * \param centry The image cache entry to update the stats with.
183 */
184static void image_cache_stats_bitmap_add(struct image_cache_entry_s *centry)
185{
186 centry->bitmap_age = image_cache->current_age;
187 centry->conversion_count++;
188
189 image_cache->total_bitmap_size += centry->bitmap_size;
190 image_cache->bitmap_count++;
191
192 if (image_cache->total_bitmap_size > image_cache->max_bitmap_size) {
193 image_cache->max_bitmap_size = image_cache->total_bitmap_size;
194 image_cache->max_bitmap_size_count = image_cache->bitmap_count;
195
196 }
197
198 if (image_cache->bitmap_count > image_cache->max_bitmap_count) {
199 image_cache->max_bitmap_count = image_cache->bitmap_count;
200 image_cache->max_bitmap_count_size = image_cache->total_bitmap_size;
201 }
202
203 if (centry->conversion_count == 2) {
204 image_cache->total_extra_conversions_count++;
205 }
206
207 if (centry->conversion_count > 1) {
208 image_cache->total_extra_conversions++;
209 }
210
211 if ((centry->conversion_count > image_cache->peak_conversions) ||
212 (centry->conversion_count == image_cache->peak_conversions &&
213 centry->bitmap_size > image_cache->peak_conversions_size)) {
214 image_cache->peak_conversions = centry->conversion_count;
215 image_cache->peak_conversions_size = centry->bitmap_size;
216 }
217}
218
219static void image_cache__link(struct image_cache_entry_s *centry)
220{
221 centry->next = image_cache->entries;
222 centry->prev = NULL((void*)0);
223 if (centry->next != NULL((void*)0)) {
224 centry->next->prev = centry;
225 }
226 image_cache->entries = centry;
227}
228
229static void image_cache__unlink(struct image_cache_entry_s *centry)
230{
231 /* unlink entry */
232 if (centry->prev == NULL((void*)0)) {
233 /* first in list */
234 if (centry->next != NULL((void*)0)) {
235 centry->next->prev = centry->prev;
236 image_cache->entries = centry->next;
237 } else {
238 /* empty list */
239 image_cache->entries = NULL((void*)0);
240 }
241 } else {
242 centry->prev->next = centry->next;
243
244 if (centry->next != NULL((void*)0)) {
245 centry->next->prev = centry->prev;
246 }
247 }
248}
249
250/**
251 * free bitmap from an image cache entry
252 *
253 * \param centry The image cache entry to free bitmap from.
254 */
255static void image_cache__free_bitmap(struct image_cache_entry_s *centry)
256{
257 if (centry->bitmap != NULL((void*)0)) {
258#ifdef IMAGE_CACHE_VERBOSE
259 NSLOG(netsurf, INFO,do { if (NSLOG_LEVEL_INFO >= NSLOG_LEVEL_VERBOSE) { static
nslog_entry_context_t _nslog_ctx = { &__nslog_category_netsurf
, NSLOG_LEVEL_INFO, "content/handlers/image/image_cache.c", sizeof
("content/handlers/image/image_cache.c") - 1, __PRETTY_FUNCTION__
, sizeof(__PRETTY_FUNCTION__) - 1, 264, }; nslog__log(&_nslog_ctx
, "Freeing bitmap %p size %d age %d redraw count %d", centry->
bitmap, centry->bitmap_size, image_cache->current_age -
centry->bitmap_age, centry->redraw_count); } } while(0
)
260 "Freeing bitmap %p size %d age %d redraw count %d",do { if (NSLOG_LEVEL_INFO >= NSLOG_LEVEL_VERBOSE) { static
nslog_entry_context_t _nslog_ctx = { &__nslog_category_netsurf
, NSLOG_LEVEL_INFO, "content/handlers/image/image_cache.c", sizeof
("content/handlers/image/image_cache.c") - 1, __PRETTY_FUNCTION__
, sizeof(__PRETTY_FUNCTION__) - 1, 264, }; nslog__log(&_nslog_ctx
, "Freeing bitmap %p size %d age %d redraw count %d", centry->
bitmap, centry->bitmap_size, image_cache->current_age -
centry->bitmap_age, centry->redraw_count); } } while(0
)
261 centry->bitmap,do { if (NSLOG_LEVEL_INFO >= NSLOG_LEVEL_VERBOSE) { static
nslog_entry_context_t _nslog_ctx = { &__nslog_category_netsurf
, NSLOG_LEVEL_INFO, "content/handlers/image/image_cache.c", sizeof
("content/handlers/image/image_cache.c") - 1, __PRETTY_FUNCTION__
, sizeof(__PRETTY_FUNCTION__) - 1, 264, }; nslog__log(&_nslog_ctx
, "Freeing bitmap %p size %d age %d redraw count %d", centry->
bitmap, centry->bitmap_size, image_cache->current_age -
centry->bitmap_age, centry->redraw_count); } } while(0
)
262 centry->bitmap_size,do { if (NSLOG_LEVEL_INFO >= NSLOG_LEVEL_VERBOSE) { static
nslog_entry_context_t _nslog_ctx = { &__nslog_category_netsurf
, NSLOG_LEVEL_INFO, "content/handlers/image/image_cache.c", sizeof
("content/handlers/image/image_cache.c") - 1, __PRETTY_FUNCTION__
, sizeof(__PRETTY_FUNCTION__) - 1, 264, }; nslog__log(&_nslog_ctx
, "Freeing bitmap %p size %d age %d redraw count %d", centry->
bitmap, centry->bitmap_size, image_cache->current_age -
centry->bitmap_age, centry->redraw_count); } } while(0
)
263 image_cache->current_age - centry->bitmap_age,do { if (NSLOG_LEVEL_INFO >= NSLOG_LEVEL_VERBOSE) { static
nslog_entry_context_t _nslog_ctx = { &__nslog_category_netsurf
, NSLOG_LEVEL_INFO, "content/handlers/image/image_cache.c", sizeof
("content/handlers/image/image_cache.c") - 1, __PRETTY_FUNCTION__
, sizeof(__PRETTY_FUNCTION__) - 1, 264, }; nslog__log(&_nslog_ctx
, "Freeing bitmap %p size %d age %d redraw count %d", centry->
bitmap, centry->bitmap_size, image_cache->current_age -
centry->bitmap_age, centry->redraw_count); } } while(0
)
264 centry->redraw_count)do { if (NSLOG_LEVEL_INFO >= NSLOG_LEVEL_VERBOSE) { static
nslog_entry_context_t _nslog_ctx = { &__nslog_category_netsurf
, NSLOG_LEVEL_INFO, "content/handlers/image/image_cache.c", sizeof
("content/handlers/image/image_cache.c") - 1, __PRETTY_FUNCTION__
, sizeof(__PRETTY_FUNCTION__) - 1, 264, }; nslog__log(&_nslog_ctx
, "Freeing bitmap %p size %d age %d redraw count %d", centry->
bitmap, centry->bitmap_size, image_cache->current_age -
centry->bitmap_age, centry->redraw_count); } } while(0
)
;
265#endif
266 guit->bitmap->destroy(centry->bitmap);
267 centry->bitmap = NULL((void*)0);
268 image_cache->total_bitmap_size -= centry->bitmap_size;
269 image_cache->bitmap_count--;
270 if (centry->redraw_count == 0) {
271 image_cache->specultive_miss_count++;
272 }
273 }
274
275}
276
277/**
278 * free image cache entry
279 *
280 * \param centry The image cache entry to free.
281 */
282static void image_cache__free_entry(struct image_cache_entry_s *centry)
283{
284#ifdef IMAGE_CACHE_VERBOSE
285 NSLOG(netsurf, INFO, "freeing %p ", centry)do { if (NSLOG_LEVEL_INFO >= NSLOG_LEVEL_VERBOSE) { static
nslog_entry_context_t _nslog_ctx = { &__nslog_category_netsurf
, NSLOG_LEVEL_INFO, "content/handlers/image/image_cache.c", sizeof
("content/handlers/image/image_cache.c") - 1, __PRETTY_FUNCTION__
, sizeof(__PRETTY_FUNCTION__) - 1, 285, }; nslog__log(&_nslog_ctx
, "freeing %p ", centry); } } while(0)
;
286#endif
287
288 if (centry->redraw_count == 0) {
6
Assuming field 'redraw_count' is not equal to 0
7
Taking false branch
289 image_cache->total_unrendered++;
290 }
291
292 image_cache__free_bitmap(centry);
293
294 image_cache__unlink(centry);
295
296 free(centry);
8
Memory is released
297}
298
299/**
300 * Image cache cleaner
301 *
302 * \param icache The image cache context.
303 */
304static void image_cache__clean(struct image_cache_s *icache)
305{
306 struct image_cache_entry_s *centry = icache->entries;
307
308 while (centry != NULL((void*)0)) {
309 if ((icache->current_age - centry->redraw_age) >
310 icache->params.bg_clean_time) {
311 /* only consider older entries, avoids active entries */
312 if ((icache->total_bitmap_size >
313 (icache->params.limit - icache->params.hysteresis)) &&
314 (rand() > (RAND_MAX2147483647 / 2))) {
315 image_cache__free_bitmap(centry);
316 }
317 }
318 centry=centry->next;
319 }
320}
321
322/**
323 * Cache background scheduled callback.
324 *
325 * \param p The image cache context.
326 */
327static void image_cache__background_update(void *p)
328{
329 struct image_cache_s *icache = p;
330
331 /* increment current cache age */
332 icache->current_age += icache->params.bg_clean_time;
333
334#ifdef IMAGE_CACHE_VERBOSE
335 NSLOG(netsurf, INFO, "Cache age %ds", icache->current_age / 1000)do { if (NSLOG_LEVEL_INFO >= NSLOG_LEVEL_VERBOSE) { static
nslog_entry_context_t _nslog_ctx = { &__nslog_category_netsurf
, NSLOG_LEVEL_INFO, "content/handlers/image/image_cache.c", sizeof
("content/handlers/image/image_cache.c") - 1, __PRETTY_FUNCTION__
, sizeof(__PRETTY_FUNCTION__) - 1, 335, }; nslog__log(&_nslog_ctx
, "Cache age %ds", icache->current_age / 1000); } } while(
0)
;
336#endif
337
338 image_cache__clean(icache);
339
340 guit->misc->schedule(icache->params.bg_clean_time,
341 image_cache__background_update,
342 icache);
343}
344
345/* exported interface documented in image_cache.h */
346struct bitmap *image_cache_get_bitmap(const struct content *c)
347{
348 struct image_cache_entry_s *centry;
349
350 centry = image_cache__find(c);
351 if (centry == NULL((void*)0)) {
352 return NULL((void*)0);
353 }
354
355 if (centry->bitmap == NULL((void*)0)) {
356 if (centry->convert != NULL((void*)0)) {
357 centry->bitmap = centry->convert(centry->content);
358 }
359
360 if (centry->bitmap != NULL((void*)0)) {
361 image_cache_stats_bitmap_add(centry);
362 image_cache->miss_count++;
363 image_cache->miss_size += centry->bitmap_size;
364 } else {
365 image_cache->fail_count++;
366 image_cache->fail_size += centry->bitmap_size;
367 }
368 } else {
369 image_cache->hit_count++;
370 image_cache->hit_size += centry->bitmap_size;
371 }
372
373 return centry->bitmap;
374}
375
376/* exported interface documented in image_cache.h */
377bool_Bool image_cache_speculate(struct content *c)
378{
379 bool_Bool decision = false0;
380
381 /* If the cache is below its target usage and the bitmap is
382 * small enough speculate.
383 */
384 if ((image_cache->total_bitmap_size < image_cache->params.limit) &&
385 (c->size <= image_cache->params.speculative_small)) {
386#ifdef IMAGE_CACHE_VERBOSE
387 NSLOG(netsurf, INFO,do { if (NSLOG_LEVEL_INFO >= NSLOG_LEVEL_VERBOSE) { static
nslog_entry_context_t _nslog_ctx = { &__nslog_category_netsurf
, NSLOG_LEVEL_INFO, "content/handlers/image/image_cache.c", sizeof
("content/handlers/image/image_cache.c") - 1, __PRETTY_FUNCTION__
, sizeof(__PRETTY_FUNCTION__) - 1, 390, }; nslog__log(&_nslog_ctx
, "content size (%d) is smaller than minimum (%d)", c->size
, SPECULATE_SMALL); } } while(0)
388 "content size (%d) is smaller than minimum (%d)",do { if (NSLOG_LEVEL_INFO >= NSLOG_LEVEL_VERBOSE) { static
nslog_entry_context_t _nslog_ctx = { &__nslog_category_netsurf
, NSLOG_LEVEL_INFO, "content/handlers/image/image_cache.c", sizeof
("content/handlers/image/image_cache.c") - 1, __PRETTY_FUNCTION__
, sizeof(__PRETTY_FUNCTION__) - 1, 390, }; nslog__log(&_nslog_ctx
, "content size (%d) is smaller than minimum (%d)", c->size
, SPECULATE_SMALL); } } while(0)
389 c->size,do { if (NSLOG_LEVEL_INFO >= NSLOG_LEVEL_VERBOSE) { static
nslog_entry_context_t _nslog_ctx = { &__nslog_category_netsurf
, NSLOG_LEVEL_INFO, "content/handlers/image/image_cache.c", sizeof
("content/handlers/image/image_cache.c") - 1, __PRETTY_FUNCTION__
, sizeof(__PRETTY_FUNCTION__) - 1, 390, }; nslog__log(&_nslog_ctx
, "content size (%d) is smaller than minimum (%d)", c->size
, SPECULATE_SMALL); } } while(0)
390 SPECULATE_SMALL)do { if (NSLOG_LEVEL_INFO >= NSLOG_LEVEL_VERBOSE) { static
nslog_entry_context_t _nslog_ctx = { &__nslog_category_netsurf
, NSLOG_LEVEL_INFO, "content/handlers/image/image_cache.c", sizeof
("content/handlers/image/image_cache.c") - 1, __PRETTY_FUNCTION__
, sizeof(__PRETTY_FUNCTION__) - 1, 390, }; nslog__log(&_nslog_ctx
, "content size (%d) is smaller than minimum (%d)", c->size
, SPECULATE_SMALL); } } while(0)
;
391#endif
392 decision = true1;
393 }
394
395#ifdef IMAGE_CACHE_VERBOSE
396 NSLOG(netsurf, INFO, "returning %d", decision)do { if (NSLOG_LEVEL_INFO >= NSLOG_LEVEL_VERBOSE) { static
nslog_entry_context_t _nslog_ctx = { &__nslog_category_netsurf
, NSLOG_LEVEL_INFO, "content/handlers/image/image_cache.c", sizeof
("content/handlers/image/image_cache.c") - 1, __PRETTY_FUNCTION__
, sizeof(__PRETTY_FUNCTION__) - 1, 396, }; nslog__log(&_nslog_ctx
, "returning %d", decision); } } while(0)
;
397#endif
398 return decision;
399}
400
401/* exported interface documented in image_cache.h */
402struct bitmap *image_cache_find_bitmap(struct content *c)
403{
404 struct image_cache_entry_s *centry;
405
406 centry = image_cache__find(c);
407 if (centry == NULL((void*)0)) {
408 return NULL((void*)0);
409 }
410
411 return centry->bitmap;
412}
413
414/* exported interface documented in image_cache.h */
415nserror
416image_cache_init(const struct image_cache_parameters *image_cache_parameters)
417{
418 image_cache = calloc(1, sizeof(struct image_cache_s));
419 if (image_cache == NULL((void*)0)) {
420 return NSERROR_NOMEM;
421 }
422
423 image_cache->params = *image_cache_parameters;
424
425 guit->misc->schedule(image_cache->params.bg_clean_time,
426 image_cache__background_update,
427 image_cache);
428
429 NSLOG(netsurf, INFO,do { if (NSLOG_LEVEL_INFO >= NSLOG_LEVEL_VERBOSE) { static
nslog_entry_context_t _nslog_ctx = { &__nslog_category_netsurf
, NSLOG_LEVEL_INFO, "content/handlers/image/image_cache.c", sizeof
("content/handlers/image/image_cache.c") - 1, __PRETTY_FUNCTION__
, sizeof(__PRETTY_FUNCTION__) - 1, 432, }; nslog__log(&_nslog_ctx
, "Image cache initialised with a limit of %""zu"" hysteresis of %"
"zu", image_cache->params.limit, image_cache->params.hysteresis
); } } while(0)
430 "Image cache initialised with a limit of %"PRIsizet" hysteresis of %"PRIsizet,do { if (NSLOG_LEVEL_INFO >= NSLOG_LEVEL_VERBOSE) { static
nslog_entry_context_t _nslog_ctx = { &__nslog_category_netsurf
, NSLOG_LEVEL_INFO, "content/handlers/image/image_cache.c", sizeof
("content/handlers/image/image_cache.c") - 1, __PRETTY_FUNCTION__
, sizeof(__PRETTY_FUNCTION__) - 1, 432, }; nslog__log(&_nslog_ctx
, "Image cache initialised with a limit of %""zu"" hysteresis of %"
"zu", image_cache->params.limit, image_cache->params.hysteresis
); } } while(0)
431 image_cache->params.limit,do { if (NSLOG_LEVEL_INFO >= NSLOG_LEVEL_VERBOSE) { static
nslog_entry_context_t _nslog_ctx = { &__nslog_category_netsurf
, NSLOG_LEVEL_INFO, "content/handlers/image/image_cache.c", sizeof
("content/handlers/image/image_cache.c") - 1, __PRETTY_FUNCTION__
, sizeof(__PRETTY_FUNCTION__) - 1, 432, }; nslog__log(&_nslog_ctx
, "Image cache initialised with a limit of %""zu"" hysteresis of %"
"zu", image_cache->params.limit, image_cache->params.hysteresis
); } } while(0)
432 image_cache->params.hysteresis)do { if (NSLOG_LEVEL_INFO >= NSLOG_LEVEL_VERBOSE) { static
nslog_entry_context_t _nslog_ctx = { &__nslog_category_netsurf
, NSLOG_LEVEL_INFO, "content/handlers/image/image_cache.c", sizeof
("content/handlers/image/image_cache.c") - 1, __PRETTY_FUNCTION__
, sizeof(__PRETTY_FUNCTION__) - 1, 432, }; nslog__log(&_nslog_ctx
, "Image cache initialised with a limit of %""zu"" hysteresis of %"
"zu", image_cache->params.limit, image_cache->params.hysteresis
); } } while(0)
;
433
434 return NSERROR_OK;
435}
436
437/* exported interface documented in image_cache.h */
438nserror image_cache_fini(void)
439{
440 unsigned int op_count;
441 uint64_t op_size;
442
443 guit->misc->schedule(-1, image_cache__background_update, image_cache);
444
445 NSLOG(netsurf, INFO, "Size at finish %"PRIsizet" (in %d)",do { if (NSLOG_LEVEL_INFO >= NSLOG_LEVEL_VERBOSE) { static
nslog_entry_context_t _nslog_ctx = { &__nslog_category_netsurf
, NSLOG_LEVEL_INFO, "content/handlers/image/image_cache.c", sizeof
("content/handlers/image/image_cache.c") - 1, __PRETTY_FUNCTION__
, sizeof(__PRETTY_FUNCTION__) - 1, 446, }; nslog__log(&_nslog_ctx
, "Size at finish %""zu"" (in %d)", image_cache->total_bitmap_size
, image_cache->bitmap_count); } } while(0)
1
Taking true branch
2
Loop condition is false. Exiting loop
446 image_cache->total_bitmap_size, image_cache->bitmap_count)do { if (NSLOG_LEVEL_INFO >= NSLOG_LEVEL_VERBOSE) { static
nslog_entry_context_t _nslog_ctx = { &__nslog_category_netsurf
, NSLOG_LEVEL_INFO, "content/handlers/image/image_cache.c", sizeof
("content/handlers/image/image_cache.c") - 1, __PRETTY_FUNCTION__
, sizeof(__PRETTY_FUNCTION__) - 1, 446, }; nslog__log(&_nslog_ctx
, "Size at finish %""zu"" (in %d)", image_cache->total_bitmap_size
, image_cache->bitmap_count); } } while(0)
;
447
448 while (image_cache->entries
9.1
Field 'entries' is not equal to NULL
!= NULL((void*)0)
) {
3
Assuming field 'entries' is not equal to NULL
4
Loop condition is true. Entering loop body
10
Loop condition is true. Entering loop body
449 image_cache__free_entry(image_cache->entries);
5
Calling 'image_cache__free_entry'
9
Returning; memory was released via 1st parameter
11
Use of memory after it is freed
450 }
451
452 op_count = image_cache->hit_count +
453 image_cache->miss_count +
454 image_cache->fail_count;
455
456 op_size = image_cache->hit_size +
457 image_cache->miss_size +
458 image_cache->fail_size;
459
460 NSLOG(netsurf, INFO, "Age %ds", image_cache->current_age / 1000)do { if (NSLOG_LEVEL_INFO >= NSLOG_LEVEL_VERBOSE) { static
nslog_entry_context_t _nslog_ctx = { &__nslog_category_netsurf
, NSLOG_LEVEL_INFO, "content/handlers/image/image_cache.c", sizeof
("content/handlers/image/image_cache.c") - 1, __PRETTY_FUNCTION__
, sizeof(__PRETTY_FUNCTION__) - 1, 460, }; nslog__log(&_nslog_ctx
, "Age %ds", image_cache->current_age / 1000); } } while(0
)
;
461 NSLOG(netsurf, INFO, "Peak size %"PRIsizet" (in %d)",do { if (NSLOG_LEVEL_INFO >= NSLOG_LEVEL_VERBOSE) { static
nslog_entry_context_t _nslog_ctx = { &__nslog_category_netsurf
, NSLOG_LEVEL_INFO, "content/handlers/image/image_cache.c", sizeof
("content/handlers/image/image_cache.c") - 1, __PRETTY_FUNCTION__
, sizeof(__PRETTY_FUNCTION__) - 1, 463, }; nslog__log(&_nslog_ctx
, "Peak size %""zu"" (in %d)", image_cache->max_bitmap_size
, image_cache->max_bitmap_size_count); } } while(0)
462 image_cache->max_bitmap_size,do { if (NSLOG_LEVEL_INFO >= NSLOG_LEVEL_VERBOSE) { static
nslog_entry_context_t _nslog_ctx = { &__nslog_category_netsurf
, NSLOG_LEVEL_INFO, "content/handlers/image/image_cache.c", sizeof
("content/handlers/image/image_cache.c") - 1, __PRETTY_FUNCTION__
, sizeof(__PRETTY_FUNCTION__) - 1, 463, }; nslog__log(&_nslog_ctx
, "Peak size %""zu"" (in %d)", image_cache->max_bitmap_size
, image_cache->max_bitmap_size_count); } } while(0)
463 image_cache->max_bitmap_size_count)do { if (NSLOG_LEVEL_INFO >= NSLOG_LEVEL_VERBOSE) { static
nslog_entry_context_t _nslog_ctx = { &__nslog_category_netsurf
, NSLOG_LEVEL_INFO, "content/handlers/image/image_cache.c", sizeof
("content/handlers/image/image_cache.c") - 1, __PRETTY_FUNCTION__
, sizeof(__PRETTY_FUNCTION__) - 1, 463, }; nslog__log(&_nslog_ctx
, "Peak size %""zu"" (in %d)", image_cache->max_bitmap_size
, image_cache->max_bitmap_size_count); } } while(0)
;
464 NSLOG(netsurf, INFO, "Peak image count %d (size %"PRIsizet")",do { if (NSLOG_LEVEL_INFO >= NSLOG_LEVEL_VERBOSE) { static
nslog_entry_context_t _nslog_ctx = { &__nslog_category_netsurf
, NSLOG_LEVEL_INFO, "content/handlers/image/image_cache.c", sizeof
("content/handlers/image/image_cache.c") - 1, __PRETTY_FUNCTION__
, sizeof(__PRETTY_FUNCTION__) - 1, 466, }; nslog__log(&_nslog_ctx
, "Peak image count %d (size %""zu"")", image_cache->max_bitmap_count
, image_cache->max_bitmap_count_size); } } while(0)
465 image_cache->max_bitmap_count,do { if (NSLOG_LEVEL_INFO >= NSLOG_LEVEL_VERBOSE) { static
nslog_entry_context_t _nslog_ctx = { &__nslog_category_netsurf
, NSLOG_LEVEL_INFO, "content/handlers/image/image_cache.c", sizeof
("content/handlers/image/image_cache.c") - 1, __PRETTY_FUNCTION__
, sizeof(__PRETTY_FUNCTION__) - 1, 466, }; nslog__log(&_nslog_ctx
, "Peak image count %d (size %""zu"")", image_cache->max_bitmap_count
, image_cache->max_bitmap_count_size); } } while(0)
466 image_cache->max_bitmap_count_size)do { if (NSLOG_LEVEL_INFO >= NSLOG_LEVEL_VERBOSE) { static
nslog_entry_context_t _nslog_ctx = { &__nslog_category_netsurf
, NSLOG_LEVEL_INFO, "content/handlers/image/image_cache.c", sizeof
("content/handlers/image/image_cache.c") - 1, __PRETTY_FUNCTION__
, sizeof(__PRETTY_FUNCTION__) - 1, 466, }; nslog__log(&_nslog_ctx
, "Peak image count %d (size %""zu"")", image_cache->max_bitmap_count
, image_cache->max_bitmap_count_size); } } while(0)
;
467
468 if ((op_count > 0) && (op_size >0)) {
469
470 NSLOG(netsurf, INFO,do { if (NSLOG_LEVEL_INFO >= NSLOG_LEVEL_VERBOSE) { static
nslog_entry_context_t _nslog_ctx = { &__nslog_category_netsurf
, NSLOG_LEVEL_INFO, "content/handlers/image/image_cache.c", sizeof
("content/handlers/image/image_cache.c") - 1, __PRETTY_FUNCTION__
, sizeof(__PRETTY_FUNCTION__) - 1, 478, }; nslog__log(&_nslog_ctx
, "Cache total/hit/miss/fail (counts) %d/%d/%d/%d (100%%/%d%%/%d%%/%d%%)"
, op_count, image_cache->hit_count, image_cache->miss_count
, image_cache->fail_count, (image_cache->hit_count * 100
) / op_count, (image_cache->miss_count * 100) / op_count, (
image_cache->fail_count * 100) / op_count); } } while(0)
471 "Cache total/hit/miss/fail (counts) %d/%d/%d/%d (100%%/%d%%/%d%%/%d%%)",do { if (NSLOG_LEVEL_INFO >= NSLOG_LEVEL_VERBOSE) { static
nslog_entry_context_t _nslog_ctx = { &__nslog_category_netsurf
, NSLOG_LEVEL_INFO, "content/handlers/image/image_cache.c", sizeof
("content/handlers/image/image_cache.c") - 1, __PRETTY_FUNCTION__
, sizeof(__PRETTY_FUNCTION__) - 1, 478, }; nslog__log(&_nslog_ctx
, "Cache total/hit/miss/fail (counts) %d/%d/%d/%d (100%%/%d%%/%d%%/%d%%)"
, op_count, image_cache->hit_count, image_cache->miss_count
, image_cache->fail_count, (image_cache->hit_count * 100
) / op_count, (image_cache->miss_count * 100) / op_count, (
image_cache->fail_count * 100) / op_count); } } while(0)
472 op_count,do { if (NSLOG_LEVEL_INFO >= NSLOG_LEVEL_VERBOSE) { static
nslog_entry_context_t _nslog_ctx = { &__nslog_category_netsurf
, NSLOG_LEVEL_INFO, "content/handlers/image/image_cache.c", sizeof
("content/handlers/image/image_cache.c") - 1, __PRETTY_FUNCTION__
, sizeof(__PRETTY_FUNCTION__) - 1, 478, }; nslog__log(&_nslog_ctx
, "Cache total/hit/miss/fail (counts) %d/%d/%d/%d (100%%/%d%%/%d%%/%d%%)"
, op_count, image_cache->hit_count, image_cache->miss_count
, image_cache->fail_count, (image_cache->hit_count * 100
) / op_count, (image_cache->miss_count * 100) / op_count, (
image_cache->fail_count * 100) / op_count); } } while(0)
473 image_cache->hit_count,do { if (NSLOG_LEVEL_INFO >= NSLOG_LEVEL_VERBOSE) { static
nslog_entry_context_t _nslog_ctx = { &__nslog_category_netsurf
, NSLOG_LEVEL_INFO, "content/handlers/image/image_cache.c", sizeof
("content/handlers/image/image_cache.c") - 1, __PRETTY_FUNCTION__
, sizeof(__PRETTY_FUNCTION__) - 1, 478, }; nslog__log(&_nslog_ctx
, "Cache total/hit/miss/fail (counts) %d/%d/%d/%d (100%%/%d%%/%d%%/%d%%)"
, op_count, image_cache->hit_count, image_cache->miss_count
, image_cache->fail_count, (image_cache->hit_count * 100
) / op_count, (image_cache->miss_count * 100) / op_count, (
image_cache->fail_count * 100) / op_count); } } while(0)
474 image_cache->miss_count,do { if (NSLOG_LEVEL_INFO >= NSLOG_LEVEL_VERBOSE) { static
nslog_entry_context_t _nslog_ctx = { &__nslog_category_netsurf
, NSLOG_LEVEL_INFO, "content/handlers/image/image_cache.c", sizeof
("content/handlers/image/image_cache.c") - 1, __PRETTY_FUNCTION__
, sizeof(__PRETTY_FUNCTION__) - 1, 478, }; nslog__log(&_nslog_ctx
, "Cache total/hit/miss/fail (counts) %d/%d/%d/%d (100%%/%d%%/%d%%/%d%%)"
, op_count, image_cache->hit_count, image_cache->miss_count
, image_cache->fail_count, (image_cache->hit_count * 100
) / op_count, (image_cache->miss_count * 100) / op_count, (
image_cache->fail_count * 100) / op_count); } } while(0)
475 image_cache->fail_count,do { if (NSLOG_LEVEL_INFO >= NSLOG_LEVEL_VERBOSE) { static
nslog_entry_context_t _nslog_ctx = { &__nslog_category_netsurf
, NSLOG_LEVEL_INFO, "content/handlers/image/image_cache.c", sizeof
("content/handlers/image/image_cache.c") - 1, __PRETTY_FUNCTION__
, sizeof(__PRETTY_FUNCTION__) - 1, 478, }; nslog__log(&_nslog_ctx
, "Cache total/hit/miss/fail (counts) %d/%d/%d/%d (100%%/%d%%/%d%%/%d%%)"
, op_count, image_cache->hit_count, image_cache->miss_count
, image_cache->fail_count, (image_cache->hit_count * 100
) / op_count, (image_cache->miss_count * 100) / op_count, (
image_cache->fail_count * 100) / op_count); } } while(0)
476 (image_cache->hit_count * 100) / op_count,do { if (NSLOG_LEVEL_INFO >= NSLOG_LEVEL_VERBOSE) { static
nslog_entry_context_t _nslog_ctx = { &__nslog_category_netsurf
, NSLOG_LEVEL_INFO, "content/handlers/image/image_cache.c", sizeof
("content/handlers/image/image_cache.c") - 1, __PRETTY_FUNCTION__
, sizeof(__PRETTY_FUNCTION__) - 1, 478, }; nslog__log(&_nslog_ctx
, "Cache total/hit/miss/fail (counts) %d/%d/%d/%d (100%%/%d%%/%d%%/%d%%)"
, op_count, image_cache->hit_count, image_cache->miss_count
, image_cache->fail_count, (image_cache->hit_count * 100
) / op_count, (image_cache->miss_count * 100) / op_count, (
image_cache->fail_count * 100) / op_count); } } while(0)
477 (image_cache->miss_count * 100) / op_count,do { if (NSLOG_LEVEL_INFO >= NSLOG_LEVEL_VERBOSE) { static
nslog_entry_context_t _nslog_ctx = { &__nslog_category_netsurf
, NSLOG_LEVEL_INFO, "content/handlers/image/image_cache.c", sizeof
("content/handlers/image/image_cache.c") - 1, __PRETTY_FUNCTION__
, sizeof(__PRETTY_FUNCTION__) - 1, 478, }; nslog__log(&_nslog_ctx
, "Cache total/hit/miss/fail (counts) %d/%d/%d/%d (100%%/%d%%/%d%%/%d%%)"
, op_count, image_cache->hit_count, image_cache->miss_count
, image_cache->fail_count, (image_cache->hit_count * 100
) / op_count, (image_cache->miss_count * 100) / op_count, (
image_cache->fail_count * 100) / op_count); } } while(0)
478 (image_cache->fail_count * 100) / op_count)do { if (NSLOG_LEVEL_INFO >= NSLOG_LEVEL_VERBOSE) { static
nslog_entry_context_t _nslog_ctx = { &__nslog_category_netsurf
, NSLOG_LEVEL_INFO, "content/handlers/image/image_cache.c", sizeof
("content/handlers/image/image_cache.c") - 1, __PRETTY_FUNCTION__
, sizeof(__PRETTY_FUNCTION__) - 1, 478, }; nslog__log(&_nslog_ctx
, "Cache total/hit/miss/fail (counts) %d/%d/%d/%d (100%%/%d%%/%d%%/%d%%)"
, op_count, image_cache->hit_count, image_cache->miss_count
, image_cache->fail_count, (image_cache->hit_count * 100
) / op_count, (image_cache->miss_count * 100) / op_count, (
image_cache->fail_count * 100) / op_count); } } while(0)
;
479 NSLOG(netsurf, INFO,do { if (NSLOG_LEVEL_INFO >= NSLOG_LEVEL_VERBOSE) { static
nslog_entry_context_t _nslog_ctx = { &__nslog_category_netsurf
, NSLOG_LEVEL_INFO, "content/handlers/image/image_cache.c", sizeof
("content/handlers/image/image_cache.c") - 1, __PRETTY_FUNCTION__
, sizeof(__PRETTY_FUNCTION__) - 1, 487, }; nslog__log(&_nslog_ctx
, "Cache total/hit/miss/fail (size) %""l" "u""/%""l" "u""/%""l"
"u""/%""l" "u"" (100%%/%""l" "d""%%/%""l" "d""%%/%""l" "d""%%)"
, op_size, image_cache->hit_size, image_cache->miss_size
, image_cache->fail_size, (image_cache->hit_size * 100)
/ op_size, (image_cache->miss_size * 100) / op_size, (image_cache
->fail_size * 100) / op_size); } } while(0)
480 "Cache total/hit/miss/fail (size) %"PRIu64"/%"PRIu64"/%"PRIu64"/%"PRIu64" (100%%/%"PRId64"%%/%"PRId64"%%/%"PRId64"%%)",do { if (NSLOG_LEVEL_INFO >= NSLOG_LEVEL_VERBOSE) { static
nslog_entry_context_t _nslog_ctx = { &__nslog_category_netsurf
, NSLOG_LEVEL_INFO, "content/handlers/image/image_cache.c", sizeof
("content/handlers/image/image_cache.c") - 1, __PRETTY_FUNCTION__
, sizeof(__PRETTY_FUNCTION__) - 1, 487, }; nslog__log(&_nslog_ctx
, "Cache total/hit/miss/fail (size) %""l" "u""/%""l" "u""/%""l"
"u""/%""l" "u"" (100%%/%""l" "d""%%/%""l" "d""%%/%""l" "d""%%)"
, op_size, image_cache->hit_size, image_cache->miss_size
, image_cache->fail_size, (image_cache->hit_size * 100)
/ op_size, (image_cache->miss_size * 100) / op_size, (image_cache
->fail_size * 100) / op_size); } } while(0)
481 op_size,do { if (NSLOG_LEVEL_INFO >= NSLOG_LEVEL_VERBOSE) { static
nslog_entry_context_t _nslog_ctx = { &__nslog_category_netsurf
, NSLOG_LEVEL_INFO, "content/handlers/image/image_cache.c", sizeof
("content/handlers/image/image_cache.c") - 1, __PRETTY_FUNCTION__
, sizeof(__PRETTY_FUNCTION__) - 1, 487, }; nslog__log(&_nslog_ctx
, "Cache total/hit/miss/fail (size) %""l" "u""/%""l" "u""/%""l"
"u""/%""l" "u"" (100%%/%""l" "d""%%/%""l" "d""%%/%""l" "d""%%)"
, op_size, image_cache->hit_size, image_cache->miss_size
, image_cache->fail_size, (image_cache->hit_size * 100)
/ op_size, (image_cache->miss_size * 100) / op_size, (image_cache
->fail_size * 100) / op_size); } } while(0)
482 image_cache->hit_size,do { if (NSLOG_LEVEL_INFO >= NSLOG_LEVEL_VERBOSE) { static
nslog_entry_context_t _nslog_ctx = { &__nslog_category_netsurf
, NSLOG_LEVEL_INFO, "content/handlers/image/image_cache.c", sizeof
("content/handlers/image/image_cache.c") - 1, __PRETTY_FUNCTION__
, sizeof(__PRETTY_FUNCTION__) - 1, 487, }; nslog__log(&_nslog_ctx
, "Cache total/hit/miss/fail (size) %""l" "u""/%""l" "u""/%""l"
"u""/%""l" "u"" (100%%/%""l" "d""%%/%""l" "d""%%/%""l" "d""%%)"
, op_size, image_cache->hit_size, image_cache->miss_size
, image_cache->fail_size, (image_cache->hit_size * 100)
/ op_size, (image_cache->miss_size * 100) / op_size, (image_cache
->fail_size * 100) / op_size); } } while(0)
483 image_cache->miss_size,do { if (NSLOG_LEVEL_INFO >= NSLOG_LEVEL_VERBOSE) { static
nslog_entry_context_t _nslog_ctx = { &__nslog_category_netsurf
, NSLOG_LEVEL_INFO, "content/handlers/image/image_cache.c", sizeof
("content/handlers/image/image_cache.c") - 1, __PRETTY_FUNCTION__
, sizeof(__PRETTY_FUNCTION__) - 1, 487, }; nslog__log(&_nslog_ctx
, "Cache total/hit/miss/fail (size) %""l" "u""/%""l" "u""/%""l"
"u""/%""l" "u"" (100%%/%""l" "d""%%/%""l" "d""%%/%""l" "d""%%)"
, op_size, image_cache->hit_size, image_cache->miss_size
, image_cache->fail_size, (image_cache->hit_size * 100)
/ op_size, (image_cache->miss_size * 100) / op_size, (image_cache
->fail_size * 100) / op_size); } } while(0)
484 image_cache->fail_size,do { if (NSLOG_LEVEL_INFO >= NSLOG_LEVEL_VERBOSE) { static
nslog_entry_context_t _nslog_ctx = { &__nslog_category_netsurf
, NSLOG_LEVEL_INFO, "content/handlers/image/image_cache.c", sizeof
("content/handlers/image/image_cache.c") - 1, __PRETTY_FUNCTION__
, sizeof(__PRETTY_FUNCTION__) - 1, 487, }; nslog__log(&_nslog_ctx
, "Cache total/hit/miss/fail (size) %""l" "u""/%""l" "u""/%""l"
"u""/%""l" "u"" (100%%/%""l" "d""%%/%""l" "d""%%/%""l" "d""%%)"
, op_size, image_cache->hit_size, image_cache->miss_size
, image_cache->fail_size, (image_cache->hit_size * 100)
/ op_size, (image_cache->miss_size * 100) / op_size, (image_cache
->fail_size * 100) / op_size); } } while(0)
485 (image_cache->hit_size * 100) / op_size,do { if (NSLOG_LEVEL_INFO >= NSLOG_LEVEL_VERBOSE) { static
nslog_entry_context_t _nslog_ctx = { &__nslog_category_netsurf
, NSLOG_LEVEL_INFO, "content/handlers/image/image_cache.c", sizeof
("content/handlers/image/image_cache.c") - 1, __PRETTY_FUNCTION__
, sizeof(__PRETTY_FUNCTION__) - 1, 487, }; nslog__log(&_nslog_ctx
, "Cache total/hit/miss/fail (size) %""l" "u""/%""l" "u""/%""l"
"u""/%""l" "u"" (100%%/%""l" "d""%%/%""l" "d""%%/%""l" "d""%%)"
, op_size, image_cache->hit_size, image_cache->miss_size
, image_cache->fail_size, (image_cache->hit_size * 100)
/ op_size, (image_cache->miss_size * 100) / op_size, (image_cache
->fail_size * 100) / op_size); } } while(0)
486 (image_cache->miss_size * 100) / op_size,do { if (NSLOG_LEVEL_INFO >= NSLOG_LEVEL_VERBOSE) { static
nslog_entry_context_t _nslog_ctx = { &__nslog_category_netsurf
, NSLOG_LEVEL_INFO, "content/handlers/image/image_cache.c", sizeof
("content/handlers/image/image_cache.c") - 1, __PRETTY_FUNCTION__
, sizeof(__PRETTY_FUNCTION__) - 1, 487, }; nslog__log(&_nslog_ctx
, "Cache total/hit/miss/fail (size) %""l" "u""/%""l" "u""/%""l"
"u""/%""l" "u"" (100%%/%""l" "d""%%/%""l" "d""%%/%""l" "d""%%)"
, op_size, image_cache->hit_size, image_cache->miss_size
, image_cache->fail_size, (image_cache->hit_size * 100)
/ op_size, (image_cache->miss_size * 100) / op_size, (image_cache
->fail_size * 100) / op_size); } } while(0)
487 (image_cache->fail_size * 100) / op_size)do { if (NSLOG_LEVEL_INFO >= NSLOG_LEVEL_VERBOSE) { static
nslog_entry_context_t _nslog_ctx = { &__nslog_category_netsurf
, NSLOG_LEVEL_INFO, "content/handlers/image/image_cache.c", sizeof
("content/handlers/image/image_cache.c") - 1, __PRETTY_FUNCTION__
, sizeof(__PRETTY_FUNCTION__) - 1, 487, }; nslog__log(&_nslog_ctx
, "Cache total/hit/miss/fail (size) %""l" "u""/%""l" "u""/%""l"
"u""/%""l" "u"" (100%%/%""l" "d""%%/%""l" "d""%%/%""l" "d""%%)"
, op_size, image_cache->hit_size, image_cache->miss_size
, image_cache->fail_size, (image_cache->hit_size * 100)
/ op_size, (image_cache->miss_size * 100) / op_size, (image_cache
->fail_size * 100) / op_size); } } while(0)
;
488 }
489
490 NSLOG(netsurf, INFO,do { if (NSLOG_LEVEL_INFO >= NSLOG_LEVEL_VERBOSE) { static
nslog_entry_context_t _nslog_ctx = { &__nslog_category_netsurf
, NSLOG_LEVEL_INFO, "content/handlers/image/image_cache.c", sizeof
("content/handlers/image/image_cache.c") - 1, __PRETTY_FUNCTION__
, sizeof(__PRETTY_FUNCTION__) - 1, 493, }; nslog__log(&_nslog_ctx
, "Total images never rendered: %d (includes %d that were converted)"
, image_cache->total_unrendered, image_cache->specultive_miss_count
); } } while(0)
491 "Total images never rendered: %d (includes %d that were converted)",do { if (NSLOG_LEVEL_INFO >= NSLOG_LEVEL_VERBOSE) { static
nslog_entry_context_t _nslog_ctx = { &__nslog_category_netsurf
, NSLOG_LEVEL_INFO, "content/handlers/image/image_cache.c", sizeof
("content/handlers/image/image_cache.c") - 1, __PRETTY_FUNCTION__
, sizeof(__PRETTY_FUNCTION__) - 1, 493, }; nslog__log(&_nslog_ctx
, "Total images never rendered: %d (includes %d that were converted)"
, image_cache->total_unrendered, image_cache->specultive_miss_count
); } } while(0)
492 image_cache->total_unrendered,do { if (NSLOG_LEVEL_INFO >= NSLOG_LEVEL_VERBOSE) { static
nslog_entry_context_t _nslog_ctx = { &__nslog_category_netsurf
, NSLOG_LEVEL_INFO, "content/handlers/image/image_cache.c", sizeof
("content/handlers/image/image_cache.c") - 1, __PRETTY_FUNCTION__
, sizeof(__PRETTY_FUNCTION__) - 1, 493, }; nslog__log(&_nslog_ctx
, "Total images never rendered: %d (includes %d that were converted)"
, image_cache->total_unrendered, image_cache->specultive_miss_count
); } } while(0)
493 image_cache->specultive_miss_count)do { if (NSLOG_LEVEL_INFO >= NSLOG_LEVEL_VERBOSE) { static
nslog_entry_context_t _nslog_ctx = { &__nslog_category_netsurf
, NSLOG_LEVEL_INFO, "content/handlers/image/image_cache.c", sizeof
("content/handlers/image/image_cache.c") - 1, __PRETTY_FUNCTION__
, sizeof(__PRETTY_FUNCTION__) - 1, 493, }; nslog__log(&_nslog_ctx
, "Total images never rendered: %d (includes %d that were converted)"
, image_cache->total_unrendered, image_cache->specultive_miss_count
); } } while(0)
;
494
495 NSLOG(netsurf, INFO,do { if (NSLOG_LEVEL_INFO >= NSLOG_LEVEL_VERBOSE) { static
nslog_entry_context_t _nslog_ctx = { &__nslog_category_netsurf
, NSLOG_LEVEL_INFO, "content/handlers/image/image_cache.c", sizeof
("content/handlers/image/image_cache.c") - 1, __PRETTY_FUNCTION__
, sizeof(__PRETTY_FUNCTION__) - 1, 498, }; nslog__log(&_nslog_ctx
, "Total number of excessive conversions: %d (from %d images converted more than once)"
, image_cache->total_extra_conversions, image_cache->total_extra_conversions_count
); } } while(0)
496 "Total number of excessive conversions: %d (from %d images converted more than once)",do { if (NSLOG_LEVEL_INFO >= NSLOG_LEVEL_VERBOSE) { static
nslog_entry_context_t _nslog_ctx = { &__nslog_category_netsurf
, NSLOG_LEVEL_INFO, "content/handlers/image/image_cache.c", sizeof
("content/handlers/image/image_cache.c") - 1, __PRETTY_FUNCTION__
, sizeof(__PRETTY_FUNCTION__) - 1, 498, }; nslog__log(&_nslog_ctx
, "Total number of excessive conversions: %d (from %d images converted more than once)"
, image_cache->total_extra_conversions, image_cache->total_extra_conversions_count
); } } while(0)
497 image_cache->total_extra_conversions,do { if (NSLOG_LEVEL_INFO >= NSLOG_LEVEL_VERBOSE) { static
nslog_entry_context_t _nslog_ctx = { &__nslog_category_netsurf
, NSLOG_LEVEL_INFO, "content/handlers/image/image_cache.c", sizeof
("content/handlers/image/image_cache.c") - 1, __PRETTY_FUNCTION__
, sizeof(__PRETTY_FUNCTION__) - 1, 498, }; nslog__log(&_nslog_ctx
, "Total number of excessive conversions: %d (from %d images converted more than once)"
, image_cache->total_extra_conversions, image_cache->total_extra_conversions_count
); } } while(0)
498 image_cache->total_extra_conversions_count)do { if (NSLOG_LEVEL_INFO >= NSLOG_LEVEL_VERBOSE) { static
nslog_entry_context_t _nslog_ctx = { &__nslog_category_netsurf
, NSLOG_LEVEL_INFO, "content/handlers/image/image_cache.c", sizeof
("content/handlers/image/image_cache.c") - 1, __PRETTY_FUNCTION__
, sizeof(__PRETTY_FUNCTION__) - 1, 498, }; nslog__log(&_nslog_ctx
, "Total number of excessive conversions: %d (from %d images converted more than once)"
, image_cache->total_extra_conversions, image_cache->total_extra_conversions_count
); } } while(0)
;
499
500 NSLOG(netsurf, INFO, "Bitmap of size %d had most (%d) conversions",do { if (NSLOG_LEVEL_INFO >= NSLOG_LEVEL_VERBOSE) { static
nslog_entry_context_t _nslog_ctx = { &__nslog_category_netsurf
, NSLOG_LEVEL_INFO, "content/handlers/image/image_cache.c", sizeof
("content/handlers/image/image_cache.c") - 1, __PRETTY_FUNCTION__
, sizeof(__PRETTY_FUNCTION__) - 1, 502, }; nslog__log(&_nslog_ctx
, "Bitmap of size %d had most (%d) conversions", image_cache->
peak_conversions_size, image_cache->peak_conversions); } }
while(0)
501 image_cache->peak_conversions_size,do { if (NSLOG_LEVEL_INFO >= NSLOG_LEVEL_VERBOSE) { static
nslog_entry_context_t _nslog_ctx = { &__nslog_category_netsurf
, NSLOG_LEVEL_INFO, "content/handlers/image/image_cache.c", sizeof
("content/handlers/image/image_cache.c") - 1, __PRETTY_FUNCTION__
, sizeof(__PRETTY_FUNCTION__) - 1, 502, }; nslog__log(&_nslog_ctx
, "Bitmap of size %d had most (%d) conversions", image_cache->
peak_conversions_size, image_cache->peak_conversions); } }
while(0)
502 image_cache->peak_conversions)do { if (NSLOG_LEVEL_INFO >= NSLOG_LEVEL_VERBOSE) { static
nslog_entry_context_t _nslog_ctx = { &__nslog_category_netsurf
, NSLOG_LEVEL_INFO, "content/handlers/image/image_cache.c", sizeof
("content/handlers/image/image_cache.c") - 1, __PRETTY_FUNCTION__
, sizeof(__PRETTY_FUNCTION__) - 1, 502, }; nslog__log(&_nslog_ctx
, "Bitmap of size %d had most (%d) conversions", image_cache->
peak_conversions_size, image_cache->peak_conversions); } }
while(0)
;
503
504 free(image_cache);
505
506 return NSERROR_OK;
507}
508
509/* exported interface documented in image_cache.h */
510nserror image_cache_add(struct content *content,
511 struct bitmap *bitmap,
512 image_cache_convert_fn *convert)
513{
514 struct image_cache_entry_s *centry;
515
516 /* bump the cache age by a ms to ensure multiple items are not
517 * added at exactly the same time
518 */
519 image_cache->current_age++;
520
521 centry = image_cache__find(content);
522 if (centry == NULL((void*)0)) {
523 /* new cache entry, content not previously added */
524 centry = calloc(1, sizeof(struct image_cache_entry_s));
525 if (centry == NULL((void*)0)) {
526 return NSERROR_NOMEM;
527 }
528 image_cache__link(centry);
529 centry->content = content;
530
531 centry->bitmap_size = content->width * content->height * 4llu;
532 }
533
534 NSLOG(netsurf, INFO, "centry %p, content %p, bitmap %p", centry,do { if (NSLOG_LEVEL_INFO >= NSLOG_LEVEL_VERBOSE) { static
nslog_entry_context_t _nslog_ctx = { &__nslog_category_netsurf
, NSLOG_LEVEL_INFO, "content/handlers/image/image_cache.c", sizeof
("content/handlers/image/image_cache.c") - 1, __PRETTY_FUNCTION__
, sizeof(__PRETTY_FUNCTION__) - 1, 535, }; nslog__log(&_nslog_ctx
, "centry %p, content %p, bitmap %p", centry, content, bitmap
); } } while(0)
535 content, bitmap)do { if (NSLOG_LEVEL_INFO >= NSLOG_LEVEL_VERBOSE) { static
nslog_entry_context_t _nslog_ctx = { &__nslog_category_netsurf
, NSLOG_LEVEL_INFO, "content/handlers/image/image_cache.c", sizeof
("content/handlers/image/image_cache.c") - 1, __PRETTY_FUNCTION__
, sizeof(__PRETTY_FUNCTION__) - 1, 535, }; nslog__log(&_nslog_ctx
, "centry %p, content %p, bitmap %p", centry, content, bitmap
); } } while(0)
;
536
537 centry->convert = convert;
538
539 /* set bitmap entry if one is passed, free extant one if present */
540 if (bitmap != NULL((void*)0)) {
541 if (centry->bitmap != NULL((void*)0)) {
542 guit->bitmap->destroy(centry->bitmap);
543 } else {
544 image_cache_stats_bitmap_add(centry);
545 }
546 centry->bitmap = bitmap;
547 } else {
548 /* no bitmap, check to see if we should speculatively convert */
549 if ((centry->convert != NULL((void*)0)) &&
550 (image_cache_speculate(content) == true1)) {
551 centry->bitmap = centry->convert(centry->content);
552
553 if (centry->bitmap != NULL((void*)0)) {
554 image_cache_stats_bitmap_add(centry);
555 } else {
556 image_cache->fail_count++;
557 }
558 }
559 }
560
561
562
563 return NSERROR_OK;
564}
565
566/* exported interface documented in image_cache.h */
567nserror image_cache_remove(struct content *content)
568{
569 struct image_cache_entry_s *centry;
570
571 /* get the cache entry */
572 centry = image_cache__find(content);
573 if (centry == NULL((void*)0)) {
574 NSLOG(netsurf, INFO,do { if (NSLOG_LEVEL_INFO >= NSLOG_LEVEL_VERBOSE) { static
nslog_entry_context_t _nslog_ctx = { &__nslog_category_netsurf
, NSLOG_LEVEL_INFO, "content/handlers/image/image_cache.c", sizeof
("content/handlers/image/image_cache.c") - 1, __PRETTY_FUNCTION__
, sizeof(__PRETTY_FUNCTION__) - 1, 575, }; nslog__log(&_nslog_ctx
, "Could not find cache entry for content (%p)", content); } }
while(0)
575 "Could not find cache entry for content (%p)", content)do { if (NSLOG_LEVEL_INFO >= NSLOG_LEVEL_VERBOSE) { static
nslog_entry_context_t _nslog_ctx = { &__nslog_category_netsurf
, NSLOG_LEVEL_INFO, "content/handlers/image/image_cache.c", sizeof
("content/handlers/image/image_cache.c") - 1, __PRETTY_FUNCTION__
, sizeof(__PRETTY_FUNCTION__) - 1, 575, }; nslog__log(&_nslog_ctx
, "Could not find cache entry for content (%p)", content); } }
while(0)
;
576 return NSERROR_NOT_FOUND;
577 }
578
579 image_cache__free_entry(centry);
580
581 return NSERROR_OK;
582}
583
584/* exported interface documented in image_cache.h */
585int image_cache_snsummaryf(char *string, size_t size, const char *fmt)
586{
587 size_t slen = 0; /* current output string length */
588 int fmtc = 0; /* current index into format string */
589 bool_Bool pct;
590 unsigned int op_count;
591 uint64_t op_size;
592
593 op_count = image_cache->hit_count +
594 image_cache->miss_count +
595 image_cache->fail_count;
596
597 op_size = image_cache->hit_size +
598 image_cache->miss_size +
599 image_cache->fail_size;
600
601 while((slen < size) && (fmt[fmtc] != 0)) {
602 if (fmt[fmtc] == '%') {
603 fmtc++;
604
605 /* check for percentage modifier */
606 if (fmt[fmtc] == 'p') {
607 fmtc++;
608 pct = true1;
609 } else {
610 pct = false0;
611 }
612
613#define FMTCHR(chr,fmt,var) case chr : \
614slen += snprintf(string + slen, size - slen, "%"fmt, image_cache->var); break
615
616#define FMTPCHR(chr,fmt,var,div) \
617case chr : \
618 if (pct) { \
619 if (div > 0) { \
620 slen += snprintf(string + slen, size - slen, "%"PRId64"l" "d", (uint64_t)((image_cache->var * 100) / div)); \
621 } else { \
622 slen += snprintf(string + slen, size - slen, "100"); \
623 } \
624 } else { \
625 slen += snprintf(string + slen, size - slen, "%"fmt, image_cache->var); \
626 } break
627
628
629 switch (fmt[fmtc]) {
630 case '%':
631 string[slen] = '%';
632 slen++;
633 break;
634
635 FMTCHR('a', PRIsizet"zu", params.limit);
636 FMTCHR('b', PRIsizet"zu", params.hysteresis);
637 FMTCHR('c', PRIsizet"zu", total_bitmap_size);
638 FMTCHR('d', "d", bitmap_count);
639 FMTCHR('e', "u", current_age / 1000);
640 FMTCHR('f', PRIsizet"zu", max_bitmap_size);
641 FMTCHR('g', "d", max_bitmap_size_count);
642 FMTCHR('h', "d", max_bitmap_count);
643 FMTCHR('i', PRIsizet"zu", max_bitmap_count_size);
644
645
646 case 'j':
647 slen += snprintf(string + slen, size - slen,
648 "%u", pct?100:op_count);
649 break;
650
651 FMTPCHR('k', "d", hit_count, op_count);
652 FMTPCHR('l', "d", miss_count, op_count);
653 FMTPCHR('m', "d", fail_count, op_count);
654
655 case 'n':
656 slen += snprintf(string + slen, size - slen,
657 "%"PRId64"l" "d", pct?100:op_size);
658 break;
659
660 FMTPCHR('o', PRId64"l" "d", hit_size, op_size);
661 FMTPCHR('q', PRId64"l" "d", miss_size, op_size);
662 FMTPCHR('r', PRId64"l" "d", fail_size, op_size);
663
664 FMTCHR('s', "d", total_unrendered);
665 FMTCHR('t', "d", specultive_miss_count);
666 FMTCHR('u', "d", total_extra_conversions);
667 FMTCHR('v', "d", total_extra_conversions_count);
668 FMTCHR('w', "u", peak_conversions_size);
669 FMTCHR('x', "d", peak_conversions);
670
671
672 }
673#undef FMTCHR
674#undef FMTPCHR
675
676 fmtc++;
677 } else {
678 string[slen] = fmt[fmtc];
679 slen++;
680 fmtc++;
681 }
682 }
683
684 /* Ensure that we NUL-terminate the output */
685 string[min(slen, size - 1)(((slen)<(size - 1))?(slen):(size - 1))] = '\0';
686
687 return slen;
688}
689
690/* exported interface documented in image_cache.h */
691int
692image_cache_snentryf(char *string,
693 size_t size,
694 unsigned int entryn,
695 const char *fmt)
696{
697 struct image_cache_entry_s *centry;
698 size_t slen = 0; /* current output string length */
699 int fmtc = 0; /* current index into format string */
700 lwc_string *origin; /* current entry's origin */
701
702 centry = image_cache__findn(entryn);
703 if (centry == NULL((void*)0))
704 return -1;
705
706 while((slen < size) && (fmt[fmtc] != 0)) {
707 if (fmt[fmtc] == '%') {
708 fmtc++;
709 switch (fmt[fmtc]) {
710 case 'e':
711 slen += snprintf(string + slen, size - slen,
712 "%u", entryn);
713 break;
714
715 case 'r':
716 slen += snprintf(string + slen, size - slen,
717 "%u", centry->redraw_count);
718 break;
719
720 case 'a':
721 slen += snprintf(string + slen, size - slen,
722 "%.2f", (float)((image_cache->current_age - centry->redraw_age)) / 1000);
723 break;
724
725
726 case 'c':
727 slen += snprintf(string + slen, size - slen,
728 "%d", centry->conversion_count);
729 break;
730
731 case 'g':
732 slen += snprintf(string + slen, size - slen,
733 "%.2f", (float)((image_cache->current_age - centry->bitmap_age)) / 1000);
734 break;
735
736 case 'k':
737 slen += snprintf(string + slen, size - slen,
738 "%p", centry->content);
739 break;
740
741 case 'U':
742 slen += snprintf(string + slen, size - slen,
743 "%s", nsurl_access(llcache_handle_get_url(centry->content->llcache)));
744 break;
745
746 case 'o':
747 if (nsurl_has_component(llcache_handle_get_url(
748 centry->content->llcache),
749 NSURL_HOST)) {
750 origin = nsurl_get_component(
751 llcache_handle_get_url(
752 centry->content->
753 llcache),
754 NSURL_HOST);
755
756 slen += snprintf(string + slen,
757 size - slen, "%s",
758 lwc_string_data(({((origin != ((void*)0)) ? (void) (0) : __assert_fail ("origin != NULL"
, "content/handlers/image/image_cache.c", 759, __extension__ __PRETTY_FUNCTION__
)); (const char *)((origin)+1);})
759 origin)({((origin != ((void*)0)) ? (void) (0) : __assert_fail ("origin != NULL"
, "content/handlers/image/image_cache.c", 759, __extension__ __PRETTY_FUNCTION__
)); (const char *)((origin)+1);})
);
760
761 lwc_string_unref(origin){ lwc_string *__lwc_s = (origin); ((__lwc_s != ((void*)0)) ? (
void) (0) : __assert_fail ("__lwc_s != NULL", "content/handlers/image/image_cache.c"
, 761, __extension__ __PRETTY_FUNCTION__)); __lwc_s->refcnt
--; if ((__lwc_s->refcnt == 0) || ((__lwc_s->refcnt == 1
) && (__lwc_s->insensitive == __lwc_s))) lwc_string_destroy
(__lwc_s); }
;
762 } else {
763 slen += snprintf(string + slen,
764 size - slen, "%s",
765 "localhost");
766 }
767 break;
768
769 case 's':
770 if (centry->bitmap != NULL((void*)0)) {
771 slen += snprintf(string + slen,
772 size - slen,
773 "%" PRIsizet"zu",
774 centry->bitmap_size);
775 } else {
776 slen += snprintf(string + slen,
777 size - slen,
778 "0");
779 }
780 break;
781 }
782 fmtc++;
783 } else {
784 string[slen] = fmt[fmtc];
785 slen++;
786 fmtc++;
787 }
788 }
789
790 /* Ensure that we NUL-terminate the output */
791 string[min(slen, size - 1)(((slen)<(size - 1))?(slen):(size - 1))] = '\0';
792
793 return slen;
794}
795
796
797/* exported interface documented in image_cache.h */
798bool_Bool image_cache_redraw(struct content *c,
799 struct content_redraw_data *data,
800 const struct rect *clip,
801 const struct redraw_context *ctx)
802{
803 struct image_cache_entry_s *centry;
804
805 /* get the cache entry */
806 centry = image_cache__find(c);
807 if (centry == NULL((void*)0)) {
808 NSLOG(netsurf, INFO,do { if (NSLOG_LEVEL_INFO >= NSLOG_LEVEL_VERBOSE) { static
nslog_entry_context_t _nslog_ctx = { &__nslog_category_netsurf
, NSLOG_LEVEL_INFO, "content/handlers/image/image_cache.c", sizeof
("content/handlers/image/image_cache.c") - 1, __PRETTY_FUNCTION__
, sizeof(__PRETTY_FUNCTION__) - 1, 809, }; nslog__log(&_nslog_ctx
, "Could not find cache entry for content (%p)", c); } } while
(0)
809 "Could not find cache entry for content (%p)", c)do { if (NSLOG_LEVEL_INFO >= NSLOG_LEVEL_VERBOSE) { static
nslog_entry_context_t _nslog_ctx = { &__nslog_category_netsurf
, NSLOG_LEVEL_INFO, "content/handlers/image/image_cache.c", sizeof
("content/handlers/image/image_cache.c") - 1, __PRETTY_FUNCTION__
, sizeof(__PRETTY_FUNCTION__) - 1, 809, }; nslog__log(&_nslog_ctx
, "Could not find cache entry for content (%p)", c); } } while
(0)
;
810 return false0;
811 }
812
813 if (centry->bitmap == NULL((void*)0)) {
814 if (centry->convert != NULL((void*)0)) {
815 centry->bitmap = centry->convert(centry->content);
816 }
817
818 if (centry->bitmap != NULL((void*)0)) {
819 image_cache_stats_bitmap_add(centry);
820 image_cache->miss_count++;
821 image_cache->miss_size += centry->bitmap_size;
822 } else {
823 image_cache->fail_count++;
824 image_cache->fail_size += centry->bitmap_size;
825 return false0;
826 }
827 } else {
828 image_cache->hit_count++;
829 image_cache->hit_size += centry->bitmap_size;
830 }
831
832
833 /* update statistics */
834 centry->redraw_count++;
835 centry->redraw_age = image_cache->current_age;
836
837 return image_bitmap_plot(centry->bitmap, data, clip, ctx);
838}
839
840/* exported interface documented in image_cache.h */
841void image_cache_destroy(struct content *content)
842{
843 struct image_cache_entry_s *centry;
844
845 /* get the cache entry */
846 centry = image_cache__find(content);
847 if (centry == NULL((void*)0)) {
848 NSLOG(netsurf, INFO,do { if (NSLOG_LEVEL_INFO >= NSLOG_LEVEL_VERBOSE) { static
nslog_entry_context_t _nslog_ctx = { &__nslog_category_netsurf
, NSLOG_LEVEL_INFO, "content/handlers/image/image_cache.c", sizeof
("content/handlers/image/image_cache.c") - 1, __PRETTY_FUNCTION__
, sizeof(__PRETTY_FUNCTION__) - 1, 849, }; nslog__log(&_nslog_ctx
, "Could not find cache entry for content (%p)", content); } }
while(0)
849 "Could not find cache entry for content (%p)", content)do { if (NSLOG_LEVEL_INFO >= NSLOG_LEVEL_VERBOSE) { static
nslog_entry_context_t _nslog_ctx = { &__nslog_category_netsurf
, NSLOG_LEVEL_INFO, "content/handlers/image/image_cache.c", sizeof
("content/handlers/image/image_cache.c") - 1, __PRETTY_FUNCTION__
, sizeof(__PRETTY_FUNCTION__) - 1, 849, }; nslog__log(&_nslog_ctx
, "Could not find cache entry for content (%p)", content); } }
while(0)
;
850 } else {
851 image_cache__free_entry(centry);
852 }
853}
854
855/* exported interface documented in image_cache.h */
856void *image_cache_get_internal(const struct content *c, void *context)
857{
858 return image_cache_get_bitmap(c);
859}
860
861/* exported interface documented in image_cache.h */
862bool_Bool image_cache_is_opaque(struct content *c)
863{
864 struct bitmap *bmp;
865 bmp = image_cache_get_bitmap(c);
866 if (bmp != NULL((void*)0)) {
867 return guit->bitmap->get_opaque(bmp);
868 }
869 return false0;
870}
871
872/* exported interface documented in image_cache.h */
873content_type image_cache_content_type(void)
874{
875 return CONTENT_IMAGE;
876}