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.
This commit is contained in:
Michael Natterer 2010-02-23 23:14:09 +01:00
parent 7ea07c884b
commit f9bee0d42f
3 changed files with 37 additions and 48 deletions

View File

@ -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 */

View File

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

View File

@ -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__ */