From f9bee0d42fa1d760bc3738d8b15aaf0b1699000e Mon Sep 17 00:00:00 2001 From: Michael Natterer Date: Tue, 23 Feb 2010 23:14:09 +0100 Subject: [PATCH] app: fix XOR cursor drawing artifacts Switch to a completely new PangoLayout managing stategy: The drawing code relies on text_tool->layout being a view on text_tool->text_buffer, if they get out of sync, drawing is b0rk. Therefore, split the update_layout() function into clear_layout() (which kill the layout) and ensure_layout() (which creates the layout if it doesn't exist). Whenever the buffer gets modified, pause the draw tool before the modification so the old cursor/selection undraw, then clear the layout. Resuming the draw tool will automatically re-create the layout for the buffer's new contents. Also switch off any clipping for cursor and selection, so we can at least see that our input has some effect, even if we don't actually see the edited text because it's out-of-layer. --- app/tools/gimptexttool-editor.c | 12 +++--- app/tools/gimptexttool.c | 70 +++++++++++++-------------------- app/tools/gimptexttool.h | 3 +- 3 files changed, 37 insertions(+), 48 deletions(-) diff --git a/app/tools/gimptexttool-editor.c b/app/tools/gimptexttool-editor.c index 56ba119064..b134cf0609 100644 --- a/app/tools/gimptexttool-editor.c +++ b/app/tools/gimptexttool-editor.c @@ -471,8 +471,7 @@ gimp_text_tool_editor_get_cursor_rect (GimpTextTool *text_tool, g_return_if_fail (GIMP_IS_TEXT_TOOL (text_tool)); g_return_if_fail (cursor_rect != NULL); - if (! text_tool->layout) - gimp_text_tool_update_layout (text_tool); + gimp_text_tool_ensure_layout (text_tool); layout = gimp_text_layout_get_pango_layout (text_tool->layout); @@ -664,6 +663,8 @@ gimp_text_tool_move_cursor (GimpTextTool *text_tool, cursor_index = strlen (string); g_free (string); + gimp_text_tool_ensure_layout (text_tool); + layout = gimp_text_layout_get_pango_layout (text_tool->layout); pango_layout_index_to_line_x (layout, cursor_index, FALSE, @@ -782,8 +783,7 @@ gimp_text_tool_insert_at_cursor (GimpTextTool *text_tool, { gimp_draw_tool_pause (GIMP_DRAW_TOOL (text_tool)); - gtk_text_buffer_insert_interactive_at_cursor (text_tool->text_buffer, - str, -1, TRUE); + gtk_text_buffer_insert_at_cursor (text_tool->text_buffer, str, -1); gimp_draw_tool_resume (GIMP_DRAW_TOOL (text_tool)); } @@ -912,7 +912,7 @@ gimp_text_tool_delete_from_cursor (GimpTextTool *text_tool, { gimp_draw_tool_pause (GIMP_DRAW_TOOL (text_tool)); - gtk_text_buffer_delete_interactive (buffer, &cursor, &end, TRUE); + gtk_text_buffer_delete (buffer, &cursor, &end); gimp_draw_tool_resume (GIMP_DRAW_TOOL (text_tool)); } @@ -1097,6 +1097,8 @@ gimp_text_tool_xy_to_offset (GimpTextTool *text_tool, gint offset; gint trailing; + gimp_text_tool_ensure_layout (text_tool); + gimp_text_layout_untransform_point (text_tool->layout, &x, &y); /* adjust to offset of logical rect */ diff --git a/app/tools/gimptexttool.c b/app/tools/gimptexttool.c index 9bcc9678f2..e6e9c24cd4 100644 --- a/app/tools/gimptexttool.c +++ b/app/tools/gimptexttool.c @@ -444,9 +444,6 @@ gimp_text_tool_button_press (GimpTool *tool, if (text_tool->text) { - if (! text_tool->layout) - gimp_text_tool_update_layout (text_tool); - gimp_text_tool_editor_button_press (text_tool, x, y, press_type); } else @@ -558,7 +555,7 @@ gimp_text_tool_motion (GimpTool *tool, { gimp_rectangle_tool_motion (tool, coords, time, state, display); } - else if (text_tool->layout) + else { GimpItem *item = GIMP_ITEM (text_tool->layer); gdouble x = coords->x - gimp_item_get_offset_x (item); @@ -726,30 +723,9 @@ gimp_text_tool_draw (GimpDrawTool *draw_tool) { /* If the text buffer has a selection, highlight the selected letters */ - GdkRectangle clip_rect; - gint x1, x2; - gint y1, y2; - - /* Turn on clipping for selections */ - g_object_get (text_tool, - "x1", &x1, - "y1", &y1, - "x2", &x2, - "y2", &y2, - NULL); - - clip_rect.x = x1; - clip_rect.width = x2 - x1; - clip_rect.y = y1; - clip_rect.height = y2 - y1; - - gimp_draw_tool_set_clip_rect (draw_tool, &clip_rect, FALSE); - gimp_text_tool_draw_selection (draw_tool, logical_offset_x, logical_offset_y); - /* Turn off clipping when done */ - gimp_draw_tool_set_clip_rect (draw_tool, NULL, FALSE); } else { @@ -922,12 +898,6 @@ gimp_text_tool_halt (GimpTextTool *text_tool) gimp_text_tool_set_drawable (text_tool, NULL, FALSE); - if (text_tool->layout) - { - g_object_unref (text_tool->layout); - text_tool->layout = NULL; - } - gimp_draw_tool_resume (GIMP_DRAW_TOOL (text_tool)); } @@ -962,6 +932,8 @@ gimp_text_tool_connect (GimpTextTool *text_tool, g_object_set (text_tool->proxy, "text", NULL, NULL); gtk_text_buffer_set_text (text_tool->text_buffer, "", -1); + + gimp_text_tool_clear_layout (text_tool); } gimp_context_define_property (GIMP_CONTEXT (options), @@ -973,6 +945,8 @@ gimp_text_tool_connect (GimpTextTool *text_tool, gimp_config_sync (G_OBJECT (text), G_OBJECT (text_tool->proxy), 0); gtk_text_buffer_set_text (text_tool->text_buffer, text->text, -1); + gimp_text_tool_clear_layout (text_tool); + text_tool->text = g_object_ref (text); g_signal_connect (text, "notify", @@ -1040,6 +1014,8 @@ gimp_text_tool_text_notify (GimpText *text, { g_return_if_fail (text == text_tool->text); + gimp_draw_tool_pause (GIMP_DRAW_TOOL (text_tool)); + if ((pspec->flags & G_PARAM_READWRITE) == G_PARAM_READWRITE) { GValue value = { 0, }; @@ -1080,10 +1056,11 @@ gimp_text_tool_text_notify (GimpText *text, g_signal_handlers_unblock_by_func (text_tool->text_buffer, gimp_text_tool_buffer_changed, text_tool); - - /* force change of cursor and selection display */ - gimp_text_tool_update_layout (text_tool); } + + gimp_text_tool_clear_layout (text_tool); + + gimp_draw_tool_resume (GIMP_DRAW_TOOL (text_tool)); } static gboolean @@ -1166,6 +1143,8 @@ gimp_text_tool_apply (GimpTextTool *text_tool) } } + gimp_draw_tool_pause (GIMP_DRAW_TOOL (text_tool)); + if (push_undo) { if (layer->modified) @@ -1232,7 +1211,9 @@ gimp_text_tool_apply (GimpTextTool *text_tool) gimp_image_flush (image); - gimp_text_tool_update_layout (text_tool); + gimp_text_tool_clear_layout (text_tool); + + gimp_draw_tool_resume (GIMP_DRAW_TOOL (text_tool)); } static void @@ -1553,16 +1534,21 @@ gimp_text_tool_buffer_changed (GtkTextBuffer *text_buffer, } void -gimp_text_tool_update_layout (GimpTextTool *text_tool) +gimp_text_tool_clear_layout (GimpTextTool *text_tool) { - if (text_tool->text) + if (text_tool->layout) { - GimpImage *image; + g_object_unref (text_tool->layout); + text_tool->layout = NULL; + } +} - if (text_tool->layout) - g_object_unref (text_tool->layout); - - image = gimp_item_get_image (GIMP_ITEM (text_tool->layer)); +void +gimp_text_tool_ensure_layout (GimpTextTool *text_tool) +{ + if (! text_tool->layout && text_tool->text) + { + GimpImage *image = gimp_item_get_image (GIMP_ITEM (text_tool->layer)); text_tool->layout = gimp_text_layout_new (text_tool->layer->text, image); } diff --git a/app/tools/gimptexttool.h b/app/tools/gimptexttool.h index 0e484e660b..a61d257e28 100644 --- a/app/tools/gimptexttool.h +++ b/app/tools/gimptexttool.h @@ -113,7 +113,8 @@ void gimp_text_tool_create_vectors (GimpTextTool *text_tool); void gimp_text_tool_create_vectors_warped (GimpTextTool *text_tool); /* only for the text editor */ -void gimp_text_tool_update_layout (GimpTextTool *text_tool); +void gimp_text_tool_clear_layout (GimpTextTool *text_tool); +void gimp_text_tool_ensure_layout (GimpTextTool *text_tool); #endif /* __GIMP_TEXT_TOOL_H__ */