Upstream: http://bugzilla.gnome.org/show_bug.cgi?id=54926
Description: Fix bold font handling.
Author: Kees Cook <kees@outflux.net>

diff -Nur -x '*.orig' -x '*~' vte-0.19.4/src/vte.c vte-0.19.4.new/src/vte.c
--- vte-0.19.4/src/vte.c	2008-12-13 14:49:02.000000000 -0800
+++ vte-0.19.4.new/src/vte.c	2009-02-11 21:05:53.000000000 -0800
@@ -724,7 +724,7 @@
 					_vte_draw_get_char_width (
 						terminal->pvt->draw,
 						cell->c,
-						columns) >
+						columns, cell->attr.bold) >
 					terminal->char_width * columns) {
 				columns++;
 			}
@@ -781,7 +781,7 @@
 					_vte_draw_get_char_width (
 						terminal->pvt->draw,
 						cell->c,
-						columns) >
+						columns, cell->attr.bold) >
 			    terminal->char_width * columns) {
 				columns++;
 			}
@@ -8850,10 +8850,10 @@
 	return FALSE;
 }
 static gboolean
-vte_terminal_unichar_is_local_graphic(VteTerminal *terminal, vteunistr c)
+vte_terminal_unichar_is_local_graphic(VteTerminal *terminal, vteunistr c, gboolean bold)
 {
 	return vte_unichar_is_local_graphic (c) &&
-		!_vte_draw_has_char (terminal->pvt->draw, c);
+		!_vte_draw_has_char (terminal->pvt->draw, c, bold);
 }
 
 static void
@@ -8940,7 +8940,8 @@
 vte_terminal_draw_graphic(VteTerminal *terminal, vteunistr c,
 			  gint fore, gint back, gboolean draw_default_bg,
 			  gint x, gint y,
-			  gint column_width, gint columns, gint row_height)
+			  gint column_width, gint columns, gint row_height,
+			  gboolean bold)
 {
 	gboolean ret;
 	gint xcenter, xright, ycenter, ybottom, i, j, draw;
@@ -8968,7 +8969,7 @@
 	}
 
 	if (_vte_draw_char(terminal->pvt->draw, &request,
-			   &color, VTE_DRAW_OPAQUE)) {
+			   &color, VTE_DRAW_OPAQUE, bold)) {
 		/* We were able to draw with actual fonts. */
 		return TRUE;
 	}
@@ -9761,20 +9762,7 @@
 	color.green = fg->green;
 	_vte_draw_text(terminal->pvt->draw,
 			items, n,
-			&color, VTE_DRAW_OPAQUE);
-	if (bold) {
-		/* Take a step to the right. */
-		for (i = 0; i < n; i++) {
-			items[i].x++;
-		}
-		_vte_draw_text(terminal->pvt->draw,
-				items, n,
-				&color, VTE_DRAW_OPAQUE);
-		/* Now take a step back. */
-		for (i = 0; i < n; i++) {
-			items[i].x--;
-		}
-	}
+			&color, VTE_DRAW_OPAQUE, bold);
 	for (i = 0; i < n; i++) {
 		/* Deadjust for the border. */
 		items[i].x -= VTE_PAD_WIDTH;
@@ -10305,7 +10293,7 @@
 			j = i + items[0].columns;
 
 			/* If this is a graphics character, draw it locally. */
-			if (vte_terminal_unichar_is_local_graphic(terminal, cell->c)) {
+			if (vte_terminal_unichar_is_local_graphic(terminal, cell->c, cell->attr.bold)) {
 				if (vte_terminal_draw_graphic(terminal,
 							items[0].c,
 							fore, back,
@@ -10314,7 +10302,8 @@
 							items[0].y,
 							column_width,
 							items[0].columns,
-							row_height)) {
+							row_height,
+							cell->attr.bold)) {
 					i = j;
 					continue;
 				}
@@ -10357,7 +10346,7 @@
 							FALSE,
 							&nfore, &nback);
 					/* Graphic characters must be drawn individually. */
-					if (vte_terminal_unichar_is_local_graphic(terminal, cell->c)) {
+					if (vte_terminal_unichar_is_local_graphic(terminal, cell->c, cell->attr.bold)) {
 						if (vte_terminal_draw_graphic(terminal,
 									cell->c,
 									nfore, nback,
@@ -10366,7 +10355,8 @@
 									y,
 									column_width,
 									cell->attr.columns,
-									row_height)) {
+									row_height,
+									cell->attr.bold)) {
 
 							j += cell->attr.columns;
 							continue;
@@ -10634,9 +10624,8 @@
 	cursor_width = item.columns * width;
 	if (cell && cell->c != 0) {
 		gint cw = _vte_draw_get_char_width (terminal->pvt->draw,
-				cell->c, cell->attr.columns);
+				cell->c, cell->attr.columns, cell->attr.bold);
 		cursor_width = MAX(cursor_width, cw);
-		cursor_width += cell->attr.bold; /* for pseudo-bolding */
 	}
 
 	selected = vte_cell_is_selected(terminal, col, drow, NULL);
@@ -10685,7 +10674,7 @@
 							 &color,
 							 VTE_DRAW_OPAQUE);
 
-				if (!vte_terminal_unichar_is_local_graphic(terminal, item.c) ||
+				if (!vte_terminal_unichar_is_local_graphic(terminal, item.c, cell ? cell->attr.bold : FALSE) ||
 				    !vte_terminal_draw_graphic(terminal,
 							       item.c,
 							       fore, back,
@@ -10694,7 +10683,8 @@
 							       item.y,
 							       width,
 							       item.columns,
-							       height)) {
+							       height,
+							       cell ? cell->attr.bold : FALSE)) {
 					gboolean hilite = FALSE;
 					if (cell && terminal->pvt->show_match) {
 						hilite = vte_cell_is_between(col, row,
diff -Nur -x '*.orig' -x '*~' vte-0.19.4/src/vtedraw.c vte-0.19.4.new/src/vtedraw.c
--- vte-0.19.4/src/vtedraw.c	2008-12-11 19:31:52.000000000 -0800
+++ vte-0.19.4.new/src/vtedraw.c	2009-02-11 21:03:01.000000000 -0800
@@ -312,12 +312,13 @@
 }
 
 int
-_vte_draw_get_char_width (struct _vte_draw *draw, vteunistr c, int columns)
+_vte_draw_get_char_width (struct _vte_draw *draw, vteunistr c, int columns,
+			  gboolean bold)
 {
 	int width = 0;
 
 	if (draw->impl->get_char_width)
-		width = draw->impl->get_char_width (draw, c, columns);
+		width = draw->impl->get_char_width (draw, c, columns, bold);
 
 	if (width == 0)
 		_vte_draw_get_text_metrics (draw, &width, NULL, NULL);
@@ -328,7 +329,7 @@
 void
 _vte_draw_text (struct _vte_draw *draw,
 	       struct _vte_draw_text_request *requests, gsize n_requests,
-	       GdkColor *color, guchar alpha)
+	       GdkColor *color, guchar alpha, gboolean bold)
 {
 	g_return_if_fail (draw->started == TRUE);
 	g_return_if_fail (draw->impl->draw_text != NULL);
@@ -341,43 +342,59 @@
 			g_string_append_unichar (string, requests[n].c);
 		}
 		str = g_string_free (string, FALSE);
-		g_printerr ("draw_text (\"%s\", len=%"G_GSIZE_FORMAT", color=(%d,%d,%d,%d))\n",
+		g_printerr ("draw_text (\"%s\", len=%"G_GSIZE_FORMAT", color=(%d,%d,%d,%d), %s)\n",
 				str, n_requests, color->red, color->green, color->blue,
-				alpha);
+				alpha, bold ? "bold" : "normal");
 		g_free (str);
 	}
 
-	draw->impl->draw_text (draw, requests, n_requests, color, alpha);
+	draw->impl->draw_text (draw, requests, n_requests, color, alpha, bold);
+
+	/* handle fonts that lack a bold face by double-striking */
+	if (bold && !(draw->impl->has_bold && draw->impl->has_bold (draw))) {
+		int i;
+
+		/* Take a step to the right. */
+		for (i = 0; i < n_requests; i++) {
+			requests[i].x++;
+		}
+		draw->impl->draw_text (draw, requests, n_requests, color, alpha, FALSE);
+		/* Now take a step back. */
+		for (i = 0; i < n_requests; i++) {
+			requests[i].x--;
+		}
+	}
 }
 
 gboolean
 _vte_draw_char (struct _vte_draw *draw,
 	       struct _vte_draw_text_request *request,
-	       GdkColor *color, guchar alpha)
+	       GdkColor *color, guchar alpha, gboolean bold)
 {
 	gboolean has_char;
 
 	_vte_debug_print (VTE_DEBUG_DRAW,
-			"draw_char ('%c', color=(%d,%d,%d,%d))\n",
+			"draw_char ('%c', color=(%d,%d,%d,%d), %s)\n",
 			request->c,
 			color->red, color->green, color->blue,
-			alpha);
+			alpha, bold ? "bold" : "normal");
 
-	has_char =_vte_draw_has_char (draw, request->c);
+	has_char =_vte_draw_has_char (draw, request->c, bold);
 	if (has_char)
-		_vte_draw_text (draw, request, 1, color, alpha);
+		_vte_draw_text (draw, request, 1, color, alpha, bold);
 
 	return has_char;
 }
 gboolean
-_vte_draw_has_char (struct _vte_draw *draw, vteunistr c)
+_vte_draw_has_char (struct _vte_draw *draw, vteunistr c, gboolean bold)
 {
 	gboolean has_char = TRUE;
 
-	_vte_debug_print (VTE_DEBUG_DRAW, "draw_has_char ('0x%04X')\n", c);
+	_vte_debug_print (VTE_DEBUG_DRAW, "draw_has_char ('0x%04X', %s)\n", c,
+			  bold ? "bold" : "normal");
 
 	if (draw->impl->has_char)
-		has_char = draw->impl->has_char (draw, c);
+		has_char = draw->impl->has_char (draw, c, bold);
 
 	return has_char;
 }
diff -Nur -x '*.orig' -x '*~' vte-0.19.4/src/vtedraw.h vte-0.19.4.new/src/vtedraw.h
--- vte-0.19.4/src/vtedraw.h	2008-12-11 19:30:57.000000000 -0800
+++ vte-0.19.4.new/src/vtedraw.h	2009-02-11 21:03:01.000000000 -0800
@@ -87,11 +87,13 @@
 			      const PangoFontDescription *,
 			      VteTerminalAntiAlias);
 	void (*get_text_metrics)(struct _vte_draw *, gint *, gint *, gint *);
-	int (*get_char_width)(struct _vte_draw *, vteunistr c, int columns);
+	int (*get_char_width)(struct _vte_draw *, vteunistr c, int columns,
+			      gboolean);
+	gboolean (*has_bold)(struct _vte_draw *);
 	void (*draw_text)(struct _vte_draw *,
-			  struct _vte_draw_text_request *, gsize,
-			  GdkColor *, guchar);
-	gboolean (*has_char)(struct _vte_draw *, vteunistr);
+			  		  struct _vte_draw_text_request *, gsize,
+					  GdkColor *, guchar, gboolean);
+	gboolean (*has_char)(struct _vte_draw *, vteunistr, gboolean);
 	void (*draw_rectangle)(struct _vte_draw *,
 			       gint, gint, gint, gint,
 			       GdkColor *, guchar);
@@ -151,15 +153,17 @@
 			     VteTerminalAntiAlias anti_alias);
 void _vte_draw_get_text_metrics(struct _vte_draw *draw,
 				gint *width, gint *height, gint *ascent);
-int _vte_draw_get_char_width(struct _vte_draw *draw, vteunistr c, int columns);
+int _vte_draw_get_char_width(struct _vte_draw *draw, vteunistr c, int columns,
+			     gboolean bold);
 
 void _vte_draw_text(struct _vte_draw *draw,
 		    struct _vte_draw_text_request *requests, gsize n_requests,
-		    GdkColor *color, guchar alpha);
+		    GdkColor *color, guchar alpha, gboolean);
 gboolean _vte_draw_char(struct _vte_draw *draw,
 			struct _vte_draw_text_request *request,
-			GdkColor *color, guchar alpha);
-gboolean _vte_draw_has_char(struct _vte_draw *draw, vteunistr c);
+			GdkColor *color, guchar alpha, gboolean bold);
+gboolean _vte_draw_has_char(struct _vte_draw *draw, vteunistr c, gboolean bold);
+
 
 void _vte_draw_fill_rectangle(struct _vte_draw *draw,
 			      gint x, gint y, gint width, gint height,
diff -Nur -x '*.orig' -x '*~' vte-0.19.4/src/vtepangocairo.c vte-0.19.4.new/src/vtepangocairo.c
--- vte-0.19.4/src/vtepangocairo.c	2008-12-11 19:47:29.000000000 -0800
+++ vte-0.19.4.new/src/vtepangocairo.c	2009-02-11 21:03:01.000000000 -0800
@@ -755,6 +755,7 @@
 
 struct _vte_pangocairo_data {
 	struct font_info *font;
+	struct font_info *font_bold;
 	cairo_pattern_t *bg_pattern;
 
 	cairo_t *cr;
@@ -914,9 +915,35 @@
 			       VteTerminalAntiAlias antialias)
 {
 	struct _vte_pangocairo_data *data = draw->impl_data;
+	PangoFontDescription *bolddesc = NULL;
 
+	if (data->font_bold != data->font)
+		font_info_destroy (data->font_bold);
 	font_info_destroy (data->font);
 	data->font = font_info_create_for_widget (draw->widget, fontdesc, antialias);
+
+	/* calculate bold font desc */
+	bolddesc = pango_font_description_copy (fontdesc);
+	if (bolddesc) {
+		pango_font_description_set_weight (bolddesc, PANGO_WEIGHT_BOLD);
+
+		data->font_bold = font_info_create_for_widget (draw->widget, bolddesc, antialias);
+		pango_font_description_free (bolddesc);
+
+		/* Decide if we should keep this bold font face, per bug 54926:
+		 *  - reject bold font if it is not within 10% of normal font width
+		 */
+		if ( abs((data->font_bold->width * 100 / data->font->width) - 100) > 10 ) {
+			g_warning(_("bold font too wide (%d not within 10%% of normal width %d), falling back to double-strike"),
+				data->font_bold->width, data->font->width);
+			font_info_destroy (data->font_bold);
+			data->font_bold = data->font;
+		}
+	}
+	else {
+		g_warning(_("can not create bold font"));
+		data->font_bold = data->font;
+	}
 }
 
 static void
@@ -934,17 +961,26 @@
 
 
 static int
-_vte_pangocairo_get_char_width (struct _vte_draw *draw, vteunistr c, int columns)
+_vte_pangocairo_get_char_width (struct _vte_draw *draw, vteunistr c, int columns,
+				gboolean bold)
 {
 	struct _vte_pangocairo_data *data = draw->impl_data;
 	struct unistr_info *uinfo;
 
 	g_return_val_if_fail (data->font != NULL, 0);
 
-	uinfo = font_info_get_unistr_info (data->font, c);
+	uinfo = font_info_get_unistr_info (bold ? data->font_bold : data->font, c);
 	return uinfo->width;
 }
 
+static gboolean
+_vte_pangocairo_has_bold (struct _vte_draw *draw)
+{
+	struct _vte_pangocairo_data *data = draw->impl_data;
+
+	return (data->font != data->font_bold);
+}
+
 static void
 set_source_color_alpha (cairo_t        *cr,
 			const GdkColor *color,
@@ -960,15 +996,16 @@
 static void
 _vte_pangocairo_draw_text (struct _vte_draw *draw,
 			   struct _vte_draw_text_request *requests, gsize n_requests,
-			   GdkColor *color, guchar alpha)
+			   GdkColor *color, guchar alpha, gboolean bold)
 {
 	struct _vte_pangocairo_data *data = draw->impl_data;
 	gsize i;
 	cairo_scaled_font_t *last_scaled_font = NULL;
 	int n_cr_glyphs = 0;
 	cairo_glyph_t cr_glyphs[MAX_RUN_LENGTH];
+	struct font_info *font = bold ? data->font_bold : data->font;
 
-	g_return_if_fail (data->font != NULL);
+	g_return_if_fail (font != NULL);
 
 	set_source_color_alpha (data->cr, color, alpha);
 	cairo_set_operator (data->cr, CAIRO_OPERATOR_OVER);
@@ -976,8 +1013,8 @@
 	for (i = 0; i < n_requests; i++) {
 		vteunistr c = requests[i].c;
 		int x = requests[i].x;
-		int y = requests[i].y + data->font->ascent;
-		struct unistr_info *uinfo = font_info_get_unistr_info (data->font, c);
+		int y = requests[i].y + font->ascent;
+		struct unistr_info *uinfo = font_info_get_unistr_info (font, c);
 		union unistr_font_info *ufi = &uinfo->ufi;
 
 		switch (uinfo->coverage) {
@@ -1024,14 +1061,15 @@
 }
 
 static gboolean
-_vte_pangocairo_draw_has_char (struct _vte_draw *draw, vteunistr c)
+_vte_pangocairo_draw_has_char (struct _vte_draw *draw, vteunistr c,
+			       gboolean bold)
 {
 	struct _vte_pangocairo_data *data = draw->impl_data;
 	struct unistr_info *uinfo;
 
 	g_return_val_if_fail (data->font != NULL, FALSE);
 
-	uinfo = font_info_get_unistr_info (data->font, c);
+	uinfo = font_info_get_unistr_info (bold ? data->font_bold : data->font, c);
 	return !uinfo->has_unknown_chars;
 }
 
@@ -1080,6 +1118,7 @@
 	_vte_pangocairo_set_text_font,
 	_vte_pangocairo_get_text_metrics,
 	_vte_pangocairo_get_char_width,
+	_vte_pangocairo_has_bold,
 	_vte_pangocairo_draw_text,
 	_vte_pangocairo_draw_has_char,
 	_vte_pangocairo_draw_rectangle,
diff -Nur -x '*.orig' -x '*~' vte-0.19.4/src/vteskel.c vte-0.19.4.new/src/vteskel.c
--- vte-0.19.4/src/vteskel.c	2008-12-08 12:12:34.000000000 -0800
+++ vte-0.19.4.new/src/vteskel.c	2009-02-11 21:03:01.000000000 -0800
@@ -78,6 +78,7 @@
 	NULL, /* set_text_font */
 	_vte_skel_get_text_metrics,
 	NULL, /* get_char_width */
+	NULL, /* has_bold */
 	_vte_skel_draw_text,
 	NULL, /* draw_has_char */
 	NULL, /* draw_rectangle */
