diff options
author | Owen Taylor <otaylor@redhat.com> | 2003-06-04 23:47:23 +0000 |
---|---|---|
committer | Owen Taylor <otaylor@src.gnome.org> | 2003-06-04 23:47:23 +0000 |
commit | f9a478644e7215be2110d7b120938c47be9248d0 (patch) | |
tree | 86c63ce1097caf67bb0a9fa9b45192c23a395e62 /gdk/gdkpango.c | |
parent | 0f635335e281ec109bc8101b9a31be77411d53cc (diff) | |
download | gtk+-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.c | 146 |
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); } /** |