Last active
April 10, 2018 14:38
-
-
Save rzl24ozi/7a5c9f0ad8f8ec95e4664600db9247c6 to your computer and use it in GitHub Desktop.
add image fit option to emacs
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
--- ./lisp/image-mode.el.orig 2018-01-09 05:23:57.000000000 +0900 | |
+++ ./lisp/image-mode.el 2018-04-10 23:10:36.891658700 +0900 | |
@@ -758,9 +758,12 @@ | |
(edges (and (null image-transform-resize) | |
(window-inside-pixel-edges | |
(get-buffer-window (current-buffer))))) | |
+ (type (image-type file-or-data nil data-p)) | |
(type (if (fboundp 'imagemagick-types) | |
- 'imagemagick | |
- (image-type file-or-data nil data-p))) | |
+ (if (assoc type image-fit-option-alist) | |
+ type | |
+ 'imagemagick) | |
+ type)) | |
(image (if (not edges) | |
(create-image file-or-data type data-p) | |
(create-image file-or-data type data-p | |
--- ./lisp/image.el.orig 2018-03-13 00:59:18.000000000 +0900 | |
+++ ./lisp/image.el 2018-04-10 23:10:36.903685400 +0900 | |
@@ -240,6 +240,15 @@ | |
(nconc (list image-directory) | |
(delete image-directory (copy-sequence (or path load-path)))))) | |
+;;;###autoload | |
+(defcustom image-fit-option-alist nil | |
+ "Alist of (IMAGE-TYPE . FIT-OPTION) pairs used by image loader to specify image size. | |
+the FIT-OPTION is one of 'never, 'frame, 'width-or-height, 'width or 'height. | |
+Note: All image loaders are not supporting this `fit' capability. | |
+" | |
+ :type 'sexp | |
+ :initialize 'custom-initialize-default | |
+ :group 'image) | |
;; Used to be in image-type-header-regexps, but now not used anywhere | |
;; (since 2009-08-28). | |
--- ./lisp/startup.el.orig 2018-03-13 00:59:18.000000000 +0900 | |
+++ ./lisp/startup.el 2018-04-10 23:10:36.916713800 +0900 | |
@@ -1689,7 +1689,7 @@ | |
(defun fancy-splash-head () | |
"Insert the head part of the splash screen into the current buffer." | |
(let* ((image-file (fancy-splash-image-file)) | |
- (img (create-image image-file)) | |
+ (img (create-image image-file nil nil :fit 'never)) | |
(image-width (and img (car (image-size img)))) | |
(window-width (window-width))) | |
(when img | |
--- ./src/image.c.orig 2018-03-13 00:59:18.000000000 +0900 | |
+++ ./src/image.c 2018-04-10 23:10:36.930744900 +0900 | |
@@ -594,6 +594,102 @@ | |
return p; | |
} | |
+Lisp_Object Qnever, Qwidth_or_height; | |
+ | |
+static void image_error (const char *format, ...); | |
+static int get_fit_size(Lisp_Object opt, const struct frame *f, | |
+ int *w, int *h, | |
+ Lisp_Object image_type, int rise_error) | |
+{ | |
+ if (NILP(opt)) | |
+ return 0; | |
+ | |
+ if (EQ(opt, Qnever)) { | |
+ *w = *h = 0; | |
+ } else if (EQ(opt, Qframe)) { | |
+ *w = FRAME_PIXEL_WIDTH (f) - FRAME_CONFIG_SCROLL_BAR_WIDTH (f) - FRAME_SCROLL_BAR_AREA_WIDTH (f); | |
+ *h = FRAME_PIXEL_HEIGHT (f); | |
+ } else if (EQ(opt, Qwidth_or_height)) { | |
+ *w = -(FRAME_PIXEL_WIDTH (f) - FRAME_CONFIG_SCROLL_BAR_WIDTH (f) - FRAME_SCROLL_BAR_AREA_WIDTH (f)); | |
+ *h = -FRAME_PIXEL_HEIGHT (f); | |
+ } else if (EQ(opt, Qwidth)) { | |
+ *w = FRAME_PIXEL_WIDTH (f) - FRAME_CONFIG_SCROLL_BAR_WIDTH (f) - FRAME_SCROLL_BAR_AREA_WIDTH (f); | |
+ *h = 0; | |
+ } else if (EQ(opt, Qheight)) { | |
+ *w = 0; | |
+ *h = FRAME_PIXEL_HEIGHT (f); | |
+ } else { | |
+ if (rise_error) | |
+ xsignal2 (Qnil, build_string("unknown fit type"), opt); | |
+ else | |
+ image_error ("Invalid fit option for %s", image_type, Qnil); | |
+ return -1; | |
+ } | |
+ return 1; | |
+} | |
+ | |
+static Lisp_Object image_spec_value (Lisp_Object, Lisp_Object, bool *); | |
+static int | |
+lookup_fit_size(Lisp_Object image_type, | |
+ const struct frame *f, | |
+ const struct image *img, | |
+ int *w, int *h, int rise_error) | |
+{ | |
+ Lisp_Object a, err, pred; | |
+ static const struct frame f_ = {0}; | |
+ int w_, h_; | |
+ int r; | |
+ | |
+// assert(SYMBOLP (image_type)); | |
+ | |
+ if (img && | |
+ (r = get_fit_size(image_spec_value(img->spec, QCfit, NULL), | |
+ f, w, h, image_type, rise_error)) != 0) | |
+ return r; | |
+ | |
+#if 0 | |
+ if (!CONSP (err = Vimage_fit_option_alist)) { | |
+ pred = Qconsp; | |
+ goto error; | |
+ } | |
+#endif | |
+ | |
+ for (a = Vimage_fit_option_alist; !NILP(a); a = XCDR(a)) { | |
+ Lisp_Object o; | |
+ { | |
+ Lisp_Object e = XCAR(a); | |
+ | |
+ if (!CONSP(err = e)) { | |
+ pred = Qconsp; | |
+ goto error; | |
+ } | |
+ | |
+ if (!EQ(XCAR(e), image_type)) | |
+ continue; | |
+ o = XCDR(e); | |
+ } | |
+ | |
+ if (!SYMBOLP(err = o)) { | |
+ pred = Qsymbolp; | |
+ goto error; | |
+ } | |
+ if (f) | |
+ return get_fit_size(o, f, w, h, image_type, rise_error); | |
+ get_fit_size(o, &f_, &w_, &h_, image_type, rise_error); | |
+ } | |
+ | |
+ /* not found */ | |
+ if (f) | |
+ *w = *h = 0; | |
+ return 0; | |
+ | |
+ error: | |
+ if (rise_error) | |
+ wrong_type_argument(pred, err); | |
+ else | |
+ image_error ("Invalid fit option for %s", image_type, Qnil); | |
+ return -1; | |
+} | |
/* Value is true if OBJECT is a valid Lisp image specification. A | |
valid image specification is a list whose car is the symbol | |
@@ -6708,6 +6804,10 @@ | |
#ifndef USE_CAIRO | |
XImagePtr ximg = NULL; | |
#endif | |
+ int fit_width = 0, fit_height = 0; | |
+ | |
+ if (lookup_fit_size (Qjpeg, f, img, &fit_width, &fit_height, !0) < 0) | |
+ return 0; | |
/* Open the JPEG file. */ | |
specified_file = image_spec_value (img->spec, QCfile, NULL); | |
@@ -6787,6 +6887,43 @@ | |
jpeg_read_header (&mgr->cinfo, 1); | |
+#define JPEG8C_UNIT 8 | |
+ | |
+ if (fit_width > 0 && fit_height == 0) { | |
+ if (mgr->cinfo.image_width > fit_width) { /* fit to width */ | |
+ mgr->cinfo.scale_num = ((double) fit_width / mgr->cinfo.image_width) * JPEG8C_UNIT; | |
+ mgr->cinfo.scale_denom = JPEG8C_UNIT; | |
+ } | |
+ } else if (fit_width == 0 && fit_height > 0) { | |
+ if (mgr->cinfo.image_height > fit_height) { /* fit to width */ | |
+ mgr->cinfo.scale_num = ((double)fit_height / mgr->cinfo.image_height) * JPEG8C_UNIT; | |
+ mgr->cinfo.scale_denom = JPEG8C_UNIT; | |
+ } | |
+ } else if (fit_width > 0 && fit_height > 0) { /* fit to frame */ | |
+ if (mgr->cinfo.image_width > fit_width || | |
+ mgr->cinfo.image_height > fit_height) { | |
+ if ((double)fit_width / mgr->cinfo.image_width < | |
+ (double)fit_height / mgr->cinfo.image_height) { | |
+ mgr->cinfo.scale_num = ((double)fit_width / mgr->cinfo.image_width) * JPEG8C_UNIT; | |
+ } else { | |
+ mgr->cinfo.scale_num = ((double)fit_height / mgr->cinfo.image_height) * JPEG8C_UNIT; | |
+ mgr->cinfo.scale_denom = JPEG8C_UNIT; | |
+ } | |
+ } | |
+ } else if (fit_width < 0 && fit_height < 0) { /* fit to width or height */ | |
+ if (mgr->cinfo.image_width > -fit_width && | |
+ mgr->cinfo.image_height > -fit_height) { | |
+ if ((double)-fit_width / mgr->cinfo.image_width > | |
+ (double)-fit_height / mgr->cinfo.image_height) { | |
+ mgr->cinfo.scale_num = ((double)-fit_width / mgr->cinfo.image_width) * JPEG8C_UNIT; | |
+ mgr->cinfo.scale_denom = JPEG8C_UNIT; | |
+ } else { | |
+ mgr->cinfo.scale_num = ((double)-fit_height / mgr->cinfo.image_height) * JPEG8C_UNIT; | |
+ mgr->cinfo.scale_denom = JPEG8C_UNIT; | |
+ } | |
+ } | |
+ } | |
+ | |
/* Customize decompression so that color quantization will be used. | |
Start decompression. */ | |
mgr->cinfo.quantize_colors = 1; | |
@@ -9082,6 +9219,7 @@ | |
(RsvgHandle *, const guchar *, gsize, GError **)); | |
DEF_DLL_FN (gboolean, rsvg_handle_close, (RsvgHandle *, GError **)); | |
DEF_DLL_FN (GdkPixbuf *, rsvg_handle_get_pixbuf, (RsvgHandle *)); | |
+DEF_DLL_FN (void *, rsvg_handle_set_size_callback, (RsvgHandle *, RsvgSizeFunc, gpointer, GDestroyNotify)); | |
DEF_DLL_FN (void, rsvg_handle_set_base_uri, (RsvgHandle *, const char *)); | |
DEF_DLL_FN (int, gdk_pixbuf_get_width, (const GdkPixbuf *)); | |
@@ -9120,6 +9258,7 @@ | |
LOAD_DLL_FN (library, rsvg_handle_write); | |
LOAD_DLL_FN (library, rsvg_handle_close); | |
LOAD_DLL_FN (library, rsvg_handle_get_pixbuf); | |
+ LOAD_DLL_FN (library, rsvg_handle_set_size_callback); | |
LOAD_DLL_FN (library, rsvg_handle_set_base_uri); | |
LOAD_DLL_FN (gdklib, gdk_pixbuf_get_width); | |
@@ -9157,6 +9296,7 @@ | |
# undef rsvg_handle_close | |
# undef rsvg_handle_get_dimensions | |
# undef rsvg_handle_get_pixbuf | |
+# undef rsvg_handle_set_size_callback | |
# undef rsvg_handle_new | |
# undef rsvg_handle_set_base_uri | |
# undef rsvg_handle_write | |
@@ -9177,6 +9317,7 @@ | |
# define rsvg_handle_close fn_rsvg_handle_close | |
# define rsvg_handle_get_dimensions fn_rsvg_handle_get_dimensions | |
# define rsvg_handle_get_pixbuf fn_rsvg_handle_get_pixbuf | |
+# define rsvg_handle_set_size_callback fn_rsvg_handle_set_size_callback | |
# define rsvg_handle_new fn_rsvg_handle_new | |
# define rsvg_handle_set_base_uri fn_rsvg_handle_set_base_uri | |
# define rsvg_handle_write fn_rsvg_handle_write | |
@@ -9238,6 +9379,48 @@ | |
return success_p; | |
} | |
+static void rsvg_size_callback (gint *width, | |
+ gint *height, | |
+ gpointer user_data) | |
+{ | |
+ int *fit_size = (int *)user_data; | |
+ | |
+ /* | |
+ * 0, 0: never | |
+ * 0, +: fit to height | |
+ * +, 0: fit to width | |
+ * +, +: fit to frame | |
+ * -, -: fit to width or height | |
+ */ | |
+ if (fit_size[0] > 0 && fit_size[1] == 0) { | |
+ *height *= (double)fit_size[0] / *width; | |
+ *width = (gint)fit_size[0]; | |
+ } else if (fit_size[0] == 0 && fit_size[1] > 0) { | |
+ *width *= (double)fit_size[1] / *height; | |
+ *height = (gint)fit_size[1]; | |
+ } else if (fit_size[0] > 0 && fit_size[1] > 0) { /* fit to frame */ | |
+ if ((double)fit_size[0] / *width < (double)fit_size[1] / *height) { | |
+ /* fit to width */ | |
+ *height *= (double)fit_size[0] / *width; | |
+ *width = (gint)fit_size[0]; | |
+ } else { | |
+ /* fit to height */ | |
+ *width *= (double)fit_size[1] / *height; | |
+ *height = (gint)fit_size[1]; | |
+ } | |
+ } else if (fit_size[0] < 0 && fit_size[1] < 0) { /* fit to width or height */ | |
+ if ((double)-fit_size[0] / *width < (double)-fit_size[1] / *height) { | |
+ /* fit to height */ | |
+ *width *= (double)-fit_size[1] / *height; | |
+ *height = (gint)-fit_size[1]; | |
+ } else { | |
+ /* fit to width */ | |
+ *height *= (double)-fit_size[0] / *width; | |
+ *width = (gint)-fit_size[0]; | |
+ } | |
+ } | |
+} | |
+ | |
/* Load frame F and image IMG. CONTENTS contains the SVG XML data to | |
be parsed, SIZE is its size, and FILENAME is the name of the SVG | |
file being loaded. | |
@@ -9257,6 +9440,10 @@ | |
int height; | |
const guint8 *pixels; | |
int rowstride; | |
+ int fit_size[2] = {0, 0}; | |
+ | |
+ if (lookup_fit_size(Qsvg, f, img, fit_size, fit_size+1, 0) < 0) | |
+ return 0; | |
#if ! GLIB_CHECK_VERSION (2, 36, 0) | |
/* g_type_init is a glib function that must be called prior to | |
@@ -9273,6 +9460,9 @@ | |
if (filename) | |
rsvg_handle_set_base_uri(rsvg_handle, filename); | |
+ if (fit_size[0] || fit_size[1]) | |
+ rsvg_handle_set_size_callback(rsvg_handle, rsvg_size_callback, fit_size, NULL); | |
+ | |
/* Parse the contents argument and fill in the rsvg_handle. */ | |
rsvg_handle_write (rsvg_handle, (unsigned char *) contents, size, &err); | |
if (err) goto rsvg_error; | |
@@ -9875,6 +10065,7 @@ | |
DEFSYM (QCscale, ":scale"); | |
DEFSYM (QCcolor_adjustment, ":color-adjustment"); | |
DEFSYM (QCmask, ":mask"); | |
+ DEFSYM (QCfit, ":fit"); | |
/* Other symbols. */ | |
DEFSYM (Qlaplace, "laplace"); | |
@@ -9925,12 +10116,24 @@ | |
); | |
#endif | |
+ DEFVAR_LISP ("image-fit-option-alist", Vimage_fit_option_alist, | |
+ doc: /* Alist of (IMAGE-TYPE . FIT-OPTION) pairs used by image loader to specify image size. | |
+the FIT-OPTION is one of 'never, 'frame, 'width-or-height, 'width or 'height. | |
+Note: All image loaders are not supporting this `fit' capability. */); | |
+ Vimage_fit_option_alist = Qnil; | |
+ | |
DEFSYM (Qpbm, "pbm"); | |
ADD_IMAGE_TYPE (Qpbm); | |
DEFSYM (Qxbm, "xbm"); | |
ADD_IMAGE_TYPE (Qxbm); | |
+ Qnever = intern_c_string("never"); | |
+ staticpro (&Qnever); | |
+ Qwidth_or_height = intern_c_string("width-or-height"); | |
+ staticpro (&Qwidth_or_height); | |
+ | |
+ | |
#if defined (HAVE_XPM) || defined (HAVE_NS) | |
DEFSYM (Qxpm, "xpm"); | |
ADD_IMAGE_TYPE (Qxpm); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment