diff options
-rw-r--r-- | gtk/gtktextattributes.c | 98 | ||||
-rw-r--r-- | gtk/gtktextattributes.h | 12 | ||||
-rw-r--r-- | gtk/gtktextdisplay.c | 100 | ||||
-rw-r--r-- | gtk/gtktextlayout.c | 28 | ||||
-rw-r--r-- | gtk/gtktextlayout.h | 1 | ||||
-rw-r--r-- | gtk/gtktexttag.c | 192 | ||||
-rw-r--r-- | tests/Makefile.am | 8 | ||||
-rw-r--r-- | tests/testtextview.c | 151 |
8 files changed, 477 insertions, 113 deletions
diff --git a/gtk/gtktextattributes.c b/gtk/gtktextattributes.c index d2a9c6c3d5..67c3db392a 100644 --- a/gtk/gtktextattributes.c +++ b/gtk/gtktextattributes.c @@ -61,17 +61,17 @@ * Creates a #GtkTextAttributes, which describes * a set of properties on some text. * - * Return value: a new #GtkTextAttributes - **/ + * Return value: a new #GtkTextAttributes, + * free with gtk_text_attributes_unref(). + */ GtkTextAttributes* gtk_text_attributes_new (void) { GtkTextAttributes *values; - values = g_new0 (GtkTextAttributes, 1); + values = g_slice_new0 (GtkTextAttributes); /* 0 is a valid value for most of the struct */ - values->refcount = 1; values->language = gtk_get_default_language (); @@ -79,18 +79,19 @@ gtk_text_attributes_new (void) values->font_scale = 1.0; values->editable = TRUE; - + return values; } /** * gtk_text_attributes_copy: * @src: a #GtkTextAttributes to be copied - * + * * Copies @src and returns a new #GtkTextAttributes. - * - * Return value: a copy of @src - **/ + * + * Return value: a copy of @src, + * free with gtk_text_attributes_unref() + */ GtkTextAttributes* gtk_text_attributes_copy (GtkTextAttributes *src) { @@ -110,10 +111,10 @@ G_DEFINE_BOXED_TYPE (GtkTextAttributes, gtk_text_attributes, * gtk_text_attributes_copy_values: * @src: a #GtkTextAttributes * @dest: another #GtkTextAttributes - * - * Copies the values from @src to @dest so that @dest has the same values - * as @src. Frees existing values in @dest. - **/ + * + * Copies the values from @src to @dest so that @dest has + * the same values as @src. Frees existing values in @dest. + */ void gtk_text_attributes_copy_values (GtkTextAttributes *src, GtkTextAttributes *dest) @@ -124,10 +125,24 @@ gtk_text_attributes_copy_values (GtkTextAttributes *src, return; /* Remove refs */ + if (dest->tabs) + pango_tab_array_free (dest->tabs); if (dest->font) pango_font_description_free (dest->font); - + + if (dest->pg_bg_color) + gdk_color_free (dest->pg_bg_color); + + if (dest->pg_bg_rgba) + gdk_rgba_free (dest->pg_bg_rgba); + + if (dest->appearance.rgba[0]) + gdk_rgba_free (dest->appearance.rgba[0]); + + if (dest->appearance.rgba[1]) + gdk_rgba_free (dest->appearance.rgba[1]); + /* Copy */ orig_refcount = dest->refcount; @@ -138,12 +153,21 @@ gtk_text_attributes_copy_values (GtkTextAttributes *src, dest->language = src->language; - if (dest->font) + if (src->font) dest->font = pango_font_description_copy (src->font); - + if (src->pg_bg_color) dest->pg_bg_color = gdk_color_copy (src->pg_bg_color); + if (src->pg_bg_rgba) + dest->pg_bg_rgba = gdk_rgba_copy (src->pg_bg_rgba); + + if (src->appearance.rgba[0]) + dest->appearance.rgba[0] = gdk_rgba_copy (src->appearance.rgba[0]); + + if (src->appearance.rgba[1]) + dest->appearance.rgba[1] = gdk_rgba_copy (src->appearance.rgba[1]); + dest->refcount = orig_refcount; } @@ -191,7 +215,16 @@ gtk_text_attributes_unref (GtkTextAttributes *values) if (values->pg_bg_color) gdk_color_free (values->pg_bg_color); - g_free (values); + if (values->pg_bg_rgba) + gdk_rgba_free (values->pg_bg_rgba); + + if (values->appearance.rgba[0]) + gdk_rgba_free (values->appearance.rgba[0]); + + if (values->appearance.rgba[1]) + gdk_rgba_free (values->appearance.rgba[1]); + + g_slice_free (GtkTextAttributes, values); } } @@ -216,16 +249,41 @@ _gtk_text_attributes_fill_from_tags (GtkTextAttributes *dest, if (tag->priv->bg_color_set) { - dest->appearance.bg_color = vals->appearance.bg_color; + if (dest->appearance.rgba[0]) + { + gdk_rgba_free (dest->appearance.rgba[0]); + dest->appearance.rgba[0] = NULL; + } + + if (vals->appearance.rgba[0]) + dest->appearance.rgba[0] = gdk_rgba_copy (vals->appearance.rgba[0]); dest->appearance.draw_bg = TRUE; } + if (tag->priv->fg_color_set) - dest->appearance.fg_color = vals->appearance.fg_color; + { + if (dest->appearance.rgba[1]) + { + gdk_rgba_free (dest->appearance.rgba[1]); + dest->appearance.rgba[1] = NULL; + } + + if (vals->appearance.rgba[1]) + dest->appearance.rgba[1] = gdk_rgba_copy (vals->appearance.rgba[1]); + } if (tag->priv->pg_bg_color_set) { - dest->pg_bg_color = gdk_color_copy (vals->pg_bg_color); + if (dest->pg_bg_rgba) + { + gdk_rgba_free (dest->pg_bg_rgba); + dest->pg_bg_rgba = NULL; + + } + + if (vals->pg_bg_rgba) + dest->pg_bg_rgba = gdk_rgba_copy (vals->pg_bg_rgba); } if (vals->font) diff --git a/gtk/gtktextattributes.h b/gtk/gtktextattributes.h index aa7d6f8aa8..12c1af7063 100644 --- a/gtk/gtktextattributes.h +++ b/gtk/gtktextattributes.h @@ -102,8 +102,12 @@ struct _GtkTextAppearance guint inside_selection : 1; guint is_text : 1; - /*< private >*/ - guint padding[4]; + GdkRGBA *rgba[2]; + +#if __SIZEOF_INT__ == __SIZEOF_POINTER__ + /* unusable, just for ABI compat */ + guint padding[2]; +#endif }; struct _GtkTextAttributes @@ -155,7 +159,9 @@ struct _GtkTextAttributes guint editable : 1; /*< private >*/ - guint padding[4]; + GdkRGBA *pg_bg_rgba; + + guint padding[3]; }; GtkTextAttributes* gtk_text_attributes_new (void); diff --git a/gtk/gtktextdisplay.c b/gtk/gtktextdisplay.c index e9a24bc5f3..e3ec766dcb 100644 --- a/gtk/gtktextdisplay.c +++ b/gtk/gtktextdisplay.c @@ -110,8 +110,11 @@ struct _GtkTextRenderer GdkColor *error_color; /* Error underline color for this widget */ GList *widgets; /* widgets encountered when drawing */ - - int state; + + GdkRGBA rgba[4]; + guint8 rgba_set[4]; + + guint state : 2; }; struct _GtkTextRendererClass @@ -122,45 +125,34 @@ struct _GtkTextRendererClass G_DEFINE_TYPE (GtkTextRenderer, _gtk_text_renderer, PANGO_TYPE_RENDERER) static void -text_renderer_set_gdk_color (GtkTextRenderer *text_renderer, - PangoRenderPart part, - GdkColor *gdk_color) -{ - PangoRenderer *renderer = PANGO_RENDERER (text_renderer); - - if (gdk_color) - { - PangoColor color; - - color.red = gdk_color->red; - color.green = gdk_color->green; - color.blue = gdk_color->blue; - - pango_renderer_set_color (renderer, part, &color); - } - else - pango_renderer_set_color (renderer, part, NULL); -} - -static void text_renderer_set_rgba (GtkTextRenderer *text_renderer, PangoRenderPart part, - GdkRGBA *rgba) + const GdkRGBA *rgba) { PangoRenderer *renderer = PANGO_RENDERER (text_renderer); + PangoColor dummy = { 0, }; + + if ((!rgba && !text_renderer->rgba_set[part]) || + (rgba && text_renderer->rgba_set[part] && + text_renderer->rgba[part].red == rgba->red && + text_renderer->rgba[part].green == rgba->green && + text_renderer->rgba[part].blue == rgba->blue && + text_renderer->rgba[part].alpha == rgba->alpha)) + return; if (rgba) { - PangoColor color; + text_renderer->rgba_set[part] = TRUE; + text_renderer->rgba[part] = *rgba; - color.red = CLAMP (rgba->red * 65535. + 0.5, 0, 65535); - color.green = CLAMP (rgba->green * 65535. + 0.5, 0, 65535); - color.blue = CLAMP (rgba->blue * 65535. + 0.5, 0, 65535); - - pango_renderer_set_color (renderer, part, &color); + pango_renderer_set_color (renderer, part, &dummy); } else - pango_renderer_set_color (renderer, part, NULL); + { + text_renderer->rgba_set[part] = FALSE; + + pango_renderer_set_color (renderer, part, NULL); + } } static GtkTextAppearance * @@ -188,9 +180,8 @@ gtk_text_renderer_prepare_run (PangoRenderer *renderer, GtkStyleContext *context; GtkStateFlags state; GtkTextRenderer *text_renderer = GTK_TEXT_RENDERER (renderer); - GdkColor *bg_color = NULL; + GdkRGBA *bg_rgba = NULL; GdkRGBA *fg_rgba = NULL; - GdkColor *fg_color = NULL; GtkTextAppearance *appearance; PANGO_RENDERER_CLASS (_gtk_text_renderer_parent_class)->prepare_run (renderer, run); @@ -199,15 +190,14 @@ gtk_text_renderer_prepare_run (PangoRenderer *renderer, g_assert (appearance != NULL); context = gtk_widget_get_style_context (text_renderer->widget); - - state = gtk_widget_get_state_flags (text_renderer->widget); + state = gtk_widget_get_state_flags (text_renderer->widget); if (appearance->draw_bg && text_renderer->state == NORMAL) - bg_color = &appearance->bg_color; + bg_rgba = appearance->rgba[0]; else - bg_color = NULL; + bg_rgba = NULL; - text_renderer_set_gdk_color (text_renderer, PANGO_RENDER_PART_BACKGROUND, bg_color); + text_renderer_set_rgba (text_renderer, PANGO_RENDER_PART_BACKGROUND, bg_rgba); if (text_renderer->state == SELECTED) { @@ -224,18 +214,10 @@ gtk_text_renderer_prepare_run (PangoRenderer *renderer, NULL); } else - fg_color = &appearance->fg_color; + fg_rgba = appearance->rgba[1]; - if (fg_rgba) - { - text_renderer_set_rgba (text_renderer, PANGO_RENDER_PART_FOREGROUND, fg_rgba); - text_renderer_set_rgba (text_renderer, PANGO_RENDER_PART_STRIKETHROUGH,fg_rgba); - } - else - { - text_renderer_set_gdk_color (text_renderer, PANGO_RENDER_PART_FOREGROUND, fg_color); - text_renderer_set_gdk_color (text_renderer, PANGO_RENDER_PART_STRIKETHROUGH, fg_color); - } + text_renderer_set_rgba (text_renderer, PANGO_RENDER_PART_FOREGROUND, fg_rgba); + text_renderer_set_rgba (text_renderer, PANGO_RENDER_PART_STRIKETHROUGH,fg_rgba); if (appearance->underline == PANGO_UNDERLINE_ERROR) { @@ -252,28 +234,24 @@ gtk_text_renderer_prepare_run (PangoRenderer *renderer, } } - text_renderer_set_gdk_color (text_renderer, PANGO_RENDER_PART_UNDERLINE, text_renderer->error_color); + // XXX Transform the gdk color to an gdk rgba here + //text_renderer_set_gdk_color (text_renderer, PANGO_RENDER_PART_UNDERLINE, text_renderer->error_color); } - else if (fg_rgba) - text_renderer_set_rgba (text_renderer, PANGO_RENDER_PART_UNDERLINE, fg_rgba); else - text_renderer_set_gdk_color (text_renderer, PANGO_RENDER_PART_UNDERLINE, fg_color); + text_renderer_set_rgba (text_renderer, PANGO_RENDER_PART_UNDERLINE, fg_rgba); + + if (fg_rgba != appearance->rgba[1]) + gdk_rgba_free (fg_rgba); } static void set_color (GtkTextRenderer *text_renderer, PangoRenderPart part) { - PangoColor *color; - cairo_save (text_renderer->cr); - color = pango_renderer_get_color (PANGO_RENDERER (text_renderer), part); - if (color) - cairo_set_source_rgb (text_renderer->cr, - color->red / 65535., - color->green / 65535., - color->blue / 65535.); + if (text_renderer->rgba_set[part]) + gdk_cairo_set_source_rgba (text_renderer->cr, &text_renderer->rgba[part]); } static void diff --git a/gtk/gtktextlayout.c b/gtk/gtktextlayout.c index 35809873d5..f19ab618d2 100644 --- a/gtk/gtktextlayout.c +++ b/gtk/gtktextlayout.c @@ -1424,9 +1424,27 @@ gtk_text_attr_appearance_destroy (PangoAttribute *attr) { GtkTextAttrAppearance *appearance_attr = (GtkTextAttrAppearance *)attr; + if (appearance_attr->appearance.rgba[0]) + gdk_rgba_free (appearance_attr->appearance.rgba[0]); + + if (appearance_attr->appearance.rgba[1]) + gdk_rgba_free (appearance_attr->appearance.rgba[1]); + g_slice_free (GtkTextAttrAppearance, appearance_attr); } +static gboolean +rgba_equal (const GdkRGBA *rgba1, const GdkRGBA *rgba2) +{ + if (rgba1 && rgba2) + return gdk_rgba_equal (rgba1, rgba2); + + if (rgba1 || rgba2) + return FALSE; + + return TRUE; +} + static gboolean gtk_text_attr_appearance_compare (const PangoAttribute *attr1, const PangoAttribute *attr2) @@ -1434,8 +1452,8 @@ gtk_text_attr_appearance_compare (const PangoAttribute *attr1, const GtkTextAppearance *appearance1 = &((const GtkTextAttrAppearance *)attr1)->appearance; const GtkTextAppearance *appearance2 = &((const GtkTextAttrAppearance *)attr2)->appearance; - return (gdk_color_equal (&appearance1->fg_color, &appearance2->fg_color) && - gdk_color_equal (&appearance1->bg_color, &appearance2->bg_color) && + return (rgba_equal (appearance1->rgba[0], appearance2->rgba[0]) && + rgba_equal (appearance1->rgba[1], appearance2->rgba[1]) && appearance1->underline == appearance2->underline && appearance1->strikethrough == appearance2->strikethrough && appearance1->draw_bg == appearance2->draw_bg); @@ -1472,6 +1490,12 @@ gtk_text_attr_appearance_new (const GtkTextAppearance *appearance) result->appearance = *appearance; + if (appearance->rgba[0]) + result->appearance.rgba[0] = gdk_rgba_copy (appearance->rgba[0]); + + if (appearance->rgba[1]) + result->appearance.rgba[1] = gdk_rgba_copy (appearance->rgba[1]); + return (PangoAttribute *)result; } diff --git a/gtk/gtktextlayout.h b/gtk/gtktextlayout.h index 4e9533d0eb..09ca01c5b0 100644 --- a/gtk/gtktextlayout.h +++ b/gtk/gtktextlayout.h @@ -233,6 +233,7 @@ struct _GtkTextCursorDisplay guint is_strong : 1; guint is_weak : 1; }; + struct _GtkTextLineDisplay { PangoLayout *layout; diff --git a/gtk/gtktexttag.c b/gtk/gtktexttag.c index 1a653b3b53..dbfb5aea36 100644 --- a/gtk/gtktexttag.c +++ b/gtk/gtktexttag.c @@ -92,6 +92,8 @@ enum { PROP_FOREGROUND, PROP_BACKGROUND_GDK, PROP_FOREGROUND_GDK, + PROP_BACKGROUND_RGBA, + PROP_FOREGROUND_RGBA, PROP_FONT, PROP_FONT_DESC, PROP_FAMILY, @@ -121,6 +123,7 @@ enum { PROP_INVISIBLE, PROP_PARAGRAPH_BACKGROUND, PROP_PARAGRAPH_BACKGROUND_GDK, + PROP_PARAGRAPH_BACKGROUND_RGBA, /* Behavior args */ PROP_ACCUMULATIVE_MARGIN, @@ -206,6 +209,15 @@ gtk_text_tag_class_init (GtkTextTagClass *klass) GDK_TYPE_COLOR, GTK_PARAM_READWRITE)); + + g_object_class_install_property (object_class, + PROP_BACKGROUND_RGBA, + g_param_spec_boxed ("background-rgba", + P_("Background rgba"), + P_("Background rgba as a (possibly unallocated) GdkRGBA"), + GDK_TYPE_RGBA, + GTK_PARAM_READWRITE)); + g_object_class_install_property (object_class, PROP_BACKGROUND_FULL_HEIGHT, g_param_spec_boolean ("background-full-height", @@ -231,6 +243,14 @@ gtk_text_tag_class_init (GtkTextTagClass *klass) GTK_PARAM_READWRITE)); g_object_class_install_property (object_class, + PROP_FOREGROUND_RGBA, + g_param_spec_boxed ("foreground-rgba", + P_("Foreground rgba"), + P_("Foreground rgba as a (possibly unallocated) GdkRGBA"), + GDK_TYPE_RGBA, + GTK_PARAM_READWRITE)); + + g_object_class_install_property (object_class, PROP_DIRECTION, g_param_spec_enum ("direction", P_("Text direction"), @@ -532,6 +552,22 @@ gtk_text_tag_class_init (GtkTextTagClass *klass) GTK_PARAM_READWRITE)); /** + * GtkTextTag:paragraph-background-rgba: + * + * The paragraph background color as a as a (possibly unallocated) + * #GdkRGBA. + * + * Since: 3.2 + */ + g_object_class_install_property (object_class, + PROP_PARAGRAPH_BACKGROUND_RGBA, + g_param_spec_boxed ("paragraph-background-rgba", + P_("Paragraph background rgba"), + P_("Paragraph background rgba as a (possibly unallocated) GdkRGBA"), + GDK_TYPE_RGBA, + GTK_PARAM_READWRITE)); + + /** * GtkTextTag:accumulative-margin: * * Whether the margins accumulate or override each other. @@ -740,11 +776,16 @@ gtk_text_tag_finalize (GObject *object) } static void -set_bg_color (GtkTextTag *tag, GdkColor *color) +set_bg_rgba (GtkTextTag *tag, GdkRGBA *rgba) { GtkTextTagPrivate *priv = tag->priv; - if (color) + if (priv->values->appearance.rgba[0]) + gdk_rgba_free (priv->values->appearance.rgba[0]); + + priv->values->appearance.rgba[0] = NULL; + + if (rgba) { if (!priv->bg_color_set) { @@ -752,7 +793,7 @@ set_bg_color (GtkTextTag *tag, GdkColor *color) g_object_notify (G_OBJECT (tag), "background-set"); } - priv->values->appearance.bg_color = *color; + priv->values->appearance.rgba[0] = gdk_rgba_copy (rgba); } else { @@ -765,18 +806,24 @@ set_bg_color (GtkTextTag *tag, GdkColor *color) } static void -set_fg_color (GtkTextTag *tag, GdkColor *color) +set_fg_rgba (GtkTextTag *tag, GdkRGBA *rgba) { GtkTextTagPrivate *priv = tag->priv; - if (color) + if (priv->values->appearance.rgba[1]) + gdk_rgba_free (priv->values->appearance.rgba[1]); + + priv->values->appearance.rgba[1] = NULL; + + if (rgba) { if (!priv->fg_color_set) { priv->fg_color_set = TRUE; g_object_notify (G_OBJECT (tag), "foreground-set"); } - priv->values->appearance.fg_color = *color; + + priv->values->appearance.rgba[1] = gdk_rgba_copy (rgba); } else { @@ -789,21 +836,24 @@ set_fg_color (GtkTextTag *tag, GdkColor *color) } static void -set_pg_bg_color (GtkTextTag *tag, GdkColor *color) +set_pg_bg_rgba (GtkTextTag *tag, GdkRGBA *rgba) { GtkTextTagPrivate *priv = tag->priv; - if (color) + if (priv->values->pg_bg_rgba) + gdk_rgba_free (priv->values->pg_bg_rgba); + + priv->values->pg_bg_rgba = NULL; + + if (rgba) { if (!priv->pg_bg_color_set) { priv->pg_bg_color_set = TRUE; g_object_notify (G_OBJECT (tag), "paragraph-background-set"); } - else - gdk_color_free (priv->values->pg_bg_color); - priv->values->pg_bg_color = gdk_color_copy (color); + priv->values->pg_bg_rgba = gdk_rgba_copy (rgba); } else { @@ -811,11 +861,63 @@ set_pg_bg_color (GtkTextTag *tag, GdkColor *color) { priv->pg_bg_color_set = FALSE; g_object_notify (G_OBJECT (tag), "paragraph-background-set"); - gdk_color_free (priv->values->pg_bg_color); } + } +} - priv->values->pg_bg_color = NULL; + +static void +set_bg_color (GtkTextTag *tag, GdkColor *color) +{ + if (color) + { + gchar *str; + GdkRGBA rgba; + + str = gdk_color_to_string (color); + gdk_rgba_parse (&rgba, str); + g_free (str); + + set_bg_rgba (tag, &rgba); } + else + set_bg_rgba (tag, NULL); +} + +static void +set_fg_color (GtkTextTag *tag, GdkColor *color) +{ + if (color) + { + gchar *str; + GdkRGBA rgba; + + str = gdk_color_to_string (color); + gdk_rgba_parse (&rgba, str); + g_free (str); + + set_fg_rgba (tag, &rgba); + } + else + set_fg_rgba (tag, NULL); +} + +static void +set_pg_bg_color (GtkTextTag *tag, GdkColor *color) +{ + if (color) + { + gchar *str; + GdkRGBA rgba; + + str = gdk_color_to_string (color); + gdk_rgba_parse (&rgba, str); + g_free (str); + + set_pg_bg_rgba (tag, &rgba); + } + else + set_pg_bg_rgba (tag, NULL); } static PangoFontMask @@ -998,12 +1100,12 @@ gtk_text_tag_set_property (GObject *object, case PROP_BACKGROUND: { - GdkColor color; + GdkRGBA rgba; if (!g_value_get_string (value)) - set_bg_color (text_tag, NULL); /* reset to background_set to FALSE */ - else if (gdk_color_parse (g_value_get_string (value), &color)) - set_bg_color (text_tag, &color); + set_bg_rgba (text_tag, NULL); /* reset background_set to FALSE */ + else if (gdk_rgba_parse (&rgba, g_value_get_string (value))) + set_bg_rgba (text_tag, &rgba); else g_warning ("Don't know color `%s'", g_value_get_string (value)); @@ -1013,12 +1115,12 @@ gtk_text_tag_set_property (GObject *object, case PROP_FOREGROUND: { - GdkColor color; + GdkRGBA rgba; if (!g_value_get_string (value)) - set_fg_color (text_tag, NULL); /* reset to foreground_set to FALSE */ - else if (gdk_color_parse (g_value_get_string (value), &color)) - set_fg_color (text_tag, &color); + set_fg_rgba (text_tag, NULL); /* reset to foreground_set to FALSE */ + else if (gdk_rgba_parse (&rgba, g_value_get_string (value))) + set_fg_rgba (text_tag, &rgba); else g_warning ("Don't know color `%s'", g_value_get_string (value)); @@ -1042,6 +1144,22 @@ gtk_text_tag_set_property (GObject *object, } break; + case PROP_BACKGROUND_RGBA: + { + GdkRGBA *color = g_value_get_boxed (value); + + set_bg_rgba (text_tag, color); + } + break; + + case PROP_FOREGROUND_RGBA: + { + GdkRGBA *color = g_value_get_boxed (value); + + set_fg_rgba (text_tag, color); + } + break; + case PROP_FONT: { PangoFontDescription *font_desc = NULL; @@ -1255,12 +1373,12 @@ gtk_text_tag_set_property (GObject *object, case PROP_PARAGRAPH_BACKGROUND: { - GdkColor color; + GdkRGBA rgba; if (!g_value_get_string (value)) - set_pg_bg_color (text_tag, NULL); /* reset to paragraph_background_set to FALSE */ - else if (gdk_color_parse (g_value_get_string (value), &color)) - set_pg_bg_color (text_tag, &color); + set_pg_bg_rgba (text_tag, NULL); /* reset paragraph_background_set to FALSE */ + else if (gdk_rgba_parse (&rgba, g_value_get_string (value))) + set_pg_bg_rgba (text_tag, &rgba); else g_warning ("Don't know color `%s'", g_value_get_string (value)); @@ -1276,6 +1394,14 @@ gtk_text_tag_set_property (GObject *object, } break; + case PROP_PARAGRAPH_BACKGROUND_RGBA: + { + GdkRGBA *color = g_value_get_boxed (value); + + set_pg_bg_rgba (text_tag, color); + } + break; + case PROP_ACCUMULATIVE_MARGIN: priv->accumulative_margin = g_value_get_boolean (value); g_object_notify (object, "accumulative-margin"); @@ -1429,6 +1555,7 @@ gtk_text_tag_get_property (GObject *object, { GtkTextTag *tag = GTK_TEXT_TAG (object); GtkTextTagPrivate *priv = tag->priv; + GdkColor color = { 0, }; switch (prop_id) { @@ -1437,10 +1564,22 @@ gtk_text_tag_get_property (GObject *object, break; case PROP_BACKGROUND_GDK: - g_value_set_boxed (value, &priv->values->appearance.bg_color); + if (priv->values->appearance.rgba[0]) + { + color.red = CLAMP (priv->values->appearance.rgba[0]->red, 0.0, 1.0) * 65535.0; + color.green = CLAMP (priv->values->appearance.rgba[0]->green, 0.0, 1.0) * 65535.0; + color.blue = CLAMP (priv->values->appearance.rgba[0]->blue, 0.0, 1.0) * 65535.0; + } + g_value_set_boxed (value, &color); break; case PROP_FOREGROUND_GDK: + if (priv->values->appearance.rgba[1]) + { + color.red = CLAMP (priv->values->appearance.rgba[1]->red, 0.0, 1.0) * 65535.0; + color.green = CLAMP (priv->values->appearance.rgba[1]->green, 0.0, 1.0) * 65535.0; + color.blue = CLAMP (priv->values->appearance.rgba[1]->blue, 0.0, 1.0) * 65535.0; + } g_value_set_boxed (value, &priv->values->appearance.fg_color); break; @@ -1574,6 +1713,7 @@ gtk_text_tag_get_property (GObject *object, break; case PROP_PARAGRAPH_BACKGROUND_GDK: + /* XXX Transform the GdkRGBA here */ g_value_set_boxed (value, priv->values->pg_bg_color); break; diff --git a/tests/Makefile.am b/tests/Makefile.am index f4029a9884..3ea7981cc0 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -108,7 +108,8 @@ noinst_PROGRAMS = $(TEST_PROGS) \ testtoplevelembed \ testnoscreen \ testtreepos \ - testsensitive + testsensitive \ + testtextview if USE_X11 noinst_PROGRAMS += testerrors @@ -207,6 +208,7 @@ testtoplevelembed_DEPENDENCIES = $(TEST_DEPS) testnoscreen_DEPENDENCIES = $(TEST_DEPS) testtreepos_DEPENDENCIES = $(TEST_DEPS) testsensitive_DEPENDENCIES = $(TEST_DEPS) +testtextview_DEPENDENCIES = $(TEST_DEPS) flicker_LDADD = $(LDADDS) simple_LDADD = $(LDADDS) @@ -291,6 +293,7 @@ testtoplevelembed_LDADD = $(LDADDS) testnoscreen_LDADD = $(LDADDS) testtreepos_LDADD = $(LDADDS) testsensitive_LDADD = $(LDADDS) +testtextview_LDADD = $(LDADDS) testentrycompletion_SOURCES = \ @@ -436,6 +439,9 @@ styleexamples_SOURCES = styleexamples.c testtoplevelembed_SOURCES = testtoplevelembed.c +testtextview_SOURCES = testtextview.c + + EXTRA_DIST += \ gradient1.png \ prop-editor.h \ diff --git a/tests/testtextview.c b/tests/testtextview.c new file mode 100644 index 0000000000..2a7701f5b3 --- /dev/null +++ b/tests/testtextview.c @@ -0,0 +1,151 @@ + + +#include "config.h" +#include <gtk/gtk.h> + + +static void +create_tags (GtkTextBuffer *buffer) +{ + + gtk_text_buffer_create_tag (buffer, "italic", + "style", PANGO_STYLE_ITALIC, NULL); + + gtk_text_buffer_create_tag (buffer, "bold", + "weight", PANGO_WEIGHT_BOLD, NULL); + + gtk_text_buffer_create_tag (buffer, "x-large", + "scale", PANGO_SCALE_X_LARGE, NULL); + + gtk_text_buffer_create_tag (buffer, "semi_blue_foreground", + "foreground", "rgba(0,0,255,0.5)", NULL); + + gtk_text_buffer_create_tag (buffer, "semi_red_background", + "background", "rgba(255,0,0,0.5)", NULL); + + gtk_text_buffer_create_tag (buffer, "word_wrap", + "wrap_mode", GTK_WRAP_WORD, NULL); +} + + +static void +insert_text (GtkTextBuffer *buffer) +{ + GtkTextIter iter; + GtkTextIter start, end; + + /* get start of buffer; each insertion will revalidate the + * iterator to point to just after the inserted text. + */ + gtk_text_buffer_get_iter_at_offset (buffer, &iter, 0); + + gtk_text_buffer_insert (buffer, &iter, + "This test shows text view rendering some text with rgba colors.\n\n", -1); + + gtk_text_buffer_insert (buffer, &iter, "For example, you can have ", -1); + gtk_text_buffer_insert_with_tags_by_name (buffer, &iter, + "italic translucent blue text", -1, + "italic", + "semi_blue_foreground", + "x-large", + NULL); + + gtk_text_buffer_insert (buffer, &iter, ", or ", -1); + + gtk_text_buffer_insert (buffer, &iter, ", ", -1); + gtk_text_buffer_insert_with_tags_by_name (buffer, &iter, + "bold text with translucent red background", -1, + "bold", + "semi_red_background", + "x-large", + NULL); + gtk_text_buffer_insert (buffer, &iter, ".", -1); + + /* Apply word_wrap tag to whole buffer */ + gtk_text_buffer_get_bounds (buffer, &start, &end); + gtk_text_buffer_apply_tag_by_name (buffer, "word_wrap", &start, &end); +} + + +static cairo_pattern_t * +get_pattern (void) +{ + static cairo_pattern_t *static_pattern = NULL; + + if (!static_pattern) + { + cairo_surface_t *surface = + cairo_image_surface_create_from_png ("gradient1.png"); + + if (surface) + { + static_pattern = cairo_pattern_create_for_surface (surface); + cairo_pattern_set_extend (static_pattern, CAIRO_EXTEND_REFLECT); + } + else + g_warning ("Failed to create surface for gradient1.png\n"); + } + return static_pattern; +} + +static void +draw_background (GtkWidget *widget, cairo_t *cr) +{ + GtkAllocation allocation; + cairo_pattern_t *pat; + + gtk_widget_get_allocation (widget, &allocation); + + cairo_save (cr); + +#if 0 + pat = cairo_pattern_create_linear (0.0, 0.0, 30.0, 30.0); + cairo_pattern_add_color_stop_rgba (pat, 1, 0, 0, 0, 1); + cairo_pattern_add_color_stop_rgba (pat, 0, 1, 1, 1, 1); + cairo_pattern_set_extend (pat, CAIRO_EXTEND_REPEAT); + cairo_rectangle (cr, 0, 0, allocation.width, allocation.height); + cairo_set_source (cr, pat); + cairo_fill (cr); + cairo_pattern_destroy (pat); + +#else + + if (get_pattern ()) + { + cairo_rectangle (cr, 0, 0, allocation.width, allocation.height); + cairo_set_source (cr, get_pattern ()); + cairo_fill (cr); + } +#endif + + cairo_restore (cr); +} + +int +main (int argc, char **argv) +{ + GtkWidget *window, *textview; + GtkTextBuffer *buffer; + + gtk_init (&argc, &argv); + + window = gtk_window_new (GTK_WINDOW_TOPLEVEL); + textview = gtk_text_view_new (); + buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (textview)); + + create_tags (buffer); + insert_text (buffer); + + gtk_widget_show (textview); + gtk_container_add (GTK_CONTAINER (window), textview); + + g_signal_connect (textview, "draw", + G_CALLBACK (draw_background), NULL); + + + gtk_widget_show (window); + + gtk_main (); + + return 0; +} |