summaryrefslogtreecommitdiff
path: root/gtk
diff options
context:
space:
mode:
authorHavoc Pennington <hp@redhat.com>2000-11-15 00:23:37 +0000
committerHavoc Pennington <hp@src.gnome.org>2000-11-15 00:23:37 +0000
commitfe8da19f2a65a220c805cdf37c60f6a0c0f1d368 (patch)
tree7188631c820283bd62a658c48384db384cde3650 /gtk
parent2d24862ffdf973337ff31168c11259a3f4d5acdf (diff)
downloadgtk+-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.c193
-rw-r--r--gtk/gtktextlayout.c82
-rw-r--r--gtk/gtktexttag.c36
-rw-r--r--gtk/gtktexttag.h15
-rw-r--r--gtk/testgtk.c2
-rw-r--r--gtk/testtext.c2
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 == &gtk_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 == &gtk_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);