mirror of
https://gitlab.gnome.org/GNOME/gtk.git
synced 2024-09-19 21:40:22 +00:00
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:
parent
297e739395
commit
d399a4acab
@ -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)
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -233,6 +233,7 @@ struct _GtkTextCursorDisplay
|
||||
guint is_strong : 1;
|
||||
guint is_weak : 1;
|
||||
};
|
||||
|
||||
struct _GtkTextLineDisplay
|
||||
{
|
||||
PangoLayout *layout;
|
||||
|
194
gtk/gtktexttag.c
194
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",
|
||||
@ -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;
|
||||
|
||||
|
@ -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
151
tests/testtextview.c
Normal 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;
|
||||
}
|
Loading…
Reference in New Issue
Block a user