diff options
Diffstat (limited to 'pango/pango-layout.c')
-rw-r--r-- | pango/pango-layout.c | 114 |
1 files changed, 99 insertions, 15 deletions
diff --git a/pango/pango-layout.c b/pango/pango-layout.c index e0475a5e..2a3cb5a2 100644 --- a/pango/pango-layout.c +++ b/pango/pango-layout.c @@ -78,6 +78,7 @@ #include "pango-impl-utils.h" #include "pango-glyph-item.h" #include <string.h> +#include <math.h> #include "pango-layout-private.h" #include "pango-attributes-private.h" @@ -107,6 +108,8 @@ struct _ItemProperties gboolean shape_set; PangoRectangle *shape_ink_rect; PangoRectangle *shape_logical_rect; + double line_height; + int absolute_line_height; }; typedef struct _PangoLayoutLinePrivate PangoLayoutLinePrivate; @@ -177,7 +180,8 @@ static void pango_layout_line_postprocess (PangoLayoutLine *line, static void pango_layout_line_leaked (PangoLayoutLine *line); /* doesn't leak line */ -static PangoLayoutLine* _pango_layout_iter_get_line (PangoLayoutIter *iter); +static PangoLayoutLine * _pango_layout_iter_get_line (PangoLayoutIter *iter); +static PangoLayoutRun * _pango_layout_iter_get_run (PangoLayoutIter *iter); static void pango_layout_get_item_properties (PangoItem *item, ItemProperties *properties); @@ -587,9 +591,12 @@ pango_layout_get_indent (PangoLayout *layout) * The default value is 0. * * Note: Since 1.44, Pango is using the line height (as determined - * by the font) for placing lines when the line height factor is set + * by the font) for placing lines when the line spacing factor is set * to a non-zero value with [method@Pango.Layout.set_line_spacing]. * In that case, the @spacing set with this function is ignored. + * + * Note: for semantics that are closer to the CSS line-height + * property, see [func@Pango.attr_line_height_new]. */ void pango_layout_set_spacing (PangoLayout *layout, @@ -638,6 +645,9 @@ pango_layout_get_spacing (PangoLayout *layout) * * If @factor is zero (the default), spacing is applied as before. * + * Note: for semantics that are closer to the CSS line-height + * property, see [func@Pango.attr_line_height_new]. + * * Since: 1.44 */ void @@ -1793,7 +1803,8 @@ pango_layout_index_to_line (PangoLayout *layout, static PangoLayoutLine * pango_layout_index_to_line_and_extents (PangoLayout *layout, int index, - PangoRectangle *line_rect) + PangoRectangle *line_rect, + PangoRectangle *run_rect) { PangoLayoutIter iter; PangoLayoutLine *line = NULL; @@ -1813,7 +1824,26 @@ pango_layout_index_to_line_and_extents (PangoLayout *layout, pango_layout_iter_get_line_extents (&iter, NULL, line_rect); if (line->start_index + line->length > index) - break; + { + if (run_rect) + { + while (TRUE) + { + PangoLayoutRun *run = _pango_layout_iter_get_run (&iter); + + if (run->item->offset <= index && index < run->item->offset + run->item->length) + { + pango_layout_iter_get_run_extents (&iter, NULL, run_rect); + break; + } + + if (!pango_layout_iter_next_run (&iter)) + break; + } + } + + break; + } if (!pango_layout_iter_next_line (&iter)) break; /* Use end of last line */ @@ -2291,10 +2321,24 @@ pango_layout_index_to_pos (PangoLayout *layout, layout_line = tmp_line; - pango_layout_iter_get_line_extents (&iter, NULL, &logical_rect); - if (layout_line->start_index + layout_line->length > index) - break; + { + while (TRUE) + { + PangoLayoutRun *run = _pango_layout_iter_get_run (&iter); + + if (run->item->offset <= index && index < run->item->offset + run->item->length) + { + pango_layout_iter_get_run_extents (&iter, NULL, &logical_rect); + break; + } + + if (!pango_layout_iter_next_run (&iter)) + break; + } + + break; + } if (!pango_layout_iter_next_line (&iter)) { @@ -2367,7 +2411,7 @@ pango_layout_get_direction (PangoLayout *layout, { PangoLayoutLine *line; - line = pango_layout_index_to_line_and_extents (layout, index, NULL); + line = pango_layout_index_to_line_and_extents (layout, index, NULL, NULL); if (line) return pango_layout_line_get_char_direction (line, index); @@ -2400,6 +2444,7 @@ pango_layout_get_cursor_pos (PangoLayout *layout, PangoDirection dir1, dir2; int level1, level2; PangoRectangle line_rect; + PangoRectangle run_rect; PangoLayoutLine *layout_line = NULL; /* Quiet GCC */ int x1_trailing; int x2; @@ -2408,7 +2453,7 @@ pango_layout_get_cursor_pos (PangoLayout *layout, g_return_if_fail (index >= 0 && index <= layout->length); layout_line = pango_layout_index_to_line_and_extents (layout, index, - &line_rect); + &line_rect, &run_rect); g_assert (index >= layout_line->start_index); @@ -2457,9 +2502,9 @@ pango_layout_get_cursor_pos (PangoLayout *layout, else strong_pos->x += x2; - strong_pos->y = line_rect.y; + strong_pos->y = run_rect.y; strong_pos->width = 0; - strong_pos->height = line_rect.height; + strong_pos->height = run_rect.height; } if (weak_pos) @@ -2472,9 +2517,9 @@ pango_layout_get_cursor_pos (PangoLayout *layout, else weak_pos->x += x1_trailing; - weak_pos->y = line_rect.y; + weak_pos->y = run_rect.y; weak_pos->width = 0; - weak_pos->height = line_rect.height; + weak_pos->height = run_rect.height; } } @@ -4149,6 +4194,8 @@ affects_itemization (PangoAttribute *attr, case PANGO_ATTR_LETTER_SPACING: case PANGO_ATTR_SHAPE: case PANGO_ATTR_RISE: + case PANGO_ATTR_LINE_HEIGHT: + case PANGO_ATTR_ABSOLUTE_LINE_HEIGHT: return TRUE; default: return FALSE; @@ -5011,6 +5058,7 @@ static void pango_layout_run_get_extents_and_height (PangoLayoutRun *run, PangoRectangle *run_ink, PangoRectangle *run_logical, + PangoRectangle *line_logical, int *height) { PangoRectangle logical; @@ -5019,7 +5067,7 @@ pango_layout_run_get_extents_and_height (PangoLayoutRun *run, gboolean has_underline; gboolean has_overline; - if (G_UNLIKELY (!run_ink && !run_logical && !height)) + if (G_UNLIKELY (!run_ink && !run_logical && !line_logical && !height)) return; pango_layout_get_item_properties (run->item, &properties); @@ -5034,6 +5082,9 @@ pango_layout_run_get_extents_and_height (PangoLayoutRun *run, if (!run_logical && (has_underline || has_overline || properties.strikethrough)) run_logical = &logical; + if (!run_logical && line_logical) + run_logical = &logical; + if (properties.shape_set) _pango_shape_get_extents (run->item->num_chars, properties.shape_ink_rect, @@ -5104,6 +5155,7 @@ pango_layout_run_get_extents_and_height (PangoLayoutRun *run, if (!metrics) metrics = pango_font_get_metrics (run->item->analysis.font, run->item->analysis.language); + *height = pango_font_metrics_get_height (metrics); } @@ -5127,6 +5179,21 @@ pango_layout_run_get_extents_and_height (PangoLayoutRun *run, run_logical->y -= properties.rise; } + if (line_logical) + { + *line_logical = *run_logical; + + if (properties.absolute_line_height != 0 || properties.line_height != 0.0) + { + int line_height, leading; + + line_height = MAX (properties.absolute_line_height, ceilf (properties.line_height * line_logical->height)); + leading = line_height - line_logical->height; + line_logical->y -= leading / 2; + line_logical->height += leading; + } + } + if (metrics) pango_font_metrics_unref (metrics); } @@ -5206,6 +5273,7 @@ pango_layout_line_get_extents_and_height (PangoLayoutLine *line, pango_layout_run_get_extents_and_height (run, ink_rect ? &run_ink : NULL, + NULL, &run_logical, height ? &run_height : NULL); @@ -5985,6 +6053,8 @@ pango_layout_get_item_properties (PangoItem *item, properties->shape_set = FALSE; properties->shape_ink_rect = NULL; properties->shape_logical_rect = NULL; + properties->line_height = 0.0; + properties->absolute_line_height = 0; while (tmp_list) { @@ -6048,6 +6118,14 @@ pango_layout_get_item_properties (PangoItem *item, properties->shape_ink_rect = &((PangoAttrShape *)attr)->ink_rect; break; + case PANGO_ATTR_LINE_HEIGHT: + properties->line_height = ((PangoAttrFloat *)attr)->value; + break; + + case PANGO_ATTR_ABSOLUTE_LINE_HEIGHT: + properties->absolute_line_height = ((PangoAttrInt *)attr)->value; + break; + default: break; } @@ -6446,6 +6524,12 @@ _pango_layout_iter_get_line (PangoLayoutIter *iter) return iter->line; } +static PangoLayoutRun * +_pango_layout_iter_get_run (PangoLayoutIter *iter) +{ + return iter->run; +} + /** * pango_layout_iter_get_line: * @iter: a `PangoLayoutIter` @@ -6907,7 +6991,7 @@ pango_layout_iter_get_run_extents (PangoLayoutIter *iter, if (iter->run) { - pango_layout_run_get_extents_and_height (iter->run, ink_rect, logical_rect, NULL); + pango_layout_run_get_extents_and_height (iter->run, ink_rect, logical_rect, NULL, NULL); if (ink_rect) { |