Patch to add word underlining
- From: Damon Chaplin <damon kendo fsnet co uk>
- To: gtk-i18n-list gnome org
- Subject: Patch to add word underlining
- Date: 21 Oct 2002 19:42:00 +0100
Here's my first attempt at hacking Pango. It does word-underlining.
It creates separate PangoItems for word/non-word runs when
word-underlining is on. And for non-word runs it replaces the
PANGO_UNDERLINE_WORD with PANGO_UNDERLINE_NONE so they don't get
underlined.
I also had to hack gtktextdisplay.c a little, as it handles underlining
itself.
I'm just posting to ask if this is the correct way to do word
underlining. Note that the patch isn't quite complete. It may need a few
more tiny changes to GDK and GTK+. Also, I'm not sure if we want
PANGO_UNDERLINE_WORD_SINGLE/DOUBLE/LOW. They would be simple to add, so
I don't see why not.
Damon
--- pango-attributes.h.orig Tue Sep 18 21:05:17 2001
+++ pango-attributes.h Mon Oct 21 02:42:42 2002
@@ -87,7 +87,8 @@
PANGO_UNDERLINE_NONE,
PANGO_UNDERLINE_SINGLE,
PANGO_UNDERLINE_DOUBLE,
- PANGO_UNDERLINE_LOW
+ PANGO_UNDERLINE_LOW,
+ PANGO_UNDERLINE_WORD
} PangoUnderline;
struct _PangoAttribute
--- pango-context.c.orig Mon Oct 14 23:50:47 2002
+++ pango-context.c Mon Oct 21 18:44:20 2002
@@ -385,6 +385,7 @@
const char *p;
const char *next;
GList *result = NULL;
+ gboolean word_underline_on = FALSE, last_was_word_char = FALSE;
PangoAnalysis *analyses;
@@ -435,10 +436,29 @@
{
PangoAnalysis *analysis = &analyses[i];
PangoAnalysis *last_analysis = i > 0 ? &analyses[i-1] : 0;
+ gboolean need_new_item = FALSE;
next = g_utf8_next_char (p);
- if (i == 0 ||
+ if (word_underline_on)
+ {
+ gboolean is_word_char;
+
+ /* Check if we've just switched from a word char to a non-word
+ * char, in which case we want to start a new run.
+ */
+ if (g_unichar_isgraph (g_utf8_get_char (p)))
+ is_word_char = TRUE;
+ else
+ is_word_char = FALSE;
+
+ if (is_word_char != last_was_word_char)
+ need_new_item = TRUE;
+
+ last_was_word_char = is_word_char;
+ }
+
+ if (i == 0 || need_new_item ||
text_ucs4[i] == '\t' || text_ucs4[i-1] == '\t' ||
embedding_levels[i] != embedding_levels[i-1] ||
analysis->shape_engine != last_analysis->shape_engine ||
@@ -447,6 +467,8 @@
analysis->language != last_analysis->language ||
analysis->extra_attrs != last_analysis->extra_attrs)
{
+ GSList *tmp_list;
+
/* assert that previous item got at least one char */
g_assert (item == NULL || item->length > 0);
g_assert (item == NULL || item->num_chars > 0);
@@ -478,6 +500,32 @@
else
item->analysis.extra_attrs = analysis->extra_attrs;
+ word_underline_on = FALSE;
+ for (tmp_list = item->analysis.extra_attrs; tmp_list;
+ tmp_list = tmp_list->next)
+ {
+ PangoAttribute *attr = tmp_list->data;
+
+ if (attr->klass->type == PANGO_ATTR_UNDERLINE
+ && ((PangoAttrInt *)attr)->value == PANGO_UNDERLINE_WORD)
+ {
+ /* Set the flag to indicate word underlining is on, so we
+ * look for word/non-word boundaries.
+ */
+ word_underline_on = TRUE;
+
+ if (g_unichar_isgraph (g_utf8_get_char (p)))
+ {
+ last_was_word_char = TRUE;
+ }
+ else
+ {
+ last_was_word_char = FALSE;
+ ((PangoAttrInt *)attr)->value = PANGO_UNDERLINE_NONE;
+ }
+ }
+ }
+
result = g_list_prepend (result, item);
}
else
--- pango-layout.c.orig Mon Oct 14 23:50:47 2002
+++ pango-layout.c Mon Oct 21 02:44:48 2002
@@ -3512,6 +3512,7 @@
case PANGO_UNDERLINE_NONE:
break;
case PANGO_UNDERLINE_SINGLE:
+ case PANGO_UNDERLINE_WORD:
if (run_ink)
run_ink->height = MAX (run_ink->height, 2 * PANGO_SCALE - run_ink->y);
if (run_logical)
--- pango-markup.c.orig Tue Jul 2 18:15:22 2002
+++ pango-markup.c Mon Oct 21 02:48:09 2002
@@ -1133,6 +1133,8 @@
ul = PANGO_UNDERLINE_DOUBLE;
else if (strcmp (underline, "low") == 0)
ul = PANGO_UNDERLINE_LOW;
+ else if (strcmp (underline, "word") == 0)
+ ul = PANGO_UNDERLINE_WORD;
else if (strcmp (underline, "none") == 0)
ul = PANGO_UNDERLINE_NONE;
else
--- pangox.c.orig Mon Oct 14 23:50:47 2002
+++ pangox.c Mon Oct 21 18:53:06 2002
@@ -1582,6 +1582,7 @@
x + (x_off + ink_rect.x + ink_rect.width) / PANGO_SCALE, y + 4);
/* Fall through */
case PANGO_UNDERLINE_SINGLE:
+ case PANGO_UNDERLINE_WORD:
XDrawLine (display, 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);
--- pangoft2.c.orig Mon Oct 21 18:53:57 2002
+++ pangoft2.c Mon Oct 21 18:54:00 2002
@@ -895,6 +895,7 @@
x + PANGO_PIXELS (x_off + ink_rect.x + ink_rect.width));
/* Fall through */
case PANGO_UNDERLINE_SINGLE:
+ case PANGO_UNDERLINE_WORD:
pango_ft2_draw_hline (bitmap, y + 2,
x + PANGO_PIXELS (x_off + ink_rect.x),
x + PANGO_PIXELS (x_off + ink_rect.x + ink_rect.width));
--- pangowin32.c.orig Mon Oct 14 23:50:47 2002
+++ pangowin32.c Mon Oct 21 18:55:03 2002
@@ -676,6 +676,7 @@
Polyline (hdc, points, 2);
/* Fall through */
case PANGO_UNDERLINE_SINGLE:
+ case PANGO_UNDERLINE_WORD:
points[0].y = points[1].y = y + 2;
Polyline (hdc, points, 2);
break;
--- gtktextdisplay.c.orig Mon Oct 21 18:48:59 2002
+++ gtktextdisplay.c Mon Oct 21 18:48:09 2002
@@ -258,6 +258,7 @@
gint risen_y;
gint shaped_width_pixels = 0;
gboolean need_ink = FALSE;
+ PangoUnderline underline;
tmp_list = tmp_list->next;
@@ -281,8 +282,21 @@
fg_gc = render_state->fg_gc;
}
- if (appearance->underline != PANGO_UNDERLINE_NONE ||
- appearance->strikethrough)
+ /* If word-underlining is used, check if this is a non-word run, in
+ * which case we don't display the underline. (Pango will already have
+ * made sure the text is split into word and non-word runs.)
+ */
+ underline = appearance->underline;
+ if (underline == PANGO_UNDERLINE_WORD && run->item->num_chars)
+ {
+ const char *text = pango_layout_get_text (line->layout);
+ gunichar ch= g_utf8_get_char (text + run->item->offset);
+
+ if (!g_unichar_isgraph (ch))
+ underline = PANGO_UNDERLINE_NONE;
+ }
+
+ if (underline != PANGO_UNDERLINE_NONE || appearance->strikethrough)
need_ink = TRUE;
if (appearance->is_text)
@@ -434,7 +448,7 @@
g_assert_not_reached (); /* not a pixbuf or widget */
}
- switch (appearance->underline)
+ switch (underline)
{
case PANGO_UNDERLINE_NONE:
break;
@@ -447,6 +461,7 @@
risen_y + 3);
/* Fall through */
case PANGO_UNDERLINE_SINGLE:
+ case PANGO_UNDERLINE_WORD:
g_assert (need_ink);
gdk_draw_line (drawable, fg_gc,
x + (x_off + ink_rect.x) / PANGO_SCALE - 1,
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]