diff options
author | Chris Toshok <toshok@ximian.com> | 2002-11-20 07:59:20 +0800 |
---|---|---|
committer | Chris Toshok <toshok@src.gnome.org> | 2002-11-20 07:59:20 +0800 |
commit | f5b3a0e2e5eddbc30dd5c6841b585846b47fa264 (patch) | |
tree | 6d348936f880e26b02e4c745cf330cadaae4da8c /widgets | |
parent | e977b0e2801ead38a9b8f24465040bd2f3d2eb3c (diff) | |
download | gsoc2013-evolution-f5b3a0e2e5eddbc30dd5c6841b585846b47fa264.tar gsoc2013-evolution-f5b3a0e2e5eddbc30dd5c6841b585846b47fa264.tar.gz gsoc2013-evolution-f5b3a0e2e5eddbc30dd5c6841b585846b47fa264.tar.bz2 gsoc2013-evolution-f5b3a0e2e5eddbc30dd5c6841b585846b47fa264.tar.lz gsoc2013-evolution-f5b3a0e2e5eddbc30dd5c6841b585846b47fa264.tar.xz gsoc2013-evolution-f5b3a0e2e5eddbc30dd5c6841b585846b47fa264.tar.zst gsoc2013-evolution-f5b3a0e2e5eddbc30dd5c6841b585846b47fa264.zip |
commit clahey's original pango work.
2002-11-19 Chris Toshok <toshok@ximian.com>
* gal/e-text/e-text.[ch]: commit clahey's original pango work.
svn path=/trunk/; revision=18850
Diffstat (limited to 'widgets')
-rw-r--r-- | widgets/text/e-text.c | 1305 | ||||
-rw-r--r-- | widgets/text/e-text.h | 3 |
2 files changed, 392 insertions, 916 deletions
diff --git a/widgets/text/e-text.c b/widgets/text/e-text.c index 937812d0c6..0bd6a89164 100644 --- a/widgets/text/e-text.c +++ b/widgets/text/e-text.c @@ -295,6 +295,68 @@ e_text_dispose (GObject *object) (* G_OBJECT_CLASS (parent_class)->dispose) (object); } + static void +reset_layout_attrs (EText *text) +{ + PangoAttrList *attrs = NULL; + int object_count; + + if (text->layout == NULL) + return; + + object_count = e_text_model_object_count (text->model); + + if (text->bold || text->strikeout || object_count > 0) { + int length = 0; + int i; + + attrs = pango_attr_list_new (); + + for (i = 0; i < object_count; i++) { + int start_pos, end_pos; + PangoAttribute *attr = pango_attr_underline_new (PANGO_UNDERLINE_SINGLE); + + e_text_model_get_nth_object_bounds (text->model, i, &start_pos, &end_pos); + + attr->start_index = start_pos; + attr->end_index = end_pos; + + pango_attr_list_insert (attrs, attr); + } + + if (text->bold || text->strikeout) + length = strlen (text->text); + + if (text->bold) { + PangoAttribute *attr = pango_attr_weight_new (PANGO_WEIGHT_BOLD); + attr->start_index = 0; + attr->end_index = length; + + pango_attr_list_insert_before (attrs, attr); + } + if (text->strikeout) { + PangoAttribute *attr = pango_attr_strikethrough_new (TRUE); + attr->start_index = 0; + attr->end_index = length; + + pango_attr_list_insert_before (attrs, attr); + } + } + pango_layout_set_attributes (text->layout, attrs); + if (attrs) + pango_attr_list_unref (attrs); + calc_height (text); +} + +static void +reset_layout (EText *text) +{ + if (text->layout == NULL) + return; + pango_layout_set_text (text->layout, text->text, -1); + reset_layout_attrs (text); +} + static void e_text_text_model_changed (ETextModel *model, EText *text) { @@ -306,6 +368,7 @@ e_text_text_model_changed (ETextModel *model, EText *text) text->selection_start = CLAMP (text->selection_start, 0, model_len); text->selection_end = CLAMP (text->selection_end, 0, model_len); + text->needs_reset_layout = 1; text->needs_split_into_lines = 1; text->needs_redraw = 1; e_canvas_item_request_reflow (GNOME_CANVAS_ITEM(text)); @@ -336,117 +399,10 @@ e_text_text_model_reposition (ETextModel *model, ETextModelReposFn fn, gpointer } static void -get_bounds_item_relative (EText *text, double *px1, double *py1, double *px2, double *py2) -{ - GnomeCanvasItem *item; - double x, y; - double clip_x, clip_y; - int old_height; - - item = GNOME_CANVAS_ITEM (text); - - x = 0; - y = 0; - - clip_x = x; - clip_y = y; - - /* Calculate text dimensions */ - - old_height = text->height; - - if (text->text && text->font) - text->height = (e_font_height (text->font)) * text->num_lines; - else - text->height = 0; - - if (old_height != text->height) - e_canvas_item_request_parent_reflow(item); - - /* Anchor text */ - - switch (text->anchor) { - case GTK_ANCHOR_NW: - case GTK_ANCHOR_W: - case GTK_ANCHOR_SW: - break; - - case GTK_ANCHOR_N: - case GTK_ANCHOR_CENTER: - case GTK_ANCHOR_S: - x -= text->max_width / 2; - if ( text->clip_width >= 0) - clip_x -= text->clip_width / 2; - else - clip_x -= text->width / 2; - break; - - case GTK_ANCHOR_NE: - case GTK_ANCHOR_E: - case GTK_ANCHOR_SE: - x -= text->max_width; - if (text->clip_width >= 0) - clip_x -= text->clip_width; - else - clip_x -= text->width; - break; - } - - switch (text->anchor) { - case GTK_ANCHOR_NW: - case GTK_ANCHOR_N: - case GTK_ANCHOR_NE: - break; - - case GTK_ANCHOR_W: - case GTK_ANCHOR_CENTER: - case GTK_ANCHOR_E: - y -= text->height / 2; - if ( text->clip_height >= 0 ) - clip_y -= text->clip_height / 2; - else - clip_y -= text->height / 2; - break; - - case GTK_ANCHOR_SW: - case GTK_ANCHOR_S: - case GTK_ANCHOR_SE: - y -= text->height; - if ( text->clip_height >= 0 ) - clip_y -= text->clip_height; - else - clip_y -= text->height; - break; - } - - /* Bounds */ - - if (text->clip) { - /* maybe do bbox intersection here? */ - *px1 = clip_x; - *py1 = clip_y; - if (text->clip_width >= 0) - *px2 = clip_x + text->clip_width; - else - *px2 = clip_x + text->width; - - if ( text->clip_height >= 0 ) - *py2 = clip_y + text->clip_height; - else - *py2 = clip_y + text->height; - } else { - *px1 = x; - *py1 = y; - *px2 = x + text->max_width; - *py2 = y + text->height; - } -} - -static void get_bounds (EText *text, double *px1, double *py1, double *px2, double *py2) { GnomeCanvasItem *item; - double wx, wy, clip_width; + double wx, wy, clip_width, clip_height; item = GNOME_CANVAS_ITEM (text); @@ -456,19 +412,21 @@ get_bounds (EText *text, double *px1, double *py1, double *px2, double *py2) wy = 0; gnome_canvas_item_i2w (item, &wx, &wy); gnome_canvas_w2c (item->canvas, wx + text->xofs, wy + text->yofs, &text->cx, &text->cy); + gnome_canvas_w2c (item->canvas, wx, wy, &text->clip_cx, &text->clip_cy); if (text->clip_width < 0) - clip_width = text->max_width; + clip_width = text->width; else clip_width = text->clip_width; + if ( text->clip_height < 0 ) + clip_height = text->height; + else + clip_height = text->clip_height; + /* Get canvas pixel coordinates for clip rectangle position */ - gnome_canvas_w2c (item->canvas, wx, wy, &text->clip_cx, &text->clip_cy); text->clip_cwidth = clip_width * item->canvas->pixels_per_unit; - if ( text->clip_height >= 0 ) - text->clip_cheight = text->clip_height * item->canvas->pixels_per_unit; - else - text->clip_cheight = text->height * item->canvas->pixels_per_unit; + text->clip_cheight = clip_height * item->canvas->pixels_per_unit; /* Anchor text */ @@ -481,14 +439,14 @@ get_bounds (EText *text, double *px1, double *py1, double *px2, double *py2) case GTK_ANCHOR_N: case GTK_ANCHOR_CENTER: case GTK_ANCHOR_S: - text->cx -= text->max_width / 2; + text->cx -= text->width / 2; text->clip_cx -= text->clip_cwidth / 2; break; case GTK_ANCHOR_NE: case GTK_ANCHOR_E: case GTK_ANCHOR_SE: - text->cx -= text->max_width; + text->cx -= text->width; text->clip_cx -= text->clip_cwidth; break; } @@ -514,6 +472,14 @@ get_bounds (EText *text, double *px1, double *py1, double *px2, double *py2) break; } + text->text_cx = text->cx; + text->text_cy = text->cy; + + if (text->draw_borders) { + text->text_cx += BORDER_INDENT; + text->text_cy += BORDER_INDENT; + } + /* Bounds */ if (text->clip) { @@ -524,7 +490,7 @@ get_bounds (EText *text, double *px1, double *py1, double *px2, double *py2) } else { *px1 = text->cx; *py1 = text->cy; - *px2 = text->cx + text->max_width; + *px2 = text->cx + text->width; *py2 = text->cy + text->height; } } @@ -534,19 +500,24 @@ calc_height (EText *text) { GnomeCanvasItem *item; int old_height; + int old_width; + int width = 0; + int height = 0; item = GNOME_CANVAS_ITEM (text); /* Calculate text dimensions */ old_height = text->height; + old_width = text->width; - if (text->text && text->font) - text->height = e_font_height (text->font) * text->num_lines; - else - text->height = 0; + if (text->layout) + pango_layout_get_pixel_size (text->layout, &width, &height); + + text->height = height; + text->width = width; - if (old_height != text->height) + if (old_height != text->height || old_width != text->width) e_canvas_item_request_parent_reflow(item); } @@ -648,59 +619,6 @@ text_width_with_objects (ETextModel *model, return text && *text ? e_font_utf8_text_width (font, style, text, numbytes) : 0; } -static void -text_draw_with_objects (ETextModel *model, - GdkDrawable *drawable, - EFont *font, EFontStyle style, - GdkGC *gc, - gint x, gint y, - const gchar *text, gint numbytes) -{ - const gchar *c; - - if (text == NULL) - return; - - if (text == NULL) - return; - - while (*text && numbytes > 0) { - gint obj_num = -1; - - c = text; - - while (*c - && (obj_num = e_text_model_get_object_at_pointer (model, c)) == -1 - && numbytes > 0) { - ++c; - --numbytes; - } - - e_font_draw_utf8_text (drawable, font, style, gc, x, y, text, c-text); - x += e_font_utf8_text_width (font, style, text, c-text); - - if (obj_num != -1 && numbytes > 0) { - gint len; - gint start_x = x; - - e_text_model_get_nth_object (model, obj_num, &len); - - if (len > numbytes) - len = numbytes; - e_font_draw_utf8_text (drawable, font, style, gc, x, y, c, len); - x += e_font_utf8_text_width (font, style, c, len); - - /* We underline our objects. */ - gdk_draw_line (drawable, gc, start_x, y+1, x, y+1); - - c += len; - numbytes -= len; - } - - text = c; - } -} - typedef void (*LineSplitterFn) (int line_num, const char *start, int length, gpointer user_data); #define IS_BREAK_CHAR(break_chars, c) (g_unichar_isspace (c) || ((break_chars) && g_utf8_strchr ((break_chars), -1, (c)))) @@ -1030,6 +948,9 @@ e_text_set_property (GObject *object, case PROP_CLIP_WIDTH: text->clip_width = fabs (g_value_get_double (value)); calc_ellipsis (text); + if (text->layout) { + pango_layout_set_width (text->layout, text->clip_width < 0 ? -1 : text->clip_width * PANGO_SCALE); + } if ( text->line_wrap ) text->needs_split_into_lines = 1; else { @@ -1086,7 +1007,7 @@ e_text_set_property (GObject *object, break; case PROP_FILL_COLOR_GDK: - pcolor = g_value_get_pointer (value); + pcolor = g_value_get_boxed (value); if (pcolor) { color = *pcolor; } @@ -1217,15 +1138,10 @@ e_text_set_property (GObject *object, } if (color_changed) { -#ifndef NO_WARNINGS -#warning Color stuff ... -#endif -#if 0 - if (GNOME_CANVAS_ITEM_REALIZED & GTK_OBJECT_FLAGS(item)) - gdk_color_context_query_color (item->canvas->cc, &color); -#endif + GdkColormap *colormap = gtk_widget_get_colormap (GTK_WIDGET (item->canvas)); text->color = color; + gdk_rgb_find_color (colormap, &text->color); if (!item->canvas->aa) set_text_gc_foreground (text); @@ -1310,7 +1226,7 @@ e_text_get_property (GObject *object, break; case PROP_FILL_COLOR_GDK: - g_value_set_pointer (value, gdk_color_copy (&text->color)); + g_value_set_boxed (value, &text->color); break; case PROP_FILL_COLOR_RGBA: @@ -1322,7 +1238,7 @@ e_text_get_property (GObject *object, break; case PROP_TEXT_WIDTH: - g_value_set_double (value, text->max_width / text->item.canvas->pixels_per_unit); + g_value_set_double (value, text->width / text->item.canvas->pixels_per_unit); break; case PROP_TEXT_HEIGHT: @@ -1395,6 +1311,12 @@ e_text_reflow (GnomeCanvasItem *item, int flags) text = E_TEXT (item); + if (text->needs_reset_layout) { + reset_layout (text); + text->needs_reset_layout = 0; + text->needs_calc_height = 1; + } + if (text->needs_split_into_lines) { split_into_lines (text); @@ -1474,8 +1396,6 @@ e_text_update (GnomeCanvasItem *item, double *affine, ArtSVP *clip_path, int fla { EText *text; double x1, y1, x2, y2; - ArtDRect i_bbox, c_bbox; - int i; text = E_TEXT (item); @@ -1500,12 +1420,9 @@ e_text_update (GnomeCanvasItem *item, double *affine, ArtSVP *clip_path, int fla text->needs_redraw = 1; item->canvas->need_repick = TRUE; } - } else { - /* aa rendering */ - for (i = 0; i < 6; i++) - text->affine[i] = affine[i]; - get_bounds_item_relative (text, &i_bbox.x0, &i_bbox.y0, &i_bbox.x1, &i_bbox.y1); - art_drect_affine_transform (&c_bbox, &i_bbox, affine); + + if (!text->fill_clip_rectangle) + item->canvas->need_repick = TRUE; } text->needs_recalc_bounds = 0; } @@ -1526,6 +1443,10 @@ e_text_realize (GnomeCanvasItem *item) if (parent_class->realize) (* parent_class->realize) (item); + text->layout = gtk_widget_create_pango_layout (GTK_WIDGET (item->canvas), text->text); + pango_layout_set_width (text->layout, text->clip_width < 0 ? -1 : text->clip_width * PANGO_SCALE); + reset_layout_attrs (text); + text->gc = gdk_gc_new (item->canvas->layout.bin_window); #ifndef NO_WARNINGS #warning Color brokenness ... @@ -1558,150 +1479,116 @@ e_text_unrealize (GnomeCanvasItem *item) text->i_cursor = NULL; gdk_cursor_destroy (text->default_cursor); text->default_cursor = NULL; + g_object_unref (text->layout); + text->layout = NULL; if (parent_class->unrealize) (* parent_class->unrealize) (item); } -/* Calculates the x position of the specified line of text, based on the text's justification */ -static double -get_line_xpos_item_relative (EText *text, struct line *line) +static void +_get_tep(EText *text) { - double x; - - x = 0; - - switch (text->anchor) { - case GTK_ANCHOR_NW: - case GTK_ANCHOR_W: - case GTK_ANCHOR_SW: - break; - - case GTK_ANCHOR_N: - case GTK_ANCHOR_CENTER: - case GTK_ANCHOR_S: - x -= text->max_width / 2; - break; - - case GTK_ANCHOR_NE: - case GTK_ANCHOR_E: - case GTK_ANCHOR_SE: - x -= text->max_width; - break; + if (!text->tep) { + text->tep = e_text_event_processor_emacs_like_new(); + g_object_ref (text->tep); + text->tep_command_id = + g_signal_connect(text->tep, + "command", + G_CALLBACK (e_text_command), + (gpointer) text); } +} - switch (text->justification) { - case GTK_JUSTIFY_RIGHT: - x += text->max_width - line->width; - break; - - case GTK_JUSTIFY_CENTER: - x += (text->max_width - line->width) * 0.5; - break; - - default: - if (text->draw_borders) - x += BORDER_INDENT; - - /* For GTK_JUSTIFY_LEFT, we don't have to do anything. We do not support - * GTK_JUSTIFY_FILL, yet. - */ - break; - } - - return x; +static void +draw_pango_rectangle (GdkDrawable *drawable, GdkGC *gc, int x1, int y1, PangoRectangle rect) +{ + int width = rect.width / PANGO_SCALE; + int height = rect.height / PANGO_SCALE; + if (width <= 0) + width = 1; + if (height <= 0) + height = 1; + gdk_draw_rectangle (drawable, gc, TRUE, + x1 + rect.x / PANGO_SCALE, y1 + rect.y / PANGO_SCALE, width, height); } -#if 0 -/* Calculates the y position of the first line of text. */ -static double -get_line_ypos_item_relative (EText *text) +static gboolean +show_pango_rectangle (EText *text, PangoRectangle rect) { - double y; + int x1 = rect.x / PANGO_SCALE; + int x2 = (rect.x + rect.width) / PANGO_SCALE; - y = 0; + int y1 = rect.y / PANGO_SCALE; + int y2 = (rect.y + rect.height) / PANGO_SCALE; - switch (text->anchor) { - case GTK_ANCHOR_NW: - case GTK_ANCHOR_N: - case GTK_ANCHOR_NE: - break; + int new_xofs_edit = text->xofs_edit; + int new_yofs_edit = text->yofs_edit; - case GTK_ANCHOR_W: - case GTK_ANCHOR_CENTER: - case GTK_ANCHOR_E: - y -= text->height / 2; - break; + int clip_width, clip_height; - case GTK_ANCHOR_SW: - case GTK_ANCHOR_S: - case GTK_ANCHOR_SE: - y -= text->height; - break; + clip_width = text->clip_width; + if (clip_width >= 0 && text->draw_borders) { + clip_width -= 6; + if (clip_width < 0) + clip_width = 0; } - return y; -} -#endif + clip_height = text->clip_height; -/* Calculates the x position of the specified line of text, based on the text's justification */ -static int -get_line_xpos (EText *text, struct line *line) -{ - int x; + if (clip_height >= 0 && text->draw_borders) { + clip_height -= 6; + if (clip_height < 0) + clip_height = 0; + } - x = text->cx; + if (x1 < new_xofs_edit) + new_xofs_edit = x1; - switch (text->justification) { - case GTK_JUSTIFY_RIGHT: - x += text->max_width - line->width; - break; - - case GTK_JUSTIFY_CENTER: - x += (text->max_width - line->width) / 2; - break; + if (y1 < new_yofs_edit) + new_yofs_edit = y1; - default: - if (text->draw_borders) - x += BORDER_INDENT; - /* For GTK_JUSTIFY_LEFT, we don't have to do anything. We do not support - * GTK_JUSTIFY_FILL, yet. - */ - break; +#if 0 + if (clip_width >= 0) { + if (2 + x2 - clip_width > new_xofs_edit) + new_xofs_edit = 2 + x2 - clip_width; + } else { + new_xofs_edit = 0; } + if (clip_height >= 0) { + if (2 + y2 - clip_height > new_yofs_edit) + new_yofs_edit = 2 + y2 - clip_height; + } else { + new_yofs_edit = 0; + } +#endif + + if (new_xofs_edit < 0) + new_xofs_edit = 0; + if (new_yofs_edit < 0) + new_yofs_edit = 0; + + if (new_xofs_edit != text->xofs_edit || + new_yofs_edit != text->yofs_edit) { + text->xofs_edit = new_xofs_edit; + text->yofs_edit = new_yofs_edit; + return TRUE; + } - return x; -} -static void -_get_tep(EText *text) -{ - if (!text->tep) { - text->tep = e_text_event_processor_emacs_like_new(); - g_object_ref (text->tep); - text->tep_command_id = - g_signal_connect (text->tep, - "command", - G_CALLBACK(e_text_command), - (gpointer) text); - } + return FALSE; } /* Draw handler for the text item */ static void e_text_draw (GnomeCanvasItem *item, GdkDrawable *drawable, - int x, int y, int width, int height) + int x, int y, int width, int height) { EText *text; GdkRectangle rect, *clip_rect; - struct line *lines; - int i; int xpos, ypos; - int start_char, end_char; - int sel_start, sel_end; - GdkRectangle sel_rect; - GdkGC *fg_gc, *main_gc; + GdkGC *main_gc; GnomeCanvas *canvas; GtkWidget *widget; @@ -1709,7 +1596,6 @@ e_text_draw (GnomeCanvasItem *item, GdkDrawable *drawable, canvas = GNOME_CANVAS_ITEM(text)->canvas; widget = GTK_WIDGET(canvas); - fg_gc = widget->style->fg_gc[text->has_selection ? GTK_STATE_SELECTED : GTK_STATE_ACTIVE]; if (text->draw_background || text->draw_button) { main_gc = widget->style->fg_gc[GTK_WIDGET_STATE (widget)]; } else { @@ -1866,13 +1752,6 @@ e_text_draw (GnomeCanvasItem *item, GdkDrawable *drawable, if (!text->text || !text->font) return; - lines = text->lines; - if ( !lines ) { - text->needs_split_into_lines = 1; - e_canvas_item_request_reflow (item); - return; - } - clip_rect = NULL; if (text->clip) { rect.x = text->clip_cx - x; @@ -1881,250 +1760,124 @@ e_text_draw (GnomeCanvasItem *item, GdkDrawable *drawable, rect.height = text->clip_cheight; gdk_gc_set_clip_rectangle (main_gc, &rect); - gdk_gc_set_clip_rectangle (fg_gc, &rect); clip_rect = ▭ } - ypos = text->cy + e_font_ascent (text->font); - if (text->draw_borders) - ypos += BORDER_INDENT; - - if (text->editing) - ypos -= text->yofs_edit; if (text->stipple) gnome_canvas_set_stipple_origin (item->canvas, main_gc); - for (i = 0; i < text->num_lines; i++) { + xpos = text->text_cx; + ypos = text->text_cy; - xpos = get_line_xpos (text, lines); - if (text->editing) { - xpos -= text->xofs_edit; - start_char = lines->text - text->text; - end_char = start_char + lines->length; - sel_start = text->selection_start; - sel_end = text->selection_end; - if (sel_start > sel_end ) { - sel_start ^= sel_end; - sel_end ^= sel_start; - sel_start ^= sel_end; - } - if ( sel_start < start_char ) - sel_start = start_char; - if ( sel_end > end_char ) - sel_end = end_char; - if ( sel_start < sel_end ) { - sel_rect.x = xpos - x + text_width_with_objects (text->model, - text->font, text->style, - lines->text, - sel_start - start_char); - sel_rect.y = ypos - y - e_font_ascent (text->font); - sel_rect.width = text_width_with_objects (text->model, - text->font, text->style, - lines->text + sel_start - start_char, - sel_end - sel_start); - sel_rect.height = e_font_height (text->font); - gtk_paint_flat_box(GTK_WIDGET(item->canvas)->style, - drawable, - text->has_selection ? - GTK_STATE_SELECTED : - GTK_STATE_ACTIVE, - GTK_SHADOW_NONE, - clip_rect, - GTK_WIDGET(item->canvas), - "text", - sel_rect.x, - sel_rect.y, - sel_rect.width, - sel_rect.height); - text_draw_with_objects (text->model, - drawable, - text->font, text->style, - main_gc, - xpos - x, - ypos - y, - lines->text, - sel_start - start_char); - text_draw_with_objects (text->model, - drawable, - text->font, text->style, - fg_gc, - xpos - x + text_width_with_objects (text->model, - text->font, text->style, - lines->text, - sel_start - start_char), - ypos - y, - lines->text + sel_start - start_char, - sel_end - sel_start); - text_draw_with_objects (text->model, - drawable, - text->font, text->style, - main_gc, - xpos - x + text_width_with_objects (text->model, - text->font, text->style, - lines->text, - sel_end - start_char), - ypos - y, - lines->text + sel_end - start_char, - end_char - sel_end); - } else { - text_draw_with_objects (text->model, - drawable, - text->font, text->style, - main_gc, - xpos - x, - ypos - y, - lines->text, - lines->length); - } - if (text->selection_start == text->selection_end && - text->selection_start >= start_char && - text->selection_start <= end_char && - text->show_cursor) { - gdk_draw_rectangle (drawable, - main_gc, - TRUE, - xpos - x + text_width_with_objects (text->model, - text->font, text->style, - lines->text, - sel_start - start_char), - ypos - y - e_font_ascent (text->font), - 1, - e_font_height (text->font)); - } - } else { - if (text->clip && text->use_ellipsis && lines->ellipsis_length < lines->length) { - text_draw_with_objects (text->model, - drawable, - text->font, text->style, - main_gc, - xpos - x, - ypos - y, - lines->text, - lines->ellipsis_length); - e_font_draw_utf8_text (drawable, - text->font, text->style, - main_gc, - xpos - x + lines->width - text->ellipsis_width, - ypos - y, - text->ellipsis ? text->ellipsis : "...", - text->ellipsis ? strlen (text->ellipsis) : 3); + xpos -= x; + ypos -= y; + + if (text->editing) { + xpos -= text->xofs_edit; + ypos -= text->yofs_edit; + } + + printf ("pos = (%d,%d), ofs = (%d,%d)\n", + xpos, ypos, text->xofs_edit, text->yofs_edit); + + gdk_draw_layout (drawable, main_gc, + xpos, ypos, + text->layout); + + if (text->editing) { + if (text->selection_start != text->selection_end) { + int start_index, end_index; + PangoLayoutLine *line; + gint *ranges; + gint n_ranges, i; + PangoRectangle logical_rect; + GdkRegion *clip_region = gdk_region_new (); + GdkGC *selection_gc; + GdkGC *text_gc; + + start_index = MIN (text->selection_start, text->selection_end); + end_index = text->selection_start ^ text->selection_end ^ start_index; + + if (text->has_selection) { + selection_gc = widget->style->base_gc [GTK_STATE_SELECTED]; + text_gc = widget->style->text_gc[GTK_STATE_SELECTED]; } else { - text_draw_with_objects (text->model, - drawable, - text->font, text->style, - main_gc, - xpos - x, - ypos - y, - lines->text, - lines->length); + selection_gc = widget->style->base_gc [GTK_STATE_ACTIVE]; + text_gc = widget->style->text_gc[GTK_STATE_ACTIVE]; } - } - if (text->strikeout) - gdk_draw_rectangle (drawable, - main_gc, - TRUE, - xpos - x, - ypos - y - e_font_ascent (text->font) / 2, - lines->width, 1); - ypos += e_font_height (text->font); - lines++; - } + gdk_gc_set_clip_rectangle (selection_gc, clip_rect); - if (text->clip) { - gdk_gc_set_clip_rectangle (main_gc, NULL); - gdk_gc_set_clip_rectangle (fg_gc, NULL); - } -} + line = pango_layout_get_lines (text->layout)->data; -/* Render handler for the text item */ -static void -e_text_render (GnomeCanvasItem *item, GnomeCanvasBuf *buf) -{ -#if 0 - EText *text; - guint32 fg_color; - double xpos, ypos; - struct line *lines; - int i, j; - double affine[6]; - int dx, dy; - ArtPoint start_i, start_c; + pango_layout_line_get_x_ranges (line, start_index, end_index, &ranges, &n_ranges); - text = E_TEXT (item); + pango_layout_get_extents (text->layout, NULL, &logical_rect); - if (!text->text || !text->font || !text->suckfont) - return; + for (i=0; i < n_ranges; i++) { + GdkRectangle sel_rect; - suckfont = text->suckfont; + sel_rect.x = xpos + ranges[2*i] / PANGO_SCALE; + sel_rect.y = ypos; + sel_rect.width = (ranges[2*i + 1] - ranges[2*i]) / PANGO_SCALE; + sel_rect.height = logical_rect.height / PANGO_SCALE; - fg_color = text->rgba; + gdk_draw_rectangle (drawable, selection_gc, TRUE, + sel_rect.x, sel_rect.y, sel_rect.width, sel_rect.height); - gnome_canvas_buf_ensure_buf (buf); + gdk_region_union_with_rect (clip_region, &sel_rect); + } - lines = text->lines; - if ( !lines ) - return; + if (clip_rect) { + GdkRegion *rect_region = gdk_region_rectangle (clip_rect); + gdk_region_intersect (clip_region, rect_region); + gdk_region_destroy (rect_region); + } - start_i.y = get_line_ypos_item_relative (text); + gdk_gc_set_clip_region (text_gc, clip_region); + gdk_draw_layout (drawable, text_gc, + xpos, ypos, + text->layout); - art_affine_scale (affine, item->canvas->pixels_per_unit, item->canvas->pixels_per_unit); - for (i = 0; i < 6; i++) - affine[i] = text->affine[i]; + gdk_gc_set_clip_region (text_gc, NULL); + gdk_gc_set_clip_region (selection_gc, NULL); + + gdk_region_destroy (clip_region); + g_free (ranges); + } else { + if (text->show_cursor) { + PangoRectangle strong_pos, weak_pos; + pango_layout_get_cursor_pos (text->layout, text->selection_start, &strong_pos, &weak_pos); + draw_pango_rectangle (drawable, main_gc, xpos, ypos, strong_pos); + if (strong_pos.x != weak_pos.x || + strong_pos.y != weak_pos.y || + strong_pos.width != weak_pos.width || + strong_pos.height != weak_pos.height) + draw_pango_rectangle (drawable, main_gc, xpos, ypos, weak_pos); - for (i = 0; i < text->num_lines; i++) { - if (lines->length != 0) { - start_i.x = get_line_xpos_item_relative (text, lines); - art_affine_point (&start_c, &start_i, text->affine); - xpos = start_c.x; - ypos = start_c.y; - - for (j = 0; j < lines->length; j++) { - ETextSuckChar *ch; - - ch = &suckfont->chars[(unsigned char)((lines->text)[j])]; - - affine[4] = xpos; - affine[5] = ypos; - art_rgb_bitmap_affine ( - buf->buf, - buf->rect.x0, buf->rect.y0, buf->rect.x1, buf->rect.y1, - buf->buf_rowstride, - suckfont->bitmap + (ch->bitmap_offset >> 3), - ch->width, - suckfont->bitmap_height, - suckfont->bitmap_width >> 3, - fg_color, - affine, - ART_FILTER_NEAREST, NULL); - - dx = ch->left_sb + ch->width + ch->right_sb; - xpos += dx * affine[0]; - ypos += dx * affine[1]; } } + } - dy = text->font->ascent + text->font->descent; - start_i.y += dy; - lines++; + if (text->clip) { + gdk_gc_set_clip_rectangle (main_gc, NULL); } +} - buf->is_bg = 0; -#endif +/* Render handler for the text item */ +static void +e_text_render (GnomeCanvasItem *item, GnomeCanvasBuf *buf) +{ } /* Point handler for the text item */ static double e_text_point (GnomeCanvasItem *item, double x, double y, - int cx, int cy, GnomeCanvasItem **actual_item) + int cx, int cy, GnomeCanvasItem **actual_item) { EText *text; - int i; - struct line *lines; - int x1, y1, x2, y2; - int font_height; - int dx, dy; - double dist, best; + double clip_width; + double clip_height; text = E_TEXT (item); @@ -2136,106 +1889,35 @@ e_text_point (GnomeCanvasItem *item, double x, double y, * Otherwise, calculate the distance to the nearest rectangle. */ - if (text->font) - font_height = e_font_height (text->font); + if (text->clip_width < 0) + clip_width = text->width; else - font_height = 0; + clip_width = text->clip_width; - best = 1.0e36; + if ( text->clip_height < 0 ) + clip_height = text->height; + else + clip_height = text->clip_height; - lines = text->lines; + /* Get canvas pixel coordinates for clip rectangle position */ + clip_width = clip_width * item->canvas->pixels_per_unit; + clip_height = clip_height * item->canvas->pixels_per_unit; - if ( !lines ) { - text->needs_split_into_lines = 1; - e_canvas_item_request_reflow (item); + if (cx < text->clip_cx || + cx > text->clip_cx + clip_width || + cy < text->clip_cy || + cy > text->clip_cy + clip_height) return 1; - } - - if (text->fill_clip_rectangle) { - double clip_width; - double clip_height; - - if (text->clip_width < 0) - clip_width = text->max_width; - else - clip_width = text->clip_width; - - /* Get canvas pixel coordinates for clip rectangle position */ - clip_width = clip_width * item->canvas->pixels_per_unit; - if ( text->clip_height >= 0 ) - clip_height = text->clip_height * item->canvas->pixels_per_unit; - else - clip_height = text->height * item->canvas->pixels_per_unit; - if (cx >= text->clip_cx && - cx <= text->clip_cx + clip_width && - cy >= text->clip_cy && - cy <= text->clip_cy + clip_height) - return 0; - else - return 1; - } - - for (i = 0; i < text->num_lines; i++) { - /* Compute the coordinates of rectangle for the current line, - * clipping if appropriate. - */ - - x1 = get_line_xpos (text, lines); - y1 = text->cy + i * font_height; - x2 = x1 + lines->width; - y2 = y1 + font_height; - - if (text->clip) { - if (x1 < text->clip_cx) - x1 = text->clip_cx; - - if (y1 < text->clip_cy) - y1 = text->clip_cy; - - if ( text->clip_width >= 0 ) { - if (x2 > (text->clip_cx + text->clip_width)) - x2 = text->clip_cx + text->clip_width; - } - - if ( text->clip_height >= 0 ) { - if (y2 > (text->clip_cy + text->clip_height)) - y2 = text->clip_cy + text->clip_height; - } - - if ((x1 >= x2) || (y1 >= y2)) - continue; - } - - /* Calculate distance from point to rectangle */ - - if (cx < x1) - dx = x1 - cx; - else if (cx >= x2) - dx = cx - x2 + 1; - else - dx = 0; - - if (cy < y1) - dy = y1 - cy; - else if (cy >= y2) - dy = cy - y2 + 1; - else - dy = 0; - - if ((dx == 0) && (dy == 0)) - return 0.0; - - dist = sqrt (dx * dx + dy * dy); - if (dist < best) - best = dist; + if (text->fill_clip_rectangle) + return 0; - /* Next! */ + cx -= text->cx; - lines++; - } + if (pango_layout_xy_to_index (text->layout, cx, cy, NULL, NULL)) + return 0; - return best / item->canvas->pixels_per_unit; + return 1; } /* Bounds handler for the text item */ @@ -2250,16 +1932,19 @@ e_text_bounds (GnomeCanvasItem *item, double *x1, double *y1, double *x2, double *x1 = 0; *y1 = 0; + width = text->width; + height = text->height; + if (text->clip) { - width = text->clip_width; + if (text->clip_width >= 0) + width = text->clip_width; if ( text->clip_height >= 0 ) height = text->clip_height; - else height = text->height; - } else { - width = text->max_width / item->canvas->pixels_per_unit; - height = text->height / item->canvas->pixels_per_unit; } + width = width / item->canvas->pixels_per_unit; + height = height / item->canvas->pixels_per_unit; + switch (text->anchor) { case GTK_ANCHOR_NW: case GTK_ANCHOR_W: @@ -2302,140 +1987,31 @@ e_text_bounds (GnomeCanvasItem *item, double *x1, double *y1, double *x2, double *y2 = *y1 + height; } -static gboolean -_get_xy_from_position (EText *text, gint position, gint *xp, gint *yp) -{ - if (text->lines && (xp || yp)) { - struct line *lines = NULL; - int x, y; - double xd, yd; - int j; - x = get_line_xpos_item_relative (text, lines); - y = text->yofs; - y -= text->yofs_edit; - for (j = 0, lines = text->lines; j < text->num_lines; lines++, j++) { - if (lines->text > text->text + position) - break; - y += e_font_height (text->font); - } - lines --; - y -= e_font_descent (text->font); - - x += text_width_with_objects (text->model, - text->font, text->style, - lines->text, - position - (lines->text - text->text)); - x -= text->xofs_edit; - - xd = x; yd = y; - gnome_canvas_item_i2w (GNOME_CANVAS_ITEM(text), &xd, &yd); - gnome_canvas_w2c (GNOME_CANVAS_ITEM(text)->canvas, xd, yd, &x, &y); - - if (xp) - *xp = x; - if (yp) - *yp = y; - - return TRUE; - } - - return FALSE; -} - static gint -_get_position_from_xy (EText *text, gint x, gint y) +get_position_from_xy (EText *text, gint x, gint y) { - int i, j; - int ypos = text->yofs; - int xpos; - double xd, yd; - const char *p; - gunichar unival; - gint font_ht, adjust=0; - struct line *lines; - - xd = x; yd = y; - gnome_canvas_c2w (GNOME_CANVAS_ITEM(text)->canvas, xd, yd, &xd, &yd); - gnome_canvas_item_w2i (GNOME_CANVAS_ITEM(text), &xd, &yd); - x = xd; y = yd; + int index; + int trailing; - y += text->yofs_edit; - font_ht = e_font_height (text->font); - - if (text->draw_borders) - ypos += BORDER_INDENT; - - switch (text->anchor) { - case GTK_ANCHOR_WEST: - case GTK_ANCHOR_CENTER: - case GTK_ANCHOR_EAST: - y += (text->num_lines * font_ht)/2; - break; - case GTK_ANCHOR_SOUTH: - case GTK_ANCHOR_SOUTH_EAST: - case GTK_ANCHOR_SOUTH_WEST: - y += text->num_lines * font_ht; - default: - /* Do nothing */ - break; - } - - - j = 0; - while (y > ypos) { - ypos += font_ht; - j ++; + if (text->draw_borders) { + x -= BORDER_INDENT; + y -= BORDER_INDENT; } - j--; - if (j >= text->num_lines) - j = text->num_lines - 1; - if (j < 0) - j = 0; - i = 0; - lines = text->lines; - - if ( !lines ) - return 0; - lines += j; - x += text->xofs_edit; - xpos = get_line_xpos_item_relative (text, lines); + x -= text->xofs; + y -= text->yofs; - for (i = 0, p = lines->text; p && i < lines->length; i++, p = e_unicode_get_utf8 (p, &unival)) { - int charwidth; - int step1, step2; + if (text->editing) { + x += text->xofs_edit; + y += text->yofs_edit; + } -#if 0 - if (unival == '\1') { - const gchar *obj_str = NULL; /*e_text_model_get_nth_object (text->model, object_num);*/ - charwidth = e_font_utf8_text_width (text->font, text->style, obj_str, strlen (obj_str)); - ++object_num; + x -= text->cx; + y -= text->cy; - step1 = charwidth; - step2 = 0; - adjust = -1; + pango_layout_xy_to_index (text->layout, x * PANGO_SCALE, y * PANGO_SCALE, &index, &trailing); - } else { -#endif - charwidth = e_font_utf8_char_width (text->font, text->style, (gchar *) p); - - step1 = charwidth / 2; - step2 = (charwidth + 1) / 2; - adjust = 0; -#if 0 - } -#endif - - xpos += step1; - if (xpos > x) { - break; - } - xpos += step2; - } - - if (!p) return 0; - - return MAX (p - text->text + adjust, 0); + return g_utf8_offset_to_pointer (text->text + index, trailing) - text->text; } #define SCROLL_WAIT_TIME 30000 @@ -2459,47 +2035,50 @@ _blink_scroll_timeout (gpointer data) current_time < text->scroll_start) scroll = TRUE; } - if (scroll && text->button_down) { - if (text->lastx - text->clip_cx > text->clip_cwidth && - text->xofs_edit < text->max_width - text->clip_cwidth) { + if (scroll && text->button_down && text->clip) { + int old_xofs_edit = text->xofs_edit; + int old_yofs_edit = text->yofs_edit; + + if (text->clip_cwidth >= 0 && + text->lastx - text->clip_cx > text->clip_cwidth && + text->xofs_edit < text->width - text->clip_cwidth) { text->xofs_edit += 4; - if (text->xofs_edit > text->max_width - text->clip_cwidth + 1) - text->xofs_edit = text->max_width - text->clip_cwidth + 1; - redraw = TRUE; + if (text->xofs_edit > text->width - text->clip_cwidth + 1) + text->xofs_edit = text->width - text->clip_cwidth + 1; } if (text->lastx - text->clip_cx < 0 && text->xofs_edit > 0) { text->xofs_edit -= 4; if (text->xofs_edit < 0) text->xofs_edit = 0; - redraw = TRUE; } - if (text->lasty - text->clip_cy > text->clip_cheight && + if (text->clip_cheight >= 0 && + text->lasty - text->clip_cy > text->clip_cheight && text->yofs_edit < text->height - text->clip_cheight) { text->yofs_edit += 4; if (text->yofs_edit > text->height - text->clip_cheight + 1) text->yofs_edit = text->height - text->clip_cheight + 1; - redraw = TRUE; } if (text->lasty - text->clip_cy < 0 && text->yofs_edit > 0) { text->yofs_edit -= 4; if (text->yofs_edit < 0) text->yofs_edit = 0; - redraw = TRUE; } - if (redraw) { + if (old_xofs_edit != text->xofs_edit || + old_yofs_edit != text->yofs_edit) { ETextEventProcessorEvent e_tep_event; e_tep_event.type = GDK_MOTION_NOTIFY; e_tep_event.motion.state = text->last_state; e_tep_event.motion.time = 0; - e_tep_event.motion.position = _get_position_from_xy(text, text->lastx, text->lasty); + e_tep_event.motion.position = get_position_from_xy(text, text->lastx, text->lasty); _get_tep(text); e_text_event_processor_handle_event (text->tep, &e_tep_event); text->scroll_start = current_time; + redraw = TRUE; } } @@ -2902,7 +2481,7 @@ e_text_event (GnomeCanvasItem *item, GdkEvent *event) e_tep_event.button.time = button.time; e_tep_event.button.state = button.state; e_tep_event.button.button = button.button; - e_tep_event.button.position = _get_position_from_xy(text, button.x, button.y); + e_tep_event.button.position = get_position_from_xy(text, button.x, button.y); _get_tep(text); return_val = e_text_event_processor_handle_event (text->tep, &e_tep_event); @@ -2923,7 +2502,7 @@ e_text_event (GnomeCanvasItem *item, GdkEvent *event) g_signal_emit (text, e_text_signals[E_TEXT_POPUP], 0, &(event->button), - _get_position_from_xy (text, event->button.x, event->button.y)); + get_position_from_xy (text, event->button.x, event->button.y)); break; } @@ -2951,7 +2530,7 @@ e_text_event (GnomeCanvasItem *item, GdkEvent *event) e_tep_event.button.time = button.time; e_tep_event.button.state = button.state; e_tep_event.button.button = button.button; - e_tep_event.button.position = _get_position_from_xy(text, button.x, button.y); + e_tep_event.button.position = get_position_from_xy(text, button.x, button.y); _get_tep(text); return_val = e_text_event_processor_handle_event (text->tep, &e_tep_event); @@ -2971,7 +2550,7 @@ e_text_event (GnomeCanvasItem *item, GdkEvent *event) GdkEventMotion motion = event->motion; e_tep_event.motion.time = motion.time; e_tep_event.motion.state = motion.state; - e_tep_event.motion.position = _get_position_from_xy(text, motion.x, motion.y); + e_tep_event.motion.position = get_position_from_xy(text, motion.x, motion.y); _get_tep(text); return_val = e_text_event_processor_handle_event (text->tep, &e_tep_event); @@ -3076,7 +2655,8 @@ _get_position(EText *text, ETextEventProcessorCommand *command) gunichar unival; char *p = NULL; gint new_pos = 0; - + int index, trailing; + switch (command->position) { case E_TEP_VALUE: @@ -3187,16 +2767,38 @@ _get_position(EText *text, ETextEventProcessorCommand *command) break; case E_TEP_FORWARD_LINE: - if (_get_xy_from_position(text, text->selection_end, &x, &y)) { - y += e_font_height (text->font); - new_pos = _get_position_from_xy(text, x, y); + pango_layout_move_cursor_visually (text->layout, + TRUE, + text->selection_end, 0, + 1, + &index, &trailing); + index = g_utf8_offset_to_pointer (text->text + index, trailing) - text->text; + if (index < 0) { + new_pos = 0; + } else { + length = strlen (text->text); + if (index >= length) + new_pos = length; + else + new_pos = index; } break; case E_TEP_BACKWARD_LINE: - if (_get_xy_from_position(text, text->selection_end, &x, &y)) { - y -= e_font_height (text->font); - new_pos = _get_position_from_xy(text, x, y); + pango_layout_move_cursor_visually (text->layout, + TRUE, + text->selection_end, 0, + -1, + &index, &trailing); + index = g_utf8_offset_to_pointer (text->text + index, trailing) - text->text; + if (index < 0) { + new_pos = 0; + } else { + length = strlen (text->text); + if (index >= length) + new_pos = length; + else + new_pos = index; } break; @@ -3383,7 +2985,7 @@ e_text_command(ETextEventProcessor *tep, ETextEventProcessorCommand *command, gp { EText *text = E_TEXT(data); int sel_start, sel_end; - gboolean scroll = TRUE; + gboolean changed = TRUE; switch (command->action) { case E_TEP_MOVE: @@ -3440,7 +3042,7 @@ e_text_command(ETextEventProcessor *tep, ETextEventProcessorCommand *command, gp if (text->timer) { g_timer_reset(text->timer); } - scroll = FALSE; + changed = FALSE; break; case E_TEP_PASTE: e_text_get_selection (text, clipboard_atom, command->time); @@ -3468,13 +3070,13 @@ e_text_command(ETextEventProcessor *tep, ETextEventProcessorCommand *command, gp command->time, NULL, NULL); - scroll = FALSE; + changed = FALSE; break; case E_TEP_UNGRAB: e_canvas_item_ungrab (E_CANVAS (GNOME_CANVAS_ITEM(text)->canvas), GNOME_CANVAS_ITEM(text), command->time); - scroll = FALSE; + changed = FALSE; break; case E_TEP_CAPS: if (text->selection_start == text->selection_end) { @@ -3486,51 +3088,23 @@ e_text_command(ETextEventProcessor *tep, ETextEventProcessorCommand *command, gp } break; case E_TEP_NOP: - scroll = FALSE; + changed = FALSE; break; } - if (scroll && !text->button_down) { - int x; - int i; - struct line *lines = text->lines; - gdouble clip_width; - if ( !lines ) - return; - for (lines = text->lines, i = 0; i < text->num_lines ; i++, lines ++) { - if ((lines->text - text->text) > text->selection_end) { - break; - } - } - lines --; - i --; - x = text_width_with_objects (text->model, - text->font, text->style, - lines->text, - text->selection_end - (lines->text - text->text)); - + if (changed && !text->button_down) { + PangoRectangle strong_pos, weak_pos; - if (x < text->xofs_edit) { - text->xofs_edit = x; - } + pango_layout_get_cursor_pos (text->layout, text->selection_end, &strong_pos, &weak_pos); - clip_width = text->clip_width; - if (clip_width >= 0 && text->draw_borders) { - clip_width -= 6; - if (clip_width < 0) - clip_width = 0; - } + if (strong_pos.x != weak_pos.x || + strong_pos.y != weak_pos.y || + strong_pos.width != weak_pos.width || + strong_pos.height != weak_pos.height) + show_pango_rectangle (text, weak_pos); - if (2 + x - clip_width > text->xofs_edit) { - text->xofs_edit = 2 + x - clip_width; - } - - if (e_font_height (text->font) * i < text->yofs_edit) - text->yofs_edit = e_font_height (text->font) * i; - - if (e_font_height (text->font) * (i + 1) - (text->clip_height != -1 ? text->clip_height : text->height) > text->yofs_edit) - text->yofs_edit = e_font_height (text->font) * (i + 1) - (text->clip_height != -1 ? text->clip_height : text->height); + show_pango_rectangle (text, strong_pos); } text->needs_redraw = 1; @@ -3868,109 +3442,6 @@ e_text_real_paste_clipboard (EText *text) } #endif - -#if 0 -/* Routines for sucking fonts from the X server */ - -static ETextSuckFont * -e_suck_font (GdkFont *font) -{ - ETextSuckFont *suckfont; - int i; - int x, y; - char text[1]; - int lbearing, rbearing, ch_width, ascent, descent; - GdkPixmap *pixmap; - GdkColor black, white; - GdkImage *image; - GdkGC *gc; - guchar *line; - int width, height; - int black_pixel, pixel; - - if (!font) - return NULL; - - suckfont = g_new (ETextSuckFont, 1); - - height = font->ascent + font->descent; - x = 0; - for (i = 0; i < 256; i++) { - text[0] = i; - gdk_text_extents (font, text, 1, - &lbearing, &rbearing, &ch_width, &ascent, &descent); - suckfont->chars[i].left_sb = lbearing; - suckfont->chars[i].right_sb = ch_width - rbearing; - suckfont->chars[i].width = rbearing - lbearing; - suckfont->chars[i].ascent = ascent; - suckfont->chars[i].descent = descent; - suckfont->chars[i].bitmap_offset = x; - x += (ch_width + 31) & -32; - } - - width = x; - - suckfont->bitmap_width = width; - suckfont->bitmap_height = height; - suckfont->ascent = font->ascent; - - pixmap = gdk_pixmap_new (NULL, suckfont->bitmap_width, - suckfont->bitmap_height, 1); - gc = gdk_gc_new (pixmap); - gdk_gc_set_font (gc, font); - - black_pixel = BlackPixel (gdk_display, DefaultScreen (gdk_display)); - black.pixel = black_pixel; - white.pixel = WhitePixel (gdk_display, DefaultScreen (gdk_display)); - gdk_gc_set_foreground (gc, &white); - gdk_draw_rectangle (pixmap, gc, 1, 0, 0, width, height); - - gdk_gc_set_foreground (gc, &black); - for (i = 0; i < 256; i++) { - text[0] = i; - gdk_draw_text (pixmap, font, gc, - suckfont->chars[i].bitmap_offset - suckfont->chars[i].left_sb, - font->ascent, - text, 1); - } - - /* The handling of the image leaves me with distinct unease. But this - * is more or less copied out of gimp/app/text_tool.c, so it _ought_ to - * work. -RLL - */ - - image = gdk_image_get (pixmap, 0, 0, width, height); - suckfont->bitmap = g_malloc0 ((width >> 3) * height); - - line = suckfont->bitmap; - for (y = 0; y < height; y++) { - for (x = 0; x < width; x++) { - pixel = gdk_image_get_pixel (image, x, y); - if (pixel == black_pixel) - line[x >> 3] |= 128 >> (x & 7); - } - line += width >> 3; - } - - gdk_image_destroy (image); - - /* free the pixmap */ - gdk_pixmap_unref (pixmap); - - /* free the gc */ - gdk_gc_destroy (gc); - - return suckfont; -} - -static void -e_suck_font_free (ETextSuckFont *suckfont) -{ - g_free (suckfont->bitmap); - g_free (suckfont); -} -#endif - /* Class initialization function for the text item */ static void e_text_class_init (ETextClass *klass) @@ -4162,10 +3633,11 @@ e_text_class_init (ETextClass *klass) G_PARAM_READWRITE)); g_object_class_install_property (object_class, PROP_FILL_COLOR_GDK, - g_param_spec_pointer ("fill_color_gdk", - _( "GDK fill color" ), - _( "GDK fill color" ), - G_PARAM_READWRITE)); + g_param_spec_boxed ("fill_color_gdk", + _( "GDK fill color" ), + _( "GDK fill color" ), + GDK_TYPE_COLOR, + G_PARAM_READWRITE)); g_object_class_install_property (object_class, PROP_FILL_COLOR_RGBA, @@ -4179,7 +3651,7 @@ e_text_class_init (ETextClass *klass) g_param_spec_object ("fill_stipple", _( "Fill stipple" ), _( "FIll stipple" ), - GDK_TYPE_WINDOW, + GDK_TYPE_DRAWABLE, G_PARAM_READWRITE)); g_object_class_install_property (object_class, PROP_TEXT_WIDTH, @@ -4300,6 +3772,7 @@ e_text_init (EText *text) { text->model = e_text_model_new (); text->text = e_text_model_get_text (text->model); + text->layout = NULL; text->revert = NULL; diff --git a/widgets/text/e-text.h b/widgets/text/e-text.h index 32d3e539b4..9529962c37 100644 --- a/widgets/text/e-text.h +++ b/widgets/text/e-text.h @@ -134,6 +134,7 @@ struct _EText { gint model_repos_signal_id; const gchar *text; /* Text to display --- from the ETextModel */ + PangoLayout *layout; gpointer lines; /* Text split into lines (private field) */ int num_lines; /* Number of lines of text */ @@ -157,6 +158,7 @@ struct _EText { GdkGC *gc; /* GC for drawing text */ int cx, cy; /* Top-left canvas coordinates for text */ + int text_cx, text_cy; /* Top-left canvas coordinates for text */ int clip_cx, clip_cy; /* Top-left canvas coordinates for clip rectangle */ int clip_cwidth, clip_cheight; /* Size of clip rectangle in pixels */ int max_width; /* Maximum width of text lines */ @@ -218,6 +220,7 @@ struct _EText { guint needs_calc_height : 1; /* Need calc_height */ guint needs_calc_line_widths : 1; /* Needs calc_line_widths */ guint needs_split_into_lines : 1; /* Needs split_into_lines */ + guint needs_reset_layout : 1; /* Needs split_into_lines */ guint bold : 1; guint strikeout : 1; |