diff options
Diffstat (limited to 'pango/pango-layout.c')
-rw-r--r-- | pango/pango-layout.c | 115 |
1 files changed, 109 insertions, 6 deletions
diff --git a/pango/pango-layout.c b/pango/pango-layout.c index 7fa0f70a..9f465468 100644 --- a/pango/pango-layout.c +++ b/pango/pango-layout.c @@ -112,6 +112,21 @@ struct _PangoLayoutLinePrivate { PangoLayoutLine line; guint ref_count; + + /* Extents cache status: + * + * LEAKED means that the user has access to this line structure or a + * run included in this line, and so can change the glyphs/glyph-widths. + * If this is true, extents caching will be disabled. + */ + enum { + NOT_CACHED, + CACHED, + LEAKED + } cache_status; + + PangoRectangle ink_rect; + PangoRectangle logical_rect; }; struct _PangoLayoutClass @@ -156,6 +171,10 @@ static int *pango_layout_line_get_log2vis_map (PangoLayoutLine *line, gboolean strong); static int *pango_layout_line_get_vis2log_map (PangoLayoutLine *line, gboolean strong); +static void pango_layout_line_leaked (PangoLayoutLine *line); + +/* doesn't leak line */ +static PangoLayoutLine* _pango_layout_iter_get_line (PangoLayoutIter *iter); static void pango_layout_get_item_properties (PangoItem *item, ItemProperties *properties); @@ -1064,6 +1083,19 @@ GSList * pango_layout_get_lines (PangoLayout *layout) { pango_layout_check_lines (layout); + + if (layout->lines) + { + GSList *tmp_list = layout->lines; + while (tmp_list) + { + PangoLayoutLine *line = tmp_list->data; + tmp_list = tmp_list->next; + + pango_layout_line_leaked (line); + } + } + return layout->lines; } @@ -1092,9 +1124,17 @@ pango_layout_get_line (PangoLayout *layout, return NULL; pango_layout_check_lines (layout); + list_item = g_slist_nth (layout->lines, line); + if (list_item) - return list_item->data; + { + PangoLayoutLine *line = list_item->data; + + pango_layout_line_leaked (line); + return line; + } + return NULL; } @@ -1239,7 +1279,7 @@ pango_layout_index_to_line_and_extents (PangoLayout *layout, if (!ITER_IS_INVALID (iter)) while (TRUE) { - PangoLayoutLine *tmp_line = pango_layout_iter_get_line (iter); + PangoLayoutLine *tmp_line = _pango_layout_iter_get_line (iter); if (tmp_line->start_index > index) break; /* index was in paragraph delimiters */ @@ -1564,18 +1604,18 @@ pango_layout_xy_to_index (PangoLayout *layout, if (prev_line == NULL) outside = TRUE; /* off the top */ - found = pango_layout_iter_get_line (iter); + found = _pango_layout_iter_get_line (iter); found_line_x = x - line_logical.x; } } else if (y >= first_y && y < last_y) { - found = pango_layout_iter_get_line (iter); + found = _pango_layout_iter_get_line (iter); found_line_x = x - line_logical.x; } - prev_line = pango_layout_iter_get_line (iter); + prev_line = _pango_layout_iter_get_line (iter); prev_last = last_y; prev_line_x = x - line_logical.x; @@ -1638,7 +1678,7 @@ pango_layout_index_to_pos (PangoLayout *layout, { while (TRUE) { - PangoLayoutLine *tmp_line = pango_layout_iter_get_line (iter); + PangoLayoutLine *tmp_line = _pango_layout_iter_get_line (iter); if (tmp_line->start_index > index) { @@ -2381,6 +2421,14 @@ pango_layout_clear_lines (PangoLayout *layout) } } +static void +pango_layout_line_leaked (PangoLayoutLine *line) +{ + PangoLayoutLinePrivate *private = (PangoLayoutLinePrivate *)line; + + private->cache_status = LEAKED; +} + /************************************************ * Some functions for handling PANGO_ATTR_SHAPE * @@ -4096,14 +4144,41 @@ pango_layout_line_get_extents (PangoLayoutLine *line, PangoRectangle *ink_rect, PangoRectangle *logical_rect) { + PangoLayoutLinePrivate *private = (PangoLayoutLinePrivate *)line; GSList *tmp_list; int x_pos = 0; + gboolean caching = FALSE; g_return_if_fail (LINE_IS_VALID (line)); if (!LINE_IS_VALID (line)) return; + switch (private->cache_status) + { + case CACHED: + { + if (ink_rect) + *ink_rect = private->ink_rect; + if (logical_rect) + *logical_rect = private->logical_rect; + return; + } + case NOT_CACHED: + { + caching = TRUE; + if (!ink_rect) + ink_rect = &private->ink_rect; + if (!logical_rect) + logical_rect = &private->logical_rect; + break; + } + case LEAKED: + { + break; + } + } + if (ink_rect) { ink_rect->x = 0; @@ -4172,6 +4247,15 @@ pango_layout_line_get_extents (PangoLayoutLine *line, if (logical_rect && !line->runs) pango_layout_line_get_empty_extents (line, logical_rect); + + if (caching) + { + if (&private->ink_rect != ink_rect) + private->ink_rect = *ink_rect; + if (&private->logical_rect != logical_rect) + private->logical_rect = *logical_rect; + private->cache_status = CACHED; + } } static PangoLayoutLine * @@ -4183,6 +4267,7 @@ pango_layout_line_new (PangoLayout *layout) private->line.layout = layout; private->line.runs = NULL; private->line.length = 0; + private->cache_status = NOT_CACHED; /* Note that we leave start_index, resolved_dir, and is_paragraph_start * uninitialized */ @@ -4813,9 +4898,25 @@ pango_layout_iter_get_run (PangoLayoutIter *iter) if (ITER_IS_INVALID (iter)) return NULL; + pango_layout_line_leaked (iter->line); + return iter->run; } +/* an inline-able version for local use */ +static PangoLayoutLine* +_pango_layout_iter_get_line (PangoLayoutIter *iter) +{ + return iter->line; +} + +/* a private one for pango-renderer.c use */ +PangoLayoutLine* +_pango_layout_iter_get_line_readonly (PangoLayoutIter *iter) +{ + return iter->line; +} + /** * pango_layout_iter_get_line: * @iter: a #PangoLayoutIter @@ -4830,6 +4931,8 @@ pango_layout_iter_get_line (PangoLayoutIter *iter) if (ITER_IS_INVALID (iter)) return NULL; + pango_layout_line_leaked (iter->line); + return iter->line; } |