textview: Use paintables instead of textures, and fix the support

This changes gtk_text_buffer_insert_texture() to
gtk_text_buffer_insert_paintable() which is strictly more useful
(as textures are paintables). It also fixes the code to actually
support drawing the paintables (as well as tracking changes
to the paintables.
This commit is contained in:
Alexander Larsson 2020-02-06 16:33:34 +01:00
parent fcc3c12919
commit 8282698201
13 changed files with 251 additions and 144 deletions

View File

@ -9,6 +9,7 @@
#include <gtk/gtk.h>
#include <stdlib.h> /* for exit() */
#include "paintable.h"
static void easter_egg_callback (GtkWidget *button, gpointer data);
@ -130,20 +131,18 @@ insert_text (GtkTextView *view)
GtkTextBuffer *buffer = gtk_text_view_get_buffer (view);
GtkTextIter iter;
GtkTextIter start, end;
GdkTexture *texture;
GtkIconTheme *icon_theme;
GtkIconPaintable *icon;
GdkPaintable *nuclear;
icon_theme = gtk_icon_theme_get_for_display (gtk_widget_get_display (widget));
icon = gtk_icon_theme_lookup_icon (icon_theme,
"gtk3-demo",
"face-cool",
NULL,
32, 1,
gtk_widget_get_direction (widget),
0);
texture = gtk_icon_paintable_download_texture (icon);
g_object_unref (icon);
g_assert (texture);
nuclear = gtk_nuclear_animation_new ();
/* get start of buffer; each insertion will revalidate the
* iterator to point to just after the inserted text.
@ -239,9 +238,11 @@ insert_text (GtkTextView *view)
"heading", NULL);
gtk_text_buffer_insert (buffer, &iter, "The buffer can have images in it: ", -1);
gtk_text_buffer_insert_texture (buffer, &iter, texture);
gtk_text_buffer_insert_texture (buffer, &iter, texture);
gtk_text_buffer_insert_texture (buffer, &iter, texture);
gtk_text_buffer_insert_paintable (buffer, &iter, GDK_PAINTABLE (icon));
gtk_text_buffer_insert_paintable (buffer, &iter, GDK_PAINTABLE (icon));
gtk_text_buffer_insert_paintable (buffer, &iter, nuclear);
gtk_text_buffer_insert (buffer, &iter, " for example.\n\n", -1);
gtk_text_buffer_insert_with_tags_by_name (buffer, &iter, "Spacing. ", -1,
@ -386,7 +387,8 @@ insert_text (GtkTextView *view)
gtk_text_buffer_end_irreversible_action (buffer);
g_object_unref (texture);
g_object_unref (icon);
g_object_unref (nuclear);
}
static gboolean

View File

@ -1259,9 +1259,8 @@ _gtk_text_btree_insert (GtkTextIter *iter,
}
static void
insert_texture_or_widget_segment (GtkTextIter *iter,
GtkTextLineSegment *seg)
insert_paintable_or_widget_segment (GtkTextIter *iter,
GtkTextLineSegment *seg)
{
GtkTextIter start;
GtkTextLineSegment *prevPtr;
@ -1297,19 +1296,21 @@ insert_texture_or_widget_segment (GtkTextIter *iter,
*iter = start;
gtk_text_iter_forward_char (iter); /* skip forward past the segment */
DV (g_print ("invalidating due to inserting texture/widget (%s)\n", G_STRLOC));
DV (g_print ("invalidating due to inserting paintable/widget (%s)\n", G_STRLOC));
_gtk_text_btree_invalidate_region (tree, &start, iter, FALSE);
}
void
_gtk_text_btree_insert_texture (GtkTextIter *iter,
GdkTexture *texture)
_gtk_text_btree_insert_paintable (GtkTextIter *iter,
GdkPaintable *paintable)
{
GtkTextLineSegment *seg;
seg = _gtk_texture_segment_new (texture);
seg = _gtk_paintable_segment_new (paintable);
seg->body.paintable.tree = _gtk_text_iter_get_btree (iter);
seg->body.paintable.line = _gtk_text_iter_get_text_line (iter);
insert_texture_or_widget_segment (iter, seg);
insert_paintable_or_widget_segment (iter, seg);
}
void
@ -1330,7 +1331,7 @@ _gtk_text_btree_insert_child_anchor (GtkTextIter *iter,
tree = seg->body.child.tree = _gtk_text_iter_get_btree (iter);
seg->body.child.line = _gtk_text_iter_get_text_line (iter);
insert_texture_or_widget_segment (iter, seg);
insert_paintable_or_widget_segment (iter, seg);
if (tree->child_anchor_table == NULL)
tree->child_anchor_table = g_hash_table_new (NULL, NULL);
@ -2380,7 +2381,7 @@ copy_segment (GString *string,
/* printf (" :%s\n", string->str); */
}
else if (seg->type == &gtk_text_texture_type ||
else if (seg->type == &gtk_text_paintable_type ||
seg->type == &gtk_text_child_type)
{
gboolean copy = TRUE;

View File

@ -63,13 +63,13 @@ gboolean _gtk_text_btree_is_end (GtkTextBTree *tree,
/* Indexable segment mutation */
void _gtk_text_btree_delete (GtkTextIter *start,
GtkTextIter *end);
void _gtk_text_btree_insert (GtkTextIter *iter,
const gchar *text,
gint len);
void _gtk_text_btree_insert_texture (GtkTextIter *iter,
GdkTexture *texture);
void _gtk_text_btree_delete (GtkTextIter *start,
GtkTextIter *end);
void _gtk_text_btree_insert (GtkTextIter *iter,
const gchar *text,
gint len);
void _gtk_text_btree_insert_paintable (GtkTextIter *iter,
GdkPaintable *texture);
void _gtk_text_btree_insert_child_anchor (GtkTextIter *iter,
GtkTextChildAnchor *anchor);
@ -161,6 +161,9 @@ gboolean _gtk_text_btree_get_iter_at_mark_name (GtkTextBTree *tree,
void _gtk_text_btree_get_iter_at_mark (GtkTextBTree *tree,
GtkTextIter *iter,
GtkTextMark *mark);
void _gtk_text_btree_get_iter_at_paintable (GtkTextBTree *tree,
GtkTextIter *iter,
GtkTextLineSegment *seg);
void _gtk_text_btree_get_end_iter (GtkTextBTree *tree,
GtkTextIter *iter);
void _gtk_text_btree_get_iter_at_line (GtkTextBTree *tree,

View File

@ -87,7 +87,7 @@ struct _ClipboardRequest
enum {
INSERT_TEXT,
INSERT_TEXTURE,
INSERT_PAINTABLE,
INSERT_CHILD_ANCHOR,
DELETE_RANGE,
CHANGED,
@ -128,9 +128,9 @@ static void gtk_text_buffer_real_insert_text (GtkTextBuffer *buffe
GtkTextIter *iter,
const gchar *text,
gint len);
static void gtk_text_buffer_real_insert_texture (GtkTextBuffer *buffer,
static void gtk_text_buffer_real_insert_paintable (GtkTextBuffer *buffer,
GtkTextIter *iter,
GdkTexture *texture);
GdkPaintable *paintable);
static void gtk_text_buffer_real_insert_anchor (GtkTextBuffer *buffer,
GtkTextIter *iter,
GtkTextChildAnchor *anchor);
@ -434,7 +434,7 @@ gtk_text_buffer_class_init (GtkTextBufferClass *klass)
object_class->get_property = gtk_text_buffer_get_property;
klass->insert_text = gtk_text_buffer_real_insert_text;
klass->insert_texture = gtk_text_buffer_real_insert_texture;
klass->insert_paintable = gtk_text_buffer_real_insert_paintable;
klass->insert_child_anchor = gtk_text_buffer_real_insert_anchor;
klass->delete_range = gtk_text_buffer_real_delete_range;
klass->apply_tag = gtk_text_buffer_real_apply_tag;
@ -596,33 +596,33 @@ gtk_text_buffer_class_init (GtkTextBufferClass *klass)
_gtk_marshal_VOID__BOXED_STRING_INTv);
/**
* GtkTextBuffer::insert-texture:
* GtkTextBuffer::insert-paintable:
* @textbuffer: the object which received the signal
* @location: position to insert @texture in @textbuffer
* @texture: the #GdkTexture to be inserted
* @location: position to insert @paintable in @textbuffer
* @paintable: the #GdkPaintable to be inserted
*
* The ::insert-texture signal is emitted to insert a #GdkTexture
* The ::insert-paintable signal is emitted to insert a #GdkPaintable
* in a #GtkTextBuffer. Insertion actually occurs in the default handler.
*
* Note that if your handler runs before the default handler it must not
* invalidate the @location iter (or has to revalidate it).
* The default signal handler revalidates it to be placed after the
* inserted @texture.
* inserted @paintable.
*
* See also: gtk_text_buffer_insert_texture().
* See also: gtk_text_buffer_insert_paintable().
*/
signals[INSERT_TEXTURE] =
g_signal_new (I_("insert-texture"),
signals[INSERT_PAINTABLE] =
g_signal_new (I_("insert-paintable"),
G_OBJECT_CLASS_TYPE (object_class),
G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET (GtkTextBufferClass, insert_texture),
G_STRUCT_OFFSET (GtkTextBufferClass, insert_paintable),
NULL, NULL,
_gtk_marshal_VOID__BOXED_OBJECT,
G_TYPE_NONE,
2,
GTK_TYPE_TEXT_ITER | G_SIGNAL_TYPE_STATIC_SCOPE,
GDK_TYPE_TEXTURE);
g_signal_set_va_marshaller (signals[INSERT_TEXTURE],
GDK_TYPE_PAINTABLE);
g_signal_set_va_marshaller (signals[INSERT_PAINTABLE],
G_TYPE_FROM_CLASS (klass),
_gtk_marshal_VOID__BOXED_OBJECTv);
@ -1519,19 +1519,19 @@ insert_range_untagged (GtkTextBuffer *buffer,
}
else if (gtk_text_iter_get_char (&range_end) == GTK_TEXT_UNKNOWN_CHAR)
{
GdkTexture *texture;
GdkPaintable *paintable;
GtkTextChildAnchor *anchor;
texture = gtk_text_iter_get_texture (&range_end);
paintable = gtk_text_iter_get_paintable (&range_end);
anchor = gtk_text_iter_get_child_anchor (&range_end);
if (texture)
if (paintable)
{
r = save_range (&range_start,
&range_end,
&end);
gtk_text_buffer_insert_texture (buffer, iter, texture);
gtk_text_buffer_insert_paintable (buffer, iter, paintable);
restore_range (r);
r = NULL;
@ -1733,7 +1733,7 @@ gtk_text_buffer_real_insert_range (GtkTextBuffer *buffer,
* @start: a position in a #GtkTextBuffer
* @end: another position in the same buffer as @start
*
* Copies text, tags, and texture between @start and @end (the order
* Copies text, tags, and paintables between @start and @end (the order
* of @start and @end doesnt matter) and inserts the copy at @iter.
* Used instead of simply getting/inserting text because it preserves
* images and tags. If @start and @end are in a different buffer from
@ -2215,7 +2215,7 @@ gtk_text_buffer_get_text (GtkTextBuffer *buffer,
* the returned string do correspond to byte
* and character indexes into the buffer. Contrast with
* gtk_text_buffer_get_text(). Note that 0xFFFC can occur in normal
* text as well, so it is not a reliable indicator that a texture or
* text as well, so it is not a reliable indicator that a paintable or
* widget is in the buffer.
*
* Returns: (transfer full): an allocated UTF-8 string
@ -2243,41 +2243,41 @@ gtk_text_buffer_get_slice (GtkTextBuffer *buffer,
*/
static void
gtk_text_buffer_real_insert_texture (GtkTextBuffer *buffer,
GtkTextIter *iter,
GdkTexture *texture)
gtk_text_buffer_real_insert_paintable (GtkTextBuffer *buffer,
GtkTextIter *iter,
GdkPaintable *paintable)
{
_gtk_text_btree_insert_texture (iter, texture);
_gtk_text_btree_insert_paintable (iter, paintable);
g_signal_emit (buffer, signals[CHANGED], 0);
}
/**
* gtk_text_buffer_insert_texture:
* gtk_text_buffer_insert_paintable:
* @buffer: a #GtkTextBuffer
* @iter: location to insert the texture
* @texture: a #GdkTexture
* @iter: location to insert the paintable
* @paintable: a #GdkPaintable
*
* Inserts an image into the text buffer at @iter. The image will be
* counted as one character in character counts, and when obtaining
* the buffer contents as a string, will be represented by the Unicode
* object replacement character 0xFFFC. Note that the slice
* variants for obtaining portions of the buffer as a string include
* this character for texture, but the text variants do
* this character for paintable, but the text variants do
* not. e.g. see gtk_text_buffer_get_slice() and
* gtk_text_buffer_get_text().
**/
void
gtk_text_buffer_insert_texture (GtkTextBuffer *buffer,
GtkTextIter *iter,
GdkTexture *texture)
gtk_text_buffer_insert_paintable (GtkTextBuffer *buffer,
GtkTextIter *iter,
GdkPaintable *paintable)
{
g_return_if_fail (GTK_IS_TEXT_BUFFER (buffer));
g_return_if_fail (iter != NULL);
g_return_if_fail (GDK_IS_TEXTURE (texture));
g_return_if_fail (GDK_IS_PAINTABLE (paintable));
g_return_if_fail (gtk_text_iter_get_buffer (iter) == buffer);
g_signal_emit (buffer, signals[INSERT_TEXTURE], 0, iter, texture);
g_signal_emit (buffer, signals[INSERT_PAINTABLE], 0, iter, paintable);
}
/*

View File

@ -85,7 +85,7 @@ struct _GtkTextBuffer
* GtkTextBufferClass:
* @parent_class: The object class structure needs to be the first.
* @insert_text: The class handler for the #GtkTextBuffer::insert-text signal.
* @insert_texture: The class handler for the #GtkTextBuffer::insert-texture signal.
* @insert_paintable: The class handler for the #GtkTextBuffer::insert-paintable signal.
* @insert_child_anchor: The class handler for the #GtkTextBuffer::insert-child-anchor signal.
* @delete_range: The class handler for the #GtkTextBuffer::delete-range signal.
* @changed: The class handler for the #GtkTextBuffer::changed signal.
@ -107,9 +107,9 @@ struct _GtkTextBufferClass
const gchar *new_text,
gint new_text_length);
void (* insert_texture) (GtkTextBuffer *buffer,
void (* insert_paintable) (GtkTextBuffer *buffer,
GtkTextIter *iter,
GdkTexture *texture);
GdkPaintable *paintable);
void (* insert_child_anchor) (GtkTextBuffer *buffer,
GtkTextIter *iter,
@ -267,11 +267,11 @@ gchar *gtk_text_buffer_get_slice (GtkTextBuffer *buffer,
const GtkTextIter *end,
gboolean include_hidden_chars);
/* Insert a texture */
/* Insert a paintable */
GDK_AVAILABLE_IN_ALL
void gtk_text_buffer_insert_texture (GtkTextBuffer *buffer,
void gtk_text_buffer_insert_paintable (GtkTextBuffer *buffer,
GtkTextIter *iter,
GdkTexture *texture);
GdkPaintable *texture);
/* Insert a child anchor */
GDK_AVAILABLE_IN_ALL

View File

@ -72,67 +72,109 @@
} \
} G_STMT_END
#define TEXTURE_SEG_SIZE ((unsigned) (G_STRUCT_OFFSET (GtkTextLineSegment, body) \
+ sizeof (GtkTextTexture)))
#define PAINTABLE_SEG_SIZE ((unsigned) (G_STRUCT_OFFSET (GtkTextLineSegment, body) \
+ sizeof (GtkTextPaintable)))
#define WIDGET_SEG_SIZE ((unsigned) (G_STRUCT_OFFSET (GtkTextLineSegment, body) \
+ sizeof (GtkTextChildBody)))
static GtkTextLineSegment *
texture_segment_cleanup_func (GtkTextLineSegment *seg,
GtkTextLine *line)
static void
paintable_invalidate_size (GdkPaintable *paintable,
GtkTextLineSegment *seg)
{
/* nothing */
if (seg->body.paintable.tree)
{
GtkTextIter start, end;
_gtk_text_btree_get_iter_at_paintable (seg->body.paintable.tree, &start, seg);
end = start;
gtk_text_iter_forward_char (&end);
_gtk_text_btree_invalidate_region (seg->body.paintable.tree, &start, &end, FALSE);
}
}
static void
paintable_invalidate_contents (GdkPaintable *paintable,
GtkTextLineSegment *seg)
{
/* These do the same anyway */
paintable_invalidate_size (paintable, seg);
}
static GtkTextLineSegment *
paintable_segment_cleanup_func (GtkTextLineSegment *seg,
GtkTextLine *line)
{
seg->body.paintable.line = line;
return seg;
}
static int
texture_segment_delete_func (GtkTextLineSegment *seg,
GtkTextLine *line,
gboolean tree_gone)
paintable_segment_delete_func (GtkTextLineSegment *seg,
GtkTextLine *line,
gboolean tree_gone)
{
if (seg->body.texture.texture)
g_object_unref (seg->body.texture.texture);
GdkPaintable *paintable;
guint flags;
g_slice_free1 (TEXTURE_SEG_SIZE, seg);
seg->body.paintable.tree = NULL;
seg->body.paintable.line = NULL;
paintable = seg->body.paintable.paintable;
if (paintable)
{
flags = gdk_paintable_get_flags (paintable);
if ((flags & GDK_PAINTABLE_STATIC_CONTENTS) == 0)
g_signal_handlers_disconnect_by_func (paintable, G_CALLBACK (paintable_invalidate_contents), seg);
if ((flags & GDK_PAINTABLE_STATIC_SIZE) == 0)
g_signal_handlers_disconnect_by_func (paintable, G_CALLBACK (paintable_invalidate_size), seg);
g_object_unref (paintable);
}
g_slice_free1 (PAINTABLE_SEG_SIZE, seg);
return 0;
}
static void
texture_segment_check_func (GtkTextLineSegment *seg,
GtkTextLine *line)
paintable_segment_check_func (GtkTextLineSegment *seg,
GtkTextLine *line)
{
if (seg->next == NULL)
g_error ("texture segment is the last segment in a line");
g_error ("paintable segment is the last segment in a line");
if (seg->byte_count != GTK_TEXT_UNKNOWN_CHAR_UTF8_LEN)
g_error ("texture segment has byte count of %d", seg->byte_count);
g_error ("paintable segment has byte count of %d", seg->byte_count);
if (seg->char_count != 1)
g_error ("texture segment has char count of %d", seg->char_count);
g_error ("paintable segment has char count of %d", seg->char_count);
}
const GtkTextLineSegmentClass gtk_text_texture_type = {
"texture", /* name */
FALSE, /* leftGravity */
NULL, /* splitFunc */
texture_segment_delete_func, /* deleteFunc */
texture_segment_cleanup_func, /* cleanupFunc */
NULL, /* lineChangeFunc */
texture_segment_check_func /* checkFunc */
const GtkTextLineSegmentClass gtk_text_paintable_type = {
"paintable", /* name */
FALSE, /* leftGravity */
NULL, /* splitFunc */
paintable_segment_delete_func, /* deleteFunc */
paintable_segment_cleanup_func, /* cleanupFunc */
NULL, /* lineChangeFunc */
paintable_segment_check_func /* checkFunc */
};
GtkTextLineSegment *
_gtk_texture_segment_new (GdkTexture *texture)
_gtk_paintable_segment_new (GdkPaintable *paintable)
{
GtkTextLineSegment *seg;
guint flags;
seg = g_slice_alloc (TEXTURE_SEG_SIZE);
seg = g_slice_alloc (PAINTABLE_SEG_SIZE);
seg->type = &gtk_text_texture_type;
seg->type = &gtk_text_paintable_type;
seg->next = NULL;
@ -142,9 +184,24 @@ _gtk_texture_segment_new (GdkTexture *texture)
seg->byte_count = GTK_TEXT_UNKNOWN_CHAR_UTF8_LEN;
seg->char_count = 1;
seg->body.texture.texture = texture;
seg->body.paintable.paintable = paintable;
seg->body.paintable.tree = NULL;
seg->body.paintable.line = NULL;
g_object_ref (texture);
flags = gdk_paintable_get_flags (paintable);
if ((flags & GDK_PAINTABLE_STATIC_CONTENTS) == 0)
g_signal_connect (paintable,
"invalidate-contents",
G_CALLBACK (paintable_invalidate_contents),
seg);
if ((flags & GDK_PAINTABLE_STATIC_SIZE) == 0)
g_signal_connect (paintable,
"invalidate-size",
G_CALLBACK (paintable_invalidate_size),
seg);
g_object_ref (paintable);
return seg;
}

View File

@ -54,14 +54,16 @@
G_BEGIN_DECLS
typedef struct _GtkTextTexture GtkTextTexture;
typedef struct _GtkTextPaintable GtkTextPaintable;
struct _GtkTextTexture
struct _GtkTextPaintable
{
GdkTexture *texture;
GdkPaintable *paintable;
GtkTextBTree *tree;
GtkTextLine *line;
};
GtkTextLineSegment *_gtk_texture_segment_new (GdkTexture *texture);
GtkTextLineSegment *_gtk_paintable_segment_new (GdkPaintable *paintable);
typedef struct _GtkTextChildBody GtkTextChildBody;

View File

@ -173,7 +173,7 @@ gtk_text_iter_make_surreal (const GtkTextIter *_iter)
_gtk_text_btree_get_chars_changed_stamp (iter->tree))
{
g_warning ("Invalid text buffer iterator: either the iterator "
"is uninitialized, or the characters/textures/widgets "
"is uninitialized, or the characters/paintables/widgets "
"in the buffer have been modified since the iterator "
"was created.\nYou must use marks, character numbers, "
"or line numbers to preserve a position across buffer "
@ -896,7 +896,7 @@ gtk_text_iter_get_char (const GtkTextIter *iter)
* such as images. Because images are encoded in the slice, byte and
* character offsets in the returned array will correspond to byte
* offsets in the text buffer. Note that 0xFFFC can occur in normal
* text as well, so it is not a reliable indicator that a texture or
* text as well, so it is not a reliable indicator that a paintable or
* widget is in the buffer.
*
* Returns: (transfer full): slice of text from the buffer
@ -990,16 +990,16 @@ gtk_text_iter_get_visible_text (const GtkTextIter *start,
}
/**
* gtk_text_iter_get_texture:
* gtk_text_iter_get_paintable:
* @iter: an iterator
*
* If the element at @iter is a texture, the texture is returned
* If the element at @iter is a paintable, the paintable is returned
* (with no new reference count added). Otherwise, %NULL is returned.
*
* Returns: (transfer none): the texture at @iter
* Returns: (transfer none): the paintable at @iter
**/
GdkTexture *
gtk_text_iter_get_texture (const GtkTextIter *iter)
GdkPaintable *
gtk_text_iter_get_paintable (const GtkTextIter *iter)
{
GtkTextRealIter *real;
@ -1012,10 +1012,10 @@ gtk_text_iter_get_texture (const GtkTextIter *iter)
check_invariants (iter);
if (real->segment->type != &gtk_text_texture_type)
if (real->segment->type != &gtk_text_paintable_type)
return NULL;
else
return real->segment->body.texture.texture;
return real->segment->body.paintable.paintable;
}
/**
@ -2444,7 +2444,7 @@ gtk_text_iter_backward_chars (GtkTextIter *iter, gint count)
* @iter: a #GtkTextIter
* @count: number of chars to move
*
* Moves forward by @count text characters (textures, widgets,
* Moves forward by @count text characters (paintables, widgets,
* etc. do not count as characters for this). Equivalent to moving
* through the results of gtk_text_iter_get_text(), rather than
* gtk_text_iter_get_slice().
@ -2465,7 +2465,7 @@ gtk_text_iter_forward_text_chars (GtkTextIter *iter,
* @iter: a #GtkTextIter
* @count: number of chars to move
*
* Moves backward by @count text characters (textures, widgets,
* Moves backward by @count text characters (paintables, widgets,
* etc. do not count as characters for this). Equivalent to moving
* through the results of gtk_text_iter_get_text(), rather than
* gtk_text_iter_get_slice().
@ -5666,6 +5666,20 @@ _gtk_text_btree_get_iter_at_mark_name (GtkTextBTree *tree,
}
}
void
_gtk_text_btree_get_iter_at_paintable (GtkTextBTree *tree,
GtkTextIter *iter,
GtkTextLineSegment *seg)
{
g_return_if_fail (iter != NULL);
g_return_if_fail (tree != NULL);
iter_init_from_segment (iter, tree,
seg->body.paintable.line, seg);
g_assert (seg->body.paintable.line == _gtk_text_iter_get_text_line (iter));
check_invariants (iter);
}
void
_gtk_text_btree_get_iter_at_mark (GtkTextBTree *tree,
GtkTextIter *iter,

View File

@ -38,7 +38,7 @@ G_BEGIN_DECLS
* GtkTextSearchFlags:
* @GTK_TEXT_SEARCH_VISIBLE_ONLY: Search only visible data. A search match may
* have invisible text interspersed.
* @GTK_TEXT_SEARCH_TEXT_ONLY: Search only text. A match may have textures or
* @GTK_TEXT_SEARCH_TEXT_ONLY: Search only text. A match may have paintables or
* child widgets mixed inside the matched range.
* @GTK_TEXT_SEARCH_CASE_INSENSITIVE: The text will be matched regardless of
* what case it is in.
@ -47,7 +47,7 @@ G_BEGIN_DECLS
*
* If neither #GTK_TEXT_SEARCH_VISIBLE_ONLY nor #GTK_TEXT_SEARCH_TEXT_ONLY are
* enabled, the match must be exact; the special 0xFFFC character will match
* embedded textures or child widgets.
* embedded paintables or child widgets.
*/
typedef enum {
GTK_TEXT_SEARCH_VISIBLE_ONLY = 1 << 0,
@ -155,9 +155,9 @@ gchar *gtk_text_iter_get_visible_text (const GtkTextIter *start,
const GtkTextIter *end);
GDK_AVAILABLE_IN_ALL
GdkTexture * gtk_text_iter_get_texture (const GtkTextIter *iter);
GdkPaintable *gtk_text_iter_get_paintable (const GtkTextIter *iter);
GDK_AVAILABLE_IN_ALL
GSList * gtk_text_iter_get_marks (const GtkTextIter *iter);
GSList *gtk_text_iter_get_marks (const GtkTextIter *iter);
GDK_AVAILABLE_IN_ALL
GtkTextChildAnchor* gtk_text_iter_get_child_anchor (const GtkTextIter *iter);

View File

@ -1710,20 +1710,31 @@ add_text_attrs (GtkTextLayout *layout,
}
static void
add_texture_attrs (GtkTextLayout *layout,
GtkTextLineDisplay *display,
GtkTextAttributes *style,
GtkTextLineSegment *seg,
PangoAttrList *attrs,
gint start)
add_paintable_attrs (GtkTextLayout *layout,
GtkTextLineDisplay *display,
GtkTextAttributes *style,
GtkTextLineSegment *seg,
PangoAttrList *attrs,
gint start)
{
PangoAttribute *attr;
PangoRectangle logical_rect;
GtkTextTexture *texture = &seg->body.texture;
GtkTextPaintable *paintable = &seg->body.paintable;
gint width, height;
width = gdk_texture_get_width (texture->texture);
height = gdk_texture_get_height (texture->texture);
width = gdk_paintable_get_intrinsic_width (paintable->paintable);
height = gdk_paintable_get_intrinsic_height (paintable->paintable);
/* Pick *some* default size */
if (width == 0)
width = 32;
if (height == 0)
{
double aspect = gdk_paintable_get_intrinsic_aspect_ratio (paintable->paintable);
if (aspect == 0)
aspect = 1.0;
height = width / aspect;
}
logical_rect.x = 0;
logical_rect.y = -height * PANGO_SCALE;
@ -1731,7 +1742,7 @@ add_texture_attrs (GtkTextLayout *layout,
logical_rect.height = height * PANGO_SCALE;
attr = pango_attr_shape_new_with_data (&logical_rect, &logical_rect,
texture->texture, NULL, NULL);
paintable->paintable, NULL, NULL);
attr->start_index = start;
attr->end_index = start + seg->byte_count;
pango_attr_list_insert (attrs, attr);
@ -2149,7 +2160,7 @@ gtk_text_layout_update_display_cursors (GtkTextLayout *layout,
{
/* Displayable segments */
if (seg->type == &gtk_text_char_type ||
seg->type == &gtk_text_texture_type ||
seg->type == &gtk_text_paintable_type ||
seg->type == &gtk_text_child_type)
{
gtk_text_layout_get_iter_at_line (layout, &iter, line,
@ -2346,14 +2357,14 @@ gtk_text_layout_create_display (GtkTextLayout *layout,
{
/* Displayable segments */
if (seg->type == &gtk_text_char_type ||
seg->type == &gtk_text_texture_type ||
seg->type == &gtk_text_paintable_type ||
seg->type == &gtk_text_child_type)
{
style = get_style (layout, tags);
initial_toggle_segments = FALSE;
/* We have to delay setting the paragraph values until we
* hit the first texture or text segment because toggles at
* hit the first paintable or text segment because toggles at
* the beginning of the paragraph should affect the
* paragraph-global values
*/
@ -2430,15 +2441,15 @@ gtk_text_layout_create_display (GtkTextLayout *layout,
&last_scale_attr,
&last_fallback_attr);
}
else if (seg->type == &gtk_text_texture_type)
else if (seg->type == &gtk_text_paintable_type)
{
add_generic_attrs (layout,
&style->appearance,
seg->byte_count,
attrs, layout_byte_offset,
size_only, FALSE);
add_texture_attrs (layout, display, style,
seg, attrs, layout_byte_offset);
add_paintable_attrs (layout, display, style,
seg, attrs, layout_byte_offset);
memcpy (text + layout_byte_offset, _gtk_text_unknown_char_utf8,
seg->byte_count);
layout_byte_offset += seg->byte_count;
@ -4072,6 +4083,21 @@ render_para (GskPangoRenderer *crenderer,
pango_layout_iter_free (iter);
}
static gboolean
snapshot_shape (PangoAttrShape *attr,
GdkSnapshot *snapshot,
double width,
double height)
{
if (GDK_IS_PAINTABLE (attr->data))
{
gdk_paintable_snapshot (GDK_PAINTABLE (attr->data), snapshot, width, height);
return TRUE;
}
return FALSE;
}
void
gtk_text_layout_snapshot (GtkTextLayout *layout,
GtkWidget *widget,
@ -4106,6 +4132,8 @@ gtk_text_layout_snapshot (GtkTextLayout *layout,
crenderer = gsk_pango_renderer_acquire ();
gsk_pango_renderer_set_shape_handler (crenderer, snapshot_shape);
crenderer->widget = widget;
crenderer->snapshot = snapshot;
crenderer->fg_color = color;

View File

@ -142,10 +142,10 @@ struct _GtkTextLineSegment {
char chars[4]; /* Characters that make up character
* info. Actual length varies to
* hold as many characters as needed.*/
GtkTextToggleBody toggle; /* Information about tag toggle. */
GtkTextMarkBody mark; /* Information about mark. */
GtkTextTexture texture; /* Child texture */
GtkTextChildBody child; /* Child widget */
GtkTextToggleBody toggle; /* Information about tag toggle. */
GtkTextMarkBody mark; /* Information about mark. */
GtkTextPaintable paintable; /* Child texture */
GtkTextChildBody child; /* Child widget */
} body;
};

View File

@ -50,7 +50,7 @@ extern G_GNUC_INTERNAL const GtkTextLineSegmentClass gtk_text_left_mark_type;
extern G_GNUC_INTERNAL const GtkTextLineSegmentClass gtk_text_right_mark_type;
/* In gtktextchild.c */
extern G_GNUC_INTERNAL const GtkTextLineSegmentClass gtk_text_texture_type;
extern G_GNUC_INTERNAL const GtkTextLineSegmentClass gtk_text_paintable_type;
extern G_GNUC_INTERNAL const GtkTextLineSegmentClass gtk_text_child_type;
/*

View File

@ -686,11 +686,11 @@ fill_buffer (GtkTextBuffer *buffer)
gtk_text_buffer_get_iter_at_offset (buffer, &iter, 0);
gtk_text_buffer_insert_texture (buffer, &iter, texture);
gtk_text_buffer_insert_paintable (buffer, &iter, GDK_PAINTABLE (texture));
gtk_text_buffer_get_iter_at_offset (buffer, &iter, 1);
gtk_text_buffer_insert_texture (buffer, &iter, texture);
gtk_text_buffer_insert_paintable (buffer, &iter, GDK_PAINTABLE (texture));
str = g_strdup_printf ("%d Hello World!\nwoo woo woo woo woo woo woo woo\n",
i);
@ -706,20 +706,20 @@ fill_buffer (GtkTextBuffer *buffer)
"Spanish (Espa\303\261ol) \302\241Hola! / French (Fran\303\247ais) Bonjour, Salut / German (Deutsch S\303\274d) Gr\303\274\303\237 Gott (testing Latin-1 chars encoded in UTF8)\nThai (we can't display this, just making sure we don't crash) (\340\270\240\340\270\262\340\270\251\340\270\262\340\271\204\340\270\227\340\270\242) \340\270\252\340\270\247\340\270\261\340\270\252\340\270\224\340\270\265\340\270\204\340\270\243\340\270\261\340\270\232, \340\270\252\340\270\247\340\270\261\340\270\252\340\270\224\340\270\265\340\270\204\340\271\210\340\270\260\n",
-1);
gtk_text_buffer_insert_texture (buffer, &iter, texture);
gtk_text_buffer_insert_texture (buffer, &iter, texture);
gtk_text_buffer_insert_paintable (buffer, &iter, GDK_PAINTABLE(texture));
gtk_text_buffer_insert_paintable (buffer, &iter, GDK_PAINTABLE(texture));
gtk_text_buffer_get_iter_at_offset (buffer, &iter, 4);
gtk_text_buffer_insert_texture (buffer, &iter, texture);
gtk_text_buffer_insert_paintable (buffer, &iter, GDK_PAINTABLE(texture));
gtk_text_buffer_get_iter_at_offset (buffer, &iter, 7);
gtk_text_buffer_insert_texture (buffer, &iter, texture);
gtk_text_buffer_insert_paintable (buffer, &iter, GDK_PAINTABLE(texture));
gtk_text_buffer_get_iter_at_offset (buffer, &iter, 8);
gtk_text_buffer_insert_texture (buffer, &iter, texture);
gtk_text_buffer_insert_paintable (buffer, &iter, GDK_PAINTABLE(texture));
gtk_text_buffer_get_iter_at_line_offset (buffer, &iter, 0, 8);
iter2 = iter;