unofficial mirror of emacs-devel@gnu.org 
 help / color / mirror / code / Atom feed
* Re: A patch for enforcing double-width CJK character display
@ 2014-04-28  5:35 JunJie Nan
  2014-04-29  5:39 ` Stefan Monnier
  2014-04-29 20:41 ` Liang Wang
  0 siblings, 2 replies; 53+ messages in thread
From: JunJie Nan @ 2014-04-28  5:35 UTC (permalink / raw)
  To: emacs-devel


[-- Attachment #1.1: Type: text/plain, Size: 254 bytes --]

Do not know why the patch is still not installed, although from the
discussion thread nobody oppose it indeed.

Below is an updated version based on current stream. It still works well.


-- 
Cheers
Jun Jie Nan
  ∧ ∧︵
 ミ^ō^ミ灬)~

[-- Attachment #1.2: Type: text/html, Size: 345 bytes --]

[-- Attachment #2: emacs_src_xftfont.patch --]
[-- Type: text/x-patch, Size: 7057 bytes --]

diff --git a/src/xftfont.c b/src/xftfont.c
index 18c180f..2020b4f 100644
--- a/src/xftfont.c
+++ b/src/xftfont.c
@@ -60,6 +60,8 @@ struct xftfont_info
   Display *display;
   XftFont *xftfont;
   unsigned x_display_id;
+  struct frame *frame; /* hold frame ptr, cjk double width fix need it */
+  int is_cjk; /* Flag to tell if it is CJK font or not. */
 };
 
 /* Structure pointed by (struct face *)->extra  */
@@ -133,6 +135,83 @@ xftfont_get_colors (struct frame *f, struct face *face, GC gc,
 }
 
 
+/* Check whether the font contains CJK Ideograph 'number one', 0x4E00,
+   It should be ok for Chinese/Japanese font.
+   Or font contains Korean script syllable 'Ka',0xAC00,
+   because Korean fonts may not have any Chinese characters at all.
+   codes from xterm.*/
+static int
+xftfont_is_cjk_font(struct xftfont_info *xftfont_info)
+{
+  if(XftCharExists(xftfont_info->display, xftfont_info->xftfont, 0x4E00) ||
+      XftCharExists(xftfont_info->display, xftfont_info->xftfont, 0xAC00))
+    return 1;
+  return 0; 
+}
+
+/* Get the padding according to default monospace font width */
+static int
+xftfont_get_cjk_padding(int default_width, int char_width, int *half_width_cjk)
+{
+  int padding = 0;
+  if(half_width_cjk)
+    *half_width_cjk = 0;
+
+  if( default_width == 0 || /* something wrong */
+      default_width == -1 || /* default font is not monospace */
+      char_width == default_width) /* already good */
+    return 0;
+  if( char_width < default_width) { 
+    /* almost impossible, but we can handle it */
+    padding = default_width - char_width;
+    if(half_width_cjk)
+        *half_width_cjk = 1;
+  } else /* get the padding, all cjk symbols is DOUBLE width */
+    padding = default_width * 2 - char_width;
+  /* 1, Some old CJK pcf fonts may bigger than 2*default_width.
+     2, User may set a very big font size for script HAN manually.
+     Keep it unchanged, NOT adjust default font width. */
+  return (padding > 0 && padding < default_width) ? padding : 0;                  
+}
+
+/* Get the font width of monospace font. 
+   Something wrong: return 0;
+   Default is not monospace: return -1;
+   Otherwise: return monospace font width; */
+static int 
+xftfont_get_default_width(struct xftfont_info *xftfont_info)
+{
+  Lisp_Object font_object;
+  double request_pixel_size;
+  struct frame *frame = xftfont_info->frame;
+  FcPattern * pattern = xftfont_info->xftfont->pattern;
+  int id = lookup_basic_face (frame, DEFAULT_FACE_ID);
+  struct face *face = FACE_FROM_ID (frame, id);
+  if(!face && !face->font)
+    return 0;
+  XSETFONT (font_object, face->font);
+  /* default font is not monospace */
+  if (XINT(AREF (font_object, FONT_SPACING_INDEX)) != FONT_SPACING_MONO)
+    return -1;
+  if(FcPatternGetDouble(pattern, FC_PIXEL_SIZE, 0, &request_pixel_size) != FcResultMatch)
+    return 0;
+  /* the font of minibuf/modeline never changed when rescaling.
+     it's a little bit difficult to determine where the xftfont draw to.
+     for example, when use mule/leim to input some CJK text.
+     it will draw on the selected frame and minibuf(candidate string).
+     by the way, the 'int' conversion should be ok. */ 
+  if(FRAME_FONT(frame)->pixel_size == (int)request_pixel_size) 
+    return FRAME_FONT(frame)->space_width;
+  /* User may set a fixed font size for script han manually,
+     the font will not rescale when issue rescaling,
+     should not ajust the width offset and avoid to make it too wide.
+     its alignment will be wrong, but let's respect user settings.*/
+  if(face->font->pixel_size != (int)request_pixel_size)
+    return FRAME_FONT(frame)->space_width;
+  /* otherwise return the current font width */
+  return face->font->space_width;
+}
+
 struct font_driver xftfont_driver;
 
 static Lisp_Object
@@ -420,6 +499,15 @@ xftfont_open (struct frame *f, Lisp_Object entity, int pixel_size)
       XftTextExtents8 (display, xftfont, ascii_printable + 1, 94, &extents);
       font->average_width = (font->space_width + extents.xOff) / 95;
     }
+
+  /* to fix CJK double width alignment issue.
+     pass FRAME_PTR to every xftfont_info structure,
+     we can not get it in "xftfont_text_extents". */
+  xftfont_info->frame = f;
+  /* mark it is CJK font or not when font opened,
+     avoid calling "xftfont_is_cjk_font" many times. */
+  xftfont_info->is_cjk = xftfont_is_cjk_font(xftfont_info);
+
   unblock_input ();
 
   font->ascent = xftfont->ascent;
@@ -588,19 +676,29 @@ xftfont_text_extents (struct font *font, unsigned int *code, int nglyphs, struct
   struct xftfont_info *xftfont_info = (struct xftfont_info *) font;
   XGlyphInfo extents;
 
+  int cjk_padding = 0;
+  int l_padding = 0;
+  int r_padding = 0;
+
   block_input ();
   XftGlyphExtents (xftfont_info->display, xftfont_info->xftfont, code, nglyphs,
 		   &extents);
+  if(xftfont_info->is_cjk)
+    cjk_padding = xftfont_get_cjk_padding(xftfont_get_default_width(xftfont_info), extents.xOff, NULL);
+  /* cjk_padding may equals to 0, then all is zero, still ok */
+  l_padding = cjk_padding >> 1; /* get half */
+  r_padding = cjk_padding - l_padding; /* may not divided by 2 exactly */ 
+
   unblock_input ();
   if (metrics)
     {
-      metrics->lbearing = - extents.x;
-      metrics->rbearing = - extents.x + extents.width;
-      metrics->width = extents.xOff;
+      metrics->lbearing = - extents.x - l_padding;
+      metrics->rbearing = - extents.x + extents.width + r_padding;
+      metrics->width = extents.xOff + cjk_padding;
       metrics->ascent = extents.y;
       metrics->descent = extents.height - extents.y;
     }
-  return extents.xOff;
+  return extents.xOff + cjk_padding;
 }
 
 static XftDraw *
@@ -658,9 +756,28 @@ xftfont_draw (struct glyph_string *s, int from, int to, int x, int y,
     for (i = 0; i < len; i++)
       XftDrawGlyphs (xft_draw, &fg, xftfont_info->xftfont,
 		     x + i, y, code + i, 1);
-  else
-    XftDrawGlyphs (xft_draw, &fg, xftfont_info->xftfont,
-		   x, y, code, len);
+  else {
+      int default_width = xftfont_get_default_width(xftfont_info);
+      if(!xftfont_info->is_cjk || default_width == -1) /* not cjk or default not monospace */ 
+        XftDrawGlyphs (xft_draw, &fg, xftfont_info->xftfont, x, y, code, len);
+      else /* draw CJK glyphs one by one and adjust the offset */
+         for (i = 0; i < len; i++) {
+           int cjk_padding = 0;
+           int offset = 0;
+           int half_width_cjk = 0;
+           XGlyphInfo extents;
+           XftGlyphExtents (xftfont_info->display, xftfont_info->xftfont, code+i, 1,
+                            &extents);
+           cjk_padding = xftfont_get_cjk_padding(default_width,extents.xOff, &half_width_cjk);
+           if(cjk_padding) 
+             offset = default_width * i * (half_width_cjk ? 1 : 2) + (cjk_padding>>1);
+           else
+             offset = extents.xOff * i; 
+           XftDrawGlyphs (xft_draw, &fg, xftfont_info->xftfont,
+                            x+offset, y, code+i, 1);
+         }
+  }
+
   unblock_input ();
 
   return len;

^ permalink raw reply related	[flat|nested] 53+ messages in thread
* Re: A patch for enforcing double-width CJK character display
@ 2014-10-04  3:26 Feng Shu
  0 siblings, 0 replies; 53+ messages in thread
From: Feng Shu @ 2014-10-04  3:26 UTC (permalink / raw)
  To: emacs-devel


This patch can't apply on current emacs development tree, could some
one update it?



-- 



^ permalink raw reply	[flat|nested] 53+ messages in thread
* Re: A patch for enforcing double-width CJK character display
@ 2014-04-30  2:00 Hui Liu
  2014-04-30 17:08 ` Liang Wang
  0 siblings, 1 reply; 53+ messages in thread
From: Hui Liu @ 2014-04-30  2:00 UTC (permalink / raw)
  To: netcasper; +Cc: emacs-devel

> But there is a bug on displaying Chinese double dash.  When I switch
> to other buffer and switch back, it looks wrong.  I attached both
> screenshots and I draw a red line under Chinese double dash in the
> correct one.

I don't think it is a bug of the patch. The font you used looks like
WenQuanYi Micro Hei, so I test a dozen other Chinese fonts. ONLY
WenQuanYi fonts have this problem.

The reason is the some characters (e.g. Chinese punctuations and Greek
letters) in WenQuanYi fonts are halfwidth. I know little about fonts,
so I doubt if it is a bug of WenQuanYi because these characters in
other Chinese fonts are all fullwidth.

Since these characters are included in the symbol charset, You can
simply leave this charset to the default English font. Or use any
other Chinese fonts except WenQuanYi.



^ permalink raw reply	[flat|nested] 53+ messages in thread
[parent not found: <4F85A138.6090900@i-soft.com.cn>]

end of thread, other threads:[~2014-10-04  3:26 UTC | newest]

Thread overview: 53+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2014-04-28  5:35 A patch for enforcing double-width CJK character display JunJie Nan
2014-04-29  5:39 ` Stefan Monnier
2014-04-29  6:36   ` Jan D.
2014-04-29  8:16   ` Thien-Thi Nguyen
2014-04-29 20:41 ` Liang Wang
  -- strict thread matches above, loose matches on Subject: below --
2014-10-04  3:26 Feng Shu
2014-04-30  2:00 Hui Liu
2014-04-30 17:08 ` Liang Wang
     [not found] <4F85A138.6090900@i-soft.com.cn>
2012-04-11 15:48 ` Kan-Ru Chen
2012-04-11 16:16   ` 黄建忠
2012-04-12  8:56     ` 黄建忠
2012-04-12  9:53       ` Eli Zaretskii
2012-04-12 11:18         ` 黄建忠
2012-04-12 14:27           ` Eli Zaretskii
2012-04-12 17:56             ` 黄建忠
2012-04-12 20:33               ` Stefan Monnier
     [not found]                 ` <4F8782C8.2030005@i-soft.com.cn>
2012-04-13 11:42                   ` 黄建忠
2012-04-13 12:03                     ` 黄建忠
2012-04-13 13:27                   ` Stefan Monnier
2012-04-15  5:10                     ` Miles Bader
2012-04-15 13:27                       ` 黄建忠
2012-04-15 16:08                       ` William Xu
2012-04-15 22:19                         ` Miles Bader
2012-04-16  0:51                           ` 黄建忠
2012-04-16  5:27                             ` Miles Bader
2012-04-16  5:40                               ` 黄建忠
2012-04-16  6:37                                 ` 黄建忠
2012-04-16  9:21                                   ` 黄建忠
2012-04-17  2:16                                     ` 黄建忠
2012-04-17  0:13                                   ` Miles Bader
2012-04-17  0:39                                     ` Miles Bader
2012-04-17  2:00                                       ` 黄建忠
2012-04-17  2:30                                         ` Miles Bader
2012-04-17  3:00                                           ` 黄建忠
2012-04-17  4:08                                             ` Miles Bader
2012-04-17  4:56                                               ` Werner LEMBERG
2012-04-17  5:02                                                 ` 黄建忠
2012-04-17  6:33                                                   ` Miles Bader
2012-04-17  7:03                                                   ` Werner LEMBERG
2012-04-17  5:52                                                 ` Miles Bader
2012-04-17  6:10                                                   ` 黄建忠
2012-04-17  7:02                                                     ` Miles Bader
2012-04-17  8:06                                                       ` Werner LEMBERG
2012-04-17  8:25                                                         ` Miles Bader
2012-04-17  9:06                                                           ` Werner LEMBERG
2012-04-17  8:51                                                       ` 黄建忠
2012-04-17  6:45                                                   ` Werner LEMBERG
2012-04-17  9:07                                       ` James Cloos
2012-04-17  9:27                                         ` 黄建忠
2012-04-17  1:47                                     ` 黄建忠
2012-04-18  6:54                               ` Kenichi Handa
2012-04-18  8:13                                 ` 黄建忠
2012-04-18 13:58                                 ` Miles Bader

Code repositories for project(s) associated with this public inbox

	https://git.savannah.gnu.org/cgit/emacs.git

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).