Compare commits

...

10 Commits

Author SHA1 Message Date
Matthias Clasen
06c244088a Add some docs
Better point people at the free function for text attributes.
2011-05-06 16:42:08 -04:00
Matthias Clasen
9787eb8cfa Remove outdated comments
Neither GdkColors nor GdkRGBAs are ever 'allocated' nowadays.
2011-05-06 16:31:36 -04:00
Matthias Clasen
b726448f29 Fix ABI compat
Make GtkTextTextAttributes stay the same size. This currently
uses gcc builtin defines. If that is an issue, we can switch
to using GLIB_SIZEOF_ defines, after adding one for ints.
2011-05-06 16:28:05 -04:00
Tristan Van Berkom
a3e1724855 Adding more traditional checkered background to testtextview. 2011-02-21 11:27:26 +09:00
Tristan Van Berkom
70a2bd972d Added Since 3.2 annotations for new GdkRGBA properties. 2011-02-21 11:27:26 +09:00
Tristan Van Berkom
1d6aee0a99 Added internal GdkRGBA support for GtkTextTag::paragraph-background-rgba
Added the remaining implementation bits for rendering paragraph backgrounds
with rgba values and updated the test case.
2011-02-21 11:27:26 +09:00
Tristan Van Berkom
d83d3f184c Fixed GtkTextTag to sync the GdkColors with the new GdkRGBA values for backwards compatability. 2011-02-21 11:27:25 +09:00
Tristan Van Berkom
a0f2aa44b4 Handled error_color with GdkRGBA in gtktextdisplay.c. 2011-02-21 11:27:25 +09:00
Tristan Van Berkom
990c61c868 Fixed textview rendering regression.
Background color was not painted on the whole tagged segment after
line breaking, this was due to the default ->prepare_run() function
wiping the internal PangoColors clean... fixed this by unconditionally
setting local rgba colors from prepare_run instead of comparing them
and bailing out.
2011-02-21 11:27:25 +09:00
Tristan Van Berkom
2fbb119dec 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.
2011-02-21 11:27:25 +09:00
8 changed files with 574 additions and 135 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,49 @@ _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 (dest->pg_bg_color)
{
gdk_color_free (dest->pg_bg_color);
dest->pg_bg_color = NULL;
}
if (vals->pg_bg_rgba)
dest->pg_bg_rgba = gdk_rgba_copy (vals->pg_bg_rgba);
if (vals->pg_bg_color)
dest->pg_bg_color = gdk_color_copy (vals->pg_bg_color);
}
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

@@ -108,10 +108,13 @@ struct _GtkTextRenderer
GtkWidget *widget;
cairo_t *cr;
GdkColor *error_color; /* Error underline color for this widget */
GList *widgets; /* widgets encountered when drawing */
int state;
GdkRGBA *error_color; /* Error underline color for this widget */
GList *widgets; /* widgets encountered when drawing */
GdkRGBA rgba[4];
guint8 rgba_set[4];
guint state : 2;
};
struct _GtkTextRendererClass
@@ -121,46 +124,23 @@ 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)
{
PangoColor color;
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);
text_renderer->rgba[part] = *rgba;
pango_renderer_set_color (renderer, part, &dummy);
}
else
pango_renderer_set_color (renderer, part, NULL);
text_renderer->rgba_set[part] = (rgba != NULL);
}
static GtkTextAppearance *
@@ -188,9 +168,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,23 +178,20 @@ 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)
{
state |= GTK_STATE_FLAG_SELECTED;
gtk_style_context_get (context, state,
"color", &fg_rgba,
NULL);
gtk_style_context_get (context, state, "color", &fg_rgba, NULL);
}
else if (text_renderer->state == CURSOR && gtk_widget_has_focus (text_renderer->widget))
{
@@ -224,56 +200,57 @@ 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)
{
if (!text_renderer->error_color)
{
GdkColor *color = NULL;
gtk_style_context_get_style (context,
"error-underline-color", &text_renderer->error_color,
"error-underline-color", &color,
NULL);
if (!text_renderer->error_color)
{
static const GdkColor red = { 0, 0xffff, 0, 0 };
text_renderer->error_color = gdk_color_copy (&red);
}
if (color)
{
GdkRGBA rgba;
rgba.red = color->red / 65535.;
rgba.green = color->green / 65535.;
rgba.blue = color->blue / 65535.;
rgba.alpha = 1;
gdk_color_free (color);
text_renderer->error_color = gdk_rgba_copy (&rgba);
}
else
{
static const GdkRGBA red = { 1, 0, 0, 1 };
text_renderer->error_color = gdk_rgba_copy (&red);
}
}
text_renderer_set_gdk_color (text_renderer, PANGO_RENDER_PART_UNDERLINE, text_renderer->error_color);
text_renderer_set_rgba (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
@@ -540,7 +517,7 @@ text_renderer_end (GtkTextRenderer *text_renderer)
if (text_renderer->error_color)
{
gdk_color_free (text_renderer->error_color);
gdk_rgba_free (text_renderer->error_color);
text_renderer->error_color = NULL;
}
@@ -672,13 +649,13 @@ render_para (GtkTextRenderer *text_renderer,
}
else
{
if (line_display->pg_bg_color)
if (line_display->pg_bg_rgba)
{
cairo_t *cr = text_renderer->cr;
cairo_save (cr);
gdk_cairo_set_source_color (cr, line_display->pg_bg_color);
gdk_cairo_set_source_rgba (text_renderer->cr, line_display->pg_bg_rgba);
cairo_rectangle (cr,
line_display->left_margin, selection_y,
screen_width, selection_height);

View File

@@ -1408,7 +1408,12 @@ set_para_values (GtkTextLayout *layout,
if (style->pg_bg_color)
display->pg_bg_color = gdk_color_copy (style->pg_bg_color);
else
display->pg_bg_color = NULL;
display->pg_bg_color = NULL;
if (style->pg_bg_rgba)
display->pg_bg_rgba = gdk_rgba_copy (style->pg_bg_rgba);
else
display->pg_bg_rgba = NULL;
}
static PangoAttribute *
@@ -1424,9 +1429,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 +1457,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 +1495,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;
}
@@ -2509,6 +2538,9 @@ gtk_text_layout_free_line_display (GtkTextLayout *layout,
if (display->pg_bg_color)
gdk_color_free (display->pg_bg_color);
if (display->pg_bg_rgba)
gdk_rgba_free (display->pg_bg_rgba);
g_free (display);
}
}

View File

@@ -233,6 +233,7 @@ struct _GtkTextCursorDisplay
guint is_strong : 1;
guint is_weak : 1;
};
struct _GtkTextLineDisplay
{
PangoLayout *layout;
@@ -263,7 +264,7 @@ struct _GtkTextLineDisplay
guint cursor_at_line_end : 1;
guint size_only : 1;
gpointer padding1;
GdkRGBA *pg_bg_rgba;
};
#ifdef GTK_COMPILATION

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,
@@ -202,10 +205,25 @@ gtk_text_tag_class_init (GtkTextTagClass *klass)
PROP_BACKGROUND_GDK,
g_param_spec_boxed ("background-gdk",
P_("Background color"),
P_("Background color as a (possibly unallocated) GdkColor"),
P_("Background color as a GdkColor"),
GDK_TYPE_COLOR,
GTK_PARAM_READWRITE));
/**
* GtkTextTag:background-rgba:
*
* Background color as a #GdkRGBA.
*
* Since: 3.2
*/
g_object_class_install_property (object_class,
PROP_BACKGROUND_RGBA,
g_param_spec_boxed ("background-rgba",
P_("Background rgba"),
P_("Background color as a 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",
@@ -226,10 +244,25 @@ gtk_text_tag_class_init (GtkTextTagClass *klass)
PROP_FOREGROUND_GDK,
g_param_spec_boxed ("foreground-gdk",
P_("Foreground color"),
P_("Foreground color as a (possibly unallocated) GdkColor"),
P_("Foreground color as a GdkColor"),
GDK_TYPE_COLOR,
GTK_PARAM_READWRITE));
/**
* GtkTextTag:foreground-rgba:
*
* Foreground color as a #GdkRGBA.
*
* Since: 3.2
*/
g_object_class_install_property (object_class,
PROP_FOREGROUND_RGBA,
g_param_spec_boxed ("foreground-rgba",
P_("Foreground rgba"),
P_("Foreground color as a GdkRGBA"),
GDK_TYPE_RGBA,
GTK_PARAM_READWRITE));
g_object_class_install_property (object_class,
PROP_DIRECTION,
g_param_spec_enum ("direction",
@@ -518,8 +551,7 @@ gtk_text_tag_class_init (GtkTextTagClass *klass)
/**
* GtkTextTag:paragraph-background-gdk:
*
* The paragraph background color as a as a (possibly unallocated)
* #GdkColor.
* The paragraph background color as a as a #GdkColor.
*
* Since: 2.8
*/
@@ -527,10 +559,25 @@ gtk_text_tag_class_init (GtkTextTagClass *klass)
PROP_PARAGRAPH_BACKGROUND_GDK,
g_param_spec_boxed ("paragraph-background-gdk",
P_("Paragraph background color"),
P_("Paragraph background color as a (possibly unallocated) GdkColor"),
P_("Paragraph background color as a GdkColor"),
GDK_TYPE_COLOR,
GTK_PARAM_READWRITE));
/**
* GtkTextTag:paragraph-background-rgba:
*
* The paragraph background color as a as a #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 GdkRGBA"),
GDK_TYPE_RGBA,
GTK_PARAM_READWRITE));
/**
* GtkTextTag:accumulative-margin:
*
@@ -740,11 +787,35 @@ gtk_text_tag_finalize (GObject *object)
}
static void
set_bg_color (GtkTextTag *tag, GdkColor *color)
copy_rgba_to_gdk_color (GdkRGBA *src,
GdkColor *dest)
{
dest->red = CLAMP (src->red, 0.0, 1.0) * 65535.0;
dest->green = CLAMP (src->green, 0.0, 1.0) * 65535.0;
dest->blue = CLAMP (src->blue, 0.0, 1.0) * 65535.0;
}
static void
copy_gdk_color_to_rgba (GdkColor *src,
GdkRGBA *dest)
{
dest->red = src->red / 65535.;
dest->green = src->green / 65535.;
dest->blue = src->blue / 65535.;
dest->alpha = 1;
}
static void
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 +823,9 @@ 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);
copy_rgba_to_gdk_color (rgba, &priv->values->appearance.bg_color);
}
else
{
@@ -765,18 +838,26 @@ 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);
copy_rgba_to_gdk_color (rgba, &priv->values->appearance.fg_color);
}
else
{
@@ -789,21 +870,33 @@ 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);
if (priv->values->pg_bg_color)
gdk_color_free (priv->values->pg_bg_color);
priv->values->pg_bg_rgba = NULL;
priv->values->pg_bg_color = NULL;
if (rgba)
{
GdkColor color = { 0, };
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);
copy_rgba_to_gdk_color (rgba, &color);
priv->values->pg_bg_color = gdk_color_copy (&color);
}
else
{
@@ -811,13 +904,53 @@ 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)
{
GdkRGBA rgba;
copy_gdk_color_to_rgba (color, &rgba);
set_bg_rgba (tag, &rgba);
}
else
set_bg_rgba (tag, NULL);
}
static void
set_fg_color (GtkTextTag *tag, GdkColor *color)
{
if (color)
{
GdkRGBA rgba;
copy_gdk_color_to_rgba (color, &rgba);
set_fg_rgba (tag, &rgba);
}
else
set_fg_rgba (tag, NULL);
}
static void
set_pg_bg_color (GtkTextTag *tag, GdkColor *color)
{
if (color)
{
GdkRGBA rgba;
copy_gdk_color_to_rgba (color, &rgba);
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 +1131,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 +1146,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 +1175,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 +1404,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 +1425,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");
@@ -1440,10 +1597,18 @@ gtk_text_tag_get_property (GObject *object,
g_value_set_boxed (value, &priv->values->appearance.bg_color);
break;
case PROP_BACKGROUND_RGBA:
g_value_set_boxed (value, priv->values->appearance.rgba[0]);
break;
case PROP_FOREGROUND_GDK:
g_value_set_boxed (value, &priv->values->appearance.fg_color);
break;
case PROP_FOREGROUND_RGBA:
g_value_set_boxed (value, priv->values->appearance.rgba[1]);
break;
case PROP_FONT:
{
gchar *str;
@@ -1577,6 +1742,10 @@ gtk_text_tag_get_property (GObject *object,
g_value_set_boxed (value, priv->values->pg_bg_color);
break;
case PROP_PARAGRAPH_BACKGROUND_RGBA:
g_value_set_boxed (value, priv->values->pg_bg_rgba);
break;
case PROP_ACCUMULATIVE_MARGIN:
g_value_set_boolean (value, priv->accumulative_margin);
break;

View File

@@ -106,7 +106,8 @@ noinst_PROGRAMS = $(TEST_PROGS) \
testtoplevelembed \
testnoscreen \
testtreepos \
testsensitive
testsensitive \
testtextview
if USE_X11
noinst_PROGRAMS += testerrors
@@ -205,6 +206,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)
@@ -289,6 +291,7 @@ testtoplevelembed_LDADD = $(LDADDS)
testnoscreen_LDADD = $(LDADDS)
testtreepos_LDADD = $(LDADDS)
testsensitive_LDADD = $(LDADDS)
testtextview_LDADD = $(LDADDS)
testentrycompletion_SOURCES = \
@@ -434,6 +437,9 @@ styleexamples_SOURCES = styleexamples.c
testtoplevelembed_SOURCES = testtoplevelembed.c
testtextview_SOURCES = testtextview.c
EXTRA_DIST += \
gradient1.png \
prop-editor.h \

182
tests/testtextview.c Normal file
View File

@@ -0,0 +1,182 @@
#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.7)", NULL);
gtk_text_buffer_create_tag (buffer, "semi_red_background",
"background", "rgba(255,0,0,0.5)", NULL);
gtk_text_buffer_create_tag (buffer, "semi_orange_paragraph_background",
"paragraph-background", "rgba(255,165,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;
GtkTextMark *para_start;
/* 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, ".\n\n", -1);
/* Store the beginning of the other paragraph */
para_start = gtk_text_buffer_create_mark (buffer, "para_start", &iter, TRUE);
gtk_text_buffer_insert (buffer, &iter,
"Paragraph background colors can also be set with rgba color values .\n", -1);
gtk_text_buffer_insert (buffer, &iter, "For instance, you can have ", -1);
gtk_text_buffer_insert_with_tags_by_name (buffer, &iter,
"bold translucent blue text", -1,
"bold",
"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,
"italic text with translucent red background", -1,
"italic",
"semi_red_background",
"x-large",
NULL);
gtk_text_buffer_insert (buffer, &iter, " all rendered onto a translucent orange paragraph background.\n", -1);
gtk_text_buffer_get_bounds (buffer, &start, &end);
gtk_text_buffer_get_iter_at_mark (buffer, &iter, para_start);
gtk_text_buffer_apply_tag_by_name (buffer, "semi_orange_paragraph_background", &iter, &end);
/* 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);
}
/* Size of checks and gray levels for alpha compositing checkerboard */
#define CHECK_SIZE 10
#define CHECK_DARK (1.0 / 3.0)
#define CHECK_LIGHT (2.0 / 3.0)
static cairo_pattern_t *
get_checkered (void)
{
/* need to respect pixman's stride being a multiple of 4 */
static unsigned char data[8] = { 0xFF, 0x00, 0x00, 0x00,
0x00, 0xFF, 0x00, 0x00 };
static cairo_surface_t *checkered = NULL;
cairo_pattern_t *pattern;
if (checkered == NULL)
{
checkered = cairo_image_surface_create_for_data (data,
CAIRO_FORMAT_A8,
2, 2, 4);
}
pattern = cairo_pattern_create_for_surface (checkered);
cairo_pattern_set_extend (pattern, CAIRO_EXTEND_REPEAT);
cairo_pattern_set_filter (pattern, CAIRO_FILTER_NEAREST);
return pattern;
}
static void
draw_background (GtkWidget *widget, cairo_t *cr)
{
cairo_pattern_t *pat;
cairo_save (cr);
cairo_set_source_rgb (cr, CHECK_DARK, CHECK_DARK, CHECK_DARK);
cairo_paint (cr);
cairo_set_source_rgb (cr, CHECK_LIGHT, CHECK_LIGHT, CHECK_LIGHT);
cairo_scale (cr, CHECK_SIZE, CHECK_SIZE);
pat = get_checkered ();
cairo_mask (cr, pat);
cairo_pattern_destroy (pat);
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));
gtk_window_set_default_size (GTK_WINDOW (window), 400, -1);
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;
}