for (tem = f->conversion.actions; tem; tem = tem->next)
mark_object (tem->data);
#endif
+
+#ifdef HAVE_WINDOW_SYSTEM
+ /* Mark this frame's image cache, though it might be common to several
+ frames with the same font size. */
+ if (FRAME_IMAGE_CACHE (f))
+ mark_image_cache (FRAME_IMAGE_CACHE (f));
+#endif /* HAVE_WINDOW_SYSTEM */
}
static void
for (t = terminal_list; t; t = t->next_terminal)
{
eassert (t->name != NULL);
-#ifdef HAVE_WINDOW_SYSTEM
- /* If a terminal object is reachable from a stacpro'ed object,
- it might have been marked already. Make sure the image cache
- gets marked. */
- mark_image_cache (t->image_cache);
-#endif /* HAVE_WINDOW_SYSTEM */
if (!vectorlike_marked_p (&t->header))
mark_vectorlike (&t->header);
}
#ifndef ANDROID_STUBIFY
-/* Some kind of reference count for the image cache. */
-static ptrdiff_t image_cache_refcount;
-
/* The frame of the currently visible tooltip, or nil if none. */
static Lisp_Object tip_frame;
/* If frame is ``official'', nothing to do. */
if (NILP (Fmemq (frame, Vframe_list)))
{
- /* If the frame's image cache refcount is still the same as our
- private shadow variable, it means we are unwinding a frame
- for which we didn't yet call init_frame_faces, where the
- refcount is incremented. Therefore, we increment it here, so
- that free_frame_faces, called in x_free_frame_resources
- below, will not mistakenly decrement the counter that was not
- incremented yet to account for this new frame. */
- if (FRAME_IMAGE_CACHE (f) != NULL
- && FRAME_IMAGE_CACHE (f)->refcount == image_cache_refcount)
- FRAME_IMAGE_CACHE (f)->refcount++;
-
android_free_frame_resources (f);
free_glyphs (f);
return Qt;
register_font_driver (&androidfont_driver, f);
register_font_driver (&android_sfntfont_driver, f);
- image_cache_refcount = (FRAME_IMAGE_CACHE (f)
- ? FRAME_IMAGE_CACHE (f)->refcount
- : 0);
-
gui_default_parameter (f, parms, Qfont_backend, Qnil,
"fontBackend", "FontBackend", RES_TYPE_STRING);
register_font_driver (&androidfont_driver, f);
register_font_driver (&android_sfntfont_driver, f);
- image_cache_refcount
- = FRAME_IMAGE_CACHE (f) ? FRAME_IMAGE_CACHE (f)->refcount : 0;
-
gui_default_parameter (f, parms, Qfont_backend, Qnil,
"fontBackend", "FontBackend", RES_TYPE_STRING);
/* Reference count (number of frames sharing this cache). */
ptrdiff_t refcount;
+
+ /* Column width by which images whose QCscale property is Qdefault
+ will be scaled, which is 10 or FRAME_COLUMN_WIDTH of each frame
+ assigned this image cache, whichever is greater. */
+ int scaling_col_width;
};
/* Size of bucket vector of image caches. Should be prime. */
int face_with_height (struct frame *, int, int);
int lookup_derived_face (struct window *, struct frame *,
Lisp_Object, int, bool);
+#ifdef HAVE_WINDOW_SYSTEM
+extern struct image_cache *share_image_cache (struct frame *f);
+#endif /* HAVE_WINDOW_SYSTEM */
void init_frame_faces (struct frame *);
void free_frame_faces (struct frame *);
void recompute_basic_faces (struct frame *);
f->tooltip = false;
f->was_invisible = false;
f->child_frame_border_width = -1;
+ f->face_caches = NULL;
+ f->image_cache = NULL;
f->last_tab_bar_item = -1;
#ifndef HAVE_EXT_TOOL_BAR
f->last_tool_bar_item = -1;
gui_set_font (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
{
Lisp_Object font_object;
- int fontset = -1;
+ int fontset = -1, iwidth;
/* Set the frame parameter back to the old value because we may
fail to use ARG as the new parameter value. */
/* Recalculate toolbar height. */
f->n_tool_bar_rows = 0;
- /* Clean F's image cache of images whose values derive from the font
- width. */
- clear_image_cache (f, Qauto);
+ /* Re-initialize F's image cache. Since `set_new_font_hook' might
+ have changed the frame's column width, by which images are scaled,
+ it might likewise need to be assigned a different image cache, or
+ have its existing cache adjusted, if by coincidence it is its sole
+ user. */
+
+ iwidth = max (10, FRAME_COLUMN_WIDTH (f));
+ if (FRAME_IMAGE_CACHE (f)
+ && (iwidth != FRAME_IMAGE_CACHE (f)->scaling_col_width))
+ {
+ eassert (FRAME_IMAGE_CACHE (f)->refcount >= 1);
+ if (FRAME_IMAGE_CACHE (f)->refcount == 1)
+ {
+ /* This frame is the only user of this image cache. */
+ FRAME_IMAGE_CACHE (f)->scaling_col_width = iwidth;
+ /* Clean F's image cache of images whose values are derived
+ from the font width. */
+ clear_image_cache (f, Qauto);
+ }
+ else
+ {
+ /* Release the current image cache, and reuse or allocate a
+ new image cache with IWIDTH. */
+ FRAME_IMAGE_CACHE (f)->refcount--;
+ FRAME_IMAGE_CACHE (f) = share_image_cache (f);
+ }
+ }
/* Ensure we redraw it. */
clear_current_matrices (f);
/* Cache of realized faces. */
struct face_cache *face_cache;
+#ifdef HAVE_WINDOW_SYSTEM
+ /* Cache of realized images, which may be shared with other
+ frames. */
+ struct image_cache *image_cache;
+#endif /* HAVE_WINDOW_SYSTEM */
+
/* Tab-bar item index of the item on which a mouse button was pressed. */
int last_tab_bar_item;
#define FRAME_KBOARD(f) ((f)->terminal->kboard)
/* Return a pointer to the image cache of frame F. */
-#define FRAME_IMAGE_CACHE(F) ((F)->terminal->image_cache)
+#define FRAME_IMAGE_CACHE(F) ((F)->image_cache)
#define XFRAME(p) \
(eassert (FRAMEP (p)), XUNTAG (p, Lisp_Vectorlike, struct frame))
static void haiku_explicitly_set_name (struct frame *, Lisp_Object, Lisp_Object);
static void haiku_set_title (struct frame *, Lisp_Object, Lisp_Object);
-/* The number of references to an image cache. */
-static ptrdiff_t image_cache_refcount;
-
static Lisp_Object
get_geometry_from_preferences (struct haiku_display_info *dpyinfo,
Lisp_Object parms)
/* If frame is ``official'', nothing to do. */
if (NILP (Fmemq (frame, Vframe_list)))
{
-#if defined GLYPH_DEBUG && defined ENABLE_CHECKING
- struct haiku_display_info *dpyinfo = FRAME_DISPLAY_INFO (f);
-#endif
-
- /* If the frame's image cache refcount is still the same as our
- private shadow variable, it means we are unwinding a frame
- for which we didn't yet call init_frame_faces, where the
- refcount is incremented. Therefore, we increment it here, so
- that free_frame_faces, called in free_frame_resources later,
- will not mistakenly decrement the counter that was not
- incremented yet to account for this new frame. */
- if (FRAME_IMAGE_CACHE (f) != NULL
- && FRAME_IMAGE_CACHE (f)->refcount == image_cache_refcount)
- FRAME_IMAGE_CACHE (f)->refcount++;
-
haiku_free_frame_resources (f);
free_glyphs (f);
-
-#if defined GLYPH_DEBUG && defined ENABLE_CHECKING
- /* Check that reference counts are indeed correct. */
- if (dpyinfo->terminal->image_cache)
- eassert (dpyinfo->terminal->image_cache->refcount == image_cache_refcount);
-#endif
}
}
#endif
register_font_driver (&haikufont_driver, f);
- image_cache_refcount =
- FRAME_IMAGE_CACHE (f) ? FRAME_IMAGE_CACHE (f)->refcount : 0;
-
gui_default_parameter (f, parms, Qfont_backend, Qnil,
"fontBackend", "FontBackend", RES_TYPE_STRING);
#endif
register_font_driver (&haikufont_driver, f);
- image_cache_refcount =
- FRAME_IMAGE_CACHE (f) ? FRAME_IMAGE_CACHE (f)->refcount : 0;
-
gui_default_parameter (f, parms, Qfont_backend, Qnil,
"fontBackend", "FontBackend", RES_TYPE_STRING);
c->used = c->refcount = 0;
c->images = xmalloc (c->size * sizeof *c->images);
c->buckets = xzalloc (IMAGE_CACHE_BUCKETS_SIZE * sizeof *c->buckets);
+ /* This value should never be encountered. */
+ c->scaling_col_width = -1;
return c;
}
ptrdiff_t i;
if (!c)
- c = FRAME_IMAGE_CACHE (f) = make_image_cache ();
+ {
+ c = FRAME_IMAGE_CACHE (f) = share_image_cache (f);
+ c->refcount++;
+ }
/* Find a free slot in c->images. */
for (i = 0; i < c->used; ++i)
static Lisp_Object as_script, *as_result;
static int as_status;
-static ptrdiff_t image_cache_refcount;
-
static struct ns_display_info *ns_display_info_for_name (Lisp_Object);
/* ==========================================================================
/* If frame is ``official'', nothing to do. */
if (NILP (Fmemq (frame, Vframe_list)))
{
-#if defined GLYPH_DEBUG && defined ENABLE_CHECKING
- struct ns_display_info *dpyinfo = FRAME_DISPLAY_INFO (f);
-#endif
-
- /* If the frame's image cache refcount is still the same as our
- private shadow variable, it means we are unwinding a frame
- for which we didn't yet call init_frame_faces, where the
- refcount is incremented. Therefore, we increment it here, so
- that free_frame_faces, called in ns_free_frame_resources
- below, will not mistakenly decrement the counter that was not
- incremented yet to account for this new frame. */
- if (FRAME_IMAGE_CACHE (f) != NULL
- && FRAME_IMAGE_CACHE (f)->refcount == image_cache_refcount)
- FRAME_IMAGE_CACHE (f)->refcount++;
-
ns_free_frame_resources (f);
free_glyphs (f);
-
-#if defined GLYPH_DEBUG && defined ENABLE_CHECKING
- /* Check that reference counts are indeed correct. */
- eassert (dpyinfo->terminal->image_cache->refcount == image_cache_refcount);
-#endif
-
return Qt;
}
#include "xsettings.h"
#include "atimer.h"
-static ptrdiff_t image_cache_refcount;
-
static int x_decode_color (struct frame *f, Lisp_Object color_name,
int mono_color);
static struct pgtk_display_info *pgtk_display_info_for_name (Lisp_Object);
/* If frame is ``official'', nothing to do. */
if (NILP (Fmemq (frame, Vframe_list)))
{
- /* If the frame's image cache refcount is still the same as our
- private shadow variable, it means we are unwinding a frame
- for which we didn't yet call init_frame_faces, where the
- refcount is incremented. Therefore, we increment it here, so
- that free_frame_faces, called in x_free_frame_resources
- below, will not mistakenly decrement the counter that was not
- incremented yet to account for this new frame. */
- if (FRAME_IMAGE_CACHE (f) != NULL
- && FRAME_IMAGE_CACHE (f)->refcount == image_cache_refcount)
- FRAME_IMAGE_CACHE (f)->refcount++;
-
pgtk_free_frame_resources (f);
free_glyphs (f);
return Qt;
register_font_driver (&ftcrhbfont_driver, f);
#endif /* HAVE_HARFBUZZ */
- image_cache_refcount =
- FRAME_IMAGE_CACHE (f) ? FRAME_IMAGE_CACHE (f)->refcount : 0;
-
gui_default_parameter (f, parms, Qfont_backend, Qnil,
"fontBackend", "FontBackend", RES_TYPE_STRING);
register_font_driver (&ftcrhbfont_driver, f);
#endif /* HAVE_HARFBUZZ */
- image_cache_refcount =
- FRAME_IMAGE_CACHE (f) ? FRAME_IMAGE_CACHE (f)->refcount : 0;
-
gui_default_parameter (f, parms, Qfont_backend, Qnil,
"fontBackend", "FontBackend", RES_TYPE_STRING);
/* The terminal's keyboard object. */
struct kboard *kboard;
-#ifdef HAVE_WINDOW_SYSTEM
- /* Cache of images. */
- struct image_cache *image_cache;
-#endif /* HAVE_WINDOW_SYSTEM */
-
/* Device-type dependent data shared amongst all frames on this terminal. */
union display_info
{
static unsigned menu_free_timer = 0;
#ifdef GLYPH_DEBUG
-static ptrdiff_t image_cache_refcount;
static int dpyinfo_refcount;
#endif
{
#ifdef GLYPH_DEBUG
struct w32_display_info *dpyinfo = FRAME_DISPLAY_INFO (f);
-
- /* If the frame's image cache refcount is still the same as our
- private shadow variable, it means we are unwinding a frame
- for which we didn't yet call init_frame_faces, where the
- refcount is incremented. Therefore, we increment it here, so
- that free_frame_faces, called in w32_free_frame_resources
- below, will not mistakenly decrement the counter that was not
- incremented yet to account for this new frame. */
- if (FRAME_IMAGE_CACHE (f) != NULL
- && FRAME_IMAGE_CACHE (f)->refcount == image_cache_refcount)
- FRAME_IMAGE_CACHE (f)->refcount++;
#endif
w32_free_frame_resources (f);
#ifdef GLYPH_DEBUG
/* Check that reference counts are indeed correct. */
eassert (dpyinfo->reference_count == dpyinfo_refcount);
- eassert ((dpyinfo->terminal->image_cache == NULL
- && image_cache_refcount == 0)
- || (dpyinfo->terminal->image_cache != NULL
- && dpyinfo->terminal->image_cache->refcount == image_cache_refcount));
#endif
return Qt;
}
record_unwind_protect (do_unwind_create_frame, frame);
#ifdef GLYPH_DEBUG
- image_cache_refcount =
- FRAME_IMAGE_CACHE (f) ? FRAME_IMAGE_CACHE (f)->refcount : 0;
dpyinfo_refcount = dpyinfo->reference_count;
#endif /* GLYPH_DEBUG */
f->tooltip = true;
#ifdef GLYPH_DEBUG
- image_cache_refcount =
- FRAME_IMAGE_CACHE (f) ? FRAME_IMAGE_CACHE (f)->refcount : 0;
dpyinfo_refcount = dpyinfo->reference_count;
#endif /* GLYPH_DEBUG */
FRAME_KBOARD (f) = kb;
Frames and faces
***********************************************************************/
+#ifdef HAVE_WINDOW_SYSTEM
+
+/* Find an existing image cache registered for a frame on F's display
+ and with a `scaling_col_width' of F's FRAME_COLUMN_WIDTH, or, in the
+ absence of an eligible image cache, allocate an image cache with the
+ same width value. */
+
+struct image_cache *
+share_image_cache (struct frame *f)
+{
+ int width = max (10, FRAME_COLUMN_WIDTH (f));
+ Lisp_Object tail, frame;
+ struct image_cache *cache;
+
+ FOR_EACH_FRAME (tail, frame)
+ {
+ struct frame *x = XFRAME (frame);
+
+ if (FRAME_TERMINAL (x) == FRAME_TERMINAL (f)
+ && FRAME_IMAGE_CACHE (x)
+ && FRAME_IMAGE_CACHE (x)->scaling_col_width == width)
+ return FRAME_IMAGE_CACHE (x);
+ }
+
+ cache = make_image_cache ();
+ cache->scaling_col_width = width;
+ return cache;
+}
+
+#endif /* HAVE_WINDOW_SYSTEM */
+
/* Initialize face cache and basic faces for frame F. */
void
FRAME_FACE_CACHE (f) = make_face_cache (f);
#ifdef HAVE_WINDOW_SYSTEM
- /* Make the image cache. */
+ /* Make or share an image cache. */
if (FRAME_WINDOW_P (f))
{
- /* We initialize the image cache when creating the first frame
- on a terminal, and not during terminal creation. This way,
- `x-open-connection' on a tty won't create an image cache. */
- if (FRAME_IMAGE_CACHE (f) == NULL)
- FRAME_IMAGE_CACHE (f) = make_image_cache ();
+ FRAME_IMAGE_CACHE (f) = share_image_cache (f);
++FRAME_IMAGE_CACHE (f)->refcount;
}
#endif /* HAVE_WINDOW_SYSTEM */
#define MAXREQUEST(dpy) (XMaxRequestSize (dpy))
-static ptrdiff_t image_cache_refcount;
#ifdef GLYPH_DEBUG
static int dpyinfo_refcount;
#endif
/* If frame is ``official'', nothing to do. */
if (NILP (Fmemq (frame, Vframe_list)))
{
-#if defined GLYPH_DEBUG && defined ENABLE_CHECKING
- struct x_display_info *dpyinfo = FRAME_DISPLAY_INFO (f);
-#endif
-
- /* If the frame's image cache refcount is still the same as our
- private shadow variable, it means we are unwinding a frame
- for which we didn't yet call init_frame_faces, where the
- refcount is incremented. Therefore, we increment it here, so
- that free_frame_faces, called in x_free_frame_resources
- below, will not mistakenly decrement the counter that was not
- incremented yet to account for this new frame. */
- if (FRAME_IMAGE_CACHE (f) != NULL
- && FRAME_IMAGE_CACHE (f)->refcount == image_cache_refcount)
- FRAME_IMAGE_CACHE (f)->refcount++;
-
x_free_frame_resources (f);
free_glyphs (f);
-
#if defined GLYPH_DEBUG && defined ENABLE_CHECKING
/* Check that reference counts are indeed correct. */
eassert (dpyinfo->reference_count == dpyinfo_refcount);
- eassert (dpyinfo->terminal->image_cache->refcount == image_cache_refcount);
-#endif
+#endif /* GLYPH_DEBUG && ENABLE_CHECKING */
return Qt;
}
#endif /* HAVE_FREETYPE */
#endif /* not USE_CAIRO */
register_font_driver (&xfont_driver, f);
-
- image_cache_refcount =
- FRAME_IMAGE_CACHE (f) ? FRAME_IMAGE_CACHE (f)->refcount : 0;
#ifdef GLYPH_DEBUG
dpyinfo_refcount = dpyinfo->reference_count;
#endif /* GLYPH_DEBUG */
#endif /* not USE_CAIRO */
register_font_driver (&xfont_driver, f);
- image_cache_refcount =
- FRAME_IMAGE_CACHE (f) ? FRAME_IMAGE_CACHE (f)->refcount : 0;
#ifdef GLYPH_DEBUG
dpyinfo_refcount = dpyinfo->reference_count;
#endif /* GLYPH_DEBUG */