Added GdkRGBA properties to GtkTextTag.

This now allows text view to render text with alpha values in
the text foreground and backgrounds, the work is almost complete,
currently the error-underline-color is still a GdkColor style property
and since we use only GdkRGBA for rendering it needs to be converted
and applied, probably a new rgba version of the style property should
also be introduced.

This commit adds tests/testtextview that must be run from the tests/
directory to show translucent text in action.
This commit is contained in:
Tristan Van Berkom 2011-02-09 23:41:39 +09:00 committed by Matthias Clasen
parent 297e739395
commit d399a4acab
8 changed files with 478 additions and 114 deletions

View File

@ -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)

View File

@ -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);

View File

@ -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
@ -121,46 +124,35 @@ 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

View File

@ -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;
}

View File

@ -233,6 +233,7 @@ struct _GtkTextCursorDisplay
guint is_strong : 1;
guint is_weak : 1;
};
struct _GtkTextLineDisplay
{
PangoLayout *layout;

View File

@ -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",
@ -230,6 +242,14 @@ gtk_text_tag_class_init (GtkTextTagClass *klass)
GDK_TYPE_COLOR,
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",
@ -531,6 +551,22 @@ gtk_text_tag_class_init (GtkTextTagClass *klass)
GDK_TYPE_COLOR,
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:
*
@ -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,13 +861,65 @@ 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
get_property_font_set_mask (guint prop_id)
{
@ -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;

View File

@ -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 \

151
tests/testtextview.c Normal file
View File

@ -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;
}