From 342a0265b3992925105d04b1ef22cda6a7fa8786 Mon Sep 17 00:00:00 2001 From: Matthias Clasen Date: Tue, 25 Jan 2022 01:57:43 -0500 Subject: Rename PangoLayoutIter to PangoLineIter --- pango/meson.build | 4 +- pango/pango-attributes.c | 6 +- pango/pango-layout-iter-private.h | 5 - pango/pango-layout-iter.c | 884 -------------------------------------- pango/pango-layout-iter.h | 84 ---- pango/pango-layout.c | 6 +- pango/pango-layout.h | 2 +- pango/pango-line-iter-private.h | 5 + pango/pango-line-iter.c | 884 ++++++++++++++++++++++++++++++++++++++ pango/pango-line-iter.h | 84 ++++ pango/pango-line.c | 2 +- pango/pango-lines.c | 10 +- pango/pango-lines.h | 4 +- pango/pango-types.h | 2 +- pango/pango.h | 2 +- pango/pangowin32.c | 2 +- tests/test-bidi.c | 18 +- tests/testiter.c | 32 +- tests/testmisc.c | 26 +- utils/viewer-pangocairo.c | 56 +-- 20 files changed, 1058 insertions(+), 1060 deletions(-) delete mode 100644 pango/pango-layout-iter-private.h delete mode 100644 pango/pango-layout-iter.c delete mode 100644 pango/pango-layout-iter.h create mode 100644 pango/pango-line-iter-private.h create mode 100644 pango/pango-line-iter.c create mode 100644 pango/pango-line-iter.h diff --git a/pango/meson.build b/pango/meson.build index 4f603dc9..9cfc0400 100644 --- a/pango/meson.build +++ b/pango/meson.build @@ -35,7 +35,7 @@ pango_sources = [ 'pango-run.c', 'pango-line-breaker.c', 'pango-lines.c', - 'pango-layout-iter.c', + 'pango-line-iter.c', ] pango_headers = [ @@ -60,7 +60,7 @@ pango_headers = [ 'pango-line.h', 'pango-run.h', 'pango-line-breaker.h', - 'pango-layout-iter.h', + 'pango-line-iter.h', 'pango-lines.h', 'pango-layout.h', 'pango-matrix.h', diff --git a/pango/pango-attributes.c b/pango/pango-attributes.c index e3d5191f..6f50d3fe 100644 --- a/pango/pango-attributes.c +++ b/pango/pango-attributes.c @@ -1511,7 +1511,7 @@ pango_attr_overline_color_new (guint16 red, * * This affects the values returned by * [method@Pango.Line.get_extents] and - * [method@Pango.LayoutIter.get_line_extents]. + * [method@Pango.LineIter.get_line_extents]. * * * Since: 1.50 @@ -1537,7 +1537,7 @@ pango_attr_line_height_new (double factor) * * This affects the values returned by * [method@Pango.Line.get_extents], - * [method@Pango.LayoutIter.get_line_extents]. + * [method@Pango.LineIter.get_line_extents]. * * Since: 1.50 */ @@ -1563,7 +1563,7 @@ pango_attr_line_height_new_absolute (int height) * * This affects the values returned by * [method@Pango.Line.get_extents], - * [method@Pango.LayoutIter.get_line_extents]. + * [method@Pango.LineIter.get_line_extents]. */ PangoAttribute * pango_attr_line_spacing_new (int spacing) diff --git a/pango/pango-layout-iter-private.h b/pango/pango-layout-iter-private.h deleted file mode 100644 index 7cf69b30..00000000 --- a/pango/pango-layout-iter-private.h +++ /dev/null @@ -1,5 +0,0 @@ -#pragma once - -#include "pango-layout-iter.h" - -PangoLayoutIter * pango_layout_iter_new (PangoLines *lines); diff --git a/pango/pango-layout-iter.c b/pango/pango-layout-iter.c deleted file mode 100644 index 87b4ab77..00000000 --- a/pango/pango-layout-iter.c +++ /dev/null @@ -1,884 +0,0 @@ -#include "config.h" - -#include "pango-layout-iter-private.h" -#include "pango-lines-private.h" -#include "pango-line-private.h" -#include "pango-run-private.h" - -/** - * PangoLayoutIter: - * - * A `PangoLayoutIter` can be used to iterate over the visual - * extents of a `PangoLayout` or `PangoLines`. - * - * To obtain a `PangoLayoutIter`, use [method@Pango.Layout.get_iter] - * or [method@Pango.Lines.get_iter]. - * - * The `PangoLayoutIter` structure is opaque, and has no user-visible - * fields. - */ - - -/* {{{ PangoLayoutIter implementation */ - -struct _PangoLayoutIter -{ - PangoLines *lines; - guint serial; - - int line_no; - int line_x; - int line_y; - PangoLine *line; - GSList *run_link; - PangoRun *run; - int index; - - /* run handling */ - int run_x; - int run_width; - int end_x_offset; - gboolean ltr; - - /* cluster handling */ - int cluster_x; - int cluster_width; - int cluster_start; - int next_cluster_glyph; - int cluster_num_chars; - - int character_position; -}; - -G_DEFINE_BOXED_TYPE (PangoLayoutIter, pango_layout_iter, - pango_layout_iter_copy, pango_layout_iter_free); - - -/* }}} */ -/* {{{ Utilities */ - -#define ITER_IS_VALID(iter) ((iter)->serial == (iter)->lines->serial) - -static gboolean -line_is_terminated (PangoLayoutIter *iter) -{ - if (iter->line_no + 1 < pango_lines_get_line_count (iter->lines)) - return pango_line_is_paragraph_end (iter->line); - - return FALSE; - -} - -static int -next_cluster_start (PangoGlyphString *glyphs, - int cluster_start) -{ - int i; - - i = cluster_start + 1; - while (i < glyphs->num_glyphs) - { - if (glyphs->glyphs[i].attr.is_cluster_start) - return i; - - i++; - } - - return glyphs->num_glyphs; -} - -static int -cluster_width (PangoGlyphString *glyphs, - int cluster_start) -{ - int i; - int width; - - width = glyphs->glyphs[cluster_start].geometry.width; - i = cluster_start + 1; - while (i < glyphs->num_glyphs) - { - if (glyphs->glyphs[i].attr.is_cluster_start) - break; - - width += glyphs->glyphs[i].geometry.width; - i++; - } - - return width; -} - -/* Sets up the iter for the start of a new cluster. cluster_start_index - * is the byte index of the cluster start relative to the run. - */ -static void -update_cluster (PangoLayoutIter *iter, - int cluster_start_index) -{ - PangoGlyphItem *glyph_item; - char *cluster_text; - int cluster_length; - - glyph_item = pango_run_get_glyph_item (iter->run); - - iter->character_position = 0; - - iter->cluster_width = cluster_width (glyph_item->glyphs, iter->cluster_start); - iter->next_cluster_glyph = next_cluster_start (glyph_item->glyphs, iter->cluster_start); - - if (iter->ltr) - { - /* For LTR text, finding the length of the cluster is easy - * since logical and visual runs are in the same direction. - */ - if (iter->next_cluster_glyph < glyph_item->glyphs->num_glyphs) - cluster_length = glyph_item->glyphs->log_clusters[iter->next_cluster_glyph] - cluster_start_index; - else - cluster_length = glyph_item->item->length - cluster_start_index; - } - else - { - /* For RTL text, we have to scan backwards to find the previous - * visual cluster which is the next logical cluster. - */ - int i = iter->cluster_start; - while (i > 0 && glyph_item->glyphs->log_clusters[i - 1] == cluster_start_index) - i--; - - if (i == 0) - cluster_length = glyph_item->item->length - cluster_start_index; - else - cluster_length = glyph_item->glyphs->log_clusters[i - 1] - cluster_start_index; - } - - cluster_text = iter->line->data->text + glyph_item->item->offset + cluster_start_index; - iter->cluster_num_chars = g_utf8_strlen (cluster_text, cluster_length); - - if (iter->ltr) - iter->index = cluster_text - iter->line->data->text; - else - iter->index = g_utf8_prev_char (cluster_text + cluster_length) - iter->line->data->text; -} - -/* Moves to the next non-empty line. If @include_terminators - * is set, a line with just an explicit paragraph separator - * is considered non-empty. - */ -static gboolean -next_nonempty_line (PangoLayoutIter *iter, - gboolean include_terminators) -{ - gboolean result; - - while (TRUE) - { - result = pango_layout_iter_next_line (iter); - if (!result) - break; - - if (iter->line->runs) - break; - - if (include_terminators && line_is_terminated (iter)) - break; - } - - return result; -} - -/* Moves to the next non-empty run. If @include_terminators - * is set, the trailing run at the end of a line with an explicit - * paragraph separator is considered non-empty. - */ -static gboolean -next_nonempty_run (PangoLayoutIter *iter, - gboolean include_terminators) -{ - gboolean result; - - while (TRUE) - { - result = pango_layout_iter_next_run (iter); - if (!result) - break; - - if (iter->run) - break; - - if (include_terminators && line_is_terminated (iter)) - break; - } - - return result; -} - -/* Like pango_layout_next_cluster(), but if @include_terminators - * is set, includes the fake runs/clusters for empty lines. - * (But not positions introduced by line wrapping). - */ -static gboolean -next_cluster_internal (PangoLayoutIter *iter, - gboolean include_terminators) -{ - PangoGlyphItem *glyph_item; - - if (iter->run == NULL) - return next_nonempty_line (iter, include_terminators); - - glyph_item = pango_run_get_glyph_item (iter->run); - - if (iter->next_cluster_glyph == glyph_item->glyphs->num_glyphs) - { - return next_nonempty_run (iter, include_terminators); - } - else - { - iter->cluster_start = iter->next_cluster_glyph; - iter->cluster_x += iter->cluster_width; - update_cluster (iter, glyph_item->glyphs->log_clusters[iter->cluster_start]); - - return TRUE; - } -} - -static void -update_run (PangoLayoutIter *iter, - int start_index) -{ - PangoGlyphItem *glyph_item; - - if (iter->run) - glyph_item = pango_run_get_glyph_item (iter->run); - - if (iter->run_link == iter->line->runs) - iter->run_x = 0; - else - { - iter->run_x += iter->end_x_offset + iter->run_width; - if (iter->run) - iter->run_x += glyph_item->start_x_offset; - } - - if (iter->run) - { - iter->run_width = pango_glyph_string_get_width (glyph_item->glyphs); - iter->end_x_offset = glyph_item->end_x_offset; - } - else - { - /* The empty run at the end of a line */ - iter->run_width = 0; - iter->end_x_offset = 0; - } - - if (iter->run) - iter->ltr = (glyph_item->item->analysis.level % 2) == 0; - else - iter->ltr = TRUE; - - iter->cluster_start = 0; - iter->cluster_x = iter->run_x; - - if (iter->run) - { - update_cluster (iter, glyph_item->glyphs->log_clusters[0]); - } - else - { - iter->cluster_width = 0; - iter->character_position = 0; - iter->cluster_num_chars = 0; - iter->index = start_index; - } -} - -static inline void -offset_line (PangoLayoutIter *iter, - PangoRectangle *ink_rect, - PangoRectangle *logical_rect) -{ - if (ink_rect) - { - ink_rect->x += iter->line_x; - ink_rect->y += iter->line_y; - } - if (logical_rect) - { - logical_rect->x += iter->line_x; - logical_rect->y += iter->line_y; - } -} - -static inline void -offset_run (PangoLayoutIter *iter, - PangoRectangle *ink_rect, - PangoRectangle *logical_rect) -{ - if (ink_rect) - ink_rect->x += iter->run_x; - if (logical_rect) - logical_rect->x += iter->run_x; -} - -/* }}} */ -/* {{{ Private API */ - -PangoLayoutIter * -pango_layout_iter_new (PangoLines *lines) -{ - PangoLayoutIter *iter; - int run_start_index; - - g_return_val_if_fail (PANGO_IS_LINES (lines), NULL); - - iter = g_new0 (PangoLayoutIter, 1); - - iter->lines = g_object_ref (lines); - iter->serial = pango_lines_get_serial (lines); - - iter->line_no = 0; - iter->line = pango_lines_get_line (iter->lines, 0, &iter->line_x, &iter->line_y); - iter->run_link = pango_line_get_runs (iter->line); - if (iter->run_link) - { - iter->run = iter->run_link->data; - run_start_index = pango_run_get_glyph_item (iter->run)->item->offset; - } - else - { - iter->run = NULL; - run_start_index = 0; - } - - update_run (iter, run_start_index); - - return iter; -} - -/* }}} */ -/* {{{ Public API */ - -/** - * pango_layout_iter_copy: - * @iter: (nullable): a `PangoLayoutIter` - * - * Copies a `PangoLayoutIter`. - * - * Return value: (nullable): the newly allocated `PangoLayoutIter` - */ -PangoLayoutIter * -pango_layout_iter_copy (PangoLayoutIter *iter) -{ - PangoLayoutIter *copy; - - if (iter == NULL) - return NULL; - - copy = g_new0 (PangoLayoutIter, 1); - memcpy (iter, copy, sizeof (PangoLayoutIter)); - g_object_ref (copy->lines); - - return copy; -} - -/** - * pango_layout_iter_free: - * @iter: (nullable): a `PangoLayoutIter` - * - * Frees an iterator that's no longer in use. - */ -void -pango_layout_iter_free (PangoLayoutIter *iter) -{ - if (iter == NULL) - return; - - g_object_unref (iter->lines); - g_free (iter); -} - -/** - * pango_layout_iter_get_lines: - * @iter: a `PangoLayoutIter` - * - * Gets the `PangoLines` object associated with a `PangoLayoutIter`. - * - * Return value: (transfer none): the lines associated with @iter - */ -PangoLines * -pango_layout_iter_get_lines (PangoLayoutIter *iter) -{ - return iter->lines; -} - -/** - * pango_layout_iter_get_line: - * @iter: a `PangoLayoutIter` - * - * Gets the current line. - * - * Return value: (transfer none): the current line - */ -PangoLine * -pango_layout_iter_get_line (PangoLayoutIter *iter) -{ - g_return_val_if_fail (ITER_IS_VALID (iter), NULL); - - return iter->line; -} - -/** - * pango_layout_iter_at_last_line: - * @iter: a `PangoLayoutIter` - * - * Determines whether @iter is on the last line. - * - * Return value: %TRUE if @iter is on the last line - */ -gboolean -pango_layout_iter_at_last_line (PangoLayoutIter *iter) -{ - g_return_val_if_fail (ITER_IS_VALID (iter), FALSE); - - return iter->line_no + 1 == pango_lines_get_line_count (iter->lines); -} - -/** - * pango_layout_iter_get_run: - * @iter: a `PangoLayoutIter` - * - * Gets the current run. - * - * When iterating by run, at the end of each line, there's a position - * with a %NULL run, so this function can return %NULL. The %NULL run - * at the end of each line ensures that all lines have at least one run, - * even lines consisting of only a newline. - * - * Return value: (transfer none) (nullable): the current run - */ -PangoRun * -pango_layout_iter_get_run (PangoLayoutIter *iter) -{ - g_return_val_if_fail (ITER_IS_VALID (iter), NULL); - - return iter->run; -} - -/** - * pango_layout_iter_get_index: - * @iter: a `PangoLayoutIter` - * - * Gets the current byte index. - * - * The byte index is relative to the text backing the current - * line. - * - * Note that iterating forward by char moves in visual order, - * not logical order, so indexes may not be sequential. Also, - * the index may be equal to the length of the text in the - * layout, if on the %NULL run (see [method@Pango.LayoutIter.get_run]). - * - * Return value: current byte index - */ -int -pango_layout_iter_get_index (PangoLayoutIter *iter) -{ - g_return_val_if_fail (ITER_IS_VALID (iter), 0); - - return iter->index; -} - -/** - * pango_layout_iter_next_line: - * @iter: a `PangoLayoutIter` - * - * Moves @iter forward to the start of the next line. - * - * If @iter is already on the last line, returns %FALSE. - * - * Return value: whether motion was possible - */ -gboolean -pango_layout_iter_next_line (PangoLayoutIter *iter) -{ - g_return_val_if_fail (ITER_IS_VALID (iter), FALSE); - - iter->line = pango_lines_get_line (iter->lines, iter->line_no + 1, &iter->line_x, &iter->line_y); - if (!iter->line) - return FALSE; - - iter->line_no++; - iter->run_link = pango_line_get_runs (iter->line); - if (iter->run_link) - iter->run = iter->run_link->data; - else - iter->run = NULL; - - update_run (iter, iter->line->start_index); - - return TRUE; -} - -/** - * pango_layout_iter_next_run: - * @iter: a `PangoLayoutIter` - * - * Moves @iter forward to the next run in visual order. - * - * If @iter was already at the end, returns %FALSE. - * - * Return value: whether motion was possible - */ -gboolean -pango_layout_iter_next_run (PangoLayoutIter *iter) -{ - int run_start_index; - - g_return_val_if_fail (ITER_IS_VALID (iter), FALSE); - - if (iter->run == NULL) - return pango_layout_iter_next_line (iter); - - iter->run_link = iter->run_link->next; - if (iter->run_link == NULL) - { - PangoItem *item = pango_run_get_glyph_item (iter->run)->item; - run_start_index = item->offset + item->length; - iter->run = NULL; - } - else - { - iter->run = iter->run_link->data; - run_start_index = pango_run_get_glyph_item (iter->run)->item->offset; - } - - update_run (iter, run_start_index); - - return TRUE; -} - -/** - * pango_layout_iter_next_cluster: - * @iter: a `PangoLayoutIter` - * - * Moves @iter forward to the next cluster in visual order. - * - * If @iter was already at the end, returns %FALSE. - * - * Return value: whether motion was possible - */ -gboolean -pango_layout_iter_next_cluster (PangoLayoutIter *iter) -{ - g_return_val_if_fail (ITER_IS_VALID (iter), FALSE); - - return next_cluster_internal (iter, FALSE); -} - -/** - * pango_layout_iter_next_char: - * @iter: a `PangoLayoutIter` - * - * Moves @iter forward to the next character in visual order. - * - * If @iter was already at the end, returns %FALSE. - * - * Return value: whether motion was possible - */ -gboolean -pango_layout_iter_next_char (PangoLayoutIter *iter) -{ - const char *text; - - g_return_val_if_fail (ITER_IS_VALID (iter), FALSE); - - if (iter->run == NULL) - { - /* We need to fake an iterator position in the middle of a \r\n line terminator */ - if (line_is_terminated (iter) && - strncmp (iter->line->data->text + iter->line->start_index + iter->line->length, "\r\n", 2) == 0 && - iter->character_position == 0) - { - iter->character_position++; - - return TRUE; - } - - return next_nonempty_line (iter, TRUE); - } - - iter->character_position++; - - if (iter->character_position >= iter->cluster_num_chars) - return next_cluster_internal (iter, TRUE); - - text = iter->line->data->text; - if (iter->ltr) - iter->index = g_utf8_next_char (text + iter->index) - text; - else - iter->index = g_utf8_prev_char (text + iter->index) - text; - - return TRUE; -} - -/** - * pango_layout_iter_get_layout_extents: - * @iter: a `PangoLayoutIter` - * @ink_rect: (out) (optional): rectangle to fill with ink extents - * @logical_rect: (out) (optional): rectangle to fill with logical extents - * - * Obtains the extents of the `PangoLines` being iterated over. - */ -void -pango_layout_iter_get_layout_extents (PangoLayoutIter *iter, - PangoRectangle *ink_rect, - PangoRectangle *logical_rect) -{ - g_return_if_fail (ITER_IS_VALID (iter)); - - pango_lines_get_extents (iter->lines, ink_rect, logical_rect); -} - -/** - * pango_layout_iter_get_line_extents: - * @iter: a `PangoLayoutIter` - * @ink_rect: (out) (optional): rectangle to fill with ink extents - * @logical_rect: (out) (optional): rectangle to fill with logical extents - * - * Obtains the extents of the current line. - * - * Extents are in layout coordinates (origin is the top-left corner of the - * entire `PangoLines`). Thus the extents returned by this function will be - * the same width/height but not at the same x/y as the extents returned - * from [method@Pango.Line.get_extents]. - * - * The logical extents returned by this function always have their leading - * trimmed according to paragraph boundaries: if the line starts a paragraph, - * it has its start leading trimmed; if it ends a paragraph, it has its end - * leading trimmed. If you need other trimming, use - * [method@Pango.Line.get_trimmed_extents]. - */ -void -pango_layout_iter_get_line_extents (PangoLayoutIter *iter, - PangoRectangle *ink_rect, - PangoRectangle *logical_rect) -{ - g_return_if_fail (ITER_IS_VALID (iter)); - - pango_line_get_extents (iter->line, ink_rect, logical_rect); - offset_line (iter, ink_rect, logical_rect); -} - -void -pango_layout_iter_get_trimmed_line_extents (PangoLayoutIter *iter, - PangoLeadingTrim trim, - PangoRectangle *logical_rect) -{ - g_return_if_fail (ITER_IS_VALID (iter)); - - pango_line_get_trimmed_extents (iter->line, trim, logical_rect); - offset_line (iter, NULL, logical_rect); -} - -/** - * pango_layout_iter_get_run_extents: - * @iter: a `PangoLayoutIter` - * @ink_rect: (out) (optional): rectangle to fill with ink extents - * @logical_rect: (out) (optional): rectangle to fill with logical extents - * - * Gets the extents of the current run in layout coordinates. - * - * Layout coordinates have the origin at the top left of the entire `PangoLines`. - * - * The logical extents returned by this function always have their leading - * trimmed off. If you need extents that include leading, use - * [method@Pango.Run.get_extents]. - */ -void -pango_layout_iter_get_run_extents (PangoLayoutIter *iter, - PangoRectangle *ink_rect, - PangoRectangle *logical_rect) -{ - g_return_if_fail (ITER_IS_VALID (iter)); - - if (iter->run) - { - pango_run_get_extents (iter->run, PANGO_LEADING_TRIM_BOTH, ink_rect, logical_rect); - } - else - { - GSList *runs = pango_line_get_runs (iter->line); - if (runs) - { - /* Virtual run at the end of a nonempty line */ - PangoRun *run = g_slist_last (runs)->data; - - pango_run_get_extents (run, PANGO_LEADING_TRIM_BOTH, ink_rect, logical_rect); - if (ink_rect) - ink_rect->width = 0; - if (logical_rect) - logical_rect->width = 0; - } - else - { - /* Empty line */ - PangoRectangle r; - - pango_line_get_empty_extents (iter->line, PANGO_LEADING_TRIM_BOTH, &r); - - if (ink_rect) - *ink_rect = r; - - if (logical_rect) - *logical_rect = r; - } - } - - offset_line (iter, ink_rect, logical_rect); - offset_run (iter, ink_rect, logical_rect); -} - -/** - * pango_layout_iter_get_cluster_extents: - * @iter: a `PangoLayoutIter` - * @ink_rect: (out) (optional): rectangle to fill with ink extents - * @logical_rect: (out) (optional): rectangle to fill with logical extents - * - * Gets the extents of the current cluster, in layout coordinates. - * - * Layout coordinates have the origin at the top left of the entire `PangoLines`. - */ -void -pango_layout_iter_get_cluster_extents (PangoLayoutIter *iter, - PangoRectangle *ink_rect, - PangoRectangle *logical_rect) -{ - PangoGlyphItem *glyph_item; - - g_return_if_fail (ITER_IS_VALID (iter)); - - if (iter->run == NULL) - { - /* When on the NULL run, all extents are the same */ - pango_layout_iter_get_run_extents (iter, ink_rect, logical_rect); - return; - } - - glyph_item = pango_run_get_glyph_item (iter->run); - - pango_glyph_string_extents_range (glyph_item->glyphs, - iter->cluster_start, - iter->next_cluster_glyph, - glyph_item->item->analysis.font, - ink_rect, - logical_rect); - - offset_line (iter, ink_rect, logical_rect); - if (ink_rect) - { - ink_rect->x += iter->cluster_x + glyph_item->start_x_offset; - ink_rect->y -= glyph_item->y_offset; - } - - if (logical_rect) - { - g_assert (logical_rect->width == iter->cluster_width); - logical_rect->x += iter->cluster_x + glyph_item->start_x_offset; - logical_rect->y -= glyph_item->y_offset; - } -} - -/** - * pango_layout_iter_get_char_extents: - * @iter: a `PangoLayoutIter` - * @logical_rect: (out caller-allocates): rectangle to fill with logical extents - * - * Gets the extents of the current character, in layout coordinates. - * - * Layout coordinates have the origin at the top left of the entire `PangoLines`. - * - * Only logical extents can sensibly be obtained for characters; - * ink extents make sense only down to the level of clusters. - */ -void -pango_layout_iter_get_char_extents (PangoLayoutIter *iter, - PangoRectangle *logical_rect) -{ - PangoRectangle cluster_rect; - int x0, x1; - - g_return_if_fail (ITER_IS_VALID (iter)); - - if (logical_rect == NULL) - return; - - pango_layout_iter_get_cluster_extents (iter, NULL, &cluster_rect); - - if (iter->run == NULL) - { - /* When on the NULL run, all extents are the same */ - *logical_rect = cluster_rect; - return; - } - - if (iter->cluster_num_chars) - { - x0 = (iter->character_position * cluster_rect.width) / iter->cluster_num_chars; - x1 = ((iter->character_position + 1) * cluster_rect.width) / iter->cluster_num_chars; - } - else - { - x0 = x1 = 0; - } - - logical_rect->width = x1 - x0; - logical_rect->height = cluster_rect.height; - logical_rect->y = cluster_rect.y; - logical_rect->x = cluster_rect.x + x0; -} - -/** - * pango_layout_iter_get_line_baseline: - * @iter: a `PangoLayoutIter` - * - * Gets the Y position of the current line's baseline, in layout - * coordinates. - * - * Layout coordinates have the origin at the top left of the entire `PangoLines`. - * - * Return value: baseline of current line - */ -int -pango_layout_iter_get_line_baseline (PangoLayoutIter *iter) -{ - g_return_val_if_fail (ITER_IS_VALID (iter), 0); - - return iter->line_y; -} - -/** - * pango_layout_iter_get_run_baseline: - * @iter: a `PangoLayoutIter` - * - * Gets the Y position of the current run's baseline, in layout - * coordinates. - * - * Layout coordinates have the origin at the top left of the entire `PangoLines`. - * - * The run baseline can be different from the line baseline, for - * example due to superscript or subscript positioning. - */ -int -pango_layout_iter_get_run_baseline (PangoLayoutIter *iter) -{ - g_return_val_if_fail (ITER_IS_VALID (iter), 0); - - if (iter->run) - return pango_layout_iter_get_line_baseline (iter) - pango_run_get_glyph_item (iter->run)->y_offset; - else - return pango_layout_iter_get_line_baseline (iter); -} - -/* }}} */ - -/* vim:set foldmethod=marker expandtab: */ diff --git a/pango/pango-layout-iter.h b/pango/pango-layout-iter.h deleted file mode 100644 index b5d1db0d..00000000 --- a/pango/pango-layout-iter.h +++ /dev/null @@ -1,84 +0,0 @@ -#pragma once - -#include - -#include -#include -#include - -G_BEGIN_DECLS - -PANGO_AVAILABLE_IN_ALL -GType pango_layout_iter_get_type (void) G_GNUC_CONST; - -PANGO_AVAILABLE_IN_ALL -PangoLayoutIter * pango_layout_iter_copy (PangoLayoutIter *iter); - -PANGO_AVAILABLE_IN_ALL -void pango_layout_iter_free (PangoLayoutIter *iter); - -PANGO_AVAILABLE_IN_ALL -PangoLines * pango_layout_iter_get_lines (PangoLayoutIter *iter); - -PANGO_AVAILABLE_IN_ALL -PangoLine * pango_layout_iter_get_line (PangoLayoutIter *iter); - -PANGO_AVAILABLE_IN_ALL -gboolean pango_layout_iter_at_last_line (PangoLayoutIter *iter); - -PANGO_AVAILABLE_IN_ALL -PangoRun * pango_layout_iter_get_run (PangoLayoutIter *iter); - -PANGO_AVAILABLE_IN_ALL -int pango_layout_iter_get_index (PangoLayoutIter *iter); - -PANGO_AVAILABLE_IN_ALL -gboolean pango_layout_iter_next_line (PangoLayoutIter *iter); - -PANGO_AVAILABLE_IN_ALL -gboolean pango_layout_iter_next_run (PangoLayoutIter *iter); - -PANGO_AVAILABLE_IN_ALL -gboolean pango_layout_iter_next_cluster (PangoLayoutIter *iter); - -PANGO_AVAILABLE_IN_ALL -gboolean pango_layout_iter_next_char (PangoLayoutIter *iter); - -PANGO_AVAILABLE_IN_ALL -void pango_layout_iter_get_layout_extents (PangoLayoutIter *iter, - PangoRectangle *ink_rect, - PangoRectangle *logical_rect); - -PANGO_AVAILABLE_IN_ALL -void pango_layout_iter_get_line_extents (PangoLayoutIter *iter, - PangoRectangle *ink_rect, - PangoRectangle *logical_rect); - -PANGO_AVAILABLE_IN_ALL -void pango_layout_iter_get_trimmed_line_extents - (PangoLayoutIter *iter, - PangoLeadingTrim trim, - PangoRectangle *logical_rect); - -PANGO_AVAILABLE_IN_ALL -void pango_layout_iter_get_run_extents (PangoLayoutIter *iter, - PangoRectangle *ink_rect, - PangoRectangle *logical_rect); - -PANGO_AVAILABLE_IN_ALL -void pango_layout_iter_get_cluster_extents (PangoLayoutIter *iter, - PangoRectangle *ink_rect, - PangoRectangle *logical_rect); - -PANGO_AVAILABLE_IN_ALL -void pango_layout_iter_get_char_extents (PangoLayoutIter *iter, - PangoRectangle *logical_rect); - -PANGO_AVAILABLE_IN_ALL -int pango_layout_iter_get_line_baseline (PangoLayoutIter *iter); - -PANGO_AVAILABLE_IN_ALL -int pango_layout_iter_get_run_baseline (PangoLayoutIter *iter); - - -G_END_DECLS diff --git a/pango/pango-layout.c b/pango/pango-layout.c index bdae079b..83fa94e2 100644 --- a/pango/pango-layout.c +++ b/pango/pango-layout.c @@ -27,7 +27,7 @@ * of the resulting glyphs can be made. * * The most convenient way to access the visual extents and components - * of a formatted layout is via a [struct@Pango.LayoutIter] iterator. + * of a formatted layout is via a [struct@Pango.LineIter] iterator. * * There are a number of parameters to adjust the formatting of a * `PangoLayout`. The following image shows adjustable parameters @@ -1711,9 +1711,9 @@ pango_layout_get_log_attrs (PangoLayout *layout, * * This is a convenience wrapper for [method@Pango.Lines.get_iter]. * - * Returns: the new `PangoLayoutIter` + * Returns: the new `PangoLineIter` */ -PangoLayoutIter * +PangoLineIter * pango_layout_get_iter (PangoLayout *layout) { g_return_val_if_fail (PANGO_IS_LAYOUT (layout), NULL); diff --git a/pango/pango-layout.h b/pango/pango-layout.h index c183716d..95a2f302 100644 --- a/pango/pango-layout.h +++ b/pango/pango-layout.h @@ -145,7 +145,7 @@ PANGO_AVAILABLE_IN_ALL PangoLines * pango_layout_get_lines (PangoLayout *layout); PANGO_AVAILABLE_IN_ALL -PangoLayoutIter * pango_layout_get_iter (PangoLayout *layout); +PangoLineIter * pango_layout_get_iter (PangoLayout *layout); PANGO_AVAILABLE_IN_ALL const PangoLogAttr * pango_layout_get_log_attrs (PangoLayout *layout, diff --git a/pango/pango-line-iter-private.h b/pango/pango-line-iter-private.h new file mode 100644 index 00000000..e9ca3799 --- /dev/null +++ b/pango/pango-line-iter-private.h @@ -0,0 +1,5 @@ +#pragma once + +#include "pango-line-iter.h" + +PangoLineIter * pango_line_iter_new (PangoLines *lines); diff --git a/pango/pango-line-iter.c b/pango/pango-line-iter.c new file mode 100644 index 00000000..e3eb9368 --- /dev/null +++ b/pango/pango-line-iter.c @@ -0,0 +1,884 @@ +#include "config.h" + +#include "pango-line-iter-private.h" +#include "pango-lines-private.h" +#include "pango-line-private.h" +#include "pango-run-private.h" + +/** + * PangoLineIter: + * + * A `PangoLineIter` can be used to iterate over the visual + * extents of a `PangoLayout` or `PangoLines`. + * + * To obtain a `PangoLineIter`, use [method@Pango.Layout.get_iter] + * or [method@Pango.Lines.get_iter]. + * + * The `PangoLineIter` structure is opaque, and has no user-visible + * fields. + */ + + +/* {{{ PangoLineIter implementation */ + +struct _PangoLineIter +{ + PangoLines *lines; + guint serial; + + int line_no; + int line_x; + int line_y; + PangoLine *line; + GSList *run_link; + PangoRun *run; + int index; + + /* run handling */ + int run_x; + int run_width; + int end_x_offset; + gboolean ltr; + + /* cluster handling */ + int cluster_x; + int cluster_width; + int cluster_start; + int next_cluster_glyph; + int cluster_num_chars; + + int character_position; +}; + +G_DEFINE_BOXED_TYPE (PangoLineIter, pango_line_iter, + pango_line_iter_copy, pango_line_iter_free); + + +/* }}} */ +/* {{{ Utilities */ + +#define ITER_IS_VALID(iter) ((iter)->serial == (iter)->lines->serial) + +static gboolean +line_is_terminated (PangoLineIter *iter) +{ + if (iter->line_no + 1 < pango_lines_get_line_count (iter->lines)) + return pango_line_is_paragraph_end (iter->line); + + return FALSE; + +} + +static int +next_cluster_start (PangoGlyphString *glyphs, + int cluster_start) +{ + int i; + + i = cluster_start + 1; + while (i < glyphs->num_glyphs) + { + if (glyphs->glyphs[i].attr.is_cluster_start) + return i; + + i++; + } + + return glyphs->num_glyphs; +} + +static int +cluster_width (PangoGlyphString *glyphs, + int cluster_start) +{ + int i; + int width; + + width = glyphs->glyphs[cluster_start].geometry.width; + i = cluster_start + 1; + while (i < glyphs->num_glyphs) + { + if (glyphs->glyphs[i].attr.is_cluster_start) + break; + + width += glyphs->glyphs[i].geometry.width; + i++; + } + + return width; +} + +/* Sets up the iter for the start of a new cluster. cluster_start_index + * is the byte index of the cluster start relative to the run. + */ +static void +update_cluster (PangoLineIter *iter, + int cluster_start_index) +{ + PangoGlyphItem *glyph_item; + char *cluster_text; + int cluster_length; + + glyph_item = pango_run_get_glyph_item (iter->run); + + iter->character_position = 0; + + iter->cluster_width = cluster_width (glyph_item->glyphs, iter->cluster_start); + iter->next_cluster_glyph = next_cluster_start (glyph_item->glyphs, iter->cluster_start); + + if (iter->ltr) + { + /* For LTR text, finding the length of the cluster is easy + * since logical and visual runs are in the same direction. + */ + if (iter->next_cluster_glyph < glyph_item->glyphs->num_glyphs) + cluster_length = glyph_item->glyphs->log_clusters[iter->next_cluster_glyph] - cluster_start_index; + else + cluster_length = glyph_item->item->length - cluster_start_index; + } + else + { + /* For RTL text, we have to scan backwards to find the previous + * visual cluster which is the next logical cluster. + */ + int i = iter->cluster_start; + while (i > 0 && glyph_item->glyphs->log_clusters[i - 1] == cluster_start_index) + i--; + + if (i == 0) + cluster_length = glyph_item->item->length - cluster_start_index; + else + cluster_length = glyph_item->glyphs->log_clusters[i - 1] - cluster_start_index; + } + + cluster_text = iter->line->data->text + glyph_item->item->offset + cluster_start_index; + iter->cluster_num_chars = g_utf8_strlen (cluster_text, cluster_length); + + if (iter->ltr) + iter->index = cluster_text - iter->line->data->text; + else + iter->index = g_utf8_prev_char (cluster_text + cluster_length) - iter->line->data->text; +} + +/* Moves to the next non-empty line. If @include_terminators + * is set, a line with just an explicit paragraph separator + * is considered non-empty. + */ +static gboolean +next_nonempty_line (PangoLineIter *iter, + gboolean include_terminators) +{ + gboolean result; + + while (TRUE) + { + result = pango_line_iter_next_line (iter); + if (!result) + break; + + if (iter->line->runs) + break; + + if (include_terminators && line_is_terminated (iter)) + break; + } + + return result; +} + +/* Moves to the next non-empty run. If @include_terminators + * is set, the trailing run at the end of a line with an explicit + * paragraph separator is considered non-empty. + */ +static gboolean +next_nonempty_run (PangoLineIter *iter, + gboolean include_terminators) +{ + gboolean result; + + while (TRUE) + { + result = pango_line_iter_next_run (iter); + if (!result) + break; + + if (iter->run) + break; + + if (include_terminators && line_is_terminated (iter)) + break; + } + + return result; +} + +/* Like pango_layout_next_cluster(), but if @include_terminators + * is set, includes the fake runs/clusters for empty lines. + * (But not positions introduced by line wrapping). + */ +static gboolean +next_cluster_internal (PangoLineIter *iter, + gboolean include_terminators) +{ + PangoGlyphItem *glyph_item; + + if (iter->run == NULL) + return next_nonempty_line (iter, include_terminators); + + glyph_item = pango_run_get_glyph_item (iter->run); + + if (iter->next_cluster_glyph == glyph_item->glyphs->num_glyphs) + { + return next_nonempty_run (iter, include_terminators); + } + else + { + iter->cluster_start = iter->next_cluster_glyph; + iter->cluster_x += iter->cluster_width; + update_cluster (iter, glyph_item->glyphs->log_clusters[iter->cluster_start]); + + return TRUE; + } +} + +static void +update_run (PangoLineIter *iter, + int start_index) +{ + PangoGlyphItem *glyph_item; + + if (iter->run) + glyph_item = pango_run_get_glyph_item (iter->run); + + if (iter->run_link == iter->line->runs) + iter->run_x = 0; + else + { + iter->run_x += iter->end_x_offset + iter->run_width; + if (iter->run) + iter->run_x += glyph_item->start_x_offset; + } + + if (iter->run) + { + iter->run_width = pango_glyph_string_get_width (glyph_item->glyphs); + iter->end_x_offset = glyph_item->end_x_offset; + } + else + { + /* The empty run at the end of a line */ + iter->run_width = 0; + iter->end_x_offset = 0; + } + + if (iter->run) + iter->ltr = (glyph_item->item->analysis.level % 2) == 0; + else + iter->ltr = TRUE; + + iter->cluster_start = 0; + iter->cluster_x = iter->run_x; + + if (iter->run) + { + update_cluster (iter, glyph_item->glyphs->log_clusters[0]); + } + else + { + iter->cluster_width = 0; + iter->character_position = 0; + iter->cluster_num_chars = 0; + iter->index = start_index; + } +} + +static inline void +offset_line (PangoLineIter *iter, + PangoRectangle *ink_rect, + PangoRectangle *logical_rect) +{ + if (ink_rect) + { + ink_rect->x += iter->line_x; + ink_rect->y += iter->line_y; + } + if (logical_rect) + { + logical_rect->x += iter->line_x; + logical_rect->y += iter->line_y; + } +} + +static inline void +offset_run (PangoLineIter *iter, + PangoRectangle *ink_rect, + PangoRectangle *logical_rect) +{ + if (ink_rect) + ink_rect->x += iter->run_x; + if (logical_rect) + logical_rect->x += iter->run_x; +} + +/* }}} */ +/* {{{ Private API */ + +PangoLineIter * +pango_line_iter_new (PangoLines *lines) +{ + PangoLineIter *iter; + int run_start_index; + + g_return_val_if_fail (PANGO_IS_LINES (lines), NULL); + + iter = g_new0 (PangoLineIter, 1); + + iter->lines = g_object_ref (lines); + iter->serial = pango_lines_get_serial (lines); + + iter->line_no = 0; + iter->line = pango_lines_get_line (iter->lines, 0, &iter->line_x, &iter->line_y); + iter->run_link = pango_line_get_runs (iter->line); + if (iter->run_link) + { + iter->run = iter->run_link->data; + run_start_index = pango_run_get_glyph_item (iter->run)->item->offset; + } + else + { + iter->run = NULL; + run_start_index = 0; + } + + update_run (iter, run_start_index); + + return iter; +} + +/* }}} */ +/* {{{ Public API */ + +/** + * pango_line_iter_copy: + * @iter: (nullable): a `PangoLineIter` + * + * Copies a `PangoLineIter`. + * + * Return value: (nullable): the newly allocated `PangoLineIter` + */ +PangoLineIter * +pango_line_iter_copy (PangoLineIter *iter) +{ + PangoLineIter *copy; + + if (iter == NULL) + return NULL; + + copy = g_new0 (PangoLineIter, 1); + memcpy (iter, copy, sizeof (PangoLineIter)); + g_object_ref (copy->lines); + + return copy; +} + +/** + * pango_line_iter_free: + * @iter: (nullable): a `PangoLineIter` + * + * Frees an iterator that's no longer in use. + */ +void +pango_line_iter_free (PangoLineIter *iter) +{ + if (iter == NULL) + return; + + g_object_unref (iter->lines); + g_free (iter); +} + +/** + * pango_line_iter_get_lines: + * @iter: a `PangoLineIter` + * + * Gets the `PangoLines` object associated with a `PangoLineIter`. + * + * Return value: (transfer none): the lines associated with @iter + */ +PangoLines * +pango_line_iter_get_lines (PangoLineIter *iter) +{ + return iter->lines; +} + +/** + * pango_line_iter_get_line: + * @iter: a `PangoLineIter` + * + * Gets the current line. + * + * Return value: (transfer none): the current line + */ +PangoLine * +pango_line_iter_get_line (PangoLineIter *iter) +{ + g_return_val_if_fail (ITER_IS_VALID (iter), NULL); + + return iter->line; +} + +/** + * pango_line_iter_at_last_line: + * @iter: a `PangoLineIter` + * + * Determines whether @iter is on the last line. + * + * Return value: %TRUE if @iter is on the last line + */ +gboolean +pango_line_iter_at_last_line (PangoLineIter *iter) +{ + g_return_val_if_fail (ITER_IS_VALID (iter), FALSE); + + return iter->line_no + 1 == pango_lines_get_line_count (iter->lines); +} + +/** + * pango_line_iter_get_run: + * @iter: a `PangoLineIter` + * + * Gets the current run. + * + * When iterating by run, at the end of each line, there's a position + * with a %NULL run, so this function can return %NULL. The %NULL run + * at the end of each line ensures that all lines have at least one run, + * even lines consisting of only a newline. + * + * Return value: (transfer none) (nullable): the current run + */ +PangoRun * +pango_line_iter_get_run (PangoLineIter *iter) +{ + g_return_val_if_fail (ITER_IS_VALID (iter), NULL); + + return iter->run; +} + +/** + * pango_line_iter_get_index: + * @iter: a `PangoLineIter` + * + * Gets the current byte index. + * + * The byte index is relative to the text backing the current + * line. + * + * Note that iterating forward by char moves in visual order, + * not logical order, so indexes may not be sequential. Also, + * the index may be equal to the length of the text in the + * layout, if on the %NULL run (see [method@Pango.LineIter.get_run]). + * + * Return value: current byte index + */ +int +pango_line_iter_get_index (PangoLineIter *iter) +{ + g_return_val_if_fail (ITER_IS_VALID (iter), 0); + + return iter->index; +} + +/** + * pango_line_iter_next_line: + * @iter: a `PangoLineIter` + * + * Moves @iter forward to the start of the next line. + * + * If @iter is already on the last line, returns %FALSE. + * + * Return value: whether motion was possible + */ +gboolean +pango_line_iter_next_line (PangoLineIter *iter) +{ + g_return_val_if_fail (ITER_IS_VALID (iter), FALSE); + + iter->line = pango_lines_get_line (iter->lines, iter->line_no + 1, &iter->line_x, &iter->line_y); + if (!iter->line) + return FALSE; + + iter->line_no++; + iter->run_link = pango_line_get_runs (iter->line); + if (iter->run_link) + iter->run = iter->run_link->data; + else + iter->run = NULL; + + update_run (iter, iter->line->start_index); + + return TRUE; +} + +/** + * pango_line_iter_next_run: + * @iter: a `PangoLineIter` + * + * Moves @iter forward to the next run in visual order. + * + * If @iter was already at the end, returns %FALSE. + * + * Return value: whether motion was possible + */ +gboolean +pango_line_iter_next_run (PangoLineIter *iter) +{ + int run_start_index; + + g_return_val_if_fail (ITER_IS_VALID (iter), FALSE); + + if (iter->run == NULL) + return pango_line_iter_next_line (iter); + + iter->run_link = iter->run_link->next; + if (iter->run_link == NULL) + { + PangoItem *item = pango_run_get_glyph_item (iter->run)->item; + run_start_index = item->offset + item->length; + iter->run = NULL; + } + else + { + iter->run = iter->run_link->data; + run_start_index = pango_run_get_glyph_item (iter->run)->item->offset; + } + + update_run (iter, run_start_index); + + return TRUE; +} + +/** + * pango_line_iter_next_cluster: + * @iter: a `PangoLineIter` + * + * Moves @iter forward to the next cluster in visual order. + * + * If @iter was already at the end, returns %FALSE. + * + * Return value: whether motion was possible + */ +gboolean +pango_line_iter_next_cluster (PangoLineIter *iter) +{ + g_return_val_if_fail (ITER_IS_VALID (iter), FALSE); + + return next_cluster_internal (iter, FALSE); +} + +/** + * pango_line_iter_next_char: + * @iter: a `PangoLineIter` + * + * Moves @iter forward to the next character in visual order. + * + * If @iter was already at the end, returns %FALSE. + * + * Return value: whether motion was possible + */ +gboolean +pango_line_iter_next_char (PangoLineIter *iter) +{ + const char *text; + + g_return_val_if_fail (ITER_IS_VALID (iter), FALSE); + + if (iter->run == NULL) + { + /* We need to fake an iterator position in the middle of a \r\n line terminator */ + if (line_is_terminated (iter) && + strncmp (iter->line->data->text + iter->line->start_index + iter->line->length, "\r\n", 2) == 0 && + iter->character_position == 0) + { + iter->character_position++; + + return TRUE; + } + + return next_nonempty_line (iter, TRUE); + } + + iter->character_position++; + + if (iter->character_position >= iter->cluster_num_chars) + return next_cluster_internal (iter, TRUE); + + text = iter->line->data->text; + if (iter->ltr) + iter->index = g_utf8_next_char (text + iter->index) - text; + else + iter->index = g_utf8_prev_char (text + iter->index) - text; + + return TRUE; +} + +/** + * pango_line_iter_get_layout_extents: + * @iter: a `PangoLineIter` + * @ink_rect: (out) (optional): rectangle to fill with ink extents + * @logical_rect: (out) (optional): rectangle to fill with logical extents + * + * Obtains the extents of the `PangoLines` being iterated over. + */ +void +pango_line_iter_get_layout_extents (PangoLineIter *iter, + PangoRectangle *ink_rect, + PangoRectangle *logical_rect) +{ + g_return_if_fail (ITER_IS_VALID (iter)); + + pango_lines_get_extents (iter->lines, ink_rect, logical_rect); +} + +/** + * pango_line_iter_get_line_extents: + * @iter: a `PangoLineIter` + * @ink_rect: (out) (optional): rectangle to fill with ink extents + * @logical_rect: (out) (optional): rectangle to fill with logical extents + * + * Obtains the extents of the current line. + * + * Extents are in layout coordinates (origin is the top-left corner of the + * entire `PangoLines`). Thus the extents returned by this function will be + * the same width/height but not at the same x/y as the extents returned + * from [method@Pango.Line.get_extents]. + * + * The logical extents returned by this function always have their leading + * trimmed according to paragraph boundaries: if the line starts a paragraph, + * it has its start leading trimmed; if it ends a paragraph, it has its end + * leading trimmed. If you need other trimming, use + * [method@Pango.Line.get_trimmed_extents]. + */ +void +pango_line_iter_get_line_extents (PangoLineIter *iter, + PangoRectangle *ink_rect, + PangoRectangle *logical_rect) +{ + g_return_if_fail (ITER_IS_VALID (iter)); + + pango_line_get_extents (iter->line, ink_rect, logical_rect); + offset_line (iter, ink_rect, logical_rect); +} + +void +pango_line_iter_get_trimmed_line_extents (PangoLineIter *iter, + PangoLeadingTrim trim, + PangoRectangle *logical_rect) +{ + g_return_if_fail (ITER_IS_VALID (iter)); + + pango_line_get_trimmed_extents (iter->line, trim, logical_rect); + offset_line (iter, NULL, logical_rect); +} + +/** + * pango_line_iter_get_run_extents: + * @iter: a `PangoLineIter` + * @ink_rect: (out) (optional): rectangle to fill with ink extents + * @logical_rect: (out) (optional): rectangle to fill with logical extents + * + * Gets the extents of the current run in layout coordinates. + * + * Layout coordinates have the origin at the top left of the entire `PangoLines`. + * + * The logical extents returned by this function always have their leading + * trimmed off. If you need extents that include leading, use + * [method@Pango.Run.get_extents]. + */ +void +pango_line_iter_get_run_extents (PangoLineIter *iter, + PangoRectangle *ink_rect, + PangoRectangle *logical_rect) +{ + g_return_if_fail (ITER_IS_VALID (iter)); + + if (iter->run) + { + pango_run_get_extents (iter->run, PANGO_LEADING_TRIM_BOTH, ink_rect, logical_rect); + } + else + { + GSList *runs = pango_line_get_runs (iter->line); + if (runs) + { + /* Virtual run at the end of a nonempty line */ + PangoRun *run = g_slist_last (runs)->data; + + pango_run_get_extents (run, PANGO_LEADING_TRIM_BOTH, ink_rect, logical_rect); + if (ink_rect) + ink_rect->width = 0; + if (logical_rect) + logical_rect->width = 0; + } + else + { + /* Empty line */ + PangoRectangle r; + + pango_line_get_empty_extents (iter->line, PANGO_LEADING_TRIM_BOTH, &r); + + if (ink_rect) + *ink_rect = r; + + if (logical_rect) + *logical_rect = r; + } + } + + offset_line (iter, ink_rect, logical_rect); + offset_run (iter, ink_rect, logical_rect); +} + +/** + * pango_line_iter_get_cluster_extents: + * @iter: a `PangoLineIter` + * @ink_rect: (out) (optional): rectangle to fill with ink extents + * @logical_rect: (out) (optional): rectangle to fill with logical extents + * + * Gets the extents of the current cluster, in layout coordinates. + * + * Layout coordinates have the origin at the top left of the entire `PangoLines`. + */ +void +pango_line_iter_get_cluster_extents (PangoLineIter *iter, + PangoRectangle *ink_rect, + PangoRectangle *logical_rect) +{ + PangoGlyphItem *glyph_item; + + g_return_if_fail (ITER_IS_VALID (iter)); + + if (iter->run == NULL) + { + /* When on the NULL run, all extents are the same */ + pango_line_iter_get_run_extents (iter, ink_rect, logical_rect); + return; + } + + glyph_item = pango_run_get_glyph_item (iter->run); + + pango_glyph_string_extents_range (glyph_item->glyphs, + iter->cluster_start, + iter->next_cluster_glyph, + glyph_item->item->analysis.font, + ink_rect, + logical_rect); + + offset_line (iter, ink_rect, logical_rect); + if (ink_rect) + { + ink_rect->x += iter->cluster_x + glyph_item->start_x_offset; + ink_rect->y -= glyph_item->y_offset; + } + + if (logical_rect) + { + g_assert (logical_rect->width == iter->cluster_width); + logical_rect->x += iter->cluster_x + glyph_item->start_x_offset; + logical_rect->y -= glyph_item->y_offset; + } +} + +/** + * pango_line_iter_get_char_extents: + * @iter: a `PangoLineIter` + * @logical_rect: (out caller-allocates): rectangle to fill with logical extents + * + * Gets the extents of the current character, in layout coordinates. + * + * Layout coordinates have the origin at the top left of the entire `PangoLines`. + * + * Only logical extents can sensibly be obtained for characters; + * ink extents make sense only down to the level of clusters. + */ +void +pango_line_iter_get_char_extents (PangoLineIter *iter, + PangoRectangle *logical_rect) +{ + PangoRectangle cluster_rect; + int x0, x1; + + g_return_if_fail (ITER_IS_VALID (iter)); + + if (logical_rect == NULL) + return; + + pango_line_iter_get_cluster_extents (iter, NULL, &cluster_rect); + + if (iter->run == NULL) + { + /* When on the NULL run, all extents are the same */ + *logical_rect = cluster_rect; + return; + } + + if (iter->cluster_num_chars) + { + x0 = (iter->character_position * cluster_rect.width) / iter->cluster_num_chars; + x1 = ((iter->character_position + 1) * cluster_rect.width) / iter->cluster_num_chars; + } + else + { + x0 = x1 = 0; + } + + logical_rect->width = x1 - x0; + logical_rect->height = cluster_rect.height; + logical_rect->y = cluster_rect.y; + logical_rect->x = cluster_rect.x + x0; +} + +/** + * pango_line_iter_get_line_baseline: + * @iter: a `PangoLineIter` + * + * Gets the Y position of the current line's baseline, in layout + * coordinates. + * + * Layout coordinates have the origin at the top left of the entire `PangoLines`. + * + * Return value: baseline of current line + */ +int +pango_line_iter_get_line_baseline (PangoLineIter *iter) +{ + g_return_val_if_fail (ITER_IS_VALID (iter), 0); + + return iter->line_y; +} + +/** + * pango_line_iter_get_run_baseline: + * @iter: a `PangoLineIter` + * + * Gets the Y position of the current run's baseline, in layout + * coordinates. + * + * Layout coordinates have the origin at the top left of the entire `PangoLines`. + * + * The run baseline can be different from the line baseline, for + * example due to superscript or subscript positioning. + */ +int +pango_line_iter_get_run_baseline (PangoLineIter *iter) +{ + g_return_val_if_fail (ITER_IS_VALID (iter), 0); + + if (iter->run) + return pango_line_iter_get_line_baseline (iter) - pango_run_get_glyph_item (iter->run)->y_offset; + else + return pango_line_iter_get_line_baseline (iter); +} + +/* }}} */ + +/* vim:set foldmethod=marker expandtab: */ diff --git a/pango/pango-line-iter.h b/pango/pango-line-iter.h new file mode 100644 index 00000000..2d61e478 --- /dev/null +++ b/pango/pango-line-iter.h @@ -0,0 +1,84 @@ +#pragma once + +#include + +#include +#include +#include + +G_BEGIN_DECLS + +PANGO_AVAILABLE_IN_ALL +GType pango_line_iter_get_type (void) G_GNUC_CONST; + +PANGO_AVAILABLE_IN_ALL +PangoLineIter * pango_line_iter_copy (PangoLineIter *iter); + +PANGO_AVAILABLE_IN_ALL +void pango_line_iter_free (PangoLineIter *iter); + +PANGO_AVAILABLE_IN_ALL +PangoLines * pango_line_iter_get_lines (PangoLineIter *iter); + +PANGO_AVAILABLE_IN_ALL +PangoLine * pango_line_iter_get_line (PangoLineIter *iter); + +PANGO_AVAILABLE_IN_ALL +gboolean pango_line_iter_at_last_line (PangoLineIter *iter); + +PANGO_AVAILABLE_IN_ALL +PangoRun * pango_line_iter_get_run (PangoLineIter *iter); + +PANGO_AVAILABLE_IN_ALL +int pango_line_iter_get_index (PangoLineIter *iter); + +PANGO_AVAILABLE_IN_ALL +gboolean pango_line_iter_next_line (PangoLineIter *iter); + +PANGO_AVAILABLE_IN_ALL +gboolean pango_line_iter_next_run (PangoLineIter *iter); + +PANGO_AVAILABLE_IN_ALL +gboolean pango_line_iter_next_cluster (PangoLineIter *iter); + +PANGO_AVAILABLE_IN_ALL +gboolean pango_line_iter_next_char (PangoLineIter *iter); + +PANGO_AVAILABLE_IN_ALL +void pango_line_iter_get_layout_extents (PangoLineIter *iter, + PangoRectangle *ink_rect, + PangoRectangle *logical_rect); + +PANGO_AVAILABLE_IN_ALL +void pango_line_iter_get_line_extents (PangoLineIter *iter, + PangoRectangle *ink_rect, + PangoRectangle *logical_rect); + +PANGO_AVAILABLE_IN_ALL +void pango_line_iter_get_trimmed_line_extents + (PangoLineIter *iter, + PangoLeadingTrim trim, + PangoRectangle *logical_rect); + +PANGO_AVAILABLE_IN_ALL +void pango_line_iter_get_run_extents (PangoLineIter *iter, + PangoRectangle *ink_rect, + PangoRectangle *logical_rect); + +PANGO_AVAILABLE_IN_ALL +void pango_line_iter_get_cluster_extents (PangoLineIter *iter, + PangoRectangle *ink_rect, + PangoRectangle *logical_rect); + +PANGO_AVAILABLE_IN_ALL +void pango_line_iter_get_char_extents (PangoLineIter *iter, + PangoRectangle *logical_rect); + +PANGO_AVAILABLE_IN_ALL +int pango_line_iter_get_line_baseline (PangoLineIter *iter); + +PANGO_AVAILABLE_IN_ALL +int pango_line_iter_get_run_baseline (PangoLineIter *iter); + + +G_END_DECLS diff --git a/pango/pango-line.c b/pango/pango-line.c index 61258956..04b01a43 100644 --- a/pango/pango-line.c +++ b/pango/pango-line.c @@ -27,7 +27,7 @@ * offset each line to. * * The most convenient way to access the visual extents and components - * of a `PangoLine` is via a [struct@Pango.LayoutIter] iterator. + * of a `PangoLine` is via a [struct@Pango.LineIter] iterator. */ /* {{{ LineData */ diff --git a/pango/pango-lines.c b/pango/pango-lines.c index 26b408ed..2d5fea44 100644 --- a/pango/pango-lines.c +++ b/pango/pango-lines.c @@ -3,7 +3,7 @@ #include "pango-lines-private.h" #include "pango-line-private.h" #include "pango-item-private.h" -#include "pango-layout-iter-private.h" +#include "pango-line-iter-private.h" /** * PangoLines: @@ -35,7 +35,7 @@ * for the `PangoLines*`. * * The most convenient way to access the visual extents and components - * of a `PangoLines` is via a [struct@Pango.LayoutIter] iterator. + * of a `PangoLines` is via a [struct@Pango.LineIter] iterator. */ /* {{{ PangoLines implementation */ @@ -242,12 +242,12 @@ pango_lines_add_line (PangoLines *lines, * * Note that the iter holds a reference to @lines. * - * Return value: the new `PangoLayoutIter` + * Return value: the new `PangoLineIter` */ -PangoLayoutIter * +PangoLineIter * pango_lines_get_iter (PangoLines *lines) { - return pango_layout_iter_new (lines); + return pango_line_iter_new (lines); } /** diff --git a/pango/pango-lines.h b/pango/pango-lines.h index 1e3ec82f..1326b35b 100644 --- a/pango/pango-lines.h +++ b/pango/pango-lines.h @@ -12,8 +12,6 @@ G_BEGIN_DECLS PANGO_AVAILABLE_IN_ALL G_DECLARE_FINAL_TYPE (PangoLines, pango_lines, PANGO, LINES, GObject); -typedef struct _PangoLayoutIter PangoLayoutIter; - PANGO_AVAILABLE_IN_ALL PangoLines * pango_lines_new (void); @@ -36,7 +34,7 @@ PangoLine * pango_lines_get_line (PangoLines *lines, int *line_y); PANGO_AVAILABLE_IN_ALL -PangoLayoutIter * pango_lines_get_iter (PangoLines *lines); +PangoLineIter * pango_lines_get_iter (PangoLines *lines); PANGO_AVAILABLE_IN_ALL void pango_lines_get_extents (PangoLines *lines, diff --git a/pango/pango-types.h b/pango/pango-types.h index 6c44314e..0420698b 100644 --- a/pango/pango-types.h +++ b/pango/pango-types.h @@ -56,7 +56,7 @@ typedef guint32 PangoGlyph; typedef struct _PangoRun PangoRun; typedef struct _PangoLine PangoLine; typedef struct _PangoLines PangoLines; -typedef struct _PangoLayoutIter PangoLayoutIter; +typedef struct _PangoLineIter PangoLineIter; /** * PANGO_SCALE: diff --git a/pango/pango.h b/pango/pango.h index 4f4782d0..878b2d14 100644 --- a/pango/pango.h +++ b/pango/pango.h @@ -45,7 +45,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/pango/pangowin32.c b/pango/pangowin32.c index eed92dde..3b426ab4 100644 --- a/pango/pangowin32.c +++ b/pango/pangowin32.c @@ -1084,7 +1084,7 @@ pango_win32_render_layout (HDC hdc, int x, int y) { - PangoLayoutIter *iter; + PangoLineIter *iter; g_return_if_fail (hdc != NULL); g_return_if_fail (PANGO_IS_LAYOUT (layout)); diff --git a/tests/test-bidi.c b/tests/test-bidi.c index fe74cac2..dadad5b1 100644 --- a/tests/test-bidi.c +++ b/tests/test-bidi.c @@ -362,7 +362,7 @@ test_move_cursor_para (void) PangoLine *line; PangoRectangle ext; PangoLines *lines; - PangoLayoutIter *iter; + PangoLineIter *iter; PangoLine *new_line; layout = pango_layout_new (context); @@ -389,10 +389,10 @@ test_move_cursor_para (void) break; iter = pango_lines_get_iter (lines); - while (pango_layout_iter_get_line (iter) != line) - pango_layout_iter_next_line (iter); - pango_layout_iter_get_line_extents (iter, NULL, &ext); - pango_layout_iter_free (iter); + while (pango_line_iter_get_line (iter) != line) + pango_line_iter_next_line (iter); + pango_line_iter_get_line_extents (iter, NULL, &ext); + pango_line_iter_free (iter); pango_lines_move_cursor(lines, TRUE, NULL, @@ -433,10 +433,10 @@ test_move_cursor_para (void) pango_lines_index_to_line (lines, index, &line, NULL, NULL, NULL); g_assert_nonnull (line); iter = pango_lines_get_iter (lines); - while (pango_layout_iter_get_line (iter) != line) - pango_layout_iter_next_line (iter); - pango_layout_iter_get_line_extents (iter, NULL, &ext); - pango_layout_iter_free (iter); + while (pango_line_iter_get_line (iter) != line) + pango_line_iter_next_line (iter); + pango_line_iter_get_line_extents (iter, NULL, &ext); + pango_line_iter_free (iter); pango_lines_move_cursor (lines, TRUE, NULL, diff --git a/tests/testiter.c b/tests/testiter.c index 062cd3b9..a966342e 100644 --- a/tests/testiter.c +++ b/tests/testiter.c @@ -80,7 +80,7 @@ static void iter_char_test (PangoLayout *layout) { PangoRectangle extents, run_extents; - PangoLayoutIter *iter; + PangoLineIter *iter; PangoRun *run; int num_chars; int i, index, offset; @@ -99,19 +99,19 @@ iter_char_test (PangoLayout *layout) gchar *char_str; g_assert (iter_next_ok); - index = pango_layout_iter_get_index (iter); + index = pango_line_iter_get_index (iter); ptr = text + index; char_str = g_strndup (ptr, g_utf8_next_char (ptr) - ptr); verbose ("i=%d (visual), index = %d '%s':\n", i, index, char_str); g_free (char_str); - pango_layout_iter_get_char_extents (iter, &extents); + pango_line_iter_get_char_extents (iter, &extents); verbose (" char extents: x=%d,y=%d w=%d,h=%d\n", extents.x, extents.y, extents.width, extents.height); - run = pango_layout_iter_get_run (iter); + run = pango_line_iter_get_run (iter); if (run) { @@ -124,7 +124,7 @@ iter_char_test (PangoLayout *layout) glyphs = pango_run_get_glyphs (run); /* Get needed data for the GlyphString */ - pango_layout_iter_get_run_extents (iter, NULL, &run_extents); + pango_line_iter_get_run_extents (iter, NULL, &run_extents); offset = item->offset; rtl = item->analysis.level%2; desc = pango_font_describe (item->analysis.font); @@ -158,7 +158,7 @@ iter_char_test (PangoLayout *layout) /* We're on a line terminator */ } - iter_next_ok = pango_layout_iter_next_char (iter); + iter_next_ok = pango_line_iter_next_char (iter); verbose ("more to go? %d\n", iter_next_ok); } @@ -166,14 +166,14 @@ iter_char_test (PangoLayout *layout) * input string */ g_assert (!iter_next_ok); - pango_layout_iter_free (iter); + pango_line_iter_free (iter); } static void iter_cluster_test (PangoLayout *layout) { PangoRectangle extents; - PangoLayoutIter *iter; + PangoLineIter *iter; int index; gboolean iter_next_ok; PangoLine *last_line = NULL; @@ -184,16 +184,16 @@ iter_cluster_test (PangoLayout *layout) while (iter_next_ok) { - PangoLine *line = pango_layout_iter_get_line (iter); + PangoLine *line = pango_line_iter_get_line (iter); /* Every cluster is part of a run */ - g_assert (pango_layout_iter_get_run (iter)); + g_assert (pango_line_iter_get_run (iter)); - index = pango_layout_iter_get_index (iter); + index = pango_line_iter_get_index (iter); - pango_layout_iter_get_cluster_extents (iter, NULL, &extents); + pango_line_iter_get_cluster_extents (iter, NULL, &extents); - iter_next_ok = pango_layout_iter_next_cluster (iter); + iter_next_ok = pango_line_iter_next_cluster (iter); verbose ("index = %d:\n", index); verbose (" cluster extents: x=%d,y=%d w=%d,h=%d\n", @@ -215,11 +215,11 @@ iter_cluster_test (PangoLayout *layout) g_assert (!iter_next_ok); - pango_layout_iter_free (iter); + pango_line_iter_free (iter); } static void -test_layout_iter (void) +test_line_iter (void) { const char **ptext; PangoFontMap *fontmap; @@ -320,7 +320,7 @@ main (int argc, char *argv[]) { g_test_init (&argc, &argv, NULL); - g_test_add_func ("/layout/iter", test_layout_iter); + g_test_add_func ("/layout/iter", test_line_iter); g_test_add_func ("/layout/glyphitem-iter", test_glyphitem_iter); return g_test_run (); diff --git a/tests/testmisc.c b/tests/testmisc.c index f1e892e8..a4183478 100644 --- a/tests/testmisc.c +++ b/tests/testmisc.c @@ -178,7 +178,7 @@ test_run_height (void) { PangoContext *context; PangoLayout *layout; - PangoLayoutIter *iter; + PangoLineIter *iter; PangoRectangle logical1, logical2; if (strcmp (G_OBJECT_TYPE_NAME (pango_cairo_font_map_get_default ()), "PangoCairoCoreTextFontMap") == 0) @@ -192,14 +192,14 @@ test_run_height (void) pango_layout_set_text (layout, "one", -1); iter = pango_lines_get_iter (pango_layout_get_lines (layout)); - pango_layout_iter_get_run_extents (iter, NULL, &logical1); - pango_layout_iter_free (iter); + pango_line_iter_get_run_extents (iter, NULL, &logical1); + pango_line_iter_free (iter); pango_layout_set_text (layout, "", -1); iter = pango_lines_get_iter (pango_layout_get_lines (layout)); - pango_layout_iter_get_run_extents (iter, NULL, &logical2); - pango_layout_iter_free (iter); + pango_line_iter_get_run_extents (iter, NULL, &logical2); + pango_line_iter_free (iter); g_assert_cmpint (logical1.height, ==, logical2.height); @@ -581,7 +581,7 @@ test_extents (void) { PangoLayout *layout; PangoLines *lines; - PangoLayoutIter *iter; + PangoLineIter *iter; PangoRectangle layout_extents; PangoRectangle line_extents; PangoRectangle run_extents; @@ -602,11 +602,11 @@ test_extents (void) do { - pango_layout_iter_get_line_extents (iter, NULL, &line_extents); - pango_layout_iter_get_run_extents (iter, NULL, &run_extents); - pango_layout_iter_get_cluster_extents (iter, NULL, &cluster_extents); - pango_layout_iter_get_char_extents (iter, &char_extents); - index = pango_layout_iter_get_index (iter); + pango_line_iter_get_line_extents (iter, NULL, &line_extents); + pango_line_iter_get_run_extents (iter, NULL, &run_extents); + pango_line_iter_get_cluster_extents (iter, NULL, &cluster_extents); + pango_line_iter_get_char_extents (iter, &char_extents); + index = pango_line_iter_get_index (iter); pango_lines_index_to_pos (lines, NULL, index, &pos); if (pos.width < 0) { @@ -624,9 +624,9 @@ test_extents (void) g_assert_true (pango_rectangle_contains (&line_extents, &strong)); g_assert_true (pango_rectangle_contains (&line_extents, &weak)); } - while (pango_layout_iter_next_char (iter)); + while (pango_line_iter_next_char (iter)); - pango_layout_iter_free (iter); + pango_line_iter_free (iter); g_object_unref (layout); } diff --git a/utils/viewer-pangocairo.c b/utils/viewer-pangocairo.c index 631c2a7d..6293e086 100644 --- a/utils/viewer-pangocairo.c +++ b/utils/viewer-pangocairo.c @@ -202,7 +202,7 @@ render_callback (PangoLayout *layout, cairo_pattern_t *pattern; PangoRectangle ink, logical; double lw = cairo_get_line_width (cr); - PangoLayoutIter *iter; + PangoLineIter *iter; pango_lines_get_extents (pango_layout_get_lines (layout), &ink, &logical); @@ -282,10 +282,10 @@ render_callback (PangoLayout *layout, iter = pango_layout_get_iter (layout); do { - PangoLine *line = pango_layout_iter_get_line (iter); + PangoLine *line = pango_line_iter_get_line (iter); double width = (double)logical.width / PANGO_SCALE; - y = pango_layout_iter_get_line_baseline (iter); + y = pango_line_iter_get_line_baseline (iter); cairo_save (cr); cairo_translate (cr, (double)logical.x / PANGO_SCALE + width * 0.5, @@ -303,8 +303,8 @@ render_callback (PangoLayout *layout, cairo_fill (cr); cairo_restore (cr); } - while (pango_layout_iter_next_line (iter)); - pango_layout_iter_free (iter); + while (pango_line_iter_next_line (iter)); + pango_line_iter_free (iter); cairo_restore (cr); } @@ -345,7 +345,7 @@ render_callback (PangoLayout *layout, { PangoRectangle rect; - pango_layout_iter_get_line_extents (iter, NULL, &rect); + pango_line_iter_get_line_extents (iter, NULL, &rect); cairo_rectangle (cr, (double)rect.x / PANGO_SCALE - lw / 2, (double)rect.y / PANGO_SCALE - lw / 2, @@ -353,8 +353,8 @@ render_callback (PangoLayout *layout, (double)rect.height / PANGO_SCALE + lw); cairo_stroke (cr); } - while (pango_layout_iter_next_line (iter)); - pango_layout_iter_free (iter); + while (pango_line_iter_next_line (iter)); + pango_line_iter_free (iter); cairo_restore (cr); } @@ -370,11 +370,11 @@ render_callback (PangoLayout *layout, PangoRun *run; PangoRectangle rect; - run = pango_layout_iter_get_run (iter); + run = pango_line_iter_get_run (iter); if (!run) continue; - pango_layout_iter_get_run_extents (iter, NULL, &rect); + pango_line_iter_get_run_extents (iter, NULL, &rect); cairo_rectangle (cr, (double)rect.x / PANGO_SCALE - lw / 2, (double)rect.y / PANGO_SCALE - lw / 2, @@ -382,8 +382,8 @@ render_callback (PangoLayout *layout, (double)rect.height / PANGO_SCALE + lw); cairo_stroke (cr); } - while (pango_layout_iter_next_run (iter)); - pango_layout_iter_free (iter); + while (pango_line_iter_next_run (iter)); + pango_line_iter_free (iter); cairo_restore (cr); } @@ -398,7 +398,7 @@ render_callback (PangoLayout *layout, { PangoRectangle rect; - pango_layout_iter_get_cluster_extents (iter, NULL, &rect); + pango_line_iter_get_cluster_extents (iter, NULL, &rect); cairo_rectangle (cr, (double)rect.x / PANGO_SCALE - lw / 2, (double)rect.y / PANGO_SCALE - lw / 2, @@ -406,8 +406,8 @@ render_callback (PangoLayout *layout, (double)rect.height / PANGO_SCALE + lw); cairo_stroke (cr); } - while (pango_layout_iter_next_cluster (iter)); - pango_layout_iter_free (iter); + while (pango_line_iter_next_cluster (iter)); + pango_line_iter_free (iter); cairo_restore (cr); } @@ -422,7 +422,7 @@ render_callback (PangoLayout *layout, { PangoRectangle rect; - pango_layout_iter_get_char_extents (iter, &rect); + pango_line_iter_get_char_extents (iter, &rect); cairo_rectangle (cr, (double)rect.x / PANGO_SCALE - lw / 2, (double)rect.y / PANGO_SCALE - lw / 2, @@ -430,8 +430,8 @@ render_callback (PangoLayout *layout, (double)rect.height / PANGO_SCALE + lw); cairo_stroke (cr); } - while (pango_layout_iter_next_cluster (iter)); - pango_layout_iter_free (iter); + while (pango_line_iter_next_cluster (iter)); + pango_line_iter_free (iter); cairo_restore (cr); } @@ -450,17 +450,17 @@ render_callback (PangoLayout *layout, PangoRectangle rect; int x_pos, y_pos; - run = pango_layout_iter_get_run (iter); + run = pango_line_iter_get_run (iter); if (!run) continue; item = pango_run_get_item (run); glyphs = pango_run_get_glyphs (run); - pango_layout_iter_get_run_extents (iter, NULL, &rect); + pango_line_iter_get_run_extents (iter, NULL, &rect); x_pos = rect.x; - y_pos = pango_layout_iter_get_run_baseline (iter); + y_pos = pango_line_iter_get_run_baseline (iter); for (int i = 0; i < glyphs->num_glyphs; i++) { @@ -491,8 +491,8 @@ render_callback (PangoLayout *layout, x_pos += glyphs->glyphs[i].geometry.width; } } - while (pango_layout_iter_next_run (iter)); - pango_layout_iter_free (iter); + while (pango_line_iter_next_run (iter)); + pango_line_iter_free (iter); cairo_restore (cr); } @@ -520,8 +520,8 @@ render_callback (PangoLayout *layout, int x, y; gboolean trailing; - pango_layout_iter_get_run_extents (iter, NULL, &rect); - run = pango_layout_iter_get_run (iter); + pango_line_iter_get_run_extents (iter, NULL, &rect); + run = pango_line_iter_get_run (iter); if (!run) continue; @@ -534,7 +534,7 @@ render_callback (PangoLayout *layout, offset = g_utf8_strlen (text, start - text); - y = pango_layout_iter_get_run_baseline (iter); + y = pango_line_iter_get_run_baseline (iter); trailing = FALSE; p = start; @@ -574,8 +574,8 @@ render_callback (PangoLayout *layout, } } - while (pango_layout_iter_next_run (iter)); - pango_layout_iter_free (iter); + while (pango_line_iter_next_run (iter)); + pango_line_iter_free (iter); cairo_restore (cr); } -- cgit v1.2.1