diff options
-rw-r--r-- | ChangeLog | 30 | ||||
-rw-r--r-- | ChangeLog.pre-1-0 | 30 | ||||
-rw-r--r-- | ChangeLog.pre-1-10 | 30 | ||||
-rw-r--r-- | ChangeLog.pre-1-2 | 30 | ||||
-rw-r--r-- | ChangeLog.pre-1-4 | 30 | ||||
-rw-r--r-- | ChangeLog.pre-1-6 | 30 | ||||
-rw-r--r-- | ChangeLog.pre-1-8 | 30 | ||||
-rw-r--r-- | TODO | 9 | ||||
-rw-r--r-- | pango/pango-attributes.c | 94 | ||||
-rw-r--r-- | pango/pango-attributes.h | 41 | ||||
-rw-r--r-- | pango/pango-layout.c | 463 | ||||
-rw-r--r-- | pango/pango-layout.h | 60 | ||||
-rw-r--r-- | pango/pangox.c | 8 |
13 files changed, 807 insertions, 78 deletions
@@ -1,3 +1,33 @@ +Mon Apr 17 12:04:20 2000 Owen Taylor <otaylor@redhat.com> + + * pango/pango-layout.[ch]: Add a function pango_layout_line_get_x_ranges(), + to allow handling selections not as attributes. Which is necessary, + since currently setting the background/foreground results in + splitting shaped runs. + +Fri Apr 14 13:20:05 2000 Owen Taylor <otaylor@redhat.com> + + * pango/pango-layout.c (pango_layout_check_lines): Fix bug with + indent handling. + + * pango/pango-layout.c (process_item): Never break a line at + a non-break position, even if that position ends an item. + +Fri Apr 14 10:43:09 2000 Owen Taylor <otaylor@redhat.com> + + * pango/pangox.c (pango_x_render_layout_line): Fix a missing + PANGO_SCALE factor for UNDERLINE_SINGLE. + + * pango/pango-layout.c (pango_layout_get_cursor_pos): New function + to determine cursor positions corresponding to a particular + index. + +Wed Apr 12 15:44:22 2000 Owen Taylor <otaylor@redhat.com> + + * pango/pango-attributes.[ch]: Add PANGO_ATTR_FONT_DESC, which + allows an entire font description to be specified as a single + attribute, instead of as 6 separate attributes. + Wed Apr 12 13:59:22 2000 Owen Taylor <otaylor@redhat.com> * configure.in modules/Makefile.am modules/devanagari/*: Added Devanagari diff --git a/ChangeLog.pre-1-0 b/ChangeLog.pre-1-0 index 5436a11e..3086e653 100644 --- a/ChangeLog.pre-1-0 +++ b/ChangeLog.pre-1-0 @@ -1,3 +1,33 @@ +Mon Apr 17 12:04:20 2000 Owen Taylor <otaylor@redhat.com> + + * pango/pango-layout.[ch]: Add a function pango_layout_line_get_x_ranges(), + to allow handling selections not as attributes. Which is necessary, + since currently setting the background/foreground results in + splitting shaped runs. + +Fri Apr 14 13:20:05 2000 Owen Taylor <otaylor@redhat.com> + + * pango/pango-layout.c (pango_layout_check_lines): Fix bug with + indent handling. + + * pango/pango-layout.c (process_item): Never break a line at + a non-break position, even if that position ends an item. + +Fri Apr 14 10:43:09 2000 Owen Taylor <otaylor@redhat.com> + + * pango/pangox.c (pango_x_render_layout_line): Fix a missing + PANGO_SCALE factor for UNDERLINE_SINGLE. + + * pango/pango-layout.c (pango_layout_get_cursor_pos): New function + to determine cursor positions corresponding to a particular + index. + +Wed Apr 12 15:44:22 2000 Owen Taylor <otaylor@redhat.com> + + * pango/pango-attributes.[ch]: Add PANGO_ATTR_FONT_DESC, which + allows an entire font description to be specified as a single + attribute, instead of as 6 separate attributes. + Wed Apr 12 13:59:22 2000 Owen Taylor <otaylor@redhat.com> * configure.in modules/Makefile.am modules/devanagari/*: Added Devanagari diff --git a/ChangeLog.pre-1-10 b/ChangeLog.pre-1-10 index 5436a11e..3086e653 100644 --- a/ChangeLog.pre-1-10 +++ b/ChangeLog.pre-1-10 @@ -1,3 +1,33 @@ +Mon Apr 17 12:04:20 2000 Owen Taylor <otaylor@redhat.com> + + * pango/pango-layout.[ch]: Add a function pango_layout_line_get_x_ranges(), + to allow handling selections not as attributes. Which is necessary, + since currently setting the background/foreground results in + splitting shaped runs. + +Fri Apr 14 13:20:05 2000 Owen Taylor <otaylor@redhat.com> + + * pango/pango-layout.c (pango_layout_check_lines): Fix bug with + indent handling. + + * pango/pango-layout.c (process_item): Never break a line at + a non-break position, even if that position ends an item. + +Fri Apr 14 10:43:09 2000 Owen Taylor <otaylor@redhat.com> + + * pango/pangox.c (pango_x_render_layout_line): Fix a missing + PANGO_SCALE factor for UNDERLINE_SINGLE. + + * pango/pango-layout.c (pango_layout_get_cursor_pos): New function + to determine cursor positions corresponding to a particular + index. + +Wed Apr 12 15:44:22 2000 Owen Taylor <otaylor@redhat.com> + + * pango/pango-attributes.[ch]: Add PANGO_ATTR_FONT_DESC, which + allows an entire font description to be specified as a single + attribute, instead of as 6 separate attributes. + Wed Apr 12 13:59:22 2000 Owen Taylor <otaylor@redhat.com> * configure.in modules/Makefile.am modules/devanagari/*: Added Devanagari diff --git a/ChangeLog.pre-1-2 b/ChangeLog.pre-1-2 index 5436a11e..3086e653 100644 --- a/ChangeLog.pre-1-2 +++ b/ChangeLog.pre-1-2 @@ -1,3 +1,33 @@ +Mon Apr 17 12:04:20 2000 Owen Taylor <otaylor@redhat.com> + + * pango/pango-layout.[ch]: Add a function pango_layout_line_get_x_ranges(), + to allow handling selections not as attributes. Which is necessary, + since currently setting the background/foreground results in + splitting shaped runs. + +Fri Apr 14 13:20:05 2000 Owen Taylor <otaylor@redhat.com> + + * pango/pango-layout.c (pango_layout_check_lines): Fix bug with + indent handling. + + * pango/pango-layout.c (process_item): Never break a line at + a non-break position, even if that position ends an item. + +Fri Apr 14 10:43:09 2000 Owen Taylor <otaylor@redhat.com> + + * pango/pangox.c (pango_x_render_layout_line): Fix a missing + PANGO_SCALE factor for UNDERLINE_SINGLE. + + * pango/pango-layout.c (pango_layout_get_cursor_pos): New function + to determine cursor positions corresponding to a particular + index. + +Wed Apr 12 15:44:22 2000 Owen Taylor <otaylor@redhat.com> + + * pango/pango-attributes.[ch]: Add PANGO_ATTR_FONT_DESC, which + allows an entire font description to be specified as a single + attribute, instead of as 6 separate attributes. + Wed Apr 12 13:59:22 2000 Owen Taylor <otaylor@redhat.com> * configure.in modules/Makefile.am modules/devanagari/*: Added Devanagari diff --git a/ChangeLog.pre-1-4 b/ChangeLog.pre-1-4 index 5436a11e..3086e653 100644 --- a/ChangeLog.pre-1-4 +++ b/ChangeLog.pre-1-4 @@ -1,3 +1,33 @@ +Mon Apr 17 12:04:20 2000 Owen Taylor <otaylor@redhat.com> + + * pango/pango-layout.[ch]: Add a function pango_layout_line_get_x_ranges(), + to allow handling selections not as attributes. Which is necessary, + since currently setting the background/foreground results in + splitting shaped runs. + +Fri Apr 14 13:20:05 2000 Owen Taylor <otaylor@redhat.com> + + * pango/pango-layout.c (pango_layout_check_lines): Fix bug with + indent handling. + + * pango/pango-layout.c (process_item): Never break a line at + a non-break position, even if that position ends an item. + +Fri Apr 14 10:43:09 2000 Owen Taylor <otaylor@redhat.com> + + * pango/pangox.c (pango_x_render_layout_line): Fix a missing + PANGO_SCALE factor for UNDERLINE_SINGLE. + + * pango/pango-layout.c (pango_layout_get_cursor_pos): New function + to determine cursor positions corresponding to a particular + index. + +Wed Apr 12 15:44:22 2000 Owen Taylor <otaylor@redhat.com> + + * pango/pango-attributes.[ch]: Add PANGO_ATTR_FONT_DESC, which + allows an entire font description to be specified as a single + attribute, instead of as 6 separate attributes. + Wed Apr 12 13:59:22 2000 Owen Taylor <otaylor@redhat.com> * configure.in modules/Makefile.am modules/devanagari/*: Added Devanagari diff --git a/ChangeLog.pre-1-6 b/ChangeLog.pre-1-6 index 5436a11e..3086e653 100644 --- a/ChangeLog.pre-1-6 +++ b/ChangeLog.pre-1-6 @@ -1,3 +1,33 @@ +Mon Apr 17 12:04:20 2000 Owen Taylor <otaylor@redhat.com> + + * pango/pango-layout.[ch]: Add a function pango_layout_line_get_x_ranges(), + to allow handling selections not as attributes. Which is necessary, + since currently setting the background/foreground results in + splitting shaped runs. + +Fri Apr 14 13:20:05 2000 Owen Taylor <otaylor@redhat.com> + + * pango/pango-layout.c (pango_layout_check_lines): Fix bug with + indent handling. + + * pango/pango-layout.c (process_item): Never break a line at + a non-break position, even if that position ends an item. + +Fri Apr 14 10:43:09 2000 Owen Taylor <otaylor@redhat.com> + + * pango/pangox.c (pango_x_render_layout_line): Fix a missing + PANGO_SCALE factor for UNDERLINE_SINGLE. + + * pango/pango-layout.c (pango_layout_get_cursor_pos): New function + to determine cursor positions corresponding to a particular + index. + +Wed Apr 12 15:44:22 2000 Owen Taylor <otaylor@redhat.com> + + * pango/pango-attributes.[ch]: Add PANGO_ATTR_FONT_DESC, which + allows an entire font description to be specified as a single + attribute, instead of as 6 separate attributes. + Wed Apr 12 13:59:22 2000 Owen Taylor <otaylor@redhat.com> * configure.in modules/Makefile.am modules/devanagari/*: Added Devanagari diff --git a/ChangeLog.pre-1-8 b/ChangeLog.pre-1-8 index 5436a11e..3086e653 100644 --- a/ChangeLog.pre-1-8 +++ b/ChangeLog.pre-1-8 @@ -1,3 +1,33 @@ +Mon Apr 17 12:04:20 2000 Owen Taylor <otaylor@redhat.com> + + * pango/pango-layout.[ch]: Add a function pango_layout_line_get_x_ranges(), + to allow handling selections not as attributes. Which is necessary, + since currently setting the background/foreground results in + splitting shaped runs. + +Fri Apr 14 13:20:05 2000 Owen Taylor <otaylor@redhat.com> + + * pango/pango-layout.c (pango_layout_check_lines): Fix bug with + indent handling. + + * pango/pango-layout.c (process_item): Never break a line at + a non-break position, even if that position ends an item. + +Fri Apr 14 10:43:09 2000 Owen Taylor <otaylor@redhat.com> + + * pango/pangox.c (pango_x_render_layout_line): Fix a missing + PANGO_SCALE factor for UNDERLINE_SINGLE. + + * pango/pango-layout.c (pango_layout_get_cursor_pos): New function + to determine cursor positions corresponding to a particular + index. + +Wed Apr 12 15:44:22 2000 Owen Taylor <otaylor@redhat.com> + + * pango/pango-attributes.[ch]: Add PANGO_ATTR_FONT_DESC, which + allows an entire font description to be specified as a single + attribute, instead of as 6 separate attributes. + Wed Apr 12 13:59:22 2000 Owen Taylor <otaylor@redhat.com> * configure.in modules/Makefile.am modules/devanagari/*: Added Devanagari @@ -25,6 +25,15 @@ string and produces lines of glyphs. * optimize right alignment for width == -1 and only a single line. (Currently this causes a useless call to gtk_layout_get_extents.) +* There is currently a serious problem in that every attribute + causes items to be broken into separately shaped runs. That means + that selections can't be handled as background/foreground attributes. + + Since, for selections, you need to be able to select partial + glyphs, doing this any different would basically mean having to + separate out these attributes from the rest of the attributes, + and handle them separately while rendering a layout. + X rendering =========== diff --git a/pango/pango-attributes.c b/pango/pango-attributes.c index f7618906..905c71c8 100644 --- a/pango/pango-attributes.c +++ b/pango/pango-attributes.c @@ -425,6 +425,62 @@ pango_attr_stretch_new (PangoStretch stretch) return pango_attr_int_new (&klass, (int)stretch); } +static PangoAttribute * +pango_attr_font_desc_copy (const PangoAttribute *attr) +{ + const PangoAttrFontDesc *desc_attr = (const PangoAttrFontDesc *)attr; + + return pango_attr_font_desc_new (&desc_attr->desc); +} + +static void +pango_attr_font_desc_destroy (PangoAttribute *attr) +{ + PangoAttrFontDesc *desc_attr = (PangoAttrFontDesc *)attr; + + g_free (desc_attr->desc.family_name); + g_free (attr); +} + +static gboolean +pango_attr_font_desc_compare (const PangoAttribute *attr1, + const PangoAttribute *attr2) +{ + const PangoAttrFontDesc *desc_attr1 = (const PangoAttrFontDesc *)attr1; + const PangoAttrFontDesc *desc_attr2 = (const PangoAttrFontDesc *)attr2; + + return pango_font_description_compare (&desc_attr1->desc, &desc_attr2->desc); +} + +/** + * pango_attr_font_desc_new: + * @desc: + * + * Create a new font description attribute. (This attribute + * allows setting family, style, weight, variant, stretch, + * and size simultaneously.) + * + * Return value: + **/ +PangoAttribute * +pango_attr_font_desc_new (const PangoFontDescription *desc) +{ + static const PangoAttrClass klass = { + PANGO_ATTR_FONT_DESC, + pango_attr_font_desc_copy, + pango_attr_font_desc_destroy, + pango_attr_font_desc_compare + }; + + PangoAttrFontDesc *result = g_new (PangoAttrFontDesc, 1); + result->attr.klass = &klass; + result->desc = *desc; + result->desc.family_name = g_strdup (desc->family_name); + + return (PangoAttribute *)result; +} + + /** * pango_attr_underline_new: * @underline: the underline style. @@ -923,6 +979,40 @@ pango_attr_iterator_get_font (PangoAttrIterator *iterator, switch (attr->klass->type) { + case PANGO_ATTR_FONT_DESC: + { + if (!have_family) + { + have_family = TRUE; + current->family_name = ((PangoAttrFontDesc *)attr)->desc.family_name; + } + if (!have_style) + { + have_style = TRUE; + current->style = ((PangoAttrFontDesc *)attr)->desc.style; + } + if (!have_variant) + { + have_variant = TRUE; + current->variant = ((PangoAttrFontDesc *)attr)->desc.variant; + } + if (!have_weight) + { + have_weight = TRUE; + current->weight = ((PangoAttrFontDesc *)attr)->desc.weight; + } + if (!have_stretch) + { + have_stretch = TRUE; + current->stretch = ((PangoAttrFontDesc *)attr)->desc.stretch; + } + if (!have_size) + { + have_size = TRUE; + current->size = ((PangoAttrFontDesc *)attr)->desc.size; + } + } + case PANGO_ATTR_FAMILY: if (!have_family) { @@ -989,7 +1079,3 @@ pango_attr_iterator_get_font (PangoAttrIterator *iterator, } } } - - - - diff --git a/pango/pango-attributes.h b/pango/pango-attributes.h index 19b9b638..a0af8975 100644 --- a/pango/pango-attributes.h +++ b/pango/pango-attributes.h @@ -34,6 +34,7 @@ typedef struct _PangoAttrClass PangoAttrClass; typedef struct _PangoAttrString PangoAttrString; typedef struct _PangoAttrInt PangoAttrInt; typedef struct _PangoAttrColor PangoAttrColor; +typedef struct _PangoAttrFontDesc PangoAttrFontDesc; typedef struct _PangoAttrList PangoAttrList; typedef struct _PangoAttrIterator PangoAttrIterator; @@ -46,6 +47,7 @@ typedef enum { PANGO_ATTR_VARIANT, /* PangoAttrInt */ PANGO_ATTR_STRETCH, /* PangoAttrInt */ PANGO_ATTR_SIZE, /* PangoAttrSize */ + PANGO_ATTR_FONT_DESC, /* PangoAttrFontDesc */ PANGO_ATTR_FOREGROUND, /* PangoAttrColor */ PANGO_ATTR_BACKGROUND, /* PangoAttrColor */ PANGO_ATTR_UNDERLINE, /* PangoAttrInt */ @@ -95,6 +97,12 @@ struct _PangoAttrColor guint16 blue; }; +struct _PangoAttrFontDesc +{ + PangoAttribute attr; + PangoFontDescription desc; +}; + PangoAttrType pango_attr_type_register (const gchar *name); PangoAttribute * pango_attribute_copy (const PangoAttribute *attr); @@ -102,22 +110,23 @@ void pango_attribute_destroy (PangoAttribute *attr); gboolean pango_attribute_compare (const PangoAttribute *attr1, const PangoAttribute *attr2); -PangoAttribute *pango_attr_lang_new (const char *lang); -PangoAttribute *pango_attr_family_new (const char *family); -PangoAttribute *pango_attr_foreground_new (guint16 red, - guint16 green, - guint16 blue); -PangoAttribute *pango_attr_background_new (guint16 red, - guint16 green, - guint16 blue); -PangoAttribute *pango_attr_size_new (int size); -PangoAttribute *pango_attr_style_new (PangoStyle style); -PangoAttribute *pango_attr_weight_new (PangoWeight weight); -PangoAttribute *pango_attr_variant_new (PangoVariant variant); -PangoAttribute *pango_attr_stretch_new (PangoStretch stretch); -PangoAttribute *pango_attr_underline_new (PangoUnderline underline); -PangoAttribute *pango_attr_strikethrough_new (gboolean strikethrough); -PangoAttribute *pango_attr_rise_new (int rise); +PangoAttribute *pango_attr_lang_new (const char *lang); +PangoAttribute *pango_attr_family_new (const char *family); +PangoAttribute *pango_attr_foreground_new (guint16 red, + guint16 green, + guint16 blue); +PangoAttribute *pango_attr_background_new (guint16 red, + guint16 green, + guint16 blue); +PangoAttribute *pango_attr_size_new (int size); +PangoAttribute *pango_attr_style_new (PangoStyle style); +PangoAttribute *pango_attr_weight_new (PangoWeight weight); +PangoAttribute *pango_attr_variant_new (PangoVariant variant); +PangoAttribute *pango_attr_stretch_new (PangoStretch stretch); +PangoAttribute *pango_attr_font_desc_new (const PangoFontDescription *desc); +PangoAttribute *pango_attr_underline_new (PangoUnderline underline); +PangoAttribute *pango_attr_strikethrough_new (gboolean strikethrough); +PangoAttribute *pango_attr_rise_new (int rise); PangoAttrList * pango_attr_list_new (void); void pango_attr_list_ref (PangoAttrList *list); diff --git a/pango/pango-layout.c b/pango/pango-layout.c index 12076d33..bc031e89 100644 --- a/pango/pango-layout.c +++ b/pango/pango-layout.c @@ -38,6 +38,7 @@ struct _PangoLayout int length; /* length of text in bytes */ int width; /* wrap width, in device units */ int indent; /* amount by which first line should be shorter */ + int spacing; /* spacing between lines */ guint justify : 1; guint alignment : 2; @@ -156,7 +157,7 @@ pango_layout_unref (PangoLayout *layout) PangoContext * pango_layout_get_context (PangoLayout *layout) { - g_return_if_fail (layout != NULL); + g_return_val_if_fail (layout != NULL, NULL); return layout->context; } @@ -238,6 +239,41 @@ pango_layout_get_indent (PangoLayout *layout) } /** + * pango_layout_set_indent + * @layout: a #PangoLayout. + * @indent: the amount of spacing + * + * Sets the amount of spacing between the lines of the layout. + **/ +void +pango_layout_set_spacing (PangoLayout *layout, + int spacing) +{ + g_return_if_fail (layout != NULL); + + if (spacing != layout->spacing) + { + layout->spacing = spacing; + pango_layout_clear_lines (layout); + } +} + +/** + * pango_layout_get_spacing: + * @layout: a #PangoLayout + * + * Gets the amount of spacing between the lines of the layout. + * + * Return value: the spacing (in thousandths of a device unit) + **/ +int +pango_layout_get_spacing (PangoLayout *layout) +{ + g_return_val_if_fail (layout != NULL, 0); + return layout->spacing; +} + +/** * pango_layout_set_attributes: * @layout: a #PangoLayout * @attrs: a #PangoAttrList @@ -743,6 +779,154 @@ pango_layout_index_to_pos (PangoLayout *layout, } } +static PangoDirection +pango_layout_line_get_char_direction (PangoLayoutLine *layout_line, + int index) +{ + GSList *run_list; + + run_list = layout_line->runs; + while (run_list) + { + PangoLayoutRun *run = run_list->data; + + if (run->item->offset <= index && run->item->offset + run->item->length > index) + return run->item->analysis.level % 2 ? PANGO_DIRECTION_RTL : PANGO_DIRECTION_LTR; + + run_list = run_list->next; + } + + g_assert_not_reached (); + + return PANGO_DIRECTION_LTR; +} + +/** + * pango_layout_get_cursor_pos: + * @layout: a #PangoLayout + * @index: the byte index of the cursor + * @strong_pos: location to store the strong cursor position (may be %NULL) + * @weak_pos: location to store the weak cursor position (may be %NULL) + * + * Given an index within a layout, determine the positions that of the + * strong and weak cursors if the insertion point is at that + * index. The position of each cursor is stored as a zero-width + * rectangle. The strong cursor location is the location where + * characters of the directionality equal to the base direction of the + * layout are inserted. The weak cursor location is the location + * where characters of the directionality opposite to the base + * direction of the layout are inserted. + **/ +void +pango_layout_get_cursor_pos (PangoLayout *layout, + int index, + PangoRectangle *strong_pos, + PangoRectangle *weak_pos) +{ + PangoDirection base_dir; + PangoDirection dir1, dir2; + PangoRectangle logical_rect; + PangoLayoutLine *layout_line = NULL; /* Quiet GCC */ + int x1_trailing; + int x2; + GSList *tmp_list; + int width; + int x_offset; + int y_offset = 0; + int bytes_seen = 0; + + g_return_if_fail (layout != NULL); + g_return_if_fail (index >= 0 && index <= layout->length); + + base_dir = pango_context_get_base_dir (layout->context); + + pango_layout_check_lines (layout); + + width = layout->width; + if (width == -1 && layout->alignment != PANGO_ALIGN_LEFT) + { + pango_layout_get_extents (layout, NULL, &logical_rect); + width = logical_rect.width; + } + + /* Find the line */ + tmp_list = layout->lines; + while (tmp_list) + { + layout_line = tmp_list->data; + + pango_layout_line_get_extents (layout_line, NULL, &logical_rect); + layout_line = tmp_list->data; + + if (bytes_seen + layout_line->length > index) + break; + + tmp_list = tmp_list->next; + + if (tmp_list) /* Want last line of layout for trailing position */ + { + y_offset += logical_rect.height; + bytes_seen += layout_line->length; + } + } + + /* Examine the trailing edge of the character before the cursor */ + if (index == bytes_seen) + { + dir1 = base_dir; + x1_trailing = (base_dir == PANGO_DIRECTION_LTR) ? 0 : logical_rect.width; + } + else + { + gint prev_index = unicode_previous_utf8 (layout->text, layout->text + index) - layout->text; + dir1 = pango_layout_line_get_char_direction (layout_line, prev_index); + pango_layout_line_index_to_x (layout_line, prev_index, TRUE, &x1_trailing); + } + + /* Examine the leading edge of the character after the cursor */ + if (index == bytes_seen + layout_line->length) + { + dir2 = base_dir; + x2 = (base_dir == PANGO_DIRECTION_LTR) ? logical_rect.width : 0; + } + else + { + dir2 = pango_layout_line_get_char_direction (layout_line, index); + pango_layout_line_index_to_x (layout_line, index, FALSE, &x2); + } + + if (layout->alignment == PANGO_ALIGN_RIGHT) + x_offset = width - logical_rect.width; + else if (layout->alignment == PANGO_ALIGN_CENTER) + x_offset = (width - logical_rect.width) / 2; + else + x_offset = 0; + + if (strong_pos) + { + if (dir1 == base_dir) + strong_pos->x = x_offset + x1_trailing; + else + strong_pos->x = x_offset + x2; + + strong_pos->y = y_offset; + strong_pos->width = 0; + strong_pos->height = logical_rect.height; + } + + if (weak_pos) + { + if (dir1 == base_dir) + weak_pos->x = x_offset + x2; + else + weak_pos->x = x_offset + x1_trailing; + + weak_pos->y = y_offset; + weak_pos->width = 0; + weak_pos->height = logical_rect.height; + } +} + /** * pango_layout_get_extents: * @layout: a #PangoLayout @@ -889,11 +1073,25 @@ insert_run (PangoLayoutLine *line, PangoItem *item, PangoGlyphString *glyphs) line->length += item->length; } +static void +free_run (PangoLayoutRun *run, gboolean free_item) +{ + if (free_item) + { + pango_font_unref (run->item->analysis.font); + g_free (run->item); + } + + pango_glyph_string_free (run->glyphs); + g_free (run); +} + static gboolean process_item (PangoLayoutLine *line, PangoItem *item, const char *text, PangoLogAttr *log_attrs, + gboolean no_break_at_end, int *remaining_width) { PangoGlyphString *glyphs = pango_glyph_string_new (); @@ -909,11 +1107,15 @@ process_item (PangoLayoutLine *line, insert_run (line, item, glyphs); return TRUE; } - + + /* We special-case the case where the whole item fits. Removing this special + * case would simplify the code, speed up the break case, and wouldn't + * slow things down much for the non-break case. + */ pango_glyph_string_extents (glyphs, item->analysis.font, NULL, &logical_rect); width = logical_rect.width; - - if (logical_rect.width < *remaining_width) + + if (logical_rect.width < *remaining_width && !no_break_at_end) { *remaining_width -= width; insert_run (line, item, glyphs); @@ -1037,13 +1239,9 @@ get_para_log_attrs (const char *text, static void pango_layout_check_lines (PangoLayout *layout) { - GList *items, *tmp_list; const char *start; gboolean done = FALSE; - int para_chars, start_offset; - - PangoLayoutLine *line; - int remaining_width; + int start_offset; if (layout->lines) return; @@ -1056,9 +1254,16 @@ pango_layout_check_lines (PangoLayout *layout) start = layout->text; do { + PangoLayoutLine *line; + GList *items, *tmp_list; + gboolean last_cant_end = FALSE; + gboolean current_cant_end = FALSE; + int remaining_width; + int last_remaining_width = 0; /* Quiet GCC */ + const char *end = start; + int para_chars = 0; - para_chars = 0; while (end != layout->text + layout->length && *end != '\n') { end = unicode_next_utf8 (end); @@ -1081,7 +1286,7 @@ pango_layout_check_lines (PangoLayout *layout) get_para_log_attrs (start, items, layout->log_attrs + start_offset); line = pango_layout_line_new (layout); - remaining_width = (layout->indent >= 0) ? layout->width - layout->indent : layout->indent; + remaining_width = (layout->indent >= 0) ? layout->width - layout->indent : layout->width; tmp_list = items; while (tmp_list) @@ -1089,28 +1294,71 @@ pango_layout_check_lines (PangoLayout *layout) PangoItem *item = tmp_list->data; gboolean fits; int old_num_chars = item->num_chars; - - fits = process_item (line, item, start, layout->log_attrs + start_offset, &remaining_width); + + fits = process_item (line, item, start, + layout->log_attrs + start_offset, current_cant_end, + &remaining_width); + current_cant_end = FALSE; if (fits) { tmp_list = tmp_list->next; start_offset += old_num_chars; + + if (start_offset < layout->n_chars && !layout->log_attrs[start_offset].is_break) + last_cant_end = TRUE; + else + { + last_cant_end = FALSE; + last_remaining_width = remaining_width; + } } - - if (!fits) + else { - /* Complete line + /* Handle the case where the last item wasn't broken, but ended in a non-break + * and we didn't manage to get any of this item in the line. In that case + * we need to back up and break the last item. */ - line->runs = g_slist_reverse (line->runs); - pango_layout_line_reorder (line); - - layout->lines = g_slist_prepend (layout->lines, line); - - line = pango_layout_line_new (layout); - remaining_width = (layout->indent >= 0) ? layout->width : layout->indent + layout->indent; - start_offset += old_num_chars - item->num_chars; + if (last_cant_end && old_num_chars - item->num_chars == 0) + { + GSList *tmp_node; + + /* Back up + */ + tmp_list = tmp_list->prev; + item = tmp_list->data; + + start_offset -= item->num_chars; + remaining_width = last_remaining_width; + + current_cant_end = TRUE; + + /* Remove last run from line + */ + tmp_node = line->runs; + line->runs = tmp_node->next; + + free_run (tmp_node->data, FALSE); + g_slist_free_1 (tmp_node); + + line->length -= item->length; + } + else + { + line->runs = g_slist_reverse (line->runs); + pango_layout_line_reorder (line); + + layout->lines = g_slist_prepend (layout->lines, line); + + line = pango_layout_line_new (layout); + remaining_width = (layout->indent >= 0) ? layout->width : layout->indent + layout->indent; + + start_offset += old_num_chars - item->num_chars; + } + + last_cant_end = FALSE; + last_remaining_width = remaining_width; } } @@ -1174,16 +1422,9 @@ pango_layout_line_unref (PangoLayoutLine *line) if (private->ref_count == 0) { GSList *tmp_list = line->runs; - while (tmp_list) { - PangoLayoutRun *run = tmp_list->data; - - pango_font_unref (run->item->analysis.font); - g_free (run->item); - - pango_glyph_string_free (run->glyphs); - + free_run (tmp_list->data, TRUE); tmp_list = tmp_list->next; } @@ -1256,6 +1497,164 @@ pango_layout_line_x_to_index (PangoLayoutLine *line, } /** + * pango_layout_line_get_x_ranges: + * @line: a #PangoLayoutLine + * @start_index: Start byte index of the logical range. If this value + * is less than the start index for the line, then + * the first range will extend all the way to the leading + * edge of the layout. Otherwise it will start at the + * leading edge of the first character. + * @end_index: Ending byte index of the logical range. If this value + * is greater than the end index for the line, then + * the last range will extend all the way to the trailing + * edge of the layout. Otherwise, it will end at the + * trailing edge of the last character. + * @ranges: location to store a pointer to an array of arranges. + * The array will be of length 2*@n_ranges, with each + * range including the pixels from (*ranges)[2*n] to + * (*ranges)[2*n + 1] - 1. This array must be freed + * with g_free. + * @n_ranges: The number of ranges stored in @ranges. + * + * Get a list of visual ranges corresponding to a given logical range. + * This list is not necessarily minimal - there may be consecutive + * ranges which are adjacent. The ranges will be sorted from left to + * right. + **/ +void +pango_layout_line_get_x_ranges (PangoLayoutLine *line, + int start_index, + int end_index, + int **ranges, + int *n_ranges) +{ + PangoDirection base_dir; + PangoRectangle logical_rect; + gint line_start_index = 0; + GSList *tmp_list; + int range_count = 0; + int accumulated_width = 0; + int x_offset; + int width; + + g_return_if_fail (line != NULL); + g_return_if_fail (line->layout != NULL); + g_return_if_fail (start_index <= end_index); + + base_dir = pango_context_get_base_dir (line->layout->context); + + width = line->layout->width; + if (width == -1 && line->layout->alignment != PANGO_ALIGN_LEFT) + { + pango_layout_get_extents (line->layout, NULL, &logical_rect); + width = logical_rect.width; + } + + /* FIXME: The computations here could be optimized, by moving the + * computations of the x_offset after we go through and figure + * out where each range is. + */ + pango_layout_line_get_extents (line, NULL, &logical_rect); + + if (line->layout->alignment == PANGO_ALIGN_RIGHT) + x_offset = width - logical_rect.width; + else if (line->layout->alignment == PANGO_ALIGN_CENTER) + x_offset = (width - logical_rect.width) / 2; + else + x_offset = 0; + + tmp_list = line->layout->lines; + while (tmp_list->data != line) + { + line_start_index += ((PangoLayoutLine *)tmp_list->data)->length; + tmp_list = tmp_list->next; + } + + /* Allocate the maximum possible size */ + if (ranges) + *ranges = g_new (int, 2 * (2 + g_slist_length (line->runs))); + + if (x_offset > 0 && + ((base_dir == PANGO_DIRECTION_LTR && start_index < line_start_index) || + (base_dir == PANGO_DIRECTION_RTL && end_index > line_start_index + line->length))) + { + if (ranges) + { + (*ranges)[2*range_count] = 0; + (*ranges)[2*range_count + 1] = x_offset; + } + + range_count ++; + } + + tmp_list = line->runs; + while (tmp_list) + { + PangoLayoutRun *run = (PangoLayoutRun *)tmp_list->data; + + if ((start_index < run->item->offset + run->item->length && + end_index > run->item->offset)) + { + if (ranges) + { + int run_start_index = MAX (start_index, run->item->offset); + int run_end_index = MIN (end_index, run->item->offset + run->item->length); + int run_start_x, run_end_x; + + /* Back the end_index off one since we want to find the trailing edge of the preceding character */ + + run_end_index = unicode_previous_utf8 (line->layout->text, line->layout->text + run_end_index) - line->layout->text; + + pango_glyph_string_index_to_x (run->glyphs, + line->layout->text + run->item->offset, + run->item->length, + &run->item->analysis, + run_start_index - run->item->offset, FALSE, + &run_start_x); + pango_glyph_string_index_to_x (run->glyphs, + line->layout->text + run->item->offset, + run->item->length, + &run->item->analysis, + run_end_index - run->item->offset, TRUE, + &run_end_x); + + (*ranges)[2*range_count] = x_offset + accumulated_width + MIN (run_start_x, run_end_x); + (*ranges)[2*range_count + 1] = x_offset + accumulated_width + MAX (run_start_x, run_end_x); + } + + range_count++; + } + + if (tmp_list->next) + { + PangoRectangle run_logical; + + pango_glyph_string_extents (run->glyphs, run->item->analysis.font, + NULL, &run_logical); + accumulated_width += run_logical.width; + } + + tmp_list = tmp_list->next; + } + + if (x_offset + logical_rect.width < line->layout->width && + ((base_dir == PANGO_DIRECTION_LTR && end_index > line_start_index + line->length) || + (base_dir == PANGO_DIRECTION_RTL && start_index < line_start_index))) + { + if (ranges) + { + (*ranges)[2*range_count] = x_offset + logical_rect.width; + (*ranges)[2*range_count + 1] = line->layout->width; + } + + range_count ++; + } + + if (n_ranges) + *n_ranges = range_count; +} + +/** * pango_layout_line_get_extents: * @line: a #PangoLayoutLine * @ink_rect: rectangle used to store the extents of the glyph string as drawn diff --git a/pango/pango-layout.h b/pango/pango-layout.h index b1a9bf1e..02fef3b0 100644 --- a/pango/pango-layout.h +++ b/pango/pango-layout.h @@ -72,6 +72,9 @@ int pango_layout_get_width (PangoLayout *layout); void pango_layout_set_indent (PangoLayout *layout, int indent); int pango_layout_get_indent (PangoLayout *layout); +void pango_layout_set_spacing (PangoLayout *layout, + int spacing); +int pango_layout_get_spacing (PangoLayout *layout); void pango_layout_set_justify (PangoLayout *layout, gboolean justify); gboolean pango_layout_get_justify (PangoLayout *layout); @@ -85,36 +88,45 @@ void pango_layout_get_log_attrs (PangoLayout *layout, PangoLogAttr **attrs, gint *n_attrs); -void pango_layout_index_to_pos (PangoLayout *layout, - int index, - PangoRectangle *pos); -gboolean pango_layout_xy_to_index (PangoLayout *layout, - int x, - int y, - int *index, - gboolean *trailing); -void pango_layout_get_extents (PangoLayout *layout, - PangoRectangle *ink_rect, - PangoRectangle *logical_rect); +void pango_layout_index_to_pos (PangoLayout *layout, + int index, + PangoRectangle *pos); +void pango_layout_get_cursor_pos (PangoLayout *layout, + int index, + PangoRectangle *strong_pos, + PangoRectangle *weak_pos); +gboolean pango_layout_xy_to_index (PangoLayout *layout, + int x, + int y, + int *index, + gboolean *trailing); +void pango_layout_get_extents (PangoLayout *layout, + PangoRectangle *ink_rect, + PangoRectangle *logical_rect); int pango_layout_get_line_count (PangoLayout *layout); PangoLayoutLine *pango_layout_get_line (PangoLayout *layout, int line); GSList * pango_layout_get_lines (PangoLayout *layout); -void pango_layout_line_ref (PangoLayoutLine *line); -void pango_layout_line_unref (PangoLayoutLine *line); -gboolean pango_layout_line_x_to_index (PangoLayoutLine *line, - int x_pos, - int *index, - int *trailing); -void pango_layout_line_index_to_x (PangoLayoutLine *line, - int index, - gboolean trailing, - int *x_pos); -void pango_layout_line_get_extents (PangoLayoutLine *line, - PangoRectangle *ink_rect, - PangoRectangle *logical_rect); +void pango_layout_line_ref (PangoLayoutLine *line); +void pango_layout_line_unref (PangoLayoutLine *line); +gboolean pango_layout_line_x_to_index (PangoLayoutLine *line, + int x_pos, + int *index, + int *trailing); +void pango_layout_line_index_to_x (PangoLayoutLine *line, + int index, + gboolean trailing, + int *x_pos); +void pango_layout_line_get_x_ranges (PangoLayoutLine *line, + int start_index, + int end_index, + int **ranges, + int *n_ranges); +void pango_layout_line_get_extents (PangoLayoutLine *line, + PangoRectangle *ink_rect, + PangoRectangle *logical_rect); #ifdef __cplusplus } diff --git a/pango/pangox.c b/pango/pangox.c index f29708ec..520ae7fb 100644 --- a/pango/pangox.c +++ b/pango/pangox.c @@ -409,7 +409,11 @@ pango_x_font_map_load_font (PangoFontMap *fontmap, ((PangoXFont *)result)->entry = best_match; best_match->cached_fonts = g_slist_prepend (best_match->cached_fonts, result); } - + + /* HORRIBLE performance hack until some better caching scheme is arrived at + */ + if (result) + pango_font_ref (result); } } @@ -2393,7 +2397,7 @@ pango_x_render_layout_line (Display *display, /* Fall through */ case PANGO_UNDERLINE_SINGLE: XDrawLine (display, drawable, fg_gc, - x + (x_off + ink_rect.x) -1, y + 2, + x + (x_off + ink_rect.x) / PANGO_SCALE - 1, y + 2, x + (x_off + ink_rect.x + ink_rect.width) / PANGO_SCALE, y + 2); break; case PANGO_UNDERLINE_LOW: |