X-Git-Url: http://pileus.org/git/?a=blobdiff_plain;f=gtk%2Fgtktextdisplay.c;h=24cc0ec6b4850970c08c3b46f341184232b7b328;hb=17d3775555888151780fa404242e734a8e7f6b21;hp=a41f5b881a886a000ecbc4f6ca2e85ab92e3c541;hpb=9e203417752584b923cf5baec8940836ff2c0bcb;p=~andy%2Fgtk diff --git a/gtk/gtktextdisplay.c b/gtk/gtktextdisplay.c index a41f5b881..24cc0ec6b 100644 --- a/gtk/gtktextdisplay.c +++ b/gtk/gtktextdisplay.c @@ -21,8 +21,7 @@ * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free - * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * License along with this library. If not, see .Free * * Original Tk license: * @@ -78,6 +77,7 @@ #include "config.h" #include "gtktextdisplay.h" #include "gtkwidgetprivate.h" +#include "gtkstylecontextprivate.h" #include "gtkintl.h" /* DO NOT go putting private headers in here. This file should only @@ -107,10 +107,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 @@ -118,48 +121,27 @@ struct _GtkTextRendererClass PangoRendererClass parent_class; }; -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); +GType _gtk_text_renderer_get_type (void); - 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); -} +G_DEFINE_TYPE (GtkTextRenderer, _gtk_text_renderer, PANGO_TYPE_RENDERER) 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 * @@ -187,9 +169,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); @@ -198,23 +179,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)) { @@ -223,56 +201,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 @@ -539,7 +518,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; } @@ -581,9 +560,6 @@ get_selected_clip (GtkTextRenderer *text_renderer, static void render_para (GtkTextRenderer *text_renderer, GtkTextLineDisplay *line_display, - /* Top-left corner of paragraph including all margins */ - int x, - int y, int selection_start_index, int selection_end_index) { @@ -609,10 +585,9 @@ render_para (GtkTextRenderer *text_renderer, screen_width = line_display->total_width; context = gtk_widget_get_style_context (text_renderer->widget); + state = gtk_widget_get_state_flags (text_renderer->widget); - state = GTK_STATE_FLAG_SELECTED; - if (gtk_widget_has_focus (text_renderer->widget)) - state |= GTK_STATE_FLAG_FOCUSED; + state |= GTK_STATE_FLAG_SELECTED; gtk_style_context_get_background_color (context, state, &selection); @@ -638,7 +613,7 @@ render_para (GtkTextRenderer *text_renderer, /* Selection is the height of the line, plus top/bottom * margin if we're the first/last line */ - selection_y = y + PANGO_PIXELS (first_y) + line_display->top_margin; + selection_y = PANGO_PIXELS (first_y) + line_display->top_margin; selection_height = PANGO_PIXELS (last_y) - PANGO_PIXELS (first_y); if (first) @@ -661,7 +636,7 @@ render_para (GtkTextRenderer *text_renderer, cairo_save (cr); gdk_cairo_set_source_rgba (cr, &selection); cairo_rectangle (cr, - x + line_display->left_margin, selection_y, + line_display->left_margin, selection_y, screen_width, selection_height); cairo_fill (cr); cairo_restore(cr); @@ -669,20 +644,20 @@ render_para (GtkTextRenderer *text_renderer, text_renderer_set_state (text_renderer, SELECTED); pango_renderer_draw_layout_line (PANGO_RENDERER (text_renderer), line, - PANGO_SCALE * x + line_rect.x, - PANGO_SCALE * y + baseline); + line_rect.x, + baseline); } 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, - x + line_display->left_margin, selection_y, + line_display->left_margin, selection_y, screen_width, selection_height); cairo_fill (cr); @@ -692,8 +667,8 @@ render_para (GtkTextRenderer *text_renderer, text_renderer_set_state (text_renderer, NORMAL); pango_renderer_draw_layout_line (PANGO_RENDERER (text_renderer), line, - PANGO_SCALE * x + line_rect.x, - PANGO_SCALE * y + baseline); + line_rect.x, + baseline); /* Check if some part of the line is selected; the newline * that is after line->length for the last line of the @@ -705,7 +680,7 @@ render_para (GtkTextRenderer *text_renderer, { cairo_t *cr = text_renderer->cr; cairo_region_t *clip_region = get_selected_clip (text_renderer, layout, line, - x + line_display->x_offset, + line_display->x_offset, selection_y, selection_height, selection_start_index, selection_end_index); @@ -717,7 +692,7 @@ render_para (GtkTextRenderer *text_renderer, gdk_cairo_set_source_rgba (cr, &selection); cairo_rectangle (cr, - x + PANGO_PIXELS (line_rect.x), + PANGO_PIXELS (line_rect.x), selection_y, PANGO_PIXELS (line_rect.width), selection_height); @@ -726,8 +701,8 @@ render_para (GtkTextRenderer *text_renderer, text_renderer_set_state (text_renderer, SELECTED); pango_renderer_draw_layout_line (PANGO_RENDERER (text_renderer), line, - PANGO_SCALE * x + line_rect.x, - PANGO_SCALE * y + baseline); + line_rect.x, + baseline); cairo_restore (cr); @@ -740,7 +715,7 @@ render_para (GtkTextRenderer *text_renderer, gdk_cairo_set_source_rgba (cr, &selection); cairo_rectangle (cr, - x + line_display->left_margin, + line_display->left_margin, selection_y, PANGO_PIXELS (line_rect.x) - line_display->left_margin, selection_height); @@ -764,7 +739,7 @@ render_para (GtkTextRenderer *text_renderer, gdk_cairo_set_source_rgba (cr, &selection); cairo_rectangle (cr, - x + PANGO_PIXELS (line_rect.x) + PANGO_PIXELS (line_rect.width), + PANGO_PIXELS (line_rect.x) + PANGO_PIXELS (line_rect.width), selection_y, nonlayout_width, selection_height); @@ -783,12 +758,12 @@ render_para (GtkTextRenderer *text_renderer, GdkRGBA cursor_color; cairo_t *cr = text_renderer->cr; - /* we draw text using base color on filled cursor rectangle of cursor color - * (normally white on black) */ - _gtk_widget_get_cursor_color (text_renderer->widget, &cursor_color); + /* we draw text using base color on filled cursor rectangle of cursor color + * (normally white on black) */ + _gtk_style_context_get_cursor_color (context, &cursor_color, NULL); - cursor_rect.x = x + line_display->x_offset + line_display->block_cursor.x; - cursor_rect.y = y + line_display->block_cursor.y + line_display->top_margin; + cursor_rect.x = line_display->x_offset + line_display->block_cursor.x; + cursor_rect.y = line_display->block_cursor.y + line_display->top_margin; cursor_rect.width = line_display->block_cursor.width; cursor_rect.height = line_display->block_cursor.height; @@ -814,8 +789,8 @@ render_para (GtkTextRenderer *text_renderer, pango_renderer_draw_layout_line (PANGO_RENDERER (text_renderer), line, - PANGO_SCALE * x + line_rect.x, - PANGO_SCALE * y + baseline); + line_rect.x, + baseline); } cairo_restore (cr); @@ -846,11 +821,11 @@ gtk_text_layout_draw (GtkTextLayout *layout, cairo_t *cr, GList **widgets) { - gint current_y; - GSList *cursor_list; + GtkStyleContext *context; + gint offset_y; GtkTextRenderer *text_renderer; GtkTextIter selection_start, selection_end; - gboolean have_selection = FALSE; + gboolean have_selection; GSList *line_list; GSList *tmp_list; GList *tmp_widgets; @@ -864,7 +839,9 @@ gtk_text_layout_draw (GtkTextLayout *layout, if (!gdk_cairo_get_clip_rectangle (cr, &clip)) return; - line_list = gtk_text_layout_get_lines (layout, clip.y, clip.y + clip.height, ¤t_y); + context = gtk_widget_get_style_context (widget); + + line_list = gtk_text_layout_get_lines (layout, clip.y, clip.y + clip.height, &offset_y); if (line_list == NULL) return; /* nothing on the screen */ @@ -872,12 +849,14 @@ gtk_text_layout_draw (GtkTextLayout *layout, text_renderer = get_text_renderer (); text_renderer_begin (text_renderer, widget, cr); + /* text_renderer_begin/end does cairo_save/restore */ + cairo_translate (cr, 0, offset_y); + gtk_text_layout_wrap_loop_start (layout); - if (gtk_text_buffer_get_selection_bounds (layout->buffer, - &selection_start, - &selection_end)) - have_selection = TRUE; + have_selection = gtk_text_buffer_get_selection_bounds (layout->buffer, + &selection_start, + &selection_end); tmp_list = line_list; while (tmp_list != NULL) @@ -885,8 +864,6 @@ gtk_text_layout_draw (GtkTextLayout *layout, GtkTextLineDisplay *line_display; gint selection_start_index = -1; gint selection_end_index = -1; - gboolean have_strong; - gboolean have_weak; GtkTextLine *line = tmp_list->data; @@ -925,55 +902,30 @@ gtk_text_layout_draw (GtkTextLayout *layout, } render_para (text_renderer, line_display, - 0, current_y, selection_start_index, selection_end_index); /* We paint the cursors last, because they overlap another chunk - and need to appear on top. */ - - have_strong = FALSE; - have_weak = FALSE; - - cursor_list = line_display->cursors; - while (cursor_list) - { - GtkTextCursorDisplay *cursor = cursor_list->data; - if (cursor->is_strong) - have_strong = TRUE; - else - have_weak = TRUE; - - cursor_list = cursor_list->next; - } - - cursor_list = line_display->cursors; - while (cursor_list) + * and need to appear on top. + */ + if (line_display->cursors != NULL) { - GtkTextCursorDisplay *cursor = cursor_list->data; - GtkTextDirection dir; - GdkRectangle cursor_location; - - dir = line_display->direction; - if (have_strong && have_weak) - { - if (!cursor->is_strong) - dir = (dir == GTK_TEXT_DIR_RTL) ? GTK_TEXT_DIR_LTR : GTK_TEXT_DIR_RTL; - } - - cursor_location.x = line_display->x_offset + cursor->x; - cursor_location.y = current_y + line_display->top_margin + cursor->y; - cursor_location.width = 0; - cursor_location.height = cursor->height; + int i; - gtk_draw_insertion_cursor (widget, cr, &cursor_location, - cursor->is_strong, - dir, have_strong && have_weak); - - cursor_list = cursor_list->next; + for (i = 0; i < line_display->cursors->len; i++) + { + int index; + PangoDirection dir; + + index = g_array_index(line_display->cursors, int, i); + dir = (line_display->direction == GTK_TEXT_DIR_RTL) ? PANGO_DIRECTION_RTL : PANGO_DIRECTION_LTR; + gtk_render_insertion_cursor (context, cr, + line_display->x_offset, line_display->top_margin, + line_display->layout, index, dir); + } } } /* line_display->height > 0 */ - - current_y += line_display->height; + + cairo_translate (cr, 0, line_display->height); gtk_text_layout_free_line_display (layout, line_display); tmp_list = g_slist_next (tmp_list); @@ -985,10 +937,7 @@ gtk_text_layout_draw (GtkTextLayout *layout, if (widgets) *widgets = tmp_widgets; else - { - g_list_foreach (tmp_widgets, (GFunc)g_object_unref, NULL); - g_list_free (tmp_widgets); - } + g_list_free_full (tmp_widgets, g_object_unref); g_slist_free (line_list); }