From 409a9dbe9da64b4d75fec1f511e168c94e60e35b Mon Sep 17 00:00:00 2001 From: =?utf8?q?Mattias=20Engdeg=C3=A5rd?= Date: Sat, 19 Dec 2020 16:47:32 +0100 Subject: [PATCH] image-cache-size improvements Implement for non-Cairo X11 and NS. Count masks as well, and XImage objects on X11. * src/image.c (image_size_in_bytes): New. (image_frame_cache_size): Use image_size_in_bytes. * src/nsterm.h: * src/nsimage.m (ns_image_size_in_bytes, [EmacsImage sizeInBytes]): New function and method. * src/w32gui.h: * src/w32term.c (w32_image_size): Update signature. --- src/image.c | 58 ++++++++++++++++++++++++++++++++++++--------------- src/nsimage.m | 22 +++++++++++++++++++ src/nsterm.h | 2 ++ src/w32gui.h | 2 +- src/w32term.c | 4 ++-- 5 files changed, 68 insertions(+), 20 deletions(-) diff --git a/src/image.c b/src/image.c index dc06e9ce208..d0ae44e7df7 100644 --- a/src/image.c +++ b/src/image.c @@ -1793,37 +1793,61 @@ which is then usually a filename. */) } static size_t -image_frame_cache_size (struct frame *f) +image_size_in_bytes (struct image *img) { - size_t total = 0; + size_t size = 0; + #if defined USE_CAIRO - struct image_cache *c = FRAME_IMAGE_CACHE (f); + Emacs_Pixmap pm = img->pixmap; + if (pm) + size += pm->height * pm->bytes_per_line; + Emacs_Pixmap msk = img->mask; + if (msk) + size += msk->height * msk->bytes_per_line; - if (!c) - return 0; +#elif defined HAVE_X_WINDOWS + /* Use a nominal depth of 24 bpp for pixmap and 1 bpp for mask, + to avoid having to query the server. */ + if (img->pixmap != NO_PIXMAP) + size += img->width * img->height * 3; + if (img->mask != NO_PIXMAP) + size += img->width * img->height / 8; + + if (img->ximg && img->ximg->data) + size += img->ximg->bytes_per_line * img->ximg->height; + if (img->mask_img && img->mask_img->data) + size += img->mask_img->bytes_per_line * img->mask_img->height; - for (ptrdiff_t i = 0; i < c->used; ++i) - { - struct image *img = c->images[i]; +#elif defined HAVE_NS + if (img->pixmap) + size += ns_image_size_in_bytes (img->pixmap); + if (img->mask) + size += ns_image_size_in_bytes (img->mask); - if (img && img->pixmap && img->pixmap != NO_PIXMAP) - total += img->pixmap->width * img->pixmap->height * - img->pixmap->bits_per_pixel / 8; - } #elif defined HAVE_NTGUI - struct image_cache *c = FRAME_IMAGE_CACHE (f); + if (img->pixmap) + size += w32_image_size (img->pixmap); + if (img->mask) + size += w32_image_size (img->mask); + +#endif + + return size; +} +static size_t +image_frame_cache_size (struct frame *f) +{ + struct image_cache *c = FRAME_IMAGE_CACHE (f); if (!c) return 0; + size_t total = 0; for (ptrdiff_t i = 0; i < c->used; ++i) { struct image *img = c->images[i]; - - if (img && img->pixmap && img->pixmap != NO_PIXMAP) - total += w32_image_size (img); + total += img ? image_size_in_bytes (img) : 0; } -#endif return total; } diff --git a/src/nsimage.m b/src/nsimage.m index da6f01cf6a3..f9fb368ba80 100644 --- a/src/nsimage.m +++ b/src/nsimage.m @@ -235,6 +235,11 @@ ns_set_alpha (void *img, int x, int y, unsigned char a) [(EmacsImage *)img setAlphaAtX: x Y: y to: a]; } +size_t +ns_image_size_in_bytes (void *img) +{ + return [(EmacsImage *)img sizeInBytes]; +} /* ========================================================================== @@ -610,5 +615,22 @@ ns_set_alpha (void *img, int x, int y, unsigned char a) smoothing = s; } +/* Approximate allocated size of image in bytes. */ +- (size_t) sizeInBytes +{ + size_t bytes = 0; + NSImageRep *rep; + NSEnumerator *reps = [[self representations] objectEnumerator]; + while ((rep = (NSImageRep *) [reps nextObject])) + { + if ([rep respondsToSelector: @selector (bytesPerRow)]) + { + NSBitmapImageRep *bmr = (NSBitmapImageRep *) rep; + bytes += [bmr bytesPerRow] * [bmr numberOfPlanes] * [bmr pixelsHigh]; + } + } + return bytes; +} + @end diff --git a/src/nsterm.h b/src/nsterm.h index f292993d8f7..94472ec1070 100644 --- a/src/nsterm.h +++ b/src/nsterm.h @@ -666,6 +666,7 @@ typedef id instancetype; - (BOOL)setFrame: (unsigned int) index; - (void)setTransform: (double[3][3]) m; - (void)setSmoothing: (BOOL)s; +- (size_t)sizeInBytes; @end @@ -1195,6 +1196,7 @@ extern void ns_set_alpha (void *img, int x, int y, unsigned char a); extern int ns_display_pixel_height (struct ns_display_info *); extern int ns_display_pixel_width (struct ns_display_info *); +extern size_t ns_image_size_in_bytes (void *img); /* This in nsterm.m */ extern float ns_antialias_threshold; diff --git a/src/w32gui.h b/src/w32gui.h index fc8131130fb..f6cfa9fb87e 100644 --- a/src/w32gui.h +++ b/src/w32gui.h @@ -46,7 +46,7 @@ extern int w32_load_image (struct frame *f, struct image *img, Lisp_Object spec_file, Lisp_Object spec_data); extern bool w32_can_use_native_image_api (Lisp_Object); extern void w32_gdiplus_shutdown (void); -extern size_t w32_image_size (struct image *); +extern size_t w32_image_size (Emacs_Pixmap); #define FACE_DEFAULT (~0) diff --git a/src/w32term.c b/src/w32term.c index a038e4593f4..989b056ff2e 100644 --- a/src/w32term.c +++ b/src/w32term.c @@ -1992,12 +1992,12 @@ w32_draw_image_foreground (struct glyph_string *s) } size_t -w32_image_size (struct image *img) +w32_image_size (Emacs_Pixmap pixmap) { BITMAP bm_info; size_t rv = 0; - if (GetObject (img->pixmap, sizeof (BITMAP), &bm_info)) + if (GetObject (pixmap, sizeof (BITMAP), &bm_info)) rv = bm_info.bmWidth * bm_info.bmHeight * bm_info.bmBitsPixel / 8; return rv; } -- 2.39.2