成功Patch了非mac port的GNU Emacs显示retina分辨率PNG图片

Woc,为什么听你说的好像感觉用的完全不是同一个东西

我用的是这边的 GitHub - railwaycat/homebrew-emacsmacport: Emacs mac port formulae for the Homebrew package manager 直接下载或者用homebrew装都一样

1 个赞

你可以试试用 --HEAD 装 我用的HEAD版本没有全屏的问题

本来想搞一下imagemagick文件类型的,看了里面的实现以后实在懒得弄了,因为这里的代码效能简直低下到令人发指,难怪mac port的作者全部用imageio重做了。GNU Emacs的补丁在这里:

自己把PNG和JPG加到imagemagick-types-inhibit里,让这两种文件直接通过NSImage加载,反正我也只需要PNG就够了。 之前贴的elisp部分稍作修改,不必再检测mac port的函数:

(when (eq window-system 'ns)
  (defun mac-high-resolution-image-file-name (filename &optional scale)
    "Return the name of high-resolution image file for FILENAME.
     The optional arg SCALE is the scale factor, and defaults to 2."
    (let ((pos (or (string-match "\\.[^./]*\\'" filename) (length filename))))
      (format "%s@%dx%s" (substring filename 0 pos) (or scale 2)
              (substring filename pos))))
  (defun my-ob-ipython-write-base64-string-retina (oldfunc &rest args)
    (let ((file (car args)) (b64-string (cdr args)))
          (let ((file2x (mac-high-resolution-image-file-name file)))
            (apply oldfunc file2x b64-string)
            (shell-command (concat "convert " file2x " -resize 50% " file)))))
  (advice-add  'ob-ipython--write-base64-string :around
               #'my-ob-ipython-write-base64-string-retina))
1 个赞

效果就是加载文件时如果同目录下存在[email protected],就优先使用2x的版本。

我又试了下mac port。全屏按钮非常奇怪,刚启动时绿按钮里是一个加号,按下以后上下顶满,左右固定大小。但是如果我按一次F11(toggle-frame-fullscreen),就会进入所谓的full-both状态,再按一下恢复,但奇怪的是这时绿按钮不再是加号了,而是和其他程序一样的全屏图标,按下以后能进入真正的全屏模式。但是再恢复后就又是加号了。

你用 emacs -q 启动一次看看?总感觉你描述的跟 mac port 的行为很不一样……

Mac 下的模式的话,按下 option 那个绿色的全屏按钮才会变成加号。

试了-q,果然这样是正常的,看来是我init.el里的某个东西了

找到了,是(menu-bar-mode nil),得加个条件了

讲个事,(menu-bar-mode nil) 等价于 (menu-bar-mode),也就是显示 menu bar

呵呵,这行是在customize里的,所以的确是关闭

Great,但是补丁打不开

2 files changed, 60 insertions(+), 2 deletions(-)
src/image.c   |  1 +
src/nsimage.m | 61 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++--

modified   src/image.c
@@ -9875,6 +9875,7 @@ non-numeric, there is no explicit limit on the size of images.  */);
   DEFSYM (QCscale, ":scale");
   DEFSYM (QCcolor_adjustment, ":color-adjustment");
   DEFSYM (QCmask, ":mask");
+  DEFSYM (QCdpi_scale, "dpi_scale");
 
   /* Other symbols.  */
   DEFSYM (Qlaplace, "laplace");
modified   src/nsimage.m
@@ -35,7 +35,46 @@ Updated by Christian Limpach ([email protected])
 #include "frame.h"
 #include "coding.h"
 
+Lisp_Object
+get_2x_image_file_name (Lisp_Object file_name)
+{
+  Lisp_Object result;
+  char *p, *last_component;
+  ptrdiff_t prefix_len;
+
+  p = strrchr (SSDATA (file_name), '/');
+  last_component = p ? p + 1 : SSDATA (file_name);
+  p = strrchr (last_component, '.');
+  if (p == NULL)
+    p = SSDATA (file_name) + SBYTES (file_name);
+  prefix_len = p - SSDATA (file_name);
+  result = make_uninit_string (SBYTES (file_name) + sizeof ("@2x") - 1);
+  sprintf (SSDATA (result), "%.*s@2x%.*s",
+       (int) prefix_len, SSDATA (file_name),
+       (int) (SBYTES (file_name) - prefix_len), p);
+  return result;
+}
+
+void
+set_image_spec (Lisp_Object spec, Lisp_Object key, Lisp_Object value)
+{
+  Lisp_Object tail;
+
+  eassert (valid_image_p (spec));
+
+  for (tail = XCDR (spec);
+       CONSP (tail) && CONSP (XCDR (tail));
+       tail = XCDR (XCDR (tail)))
+    {
+      if (EQ (XCAR (tail), key))
+	{
+	  XSETCAR (XCDR (tail),  value);
+          return;
+	}
+    }
 
+  Fplist_put(XCDR(spec), key, value);
+}
 
 /* ==========================================================================
 
@@ -76,7 +115,7 @@ Updated by Christian Limpach ([email protected])
 {
   EmacsImage *eImg = nil;
   NSSize size;
-  Lisp_Object lisp_index, lisp_rotation;
+  Lisp_Object lisp_index, lisp_rotation, found, spec_file_2x, value;
   unsigned int index;
   double rotation;
 
@@ -92,7 +131,21 @@ Updated by Christian Limpach ([email protected])
 
   if (STRINGP (spec_file))
     {
-      eImg = [EmacsImage allocInitFromFile: spec_file];
+      /* Try 2x filename first */
+      spec_file_2x = get_2x_image_file_name(spec_file);
+      eImg = [EmacsImage allocInitFromFile: spec_file_2x];
+      if (eImg != nil)
+        {
+          /* fix image scale */
+          set_image_spec(img->spec, QCdpi_scale, make_float(0.5));
+          /* fix image name */
+          [eImg setName: [NSString stringWithUTF8String: SSDATA (spec_file)]];
+        }
+      else
+        {
+          /* failed to load 2x image */
+          eImg = [EmacsImage allocInitFromFile: spec_file];
+        }
     }
   else if (STRINGP (spec_data))
     {
@@ -535,6 +588,10 @@ - (void)setSizeFromSpec: (Lisp_Object) spec
   if (NUMBERP (value))
     scale = XFLOATINT (value) ;
 
+  value = Fplist_get (spec, QCdpi_scale);
+  if (NUMBERP (value))
+    scale *= XFLOATINT (value) ;
+
   value = Fplist_get (spec, QCmax_width);
   if (NUMBERP (value))
     max_width = XFLOATINT (value);

话说有可能用NSimage渲染SVG吗?或者用这个? GitHub - IconJar/IJSVG: MacOS SVG rendering and exporting library

这是我的版本, 16年搞的 http://algking.github.io/2016/04/08/emacs-retina-support.html 可以开关是否retina模式

From a8885f1166edafca30a51f2e88b435261bc48eb0 Mon Sep 17 00:00:00 2001
From: algking <[email protected]>
Date: Thu, 19 May 2016 13:31:56 +0800
Subject: [PATCH] add enable-retina-images option support

---
 lisp/cus-start.el |  2 ++
 src/image.c       | 13 +++++++++++++
 2 files changed, 15 insertions(+)

diff --git a/lisp/cus-start.el b/lisp/cus-start.el
index ae871f1..62166ba 100644
--- a/lisp/cus-start.el
+++ b/lisp/cus-start.el
@@ -299,6 +299,8 @@
 				    "24.1")
 	     ;; mac.c
 	     (mac-system-move-file-to-trash-use-finder mac boolean "23.4")
+             ;; image.c
+             (enable-retina-images mac boolean "24.1")
 	     ;; macselect.c
 	     (mac-dnd-known-types mac (repeat string) "22.1")
 	     ;; macterm.c
diff --git a/src/image.c b/src/image.c
index d4b2cc6..9469519 100644
--- a/src/image.c
+++ b/src/image.c
@@ -2754,6 +2754,11 @@ image_load_image_io (struct frame *f, struct image *img, CFStringRef type)
 	  image_error ("Cannot find image file `%s'", specified_file, Qnil);
 	  return 0;
 	}
+
+      /* retina 模式  */
+      if(enable_retina_images)
+        {img->target_backing_scale = 2;}
+
       file = mac_preprocess_image_for_2x_file (f, img, file);
       url = CFURLCreateFromFileSystemRepresentation (NULL, SDATA (file),
 						     SBYTES (file), false);
@@ -9458,6 +9463,10 @@ imagemagick_load_image (struct frame *f, struct image *img, 
 	img->target_backing_scale = FRAME_BACKING_SCALE_FACTOR (f);
     }
 
+  /* retina 模式  */
+  if(enable_retina_images)
+    {img->target_backing_scale = 2;}
+
   if (img->target_backing_scale == 2)
     {
       if (desired_width == -1)
@@ -11091,6 +11100,10 @@ Disabled images are those having a `:conversion disabled' property.
 A cross is always drawn on black & white displays.  */);
   cross_disabled_images = 0;
 
+  DEFVAR_BOOL ("enable-retina-images", enable_retina_images,
+               doc: /* Non-nil means always display image in retina mode.*/);
+  enable_retina_images = 0;
+
   DEFVAR_LISP ("x-bitmap-file-path", Vx_bitmap_file_path,
     doc: /* List of directories to search for window system bitmap files.  */);
   Vx_bitmap_file_path = decode_env_path (0, PATH_BITMAPS, 0);
-- 
2.1.1


我感觉SVG的适用性不如PNG。假如画一些折线图饼图分布图什么的SVG肯定没问题,但是我经常画些波形频谱之类的,本质上是位图,弄成SVG只会更大更慢。

有没有打开图片的截图? 好像从来没用emacs打开过图片, 总感觉体验会不佳, eww里显示的图片, 光标移到图片右边后光标就变得跟图片一样高, 看上去不太舒服(特别不喜欢看到这个大光标), 而且图片右边不能显示多行文字, 只能显示一行?

这个patch不是把所有的图片都用高分辨率显示,而是只有在存在[email protected]的情况下才用[email protected]取代原文件显示在同样大小的区域里。所以需要模式支持生成这样的图片才可以看到高清。之所以不是无条件用高分辨率显示,是因为这样会改变图片大小,如果模式没有有意支持的话,可能会显示不正常。 我主要是配合ob-ipython模式用,需要一小段代码动态挂接ob-ipython的输出函数生成两个不同分辨率的图片。 例子在 ob-ipython内联retina分辨率图片 这和mac port版本的高分辨率支持是一样的,但是我比较喜欢用上游master版本,因为更新一点,所以自己加了这个。

话说最近nsimage.m有不少改动。。原来的patch已经用不了了 大佬有新的patch吗?

已经不需要了,原生支持,只要image创建时加上:scale 0.5即可

2 个赞