summaryrefslogtreecommitdiff
path: root/gdk/gdkpango.c
diff options
context:
space:
mode:
authorOwen Taylor <otaylor@redhat.com>2003-06-04 23:47:23 +0000
committerOwen Taylor <otaylor@src.gnome.org>2003-06-04 23:47:23 +0000
commitf9a478644e7215be2110d7b120938c47be9248d0 (patch)
tree86c63ce1097caf67bb0a9fa9b45192c23a395e62 /gdk/gdkpango.c
parent0f635335e281ec109bc8101b9a31be77411d53cc (diff)
downloadgtk+-f9a478644e7215be2110d7b120938c47be9248d0.tar.gz
When drawing underlines, join up adjacent runs where possible, so we don't
Wed Jun 4 19:42:17 2003 Owen Taylor <otaylor@redhat.com> * gdk/gdkpango.c (gdk_draw_layout_line_with_colors): When drawing underlines, join up adjacent runs where possible, so we don't get changes in shaper/font/etc. breaking underlines. (#103662, Kang Jeong-Hee)
Diffstat (limited to 'gdk/gdkpango.c')
-rw-r--r--gdk/gdkpango.c146
1 files changed, 112 insertions, 34 deletions
diff --git a/gdk/gdkpango.c b/gdk/gdkpango.c
index af8d1936c0..db0c871359 100644
--- a/gdk/gdkpango.c
+++ b/gdk/gdkpango.c
@@ -163,6 +163,37 @@ gdk_pango_context_set_colormap (PangoContext *context,
}
}
+static void
+draw_underline (GdkDrawable *drawable,
+ GdkGC *gc,
+ PangoUnderline uline,
+ int baseline_y,
+ int low_y,
+ int start_x,
+ int end_x)
+{
+ switch (uline)
+ {
+ case PANGO_UNDERLINE_NONE:
+ break;
+ case PANGO_UNDERLINE_DOUBLE:
+ gdk_draw_line (drawable, gc,
+ start_x, baseline_y + 3,
+ end_x, baseline_y + 3);
+ /* Fall through */
+ case PANGO_UNDERLINE_SINGLE:
+ gdk_draw_line (drawable, gc,
+ start_x, baseline_y + 1,
+ end_x, baseline_y + 1);
+ break;
+ case PANGO_UNDERLINE_LOW:
+ gdk_draw_line (drawable, gc,
+ start_x, low_y + 1,
+ end_x, low_y + 1);
+ break;
+ }
+}
+
/**
* gdk_draw_layout_line_with_colors:
* @drawable: the drawable on which to draw the line
@@ -195,6 +226,15 @@ gdk_draw_layout_line_with_colors (GdkDrawable *drawable,
gint rise = 0;
gboolean embossed;
GdkBitmap *stipple;
+ PangoUnderline last_uline = PANGO_UNDERLINE_NONE;
+ gint uline_start_x = 0;
+ gint uline_end_x = 0;
+ gint uline_end_x_extended = 0;
+ gint last_risen_y = 0;
+ gint low_y = G_MININT;
+ GdkGC *last_fg_gc = NULL;
+ gboolean last_fg_set = FALSE;
+ PangoColor last_fg_color;
g_return_if_fail (GDK_IS_DRAWABLE (drawable));
g_return_if_fail (GDK_IS_GC (gc));
@@ -206,7 +246,7 @@ gdk_draw_layout_line_with_colors (GdkDrawable *drawable,
while (tmp_list)
{
- PangoUnderline uline = PANGO_UNDERLINE_NONE;
+ PangoUnderline this_uline = PANGO_UNDERLINE_NONE;
PangoLayoutRun *run = tmp_list->data;
PangoColor fg_color, bg_color;
gboolean strike, fg_set, bg_set, shape_set;
@@ -215,7 +255,7 @@ gdk_draw_layout_line_with_colors (GdkDrawable *drawable,
tmp_list = tmp_list->next;
- gdk_pango_get_item_properties (run->item, &uline,
+ gdk_pango_get_item_properties (run->item, &this_uline,
&strike,
&rise,
&fg_color, &fg_set,
@@ -231,7 +271,7 @@ gdk_draw_layout_line_with_colors (GdkDrawable *drawable,
if (!shape_set)
{
- if (uline == PANGO_UNDERLINE_NONE)
+ if (this_uline == PANGO_UNDERLINE_NONE)
pango_glyph_string_extents (run->glyphs, run->item->analysis.font,
NULL, &logical_rect);
else
@@ -281,7 +321,7 @@ gdk_draw_layout_line_with_colors (GdkDrawable *drawable,
}
else
fg_gc = gc;
-
+
if (!shape_set)
{
gint gx, gy;
@@ -304,36 +344,58 @@ gdk_draw_layout_line_with_colors (GdkDrawable *drawable,
gx, gy,
run->glyphs);
}
-
- switch (uline)
+
+ if (this_uline != last_uline ||
+ risen_y != last_risen_y ||
+ fg_set != last_fg_set ||
+ (fg_set && (last_fg_color.red != fg_color.red ||
+ last_fg_color.green != fg_color.green ||
+ last_fg_color.blue != fg_color.blue)))
{
- case PANGO_UNDERLINE_NONE:
- break;
- case PANGO_UNDERLINE_DOUBLE:
- gdk_draw_line (drawable, fg_gc,
- x + (x_off + ink_rect.x) / PANGO_SCALE - 1,
- risen_y + 3,
- x + (x_off + ink_rect.x + ink_rect.width) / PANGO_SCALE,
- risen_y + 3);
- /* Fall through */
- case PANGO_UNDERLINE_SINGLE:
- gdk_draw_line (drawable, fg_gc,
- x + (x_off + ink_rect.x) / PANGO_SCALE - 1,
- risen_y + 1,
- x + (x_off + ink_rect.x + ink_rect.width) / PANGO_SCALE,
- risen_y + 1);
- break;
- case PANGO_UNDERLINE_LOW:
- gdk_draw_line (drawable, fg_gc,
- x + (x_off + ink_rect.x) / PANGO_SCALE - 1,
- risen_y + (ink_rect.y + ink_rect.height) / PANGO_SCALE + 1,
- x + (x_off + ink_rect.x + ink_rect.width) / PANGO_SCALE,
- risen_y + (ink_rect.y + ink_rect.height) / PANGO_SCALE + 1);
- break;
+ /* If only color changes, the underlines extend to the edge
+ * of the logical rectangle so they join up; otherwise they
+ * go 1 pixel beyond the ink rectangle. This doesn't work
+ * for low underlines (they will be at a different y anyways),
+ * so they follow the normal path.
+ */
+ gboolean extend_uline = (this_uline == last_uline &&
+ this_uline != PANGO_UNDERLINE_LOW &&
+ risen_y == last_risen_y);
+
+ /* Starting a new underline run
+ */
+ if (last_uline != PANGO_UNDERLINE_NONE)
+ {
+ draw_underline (drawable, last_fg_gc, last_uline,
+ last_risen_y, low_y,
+ uline_start_x,
+ extend_uline ? uline_end_x_extended : uline_end_x);
+ }
+
+ if (this_uline != PANGO_UNDERLINE_NONE)
+ {
+ if (extend_uline)
+ uline_start_x = x + x_off / PANGO_SCALE;
+ else
+ uline_start_x = x + (x_off + ink_rect.x) / PANGO_SCALE - 1;
+
+ low_y = G_MININT;
+ }
}
+ /* Update current underline segment information
+ */
+ if (this_uline != PANGO_UNDERLINE_NONE)
+ {
+ uline_end_x = x + (x_off + ink_rect.x + ink_rect.width) / PANGO_SCALE;
+ uline_end_x_extended = x + (x_off + logical_rect.x + logical_rect.width) / PANGO_SCALE - 1;
+ }
+
+ if (this_uline == PANGO_UNDERLINE_LOW)
+ low_y = MAX (low_y, risen_y + (ink_rect.y + ink_rect.height) / PANGO_SCALE);
+
if (strike)
- {
+ {
int centerline = logical_rect.y + logical_rect.height / 2;
gdk_draw_line (drawable, fg_gc,
@@ -341,13 +403,29 @@ gdk_draw_layout_line_with_colors (GdkDrawable *drawable,
risen_y + centerline / PANGO_SCALE,
x + (x_off + logical_rect.x + logical_rect.width) / PANGO_SCALE + 1,
risen_y + centerline / PANGO_SCALE);
- }
-
- if (fg_gc != gc)
- gdk_pango_free_gc (context, fg_gc);
+ }
+
+ if (last_fg_gc != gc && last_fg_gc)
+ gdk_pango_free_gc (context, last_fg_gc);
+ last_risen_y = risen_y;
+ last_uline = this_uline;
+ last_fg_gc = fg_gc;
+ last_fg_set = fg_set;
+ if (fg_set)
+ last_fg_color = fg_color;
+
x_off += logical_rect.width;
}
+
+ /* Finish off any remaining underlines
+ */
+ if (last_uline != PANGO_UNDERLINE_NONE)
+ draw_underline (drawable, last_fg_gc, last_uline, last_risen_y, low_y,
+ uline_start_x, uline_end_x);
+
+ if (last_fg_gc != gc && last_fg_gc)
+ gdk_pango_free_gc (context, last_fg_gc);
}
/**