diff options
author | Havoc Pennington <hp@redhat.com> | 2000-11-15 00:23:37 +0000 |
---|---|---|
committer | Havoc Pennington <hp@src.gnome.org> | 2000-11-15 00:23:37 +0000 |
commit | fe8da19f2a65a220c805cdf37c60f6a0c0f1d368 (patch) | |
tree | 7188631c820283bd62a658c48384db384cde3650 /gtk | |
parent | 2d24862ffdf973337ff31168c11259a3f4d5acdf (diff) | |
download | gtk+-fe8da19f2a65a220c805cdf37c60f6a0c0f1d368.tar.gz |
Draw underlines one pixel higher.
2000-11-14 Havoc Pennington <hp@redhat.com>
* gdk/gdkpango.c (gdk_draw_layout_line): Draw underlines one pixel
higher.
* gtk/gtktextdisplay.c (render_layout_line): Take rise into
account. Also, render rise, underline, background, etc. for
pixbufs as well as text. Also, draw underlines one pixel higher.
* gtk/gtktextlayout.c (gtk_text_layout_get_line_display): Add a
PangoAttribute for the rise, so it gets drawn properly. Also,
add the GtkTextAppearance attribute for pixbuf/widget segments
as well; we should go ahead and have rise, underline, background,
stipple work for those
* gtk/gtktexttag.c: Rename "offset" property to "rise" to match
Pango
Diffstat (limited to 'gtk')
-rw-r--r-- | gtk/gtktextdisplay.c | 193 | ||||
-rw-r--r-- | gtk/gtktextlayout.c | 82 | ||||
-rw-r--r-- | gtk/gtktexttag.c | 36 | ||||
-rw-r--r-- | gtk/gtktexttag.h | 15 | ||||
-rw-r--r-- | gtk/testgtk.c | 2 | ||||
-rw-r--r-- | gtk/testtext.c | 2 |
6 files changed, 219 insertions, 111 deletions
diff --git a/gtk/gtktextdisplay.c b/gtk/gtktextdisplay.c index bc9ba18235..55e8ba3fba 100644 --- a/gtk/gtktextdisplay.c +++ b/gtk/gtktextdisplay.c @@ -185,6 +185,34 @@ gtk_text_render_state_update (GtkTextRenderState *state, } static void +get_shape_extents (PangoLayoutRun *run, + PangoRectangle *ink_rect, + PangoRectangle *logical_rect) +{ + GSList *tmp_list = run->item->extra_attrs; + + while (tmp_list) + { + PangoAttribute *attr = tmp_list->data; + + if (attr->klass->type == PANGO_ATTR_SHAPE) + { + if (logical_rect) + *logical_rect = ((PangoAttrShape *)attr)->logical_rect; + + if (ink_rect) + *ink_rect = ((PangoAttrShape *)attr)->ink_rect; + + return; + } + + tmp_list = tmp_list->next; + } + + g_assert_not_reached (); +} + +static void render_layout_line (GdkDrawable *drawable, GtkTextRenderState *render_state, PangoLayoutLine *line, @@ -197,85 +225,72 @@ render_layout_line (GdkDrawable *drawable, PangoRectangle overall_rect; PangoRectangle logical_rect; PangoRectangle ink_rect; - gint x_off = 0; - + GdkGC *fg_gc; + pango_layout_line_get_extents (line, NULL, &overall_rect); while (tmp_list) { PangoLayoutRun *run = tmp_list->data; GtkTextAppearance *appearance; - + gint risen_y; + gint shaped_width_pixels = 0; + gboolean need_ink = FALSE; + tmp_list = tmp_list->next; get_item_properties (run->item, &appearance); - if (appearance) /* A text segment */ + g_assert (appearance != NULL); + + risen_y = y - PANGO_PIXELS (appearance->rise); + + if (selected) { - GdkGC *fg_gc; - - if (selected) - { - fg_gc = render_state->widget->style->fg_gc[GTK_STATE_SELECTED]; - } - else - { - gtk_text_render_state_update (render_state, appearance); - - fg_gc = render_state->fg_gc; - } - - if (appearance->underline == PANGO_UNDERLINE_NONE && !appearance->strikethrough) + fg_gc = render_state->widget->style->fg_gc[GTK_STATE_SELECTED]; + } + else + { + gtk_text_render_state_update (render_state, appearance); + + fg_gc = render_state->fg_gc; + } + + if (appearance->underline != PANGO_UNDERLINE_NONE || + appearance->strikethrough) + need_ink = TRUE; + + if (appearance->is_text) + { + if (need_ink) pango_glyph_string_extents (run->glyphs, run->item->analysis.font, NULL, &logical_rect); else pango_glyph_string_extents (run->glyphs, run->item->analysis.font, &ink_rect, &logical_rect); - - if (appearance->draw_bg && !selected) - gdk_draw_rectangle (drawable, render_state->bg_gc, TRUE, - x + PANGO_PIXELS (x_off) + PANGO_PIXELS (logical_rect.x), - y + PANGO_PIXELS (logical_rect.y), - PANGO_PIXELS (logical_rect.width), - PANGO_PIXELS (logical_rect.height)); - - gdk_draw_glyphs (drawable, fg_gc, - run->item->analysis.font, - x + PANGO_PIXELS (x_off), y, run->glyphs); - - switch (appearance->underline) - { - case PANGO_UNDERLINE_NONE: - break; - case PANGO_UNDERLINE_DOUBLE: - gdk_draw_line (drawable, fg_gc, - x + (x_off + ink_rect.x) / PANGO_SCALE - 1, y + 4, - x + (x_off + ink_rect.x + ink_rect.width) / PANGO_SCALE, y + 4); - /* Fall through */ - case PANGO_UNDERLINE_SINGLE: - gdk_draw_line (drawable, fg_gc, - x + (x_off + ink_rect.x) / PANGO_SCALE - 1, y + 2, - x + (x_off + ink_rect.x + ink_rect.width) / PANGO_SCALE, y + 2); - break; - case PANGO_UNDERLINE_LOW: - gdk_draw_line (drawable, fg_gc, - x + (x_off + ink_rect.x) / PANGO_SCALE - 1, y + (ink_rect.y + ink_rect.height) / PANGO_SCALE + 2, - x + (x_off + ink_rect.x + ink_rect.width) / PANGO_SCALE, y + (ink_rect.y + ink_rect.height) / PANGO_SCALE + 2); - break; - } - - if (appearance->strikethrough) - { - gint strikethrough_y = y + (0.3 * logical_rect.y) / PANGO_SCALE; - gdk_draw_line (drawable, fg_gc, - x + (x_off + ink_rect.x) / PANGO_SCALE - 1, strikethrough_y, - x + (x_off + ink_rect.x + ink_rect.width) / PANGO_SCALE, strikethrough_y); - } - - x_off += logical_rect.width; } - else /* Pixbuf or widget segment */ + else + { + if (need_ink) + get_shape_extents (run, &ink_rect, &logical_rect); + else + get_shape_extents (run, NULL, &logical_rect); + } + + if (appearance->draw_bg && !selected) + gdk_draw_rectangle (drawable, render_state->bg_gc, TRUE, + x + PANGO_PIXELS (x_off) + PANGO_PIXELS (logical_rect.x), + risen_y + PANGO_PIXELS (logical_rect.y), + PANGO_PIXELS (logical_rect.width), + PANGO_PIXELS (logical_rect.height)); + + if (appearance->is_text) + gdk_draw_glyphs (drawable, fg_gc, + run->item->analysis.font, + x + PANGO_PIXELS (x_off), + risen_y, run->glyphs); + else { GObject *shaped = (*shaped_pointer)->data; @@ -293,7 +308,7 @@ render_layout_line (GdkDrawable *drawable, height = gdk_pixbuf_get_height (pixbuf); pixbuf_rect.x = x + x_off / PANGO_SCALE; - pixbuf_rect.y = y - height; + pixbuf_rect.y = risen_y - height; pixbuf_rect.width = width; pixbuf_rect.height = height; @@ -343,7 +358,7 @@ render_layout_line (GdkDrawable *drawable, } } - x_off += width * PANGO_SCALE; + shaped_width_pixels = width; } else if (GTK_IS_WIDGET (shaped)) { @@ -351,6 +366,10 @@ render_layout_line (GdkDrawable *drawable, GdkRectangle draw_rect; GtkWidget *widget; + /* FIXME this doesn't work at all, and remember to use + * risen_y + */ + widget = GTK_WIDGET (shaped); width = widget->allocation.width; @@ -364,11 +383,57 @@ render_layout_line (GdkDrawable *drawable, gtk_widget_draw (widget, &draw_rect); } - x_off += width * PANGO_SCALE; + shaped_width_pixels = width; } else g_assert_not_reached (); /* not a pixbuf or widget */ } + + switch (appearance->underline) + { + case PANGO_UNDERLINE_NONE: + break; + case PANGO_UNDERLINE_DOUBLE: + g_assert (need_ink); + 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: + g_assert (need_ink); + 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: + g_assert (need_ink); + 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 (appearance->strikethrough) + { + gint strikethrough_y = risen_y + (0.3 * logical_rect.y) / PANGO_SCALE; + + g_assert (need_ink); + + gdk_draw_line (drawable, fg_gc, + x + (x_off + ink_rect.x) / PANGO_SCALE - 1, strikethrough_y, + x + (x_off + ink_rect.x + ink_rect.width) / PANGO_SCALE, strikethrough_y); + } + + if (appearance->is_text) + x_off += logical_rect.width; + else + x_off += shaped_width_pixels * PANGO_SCALE; } } diff --git a/gtk/gtktextlayout.c b/gtk/gtktextlayout.c index be77b17a45..d8eed0c7e8 100644 --- a/gtk/gtktextlayout.c +++ b/gtk/gtktextlayout.c @@ -1227,6 +1227,51 @@ gtk_text_attr_appearance_new (const GtkTextAppearance *appearance) return (PangoAttribute *)result; } + +static void +add_generic_attrs (GtkTextLayout *layout, + GtkTextAppearance *appearance, + gint byte_count, + PangoAttrList *attrs, + gint start, + gboolean size_only, + gboolean is_text) +{ + PangoAttribute *attr; + + if (appearance->underline != PANGO_UNDERLINE_NONE) + { + attr = pango_attr_underline_new (appearance->underline); + + attr->start_index = start; + attr->end_index = start + byte_count; + + pango_attr_list_insert (attrs, attr); + } + + if (appearance->rise != 0) + { + attr = pango_attr_rise_new (appearance->rise); + + attr->start_index = start; + attr->end_index = start + byte_count; + + pango_attr_list_insert (attrs, attr); + } + + if (!size_only) + { + attr = gtk_text_attr_appearance_new (appearance); + + attr->start_index = start; + attr->end_index = start + byte_count; + + ((GtkTextAttrAppearance *)attr)->appearance.is_text = is_text; + + pango_attr_list_insert (attrs, attr); + } +} + static void add_text_attrs (GtkTextLayout *layout, GtkTextAttributes *style, @@ -1242,16 +1287,6 @@ add_text_attrs (GtkTextLayout *layout, attr->end_index = start + byte_count; pango_attr_list_insert (attrs, attr); - - if (!size_only) - { - attr = gtk_text_attr_appearance_new (&style->appearance); - - attr->start_index = start; - attr->end_index = start + byte_count; - - pango_attr_list_insert (attrs, attr); - } } static void @@ -1490,16 +1525,10 @@ add_preedit_attrs (GtkTextLayout *layout, insert_attr->end_index = end + offset; pango_attr_list_insert (attrs, insert_attr); - - if (!size_only) - { - insert_attr = gtk_text_attr_appearance_new (&appearance); - - insert_attr->start_index = start + offset; - insert_attr->end_index = end + offset; - - pango_attr_list_insert (attrs, insert_attr); - } + + add_generic_attrs (layout, &appearance, end - start, + attrs, start + offset, + size_only, TRUE); } while (pango_attr_iterator_next (iter)); @@ -1642,11 +1671,20 @@ gtk_text_layout_get_line_display (GtkTextLayout *layout, } seg = prev_seg; /* Back up one */ + add_generic_attrs (layout, &style->appearance, + byte_count, + attrs, byte_offset - byte_count, + size_only, TRUE); add_text_attrs (layout, style, byte_count, attrs, byte_offset - byte_count, size_only); } else if (seg->type == >k_text_pixbuf_type) { + add_generic_attrs (layout, + &style->appearance, + seg->byte_count, + attrs, byte_offset, + size_only, FALSE); add_pixbuf_attrs (layout, display, style, seg, attrs, byte_offset); memcpy (text + byte_offset, gtk_text_unknown_char_utf8, @@ -1655,6 +1693,10 @@ gtk_text_layout_get_line_display (GtkTextLayout *layout, } else if (seg->type == >k_text_child_type) { + add_generic_attrs (layout, &style->appearance, + seg->byte_count, + attrs, byte_offset, + size_only, FALSE); add_child_attrs (layout, display, style, seg, attrs, byte_offset); memcpy (text + byte_offset, gtk_text_unknown_char_utf8, diff --git a/gtk/gtktexttag.c b/gtk/gtktexttag.c index 98d77481c4..e812b14775 100644 --- a/gtk/gtktexttag.c +++ b/gtk/gtktexttag.c @@ -95,7 +95,7 @@ enum { ARG_STRIKETHROUGH, ARG_RIGHT_MARGIN, ARG_UNDERLINE, - ARG_OFFSET, + ARG_RISE, ARG_BG_FULL_HEIGHT, ARG_LANGUAGE, ARG_TABS, @@ -125,7 +125,7 @@ enum { ARG_STRIKETHROUGH_SET, ARG_RIGHT_MARGIN_SET, ARG_UNDERLINE_SET, - ARG_OFFSET_SET, + ARG_RISE_SET, ARG_BG_FULL_HEIGHT_SET, ARG_LANGUAGE_SET, ARG_TABS_SET, @@ -233,8 +233,8 @@ gtk_text_tag_class_init (GtkTextTagClass *klass) GTK_ARG_READWRITE, ARG_LEFT_MARGIN); gtk_object_add_arg_type ("GtkTextTag::indent", GTK_TYPE_INT, GTK_ARG_READWRITE, ARG_INDENT); - gtk_object_add_arg_type ("GtkTextTag::offset", GTK_TYPE_INT, - GTK_ARG_READWRITE, ARG_OFFSET); + gtk_object_add_arg_type ("GtkTextTag::rise", GTK_TYPE_INT, + GTK_ARG_READWRITE, ARG_RISE); gtk_object_add_arg_type ("GtkTextTag::pixels_above_lines", GTK_TYPE_INT, GTK_ARG_READWRITE, ARG_PIXELS_ABOVE_LINES); gtk_object_add_arg_type ("GtkTextTag::pixels_below_lines", GTK_TYPE_INT, @@ -291,8 +291,8 @@ gtk_text_tag_class_init (GtkTextTagClass *klass) GTK_ARG_READWRITE, ARG_LEFT_MARGIN_SET); gtk_object_add_arg_type ("GtkTextTag::indent_set", GTK_TYPE_BOOL, GTK_ARG_READWRITE, ARG_INDENT_SET); - gtk_object_add_arg_type ("GtkTextTag::offset_set", GTK_TYPE_BOOL, - GTK_ARG_READWRITE, ARG_OFFSET_SET); + gtk_object_add_arg_type ("GtkTextTag::rise_set", GTK_TYPE_BOOL, + GTK_ARG_READWRITE, ARG_RISE_SET); gtk_object_add_arg_type ("GtkTextTag::pixels_above_lines_set", GTK_TYPE_BOOL, GTK_ARG_READWRITE, ARG_PIXELS_ABOVE_LINES_SET); gtk_object_add_arg_type ("GtkTextTag::pixels_below_lines_set", GTK_TYPE_BOOL, @@ -697,9 +697,9 @@ gtk_text_tag_set_arg (GtkObject *object, GtkArg *arg, guint arg_id) text_tag->values->appearance.underline = GTK_VALUE_ENUM (*arg); break; - case ARG_OFFSET: - text_tag->offset_set = TRUE; - text_tag->values->offset = GTK_VALUE_INT (*arg); + case ARG_RISE: + text_tag->rise_set = TRUE; + text_tag->values->appearance.rise = GTK_VALUE_INT (*arg); size_changed = TRUE; break; @@ -845,8 +845,8 @@ gtk_text_tag_set_arg (GtkObject *object, GtkArg *arg, guint arg_id) text_tag->underline_set = GTK_VALUE_BOOL (*arg); break; - case ARG_OFFSET_SET: - text_tag->offset_set = GTK_VALUE_BOOL (*arg); + case ARG_RISE_SET: + text_tag->rise_set = GTK_VALUE_BOOL (*arg); size_changed = TRUE; break; @@ -1031,8 +1031,8 @@ gtk_text_tag_get_arg (GtkObject *object, GtkArg *arg, guint arg_id) GTK_VALUE_ENUM (*arg) = tag->values->appearance.underline; break; - case ARG_OFFSET: - GTK_VALUE_INT (*arg) = tag->values->offset; + case ARG_RISE: + GTK_VALUE_INT (*arg) = tag->values->appearance.rise; break; case ARG_BG_FULL_HEIGHT: @@ -1134,8 +1134,8 @@ gtk_text_tag_get_arg (GtkObject *object, GtkArg *arg, guint arg_id) GTK_VALUE_BOOL (*arg) = tag->underline_set; break; - case ARG_OFFSET_SET: - GTK_VALUE_BOOL (*arg) = tag->offset_set; + case ARG_RISE_SET: + GTK_VALUE_BOOL (*arg) = tag->rise_set; break; case ARG_BG_FULL_HEIGHT_SET: @@ -1578,8 +1578,8 @@ gtk_text_attributes_fill_from_tags (GtkTextAttributes *dest, if (tag->indent_set) dest->indent = vals->indent; - if (tag->offset_set) - dest->offset = vals->offset; + if (tag->rise_set) + dest->appearance.rise = vals->appearance.rise; if (tag->right_margin_set) dest->right_margin = vals->right_margin; @@ -1643,7 +1643,7 @@ gtk_text_tag_affects_size (GtkTextTag *tag) tag->justify_set || tag->left_margin_set || tag->indent_set || - tag->offset_set || + tag->rise_set || tag->right_margin_set || tag->pixels_above_lines_set || tag->pixels_below_lines_set || diff --git a/gtk/gtktexttag.h b/gtk/gtktexttag.h index 4924b1c102..dcf4954672 100644 --- a/gtk/gtktexttag.h +++ b/gtk/gtktexttag.h @@ -71,7 +71,7 @@ struct _GtkTextTag guint justify_set : 1; guint left_margin_set : 1; guint indent_set : 1; - guint offset_set : 1; + guint rise_set : 1; guint strikethrough_set : 1; guint right_margin_set : 1; guint pixels_above_lines_set : 1; @@ -121,6 +121,9 @@ struct _GtkTextAppearance GdkBitmap *bg_stipple; GdkBitmap *fg_stipple; + /* super/subscript rise, can be negative */ + gint rise; + guint underline : 4; /* PangoUnderline */ guint strikethrough : 1; @@ -130,12 +133,13 @@ struct _GtkTextAppearance * had background stuff set. */ guint draw_bg : 1; - - /* This is only used when we are actually laying out and rendering + + /* These are only used when we are actually laying out and rendering * a paragraph; not when a GtkTextAppearance is part of a * GtkTextAttributes. */ guint inside_selection : 1; + guint is_text : 1; }; struct _GtkTextAttributes @@ -152,10 +156,7 @@ struct _GtkTextAttributes gint left_margin; - gint indent; - - /* super/subscript offset, can be negative */ - gint offset; + gint indent; gint right_margin; diff --git a/gtk/testgtk.c b/gtk/testgtk.c index aefa384ee5..555ac978b1 100644 --- a/gtk/testgtk.c +++ b/gtk/testgtk.c @@ -2111,7 +2111,7 @@ void create_labels (void) "or even on this one\n" "la <big>la <big>la <big>la <big>la</big></big></big></big>\n" "but this _word is <span foreground=\"purple\"><big>purple</big></span>\n" - "We like <sup>superscript</sup> and <sub>subscript</sub> too"); + "<span underline=\"double\">We like <sup>superscript</sup> and <sub>subscript</sub> too</span>"); g_return_if_fail (keyval == GDK_s); diff --git a/gtk/testtext.c b/gtk/testtext.c index 9e52f2f97b..1ea511bdd7 100644 --- a/gtk/testtext.c +++ b/gtk/testtext.c @@ -454,7 +454,7 @@ fill_example_buffer (GtkTextBuffer *buffer) color.blue = color.green = 0; color.red = 0xffff; gtk_object_set (GTK_OBJECT (tag), - "offset", -4, + "rise", -4 * PANGO_SCALE, "foreground_gdk", &color, NULL); |