[PATCH v2 1/3] Handle CJK wide glyph rendering

Peng Wu peng.e.wu at gmail.com
Wed Jul 17 00:50:23 PDT 2013


Some CJK glyphs are wide, which occupy two columns.
If the glyph is wide, then use two columns instead of one.
---
 clients/Makefile.am |  2 +-
 clients/terminal.c  | 45 +++++++++++++++++++++++++++++++++++++++------
 2 files changed, 40 insertions(+), 7 deletions(-)

diff --git a/clients/Makefile.am b/clients/Makefile.am
index cad0d40..d37d66a 100644
--- a/clients/Makefile.am
+++ b/clients/Makefile.am
@@ -104,7 +104,7 @@ weston_screenshooter_SOURCES =			\
 weston_screenshooter_LDADD = libtoytoolkit.la
 
 weston_terminal_SOURCES = terminal.c
-weston_terminal_LDADD = libtoytoolkit.la -lutil
+weston_terminal_LDADD = libtoytoolkit.la -lutil $(PANGO_LIBS)
 
 image_SOURCES = image.c
 image_LDADD = libtoytoolkit.la
diff --git a/clients/terminal.c b/clients/terminal.c
index 0d4f726..97e315f 100644
--- a/clients/terminal.c
+++ b/clients/terminal.c
@@ -33,6 +33,7 @@
 #include <ctype.h>
 #include <cairo.h>
 #include <sys/epoll.h>
+#include <glib.h>
 
 #include <wayland-client.h>
 
@@ -942,6 +943,10 @@ redraw_handler(struct widget *widget, void *data)
 	struct glyph_run run;
 	cairo_font_extents_t extents;
 	double average_width;
+	gunichar unichar;
+	double unichar_width;
+	gboolean iswide;
+	int extracol;
 
 	surface = window_get_surface(terminal->window);
 	widget_get_allocation(terminal->widget, &allocation);
@@ -967,21 +972,38 @@ redraw_handler(struct widget *widget, void *data)
 			allocation.y + top_margin);
 	/* paint the background */
 	for (row = 0; row < terminal->height; row++) {
+		p_row = terminal_get_row(terminal, row);
+		extracol = 0;
 		for (col = 0; col < terminal->width; col++) {
 			/* get the attributes for this character cell */
 			terminal_decode_attr(terminal, row, col, &attr);
 
-			if (attr.attr.bg == terminal->color_scheme->border)
+			/* check dual width unicode character */
+			unichar = g_utf8_get_char((const char*) p_row[col].byte);
+			iswide = g_unichar_iswide(unichar);
+
+			if (attr.attr.bg == terminal->color_scheme->border) {
+				if (iswide)
+					extracol++;
 				continue;
+			}
+
+			if (iswide)
+				unichar_width = 2 * average_width;
+			else
+				unichar_width = average_width;
 
 			terminal_set_color(terminal, cr, attr.attr.bg);
-			cairo_move_to(cr, col * average_width,
+			cairo_move_to(cr, (col + extracol) * average_width,
 				      row * extents.height);
-			cairo_rel_line_to(cr, average_width, 0);
+			cairo_rel_line_to(cr, unichar_width, 0);
 			cairo_rel_line_to(cr, 0, extents.height);
-			cairo_rel_line_to(cr, -average_width, 0);
+			cairo_rel_line_to(cr, -unichar_width, 0);
 			cairo_close_path(cr);
 			cairo_fill(cr);
+
+			if (iswide)
+				extracol++;
 		}
 	}
 
@@ -991,22 +1013,33 @@ redraw_handler(struct widget *widget, void *data)
 	glyph_run_init(&run, terminal, cr);
 	for (row = 0; row < terminal->height; row++) {
 		p_row = terminal_get_row(terminal, row);
+		extracol = 0;
 		for (col = 0; col < terminal->width; col++) {
 			/* get the attributes for this character cell */
 			terminal_decode_attr(terminal, row, col, &attr);
 
 			glyph_run_flush(&run, attr);
 
-			text_x = col * average_width;
+			/* check dual width unicode character */
+			unichar = g_utf8_get_char((const char*) p_row[col].byte);
+			iswide = g_unichar_iswide(unichar);
+			if (iswide)
+				unichar_width = 2 * average_width;
+			else
+				unichar_width = average_width;
+
+			text_x = (col + extracol) * average_width;
 			text_y = extents.ascent + row * extents.height;
 			if (attr.attr.a & ATTRMASK_UNDERLINE) {
 				terminal_set_color(terminal, cr, attr.attr.fg);
 				cairo_move_to(cr, text_x, (double)text_y + 1.5);
-				cairo_line_to(cr, text_x + average_width, (double) text_y + 1.5);
+				cairo_line_to(cr, text_x + unichar_width, (double) text_y + 1.5);
 				cairo_stroke(cr);
 			}
 
 			glyph_run_add(&run, text_x, text_y, &p_row[col]);
+			if (iswide)
+				extracol++;
 		}
 	}
 
-- 
1.8.3.1



More information about the wayland-devel mailing list