From 61e192f6c1edcec694c38ef07f4ec9ff9af01cdc Mon Sep 17 00:00:00 2001 From: Matthias Clasen Date: Tue, 25 Jan 2022 01:44:26 -0500 Subject: Rename PangoLayoutLine to PangoLine --- examples/cairotwisted.c | 4 +- examples/columns.c | 8 +- examples/parshape.c | 10 +- pango/ellipsize.c | 10 +- pango/meson.build | 4 +- pango/pango-attributes.c | 6 +- pango/pango-layout-iter.c | 24 +- pango/pango-layout-iter.h | 2 +- pango/pango-layout-line-private.h | 65 -- pango/pango-layout-line.c | 1575 ------------------------------------- pango/pango-layout-line.h | 107 --- pango/pango-layout.c | 26 +- pango/pango-line-breaker.c | 62 +- pango/pango-line-breaker.h | 6 +- pango/pango-line-private.h | 65 ++ pango/pango-line.c | 1575 +++++++++++++++++++++++++++++++++++++ pango/pango-line.h | 106 +++ pango/pango-lines.c | 158 ++-- pango/pango-lines.h | 28 +- pango/pango-renderer.c | 30 +- pango/pango-renderer.h | 6 +- pango/pango-run.c | 2 +- pango/pango-types.h | 4 +- pango/pango.h | 2 +- pango/pangocairo-font.c | 4 +- pango/pangocairo-render.c | 30 +- pango/pangocairo.h | 10 +- pango/pangofc-font.c | 4 +- pango/pangoft2-render.c | 34 +- pango/pangoft2.h | 12 +- pango/pangoxft-render.c | 18 +- pango/pangoxft-render.h | 4 +- pango/serializer.c | 6 +- tests/test-bidi.c | 12 +- tests/testiter.c | 8 +- tests/testmisc.c | 22 +- utils/viewer-pangocairo.c | 4 +- 37 files changed, 2026 insertions(+), 2027 deletions(-) delete mode 100644 pango/pango-layout-line-private.h delete mode 100644 pango/pango-layout-line.c delete mode 100644 pango/pango-layout-line.h create mode 100644 pango/pango-line-private.h create mode 100644 pango/pango-line.c create mode 100644 pango/pango-line.h diff --git a/examples/cairotwisted.c b/examples/cairotwisted.c index 217e5e44..88f781b4 100644 --- a/examples/cairotwisted.c +++ b/examples/cairotwisted.c @@ -472,7 +472,7 @@ draw_text (cairo_t *cr, const char *text) { PangoLayout *layout; - PangoLayoutLine *line; + PangoLine *line; PangoFontDescription *desc; cairo_font_options_t *font_options; @@ -495,7 +495,7 @@ draw_text (cairo_t *cr, line = pango_lines_get_line (pango_layout_get_lines (layout), 0, NULL, NULL); cairo_move_to (cr, x, y); - pango_cairo_layout_line_path (cr, line); + pango_cairo_line_path (cr, line); g_object_unref (layout); } diff --git a/examples/columns.c b/examples/columns.c index 4001a09a..a8a21c78 100644 --- a/examples/columns.c +++ b/examples/columns.c @@ -65,7 +65,7 @@ main (int argc, char *argv[]) while (pango_line_breaker_has_line (breaker)) { - PangoLayoutLine *line; + PangoLine *line; PangoRectangle ext; retry: @@ -74,10 +74,10 @@ retry: PANGO_WRAP_CHAR, PANGO_ELLIPSIZE_NONE); - if (!pango_layout_line_is_paragraph_end (line)) - line = pango_layout_line_justify (line, width); + if (!pango_line_is_paragraph_end (line)) + line = pango_line_justify (line, width); - pango_layout_line_get_extents (line, NULL, &ext); + pango_line_get_extents (line, NULL, &ext); if (y + ext.height > height) { diff --git a/examples/parshape.c b/examples/parshape.c index 3c79b9be..c09e1ddd 100644 --- a/examples/parshape.c +++ b/examples/parshape.c @@ -57,7 +57,7 @@ main (int argc, char *argv[]) while (pango_line_breaker_has_line (breaker)) { - PangoLayoutLine *line; + PangoLine *line; PangoRectangle ext; gboolean ltr; @@ -66,8 +66,8 @@ main (int argc, char *argv[]) PANGO_WRAP_CHAR, PANGO_ELLIPSIZE_NONE); - pango_layout_line_get_extents (line, NULL, &ext); - line = pango_layout_line_justify (line, width); + pango_line_get_extents (line, NULL, &ext); + line = pango_line_justify (line, width); pango_lines_add_line (lines, line, x, y - ext.y); ltr = pango_line_breaker_get_direction (breaker) == PANGO_DIRECTION_LTR; @@ -99,11 +99,11 @@ main (int argc, char *argv[]) for (int i = 0; i < pango_lines_get_line_count (lines); i++) { - PangoLayoutLine *line = pango_lines_get_line (lines, i, &x, &y); + PangoLine *line = pango_lines_get_line (lines, i, &x, &y); cairo_save (cr); cairo_move_to (cr, x / (double)PANGO_SCALE, y / (double)PANGO_SCALE); - pango_cairo_show_layout_line (cr, line); + pango_cairo_show_line (cr, line); cairo_restore (cr); } diff --git a/pango/ellipsize.c b/pango/ellipsize.c index 149602a6..1a7f8eb6 100644 --- a/pango/ellipsize.c +++ b/pango/ellipsize.c @@ -26,7 +26,7 @@ #include "pango-font-private.h" #include "pango-attributes-private.h" #include "pango-impl-utils.h" -#include "pango-layout-line-private.h" +#include "pango-line-private.h" typedef struct _EllipsizeState EllipsizeState; typedef struct _RunInfo RunInfo; @@ -742,10 +742,10 @@ current_width (EllipsizeState *state) } void -pango_layout_line_ellipsize (PangoLayoutLine *line, - PangoContext *context, - PangoEllipsizeMode ellipsize, - int goal_width) +pango_line_ellipsize (PangoLine *line, + PangoContext *context, + PangoEllipsizeMode ellipsize, + int goal_width) { EllipsizeState state; const char *text = line->data->text; diff --git a/pango/meson.build b/pango/meson.build index 4fa5bc19..4f603dc9 100644 --- a/pango/meson.build +++ b/pango/meson.build @@ -31,7 +31,7 @@ pango_sources = [ 'serializer.c', 'json/gtkjsonparser.c', 'json/gtkjsonprinter.c', - 'pango-layout-line.c', + 'pango-line.c', 'pango-run.c', 'pango-line-breaker.c', 'pango-lines.c', @@ -57,7 +57,7 @@ pango_headers = [ 'pango-gravity.h', 'pango-item.h', 'pango-language.h', - 'pango-layout-line.h', + 'pango-line.h', 'pango-run.h', 'pango-line-breaker.h', 'pango-layout-iter.h', diff --git a/pango/pango-attributes.c b/pango/pango-attributes.c index 01683af3..e3d5191f 100644 --- a/pango/pango-attributes.c +++ b/pango/pango-attributes.c @@ -1510,7 +1510,7 @@ pango_attr_overline_color_new (guint16 red, * Modify the height of logical line extents by a factor. * * This affects the values returned by - * [method@Pango.LayoutLine.get_extents] and + * [method@Pango.Line.get_extents] and * [method@Pango.LayoutIter.get_line_extents]. * * @@ -1536,7 +1536,7 @@ pango_attr_line_height_new (double factor) * Override the height of logical line extents to be @height. * * This affects the values returned by - * [method@Pango.LayoutLine.get_extents], + * [method@Pango.Line.get_extents], * [method@Pango.LayoutIter.get_line_extents]. * * Since: 1.50 @@ -1562,7 +1562,7 @@ pango_attr_line_height_new_absolute (int height) * if not overridden by line spacing attributes. * * This affects the values returned by - * [method@Pango.LayoutLine.get_extents], + * [method@Pango.Line.get_extents], * [method@Pango.LayoutIter.get_line_extents]. */ PangoAttribute * diff --git a/pango/pango-layout-iter.c b/pango/pango-layout-iter.c index 7fd4054c..87b4ab77 100644 --- a/pango/pango-layout-iter.c +++ b/pango/pango-layout-iter.c @@ -2,7 +2,7 @@ #include "pango-layout-iter-private.h" #include "pango-lines-private.h" -#include "pango-layout-line-private.h" +#include "pango-line-private.h" #include "pango-run-private.h" /** @@ -29,7 +29,7 @@ struct _PangoLayoutIter int line_no; int line_x; int line_y; - PangoLayoutLine *line; + PangoLine *line; GSList *run_link; PangoRun *run; int index; @@ -63,7 +63,7 @@ static gboolean line_is_terminated (PangoLayoutIter *iter) { if (iter->line_no + 1 < pango_lines_get_line_count (iter->lines)) - return pango_layout_line_is_paragraph_end (iter->line); + return pango_line_is_paragraph_end (iter->line); return FALSE; @@ -338,7 +338,7 @@ pango_layout_iter_new (PangoLines *lines) iter->line_no = 0; iter->line = pango_lines_get_line (iter->lines, 0, &iter->line_x, &iter->line_y); - iter->run_link = pango_layout_line_get_runs (iter->line); + iter->run_link = pango_line_get_runs (iter->line); if (iter->run_link) { iter->run = iter->run_link->data; @@ -419,7 +419,7 @@ pango_layout_iter_get_lines (PangoLayoutIter *iter) * * Return value: (transfer none): the current line */ -PangoLayoutLine * +PangoLine * pango_layout_iter_get_line (PangoLayoutIter *iter) { g_return_val_if_fail (ITER_IS_VALID (iter), NULL); @@ -508,7 +508,7 @@ pango_layout_iter_next_line (PangoLayoutIter *iter) return FALSE; iter->line_no++; - iter->run_link = pango_layout_line_get_runs (iter->line); + iter->run_link = pango_line_get_runs (iter->line); if (iter->run_link) iter->run = iter->run_link->data; else @@ -650,13 +650,13 @@ pango_layout_iter_get_layout_extents (PangoLayoutIter *iter, * 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.LayoutLine.get_extents]. + * 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.LayoutLine.get_trimmed_extents]. + * [method@Pango.Line.get_trimmed_extents]. */ void pango_layout_iter_get_line_extents (PangoLayoutIter *iter, @@ -665,7 +665,7 @@ pango_layout_iter_get_line_extents (PangoLayoutIter *iter, { g_return_if_fail (ITER_IS_VALID (iter)); - pango_layout_line_get_extents (iter->line, ink_rect, logical_rect); + pango_line_get_extents (iter->line, ink_rect, logical_rect); offset_line (iter, ink_rect, logical_rect); } @@ -676,7 +676,7 @@ pango_layout_iter_get_trimmed_line_extents (PangoLayoutIter *iter, { g_return_if_fail (ITER_IS_VALID (iter)); - pango_layout_line_get_trimmed_extents (iter->line, trim, logical_rect); + pango_line_get_trimmed_extents (iter->line, trim, logical_rect); offset_line (iter, NULL, logical_rect); } @@ -707,7 +707,7 @@ pango_layout_iter_get_run_extents (PangoLayoutIter *iter, } else { - GSList *runs = pango_layout_line_get_runs (iter->line); + GSList *runs = pango_line_get_runs (iter->line); if (runs) { /* Virtual run at the end of a nonempty line */ @@ -724,7 +724,7 @@ pango_layout_iter_get_run_extents (PangoLayoutIter *iter, /* Empty line */ PangoRectangle r; - pango_layout_line_get_empty_extents (iter->line, PANGO_LEADING_TRIM_BOTH, &r); + pango_line_get_empty_extents (iter->line, PANGO_LEADING_TRIM_BOTH, &r); if (ink_rect) *ink_rect = r; diff --git a/pango/pango-layout-iter.h b/pango/pango-layout-iter.h index 59e59719..b5d1db0d 100644 --- a/pango/pango-layout-iter.h +++ b/pango/pango-layout-iter.h @@ -21,7 +21,7 @@ PANGO_AVAILABLE_IN_ALL PangoLines * pango_layout_iter_get_lines (PangoLayoutIter *iter); PANGO_AVAILABLE_IN_ALL -PangoLayoutLine * pango_layout_iter_get_line (PangoLayoutIter *iter); +PangoLine * pango_layout_iter_get_line (PangoLayoutIter *iter); PANGO_AVAILABLE_IN_ALL gboolean pango_layout_iter_at_last_line (PangoLayoutIter *iter); diff --git a/pango/pango-layout-line-private.h b/pango/pango-layout-line-private.h deleted file mode 100644 index 50760c52..00000000 --- a/pango/pango-layout-line-private.h +++ /dev/null @@ -1,65 +0,0 @@ -#pragma once - -#include "pango-layout-line.h" -#include "pango-break.h" -#include "pango-attributes.h" -#include "pango-glyph-item.h" - -typedef struct _LineData LineData; -struct _LineData { - char *text; - int length; - int n_chars; - PangoDirection direction; - - PangoAttrList *attrs; - PangoLogAttr *log_attrs; -}; - -LineData * line_data_new (void); -LineData * line_data_ref (LineData *data); -void line_data_unref (LineData *data); -void line_data_clear (LineData *data); - -struct _PangoLayoutLine -{ - PangoContext *context; - LineData *data; - - int start_index; - int length; - int start_offset; - int n_chars; - GSList *runs; - - guint wrapped : 1; - guint ellipsized : 1; - guint hyphenated : 1; - guint justified : 1; - guint starts_paragraph : 1; - guint ends_paragraph : 1; - guint has_extents : 1; - - PangoDirection direction; - - PangoRectangle ink_rect; - PangoRectangle logical_rect; -}; - -PangoLayoutLine * pango_layout_line_new (PangoContext *context, - LineData *data); - -void pango_layout_line_ellipsize (PangoLayoutLine *line, - PangoContext *context, - PangoEllipsizeMode ellipsize, - int goal_width); - -void pango_layout_line_index_to_run (PangoLayoutLine *line, - int idx, - PangoRun **run); - -void pango_layout_line_get_empty_extents (PangoLayoutLine *line, - PangoLeadingTrim trim, - PangoRectangle *logical_rect); - -void pango_layout_line_check_invariants (PangoLayoutLine *line); diff --git a/pango/pango-layout-line.c b/pango/pango-layout-line.c deleted file mode 100644 index b581e364..00000000 --- a/pango/pango-layout-line.c +++ /dev/null @@ -1,1575 +0,0 @@ -#include "config.h" - -#include "pango-layout-line-private.h" - -#include "pango-tabs.h" -#include "pango-impl-utils.h" -#include "pango-attributes-private.h" -#include "pango-item-private.h" -#include "pango-run-private.h" - -#include -#include - -/** - * PangoLayoutLine: - * - * A `PangoLayoutLine` is an immutable object which represents a line resulting - * from laying out text via `PangoLayout` or `PangoLineBreaker`. - * - * A line consists of a number of runs (i.e. ranges of text with uniform - * script, font and attributes that are shaped as a unit). Runs are - * represented as [struct@Pango.Run] objects. - * - * A `PangoLayoutLine` always has its origin at the leftmost point of its - * baseline. To position lines in an entire paragraph of text (i.e. in layout - * coordinates), the `PangoLines` object stores X and Y coordinates to - * offset each line to. - * - * The most convenient way to access the visual extents and components - * of a `PangoLayoutLine` is via a [struct@Pango.LayoutIter] iterator. - */ - -/* {{{ LineData */ - -void -line_data_clear (LineData *data) -{ - g_free (data->text); - g_clear_pointer (&data->attrs, pango_attr_list_unref); - g_free (data->log_attrs); -} - -LineData * -line_data_new (void) -{ - return g_rc_box_new0 (LineData); -} - -LineData * -line_data_ref (LineData *data) -{ - return g_rc_box_acquire (data); -} - -void -line_data_unref (LineData *data) -{ - g_rc_box_release_full (data, (GDestroyNotify) line_data_clear); -} - -/* }}} */ -/* {{{ PangoLayoutLine implementation */ - -G_DEFINE_BOXED_TYPE (PangoLayoutLine, pango_layout_line, - pango_layout_line_copy, pango_layout_line_free); - -/* }}} */ -/* {{{ Justification */ - -static inline void -distribute_letter_spacing (int letter_spacing, - int *space_left, - int *space_right) -{ - *space_left = letter_spacing / 2; - - /* hinting */ - if ((letter_spacing & (PANGO_SCALE - 1)) == 0) - *space_left = PANGO_UNITS_ROUND (*space_left); - *space_right = letter_spacing - *space_left; -} - -static int -pango_layout_line_compute_width (PangoLayoutLine *line) -{ - int width = 0; - - /* Compute the width of the line currently - inefficient, but easier - * than keeping the current width of the line up to date everywhere - */ - for (GSList *l = line->runs; l; l = l->next) - { - PangoGlyphItem *run = l->data; - width += pango_glyph_string_get_width (run->glyphs); - } - - return width; -} - -static void -justify_clusters (PangoLayoutLine *line, - int *remaining_width) -{ - int total_remaining_width, total_gaps = 0; - int added_so_far, gaps_so_far; - gboolean is_hinted; - GSList *run_iter; - enum { - MEASURE, - ADJUST - } mode; - - total_remaining_width = *remaining_width; - if (total_remaining_width <= 0) - return; - - /* hint to full pixel if total remaining width was so */ - is_hinted = (total_remaining_width & (PANGO_SCALE - 1)) == 0; - - for (mode = MEASURE; mode <= ADJUST; mode++) - { - gboolean leftedge = TRUE; - PangoGlyphString *rightmost_glyphs = NULL; - int rightmost_space = 0; - int residual = 0; - - added_so_far = 0; - gaps_so_far = 0; - - for (run_iter = line->runs; run_iter; run_iter = run_iter->next) - { - PangoGlyphItem *run = run_iter->data; - PangoGlyphString *glyphs = run->glyphs; - PangoGlyphItemIter cluster_iter; - gboolean have_cluster; - int dir; - int offset; - - dir = run->item->analysis.level % 2 == 0 ? +1 : -1; - /* Note: we simply assert here, since our items are all internally - * created. If that ever changes, we need to add a fallback here. - */ - g_assert (run->item->analysis.flags & PANGO_ANALYSIS_FLAG_HAS_CHAR_OFFSET); - offset = ((PangoItemPrivate *)run->item)->char_offset; - for (have_cluster = dir > 0 ? - pango_glyph_item_iter_init_start (&cluster_iter, run, line->data->text) : - pango_glyph_item_iter_init_end (&cluster_iter, run, line->data->text); - have_cluster; - have_cluster = dir > 0 ? - pango_glyph_item_iter_next_cluster (&cluster_iter) : - pango_glyph_item_iter_prev_cluster (&cluster_iter)) - { - int i; - int width = 0; - - /* don't expand in the middle of graphemes */ - if (!line->data->log_attrs[offset + cluster_iter.start_char].is_cursor_position) - continue; - - for (i = cluster_iter.start_glyph; i != cluster_iter.end_glyph; i += dir) - width += glyphs->glyphs[i].geometry.width; - - /* also don't expand zero-width clusters. */ - if (width == 0) - continue; - - gaps_so_far++; - - if (mode == ADJUST) - { - int leftmost, rightmost; - int adjustment, space_left, space_right; - - adjustment = total_remaining_width / total_gaps + residual; - if (is_hinted) - { - int old_adjustment = adjustment; - adjustment = PANGO_UNITS_ROUND (adjustment); - residual = old_adjustment - adjustment; - } - /* distribute to before/after */ - distribute_letter_spacing (adjustment, &space_left, &space_right); - - if (cluster_iter.start_glyph < cluster_iter.end_glyph) - { - /* LTR */ - leftmost = cluster_iter.start_glyph; - rightmost = cluster_iter.end_glyph - 1; - } - else - { - /* RTL */ - leftmost = cluster_iter.end_glyph + 1; - rightmost = cluster_iter.start_glyph; - } - /* Don't add to left-side of left-most glyph of left-most non-zero run. */ - if (leftedge) - leftedge = FALSE; - else - { - glyphs->glyphs[leftmost].geometry.width += space_left ; - glyphs->glyphs[leftmost].geometry.x_offset += space_left ; - added_so_far += space_left; - } - /* Don't add to right-side of right-most glyph of right-most non-zero run. */ - { - /* Save so we can undo later. */ - rightmost_glyphs = glyphs; - rightmost_space = space_right; - - glyphs->glyphs[rightmost].geometry.width += space_right; - added_so_far += space_right; - } - } - } - } - - if (mode == MEASURE) - { - total_gaps = gaps_so_far - 1; - - if (total_gaps == 0) - { - /* a single cluster, can't really justify it */ - return; - } - } - else /* mode == ADJUST */ - { - if (rightmost_glyphs) - { - rightmost_glyphs->glyphs[rightmost_glyphs->num_glyphs - 1].geometry.width -= rightmost_space; - added_so_far -= rightmost_space; - } - } - } - - *remaining_width -= added_so_far; -} - -static void -justify_words (PangoLayoutLine *line, - int *remaining_width) -{ - int total_remaining_width, total_space_width = 0; - int added_so_far, spaces_so_far; - gboolean is_hinted; - GSList *run_iter; - enum { - MEASURE, - ADJUST - } mode; - - total_remaining_width = *remaining_width; - if (total_remaining_width <= 0) - return; - - /* hint to full pixel if total remaining width was so */ - is_hinted = (total_remaining_width & (PANGO_SCALE - 1)) == 0; - - for (mode = MEASURE; mode <= ADJUST; mode++) - { - added_so_far = 0; - spaces_so_far = 0; - - for (run_iter = line->runs; run_iter; run_iter = run_iter->next) - { - PangoGlyphItem *run = run_iter->data; - PangoGlyphString *glyphs = run->glyphs; - PangoGlyphItemIter cluster_iter; - gboolean have_cluster; - int offset; - - /* Note: we simply assert here, since our items are all internally - * created. If that ever changes, we need to add a fallback here. - */ - g_assert (run->item->analysis.flags & PANGO_ANALYSIS_FLAG_HAS_CHAR_OFFSET); - offset = ((PangoItemPrivate *)run->item)->char_offset; - - for (have_cluster = pango_glyph_item_iter_init_start (&cluster_iter, run, line->data->text); - have_cluster; - have_cluster = pango_glyph_item_iter_next_cluster (&cluster_iter)) - { - int i; - int dir; - - if (!line->data->log_attrs[offset + cluster_iter.start_char].is_expandable_space) - continue; - dir = (cluster_iter.start_glyph < cluster_iter.end_glyph) ? 1 : -1; - for (i = cluster_iter.start_glyph; i != cluster_iter.end_glyph; i += dir) - { - int glyph_width = glyphs->glyphs[i].geometry.width; - - if (glyph_width == 0) - continue; - - spaces_so_far += glyph_width; - - if (mode == ADJUST) - { - int adjustment; - - adjustment = ((guint64) spaces_so_far * total_remaining_width) / total_space_width - added_so_far; - if (is_hinted) - adjustment = PANGO_UNITS_ROUND (adjustment); - - glyphs->glyphs[i].geometry.width += adjustment; - added_so_far += adjustment; - } - } - } - } - - if (mode == MEASURE) - { - total_space_width = spaces_so_far; - - if (total_space_width == 0) - { - justify_clusters (line, remaining_width); - return; - } - } - } - - *remaining_width -= added_so_far; -} - -/* }}} */ -/* {{{ Extents */ - -static void -compute_extents (PangoLayoutLine *line, - PangoLeadingTrim trim, - PangoRectangle *ink, - PangoRectangle *logical) -{ - int x_pos = 0; - - if (!line->runs) - { - memset (ink, 0, sizeof (PangoRectangle)); - pango_layout_line_get_empty_extents (line, trim, logical); - return; - } - - for (GSList *l = line->runs; l; l = l->next) - { - PangoRun *run = l->data; - PangoRectangle run_ink; - PangoRectangle run_logical; - int new_pos; - - pango_run_get_extents (run, trim, &run_ink, &run_logical); - - if (ink->width == 0 || ink->height == 0) - { - *ink = run_ink; - ink->x += x_pos; - } - else if (run_ink.width != 0 && run_ink.height != 0) - { - new_pos = MIN (ink->x, x_pos + run_ink.x); - ink->width = MAX (ink->x + ink->width, - x_pos + run_ink.x + run_ink.width) - new_pos; - ink->x = new_pos; - - new_pos = MIN (ink->y, run_ink.y); - ink->height = MAX (ink->y + ink->height, - run_ink.y + run_ink.height) - new_pos; - ink->y = new_pos; - } - - if (l == line->runs) - { - *logical = run_logical; - logical->x += x_pos; - } - else - { - new_pos = MIN (logical->x, x_pos + run_logical.x); - logical->width = MAX (logical->x + logical->width, - x_pos + run_logical.x + run_logical.width) - new_pos; - logical->x = new_pos; - - new_pos = MIN (logical->y, run_logical.y); - logical->height = MAX (logical->y + logical->height, - run_logical.y + run_logical.height) - new_pos; - logical->y = new_pos; - } - - x_pos += run_logical.width; - } -} - -/* }}} */ -/* {{{ Private API */ - -void -pango_layout_line_check_invariants (PangoLayoutLine *line) -{ - /* Check that byte and char positions agree */ - g_assert (g_utf8_strlen (line->data->text + line->start_index, line->length) == line->n_chars); - g_assert (g_utf8_offset_to_pointer (line->data->text + line->start_index, line->n_chars) == line->data->text + line->start_index + line->length); - - /* Check that runs are sane */ - if (line->runs) - { - int run_min, run_max; - int n_chars; - - run_min = G_MAXINT; - run_max = 0; - n_chars = 0; - for (GSList *l = line->runs; l; l = l->next) - { - PangoGlyphItem *run = l->data; - - run_min = MIN (run_min, run->item->offset); - run_max = MAX (run_max, run->item->offset + run->item->length); - n_chars += run->item->num_chars; - } - - g_assert (run_min == line->start_index); - g_assert (run_max == line->start_index + line->length); - g_assert (n_chars == line->n_chars); - } -} - -void -pango_layout_line_get_empty_extents (PangoLayoutLine *line, - PangoLeadingTrim trim, - PangoRectangle *logical_rect) -{ - PangoFontDescription *font_desc = NULL; - gboolean free_font_desc = FALSE; - double line_height_factor = 0.0; - int absolute_line_height = 0; - PangoFont *font; - - font_desc = pango_context_get_font_description (line->context); - - if (line->data->attrs) - { - PangoAttrIterator iter; - int start, end; - - _pango_attr_list_get_iterator (line->data->attrs, &iter); - - do - { - pango_attr_iterator_range (&iter, &start, &end); - - if (start <= line->start_index && line->start_index < end) - { - PangoAttribute *attr; - - if (!free_font_desc) - { - font_desc = pango_font_description_copy_static (font_desc); - free_font_desc = TRUE; - } - - pango_attr_iterator_get_font (&iter, font_desc, NULL, NULL); - - attr = pango_attr_iterator_get (&iter, PANGO_ATTR_LINE_HEIGHT); - if (attr) - line_height_factor = ((PangoAttrFloat *)attr)->value; - - attr = pango_attr_iterator_get (&iter, PANGO_ATTR_ABSOLUTE_LINE_HEIGHT); - if (attr) - absolute_line_height = ((PangoAttrInt *)attr)->value; - - break; - } - } - while (pango_attr_iterator_next (&iter)); - - _pango_attr_iterator_destroy (&iter); - } - - memset (logical_rect, 0, sizeof (PangoRectangle)); - - font = pango_context_load_font (line->context, font_desc); - if (font) - { - PangoFontMetrics *metrics; - - metrics = pango_font_get_metrics (font, pango_context_get_language (line->context)); - if (metrics) - { - logical_rect->y = - pango_font_metrics_get_ascent (metrics); - logical_rect->height = - logical_rect->y + pango_font_metrics_get_descent (metrics); - - if (trim != PANGO_LEADING_TRIM_BOTH) - { - int leading; - - if (absolute_line_height != 0 || line_height_factor != 0.0) - { - int line_height; - - line_height = MAX (absolute_line_height, ceilf (line_height_factor * logical_rect->height)); - - leading = line_height - logical_rect->height; - } - else - { - leading = MAX (metrics->height - (metrics->ascent + metrics->descent), 0); - } - - if ((trim & PANGO_LEADING_TRIM_START) == 0) - logical_rect->y -= leading / 2; - if (trim == PANGO_LEADING_TRIM_NONE) - logical_rect->height += leading; - else - logical_rect->height += (leading - leading / 2); - } - - pango_font_metrics_unref (metrics); - } - - g_object_unref (font); - } - - if (free_font_desc) - pango_font_description_free (font_desc); -} - -/*< private > - * pango_layout_line_new: - * @context: the `PangoContext` - * @data: the `LineData` - * - * Creates a new `PangoLayoutLine`. - * - * The line shares the immutable `LineData` with other lines. - * - * The @context is needed for shape rendering. - * - * Returns: new `PangoLayoutLine` - */ -PangoLayoutLine * -pango_layout_line_new (PangoContext *context, - LineData *data) -{ - PangoLayoutLine *line; - - line = g_new0 (PangoLayoutLine, 1); - line->context = g_object_ref (context); - line->data = line_data_ref (data); - - return line; -} - -/*< private > - * pango_layout_line_index_to_run: - * @line: a `PangoLayoutLine` - * @idx: a byte offset in the line - * @run: (out): return location for the run - * - * Finds the run in @line which contains @idx. - */ -void -pango_layout_line_index_to_run (PangoLayoutLine *line, - int idx, - PangoRun **run) -{ - *run = NULL; - - for (GSList *l = line->runs; l; l = l->next) - { - PangoRun *r = l->data; - PangoItem *item; - - item = pango_run_get_glyph_item (r)->item; - if (item->offset <= idx && idx < item->offset + item->length) - { - *run = r; - break; - } - } -} - -/* }}} */ -/* {{{ Public API */ - -PangoLayoutLine * -pango_layout_line_copy (PangoLayoutLine *line) -{ - PangoLayoutLine *copy; - - if (line == NULL) - return NULL; - - copy = g_new0 (PangoLayoutLine, 1); - copy->context = g_object_ref (line->context); - copy->data = line_data_ref (line->data); - copy->start_index = line->start_index; - copy->length = line->length; - copy->start_offset = line->start_offset; - copy->n_chars = line->n_chars; - copy->wrapped = line->wrapped; - copy->ellipsized = line->ellipsized; - copy->hyphenated = line->hyphenated; - copy->justified = TRUE; - copy->starts_paragraph = line->starts_paragraph; - copy->ends_paragraph = line->ends_paragraph; - copy->has_extents = FALSE; - copy->direction = line->direction; - copy->runs = g_slist_copy_deep (line->runs, (GCopyFunc) pango_glyph_item_copy, NULL); - - return copy; -} - -void -pango_layout_line_free (PangoLayoutLine *line) -{ - g_object_unref (line->context); - line_data_unref (line->data); - g_slist_free_full (line->runs, (GDestroyNotify)pango_glyph_item_free); - g_free (line); -} - -/* {{{ Simple getters */ - -/** - * pango_layout_line_get_runs: - * @line: a `PangoLayoutLine` - * - * Gets the runs of the line. - * - * Note that the returned list and its contents - * are owned by Pango and must not be modified. - * - * Returns: (transfer none) (element-type PangoGlyphItem): a list of `PangoGlyphItem` - */ -GSList * -pango_layout_line_get_runs (PangoLayoutLine *line) -{ - g_return_val_if_fail (line != NULL, NULL); - - return line->runs; -} - -/** - * pango_layout_line_get_text: - * @line: a `PangoLayoutLine` - * @start_index: the byte index of the first byte of @line - * @length: the number of bytes in @line - * - * Gets the text that @line presents. - * - * The `PangoLayoutLine` represents the slice from @start_index - * to @start_index + @length of the returned string. - * - * The returned string is owned by @line and must not - * be modified. - * - * Returns: the text - */ -const char * -pango_layout_line_get_text (PangoLayoutLine *line, - int *start_index, - int *length) -{ - g_return_val_if_fail (line != NULL, NULL); - g_return_val_if_fail (start_index != NULL, NULL); - g_return_val_if_fail (length != NULL, NULL); - - *start_index = line->start_index; - *length = line->length; - - return line->data->text; -} - -/** - * pango_layout_line_get_start_index: - * @line: a `PangoLayoutLine` - * - * Returns the start index of the line, as byte index - * into the text of the layout. - * - * Returns: the start index of the line - */ -int -pango_layout_line_get_start_index (PangoLayoutLine *line) -{ - g_return_val_if_fail (line != NULL, 0); - - return line->start_index; -} - -/** - * pango_layout_line_get_length: - * @line: a `PangoLayoutLine` - * - * Returns the length of the line, in bytes. - * - * Returns: the length of the line - */ -int -pango_layout_line_get_length (PangoLayoutLine *line) -{ - g_return_val_if_fail (line != NULL, 0); - - return line->length; -} - -/** - * pango_layout_line_get_log_attrs: - * @line: a `PangoLayoutLine` - * @start_offset: the character offset of the first character of @line - * @n_attrs: the number of attributes that apply to @line - * - * Gets the `PangoLogAttr` array for the line. - * - * The `PangoLogAttrs` for @line are the slice from @start_offset - * to @start_offset+@n_attrs of the returned array. @n_attrs is - * be the number of characters plus one. - * - * The returned array is owned by @line and must not be modified. - * - * Returns: the `PangoLogAttr` array - */ -const PangoLogAttr * -pango_layout_line_get_log_attrs (PangoLayoutLine *line, - int *start_offset, - int *n_attrs) -{ - g_return_val_if_fail (line != NULL, NULL); - g_return_val_if_fail (start_offset != NULL, NULL); - g_return_val_if_fail (n_attrs != NULL, NULL); - - *start_offset = line->start_offset; - *n_attrs = line->n_chars + 1; - - return line->data->log_attrs; -} - -/** - * pango_layout_line_is_wrapped: - * @line: a `PangoLayoutLine` - * - * Gets whether the line is wrapped. - * - * Returns: `TRUE` if @line has been wrapped - */ -gboolean -pango_layout_line_is_wrapped (PangoLayoutLine *line) -{ - g_return_val_if_fail (line != NULL, FALSE); - - return line->wrapped; -} - -/** - * pango_layout_line_is_ellipsized: - * @line: a `PangoLayoutLine` - * - * Gets whether the line is ellipsized. - * - * Returns: `TRUE` if @line has been ellipsized - */ -gboolean -pango_layout_line_is_ellipsized (PangoLayoutLine *line) -{ - g_return_val_if_fail (line != NULL, FALSE); - - return line->ellipsized; -} - -/** - * pango_layout_line_is_hyphenated: - * @line: a `PangoLayoutLine` - * - * Gets whether the line is hyphenated. - * - * Returns: `TRUE` if @line has been hyphenated - */ -gboolean -pango_layout_line_is_hyphenated (PangoLayoutLine *line) -{ - g_return_val_if_fail (line != NULL, FALSE); - - return line->hyphenated; -} - -/** - * pango_layout_line_is_justified: - * @line: a `PangoLayoutLine` - * - * Gets whether the line is justified. - * - * See [method@Pango.LayoutLine.justify]. - * - * Returns: `TRUE` if @line has been justified - */ -gboolean -pango_layout_line_is_justified (PangoLayoutLine *line) -{ - g_return_val_if_fail (line != NULL, FALSE); - - return line->justified; -} - -/** - * pango_layout_line_is_paragraph_start: - * @line: a `PangoLayoutLine` - * - * Gets whether the line is the first of a paragraph. - * - * Returns: `TRUE` if @line starts a paragraph - */ -gboolean -pango_layout_line_is_paragraph_start (PangoLayoutLine *line) -{ - g_return_val_if_fail (line != NULL, FALSE); - - return line->starts_paragraph; -} - -/** - * pango_layout_line_ends_paragraph: - * @line: a `PangoLayoutLine` - * - * Gets whether the line is the last of a paragraph. - * - * Returns: `TRUE` if @line ends a paragraph - */ -gboolean -pango_layout_line_is_paragraph_end (PangoLayoutLine *line) -{ - g_return_val_if_fail (line != NULL, FALSE); - - return line->ends_paragraph; -} - -/** - * pango_layout_line_get_resolved_direction: - * @line: a `PangoLayoutLine` - * - * Gets the resolved direction of the line. - * - * Returns: the resolved direction of @line - */ -PangoDirection -pango_layout_line_get_resolved_direction (PangoLayoutLine *line) -{ - g_return_val_if_fail (line != NULL, PANGO_DIRECTION_LTR); - - return line->direction; -} - -/* }}} */ -/* {{{ Justification */ - -/** - * pango_layout_line_justify: - * @line: (transfer full): a `PangoLayoutLine` - * @width: the width to justify @line to - * - * Creates a new `PangoLayoutLine` that is justified - * copy of @line. - * - * The content of the returned line is justified - * to fill the given width, by modifying inter-word - * spaces (and possibly intra-word spaces too). - * - * Note that this function consumes @line. - * - * Returns: (transfer full): a new `PangoLayoutLine` - */ -PangoLayoutLine * -pango_layout_line_justify (PangoLayoutLine *line, - int width) -{ - int remaining_width; - PangoLayoutLine *copy; - - g_return_val_if_fail (line != NULL, NULL); - - remaining_width = width - pango_layout_line_compute_width (line); - if (remaining_width <= 0) - return line; - - copy = pango_layout_line_new (line->context, line->data); - copy->start_index = line->start_index; - copy->length = line->length; - copy->start_offset = line->start_offset; - copy->n_chars = line->n_chars; - copy->wrapped = line->wrapped; - copy->ellipsized = line->ellipsized; - copy->hyphenated = line->hyphenated; - copy->justified = TRUE; - copy->starts_paragraph = line->starts_paragraph; - copy->ends_paragraph = line->ends_paragraph; - copy->has_extents = FALSE; - copy->direction = line->direction; - copy->runs = line->runs; - line->runs = NULL; - - justify_words (copy, &remaining_width); - - pango_layout_line_free (line); - - return copy; -} - -/* }}} */ -/* {{{ Extents */ - -/** - * pango_layout_line_get_extents: - * @line: a `PangoLayoutLine` - * @ink_rect: (out) (optional): rectangle that will be filled with ink extents - * @logical_rect: (out) (optional): rectangle that will be filled with the logical extents - * - * Gets the extents of the line. - * - * The logical extents returned by this function always include leading. - * If you need extents with trimmed leading, use [method@Pango.LayoutLine.get_trimmed_extents]. - * - * Note that the origin is at the left end of the baseline. - * - * Pango is following CSS in splitting the external leading, and giving one half of it - * to the line above, and the other half the the line below. Unless the line height is set - * via attributes, the external leading is determined as the difference between the - * height and ascent + descent in font metrics: - * - * - * - * Pango Font Metrics - * - * - * If spacing is set, it also gets split, for the purpose of determining the - * logical extents. - * - * - * - * Pango Extents and Spacing - * - * - * If line height is set, it determines the logical extents. - * - * - * - * Pango Extents and Line Height - * - */ -void -pango_layout_line_get_extents (PangoLayoutLine *line, - PangoRectangle *ink_rect, - PangoRectangle *logical_rect) -{ - PangoRectangle ink = { 0, }; - PangoRectangle logical = { 0, }; - - if (line->has_extents) - goto cached; - - compute_extents (line, PANGO_LEADING_TRIM_NONE, &ink, &logical); - - line->ink_rect = ink; - line->logical_rect = logical; - line->has_extents = TRUE; - -cached: - if (ink_rect) - *ink_rect = line->ink_rect; - if (logical_rect) - *logical_rect = line->logical_rect; -} - -/** - * pango_layout_line_get_trimmed_extents: - * @line: a `PangoLayoutLine` - * @trim: `PangoLeadingTrim` flags - * @logical_rect: (out): rectangle that will be filled with the logical extents - * - * Gets trimmed logical extents of the line. - * - * The @trim flags specify if line-height attributes are taken - * into consideration for determining the logical height. See the - * [CSS inline layout](https://www.w3.org/TR/css-inline-3/#inline-height) - * specification for details. - * - * Note that the origin is at the left end of the baseline. - */ -void -pango_layout_line_get_trimmed_extents (PangoLayoutLine *line, - PangoLeadingTrim trim, - PangoRectangle *logical_rect) -{ - PangoRectangle ink = { 0, }; - - if (line->has_extents && trim == PANGO_LEADING_TRIM_NONE) - { - *logical_rect = line->logical_rect; - return; - } - - compute_extents (line, trim, &ink, logical_rect); -} - -/* }}} */ -/* {{{ Editing API */ - -/** - * pango_layout_line_layout_index_to_pos: - * @line: a `PangoLayoutLine` - * @idx: byte index within @line - * @pos: (out): rectangle in which to store the position of the grapheme - * - * Converts from an index within a `PangoLayoutLine` to the - * position corresponding to the grapheme at that index. - * - * The return value is represented as rectangle. Note that `pos->x` is - * always the leading edge of the grapheme and `pos->x + pos->width` the - * trailing edge of the grapheme. If the directionality of the grapheme - * is right-to-left, then `pos->width` will be negative. - * - * Note that @idx is allowed to be @line->start_index + @line->length. - */ -void -pango_layout_line_index_to_pos (PangoLayoutLine *line, - int idx, - PangoRectangle *pos) -{ - PangoRectangle run_logical; - PangoRectangle line_logical; - PangoRun *run = NULL; - int x_pos; - - pango_layout_line_get_extents (line, NULL, &line_logical); - - if (!line->runs) - { - *pos = line_logical; - return; - } - - if (idx == line->start_index + line->length) - run = g_slist_last (line->runs)->data; - else - pango_layout_line_index_to_run (line, idx, &run); - - pango_run_get_extents (run, PANGO_LEADING_TRIM_BOTH, NULL, &run_logical); - - pos->y = run_logical.y; - pos->height = run_logical.height; - - /* FIXME: avoid iterating through the runs multiple times */ - - pango_layout_line_index_to_x (line, idx, 0, &x_pos); - pos->x = line_logical.x + x_pos; - - if (idx < line->start_index + line->length) - { - pango_layout_line_index_to_x (line, idx, 1, &x_pos); - pos->width = (line_logical.x + x_pos) - pos->x; - } - else - pos->width = 0; -} - -/** - * pango_layout_line_index_to_x: - * @line: a `PangoLayoutLine` - * @idx: byte index within @line - * @trailing: an integer indicating the edge of the grapheme to retrieve - * the position of. If > 0, the trailing edge of the grapheme, - * if 0, the leading of the grapheme - * @x_pos: (out): location to store the x_offset (in Pango units) - * - * Converts an index within a `PangoLayoutLine` to a X position. - * - * Note that @idx is allowed to be @line->start_index + @line->length. - */ -void -pango_layout_line_index_to_x (PangoLayoutLine *line, - int index, - int trailing, - int *x_pos) -{ - GSList *run_list = line->runs; - int width = 0; - - while (run_list) - { - PangoGlyphItem *run = run_list->data; - - if (run->item->offset <= index && run->item->offset + run->item->length > index) - { - int offset = g_utf8_pointer_to_offset (line->data->text, line->data->text + index); - int attr_offset; - - if (trailing) - { - while (index < line->start_index + line->length && - offset + 1 < line->data->n_chars && - !line->data->log_attrs[offset + 1].is_cursor_position) - { - offset++; - index = g_utf8_next_char (line->data->text + index) - line->data->text; - } - } - else - { - while (index > line->start_index && - !line->data->log_attrs[offset].is_cursor_position) - { - offset--; - index = g_utf8_prev_char (line->data->text + index) - line->data->text; - } - } - - /* Note: we simply assert here, since our items are all internally - * created. If that ever changes, we need to add a fallback here. - */ - g_assert (run->item->analysis.flags & PANGO_ANALYSIS_FLAG_HAS_CHAR_OFFSET); - attr_offset = ((PangoItemPrivate *)run->item)->char_offset; - pango_glyph_string_index_to_x_full (run->glyphs, - line->data->text + run->item->offset, - run->item->length, - &run->item->analysis, - line->data->log_attrs + attr_offset, - index - run->item->offset, trailing, x_pos); - if (x_pos) - *x_pos += width; - - return; - } - - width += pango_glyph_string_get_width (run->glyphs); - - run_list = run_list->next; - } - - if (x_pos) - *x_pos = width; -} - -/** - * pango_layout_line_x_to_index: - * @line: a `PangoLayoutLine` - * @x: the X offset (in Pango units) from the left edge of the line - * @idx: (out): location to store calculated byte index for the grapheme - * in which the user clicked - * @trailing: (out): location to store an integer indicating where in the - * grapheme the user clicked. It will either be zero, or the number of - * characters in the grapheme. 0 represents the leading edge of the grapheme. - * - * Converts from x offset to the byte index of the corresponding character - * within the text of the line. - * - * If @x is outside the line, @idx and @trailing will point to the very - * first or very last position in the line. This determination is based on the - * resolved direction of the paragraph; for example, if the resolved direction - * is right-to-left, then an X position to the right of the line (after it) - * results in 0 being stored in @idx and @trailing. An X position to the - * left of the line results in @idx pointing to the (logical) last grapheme - * in the line and @trailing being set to the number of characters in that - * grapheme. The reverse is true for a left-to-right line. - * - * Return value: %FALSE if @x_pos was outside the line, %TRUE if inside - */ -gboolean -pango_layout_line_x_to_index (PangoLayoutLine *line, - int x_pos, - int *index, - int *trailing) -{ - GSList *tmp_list; - gint start_pos = 0; - gint first_index = 0; /* line->start_index */ - gint first_offset; - gint last_index; /* start of last grapheme in line */ - gint last_offset; - gint end_index; /* end iterator for line */ - gint end_offset; /* end iterator for line */ - gint last_trailing; - gboolean suppress_last_trailing; - - /* Find the last index in the line */ - first_index = line->start_index; - - if (line->length == 0) - { - if (index) - *index = first_index; - if (trailing) - *trailing = 0; - - return FALSE; - } - - g_assert (line->length > 0); - - first_offset = g_utf8_pointer_to_offset (line->data->text, line->data->text + line->start_index); - - end_index = first_index + line->length; - end_offset = first_offset + g_utf8_pointer_to_offset (line->data->text + first_index, line->data->text + end_index); - - last_index = end_index; - last_offset = end_offset; - last_trailing = 0; - do - { - last_index = g_utf8_prev_char (line->data->text + last_index) - line->data->text; - last_offset--; - last_trailing++; - } - while (last_offset > first_offset && !line->data->log_attrs[last_offset].is_cursor_position); - - /* This is a HACK. If a program only keeps track of cursor (etc) - * indices and not the trailing flag, then the trailing index of the - * last character on a wrapped line is identical to the leading - * index of the next line. So, we fake it and set the trailing flag - * to zero. - * - * That is, if the text is "now is the time", and is broken between - * 'now' and 'is' - * - * Then when the cursor is actually at: - * - * n|o|w| |i|s| - * ^ - * we lie and say it is at: - * - * n|o|w| |i|s| - * ^ - * - * So the cursor won't appear on the next line before 'the'. - * - * Actually, any program keeping cursor - * positions with wrapped lines should distinguish leading and - * trailing cursors. - */ - if (line->wrapped) - suppress_last_trailing = TRUE; - else - suppress_last_trailing = FALSE; - - if (x_pos < 0) - { - /* pick the leftmost char */ - if (index) - *index = (line->direction == PANGO_DIRECTION_LTR) ? first_index : last_index; - /* and its leftmost edge */ - if (trailing) - *trailing = (line->direction == PANGO_DIRECTION_LTR || suppress_last_trailing) ? 0 : last_trailing; - - return FALSE; - } - - tmp_list = line->runs; - while (tmp_list) - { - PangoGlyphItem *run = tmp_list->data; - int logical_width; - - logical_width = pango_glyph_string_get_width (run->glyphs); - - if (x_pos >= start_pos && x_pos < start_pos + logical_width) - { - int offset; - gboolean char_trailing; - int grapheme_start_index; - int grapheme_start_offset; - int grapheme_end_offset; - int pos; - int char_index; - - pango_glyph_string_x_to_index (run->glyphs, - line->data->text + run->item->offset, run->item->length, - &run->item->analysis, - x_pos - start_pos, - &pos, &char_trailing); - - char_index = run->item->offset + pos; - - /* Convert from characters to graphemes */ - - offset = g_utf8_pointer_to_offset (line->data->text, line->data->text + char_index); - - grapheme_start_offset = offset; - grapheme_start_index = char_index; - while (grapheme_start_offset > first_offset && - !line->data->log_attrs[grapheme_start_offset].is_cursor_position) - { - grapheme_start_index = g_utf8_prev_char (line->data->text + grapheme_start_index) - line->data->text; - grapheme_start_offset--; - } - - grapheme_end_offset = offset; - do - { - grapheme_end_offset++; - } - - while (grapheme_end_offset < end_offset && - !line->data->log_attrs[grapheme_end_offset].is_cursor_position); - - if (index) - *index = grapheme_start_index; - if (trailing) - { - if ((grapheme_end_offset == end_offset && suppress_last_trailing) || - offset + char_trailing <= (grapheme_start_offset + grapheme_end_offset) / 2) - *trailing = 0; - else - *trailing = grapheme_end_offset - grapheme_start_offset; - } - - return TRUE; - } - - start_pos += logical_width; - tmp_list = tmp_list->next; - } - - /* pick the rightmost char */ - if (index) - *index = (line->direction == PANGO_DIRECTION_LTR) ? last_index : first_index; - - /* and its rightmost edge */ - if (trailing) - *trailing = (line->direction == PANGO_DIRECTION_LTR && !suppress_last_trailing) ? last_trailing : 0; - - return FALSE; -} - -/* }}} */ -/* {{{ Cursor positioning */ - -/** - * pango_layout_line_get_cursor_pos: - * @line: a `PangoLayoutLine` - * @idx: the byte index of the cursor - * @strong_pos: (out) (optional): location to store the strong cursor position - * @weak_pos: (out) (optional): location to store the weak cursor position - * - * Given an index within @line, determines the positions that of the - * strong and weak cursors if the insertion point is at that index. - * - * Note that @idx is allowed to be @line->start_index + @line->length. - * - * The position of each cursor is stored as a zero-width rectangle - * with the height of the run extents. - * - * - * - * Cursor positions - * - * - * 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. - * - * The following example shows text with both a strong and a weak cursor. - * - * - * - * Strong and weak cursors - * - * - * The strong cursor has a little arrow pointing to the right, the weak - * cursor to the left. Typing a 'c' in this situation will insert the - * character after the 'b', and typing another Hebrew character, like 'ג', - * will insert it at the end. - */ -void -pango_layout_line_get_cursor_pos (PangoLayoutLine *line, - int idx, - PangoRectangle *strong_pos, - PangoRectangle *weak_pos) -{ - PangoRectangle line_rect = { 666, }; - PangoRectangle run_rect = { 666, }; - PangoDirection dir1, dir2; - int level1, level2; - PangoRun *run = NULL; - int x1_trailing; - int x2; - - if (idx >= line->start_index + line->length) - { - if (line->runs) - run = g_slist_last (line->runs)->data; - } - else - pango_layout_line_index_to_run (line, idx, &run); - - pango_layout_line_get_extents (line, NULL, &line_rect); - if (run) - pango_run_get_extents (run, PANGO_LEADING_TRIM_BOTH, NULL, &run_rect); - else - { - run_rect = line_rect; - x1_trailing = x2 = line_rect.width; - goto done; - } - - /* Examine the trailing edge of the character before the cursor */ - if (idx == line->start_index) - { - dir1 = line->direction; - level1 = dir1 == PANGO_DIRECTION_LTR ? 0 : 1; - if (line->direction == PANGO_DIRECTION_LTR) - x1_trailing = 0; - else - x1_trailing = line_rect.width; - } - else - { - int prev_index = g_utf8_prev_char (line->data->text + idx) - line->data->text; - - if (prev_index >= line->start_index + line->length) - { - dir1 = line->direction; - level1 = dir1 == PANGO_DIRECTION_LTR ? 0 : 1; - x1_trailing = line_rect.width; - } - else - { - PangoRun *prev_run; - - pango_layout_line_index_to_run (line, prev_index, &prev_run); - level1 = pango_run_get_glyph_item (prev_run)->item->analysis.level; - dir1 = level1 % 2 ? PANGO_DIRECTION_RTL : PANGO_DIRECTION_LTR; - pango_layout_line_index_to_x (line, prev_index, TRUE, &x1_trailing); - } - } - - /* Examine the leading edge of the character after the cursor */ - if (idx >= line->start_index + line->length) - { - dir2 = line->direction; - level2 = dir2 == PANGO_DIRECTION_LTR ? 0 : 1; - if (line->direction == PANGO_DIRECTION_LTR) - x2 = line_rect.width; - else - x2 = 0; - } - else - { - pango_layout_line_index_to_x (line, idx, FALSE, &x2); - level2 = pango_run_get_glyph_item (run)->item->analysis.level; - dir2 = level2 % 2 ? PANGO_DIRECTION_RTL : PANGO_DIRECTION_LTR; - } - -done: - if (strong_pos) - { - strong_pos->x = line_rect.x; - - if (dir1 == line->direction && - (dir2 != dir1 || level1 < level2)) - strong_pos->x += x1_trailing; - else - strong_pos->x += x2; - - strong_pos->y = run_rect.y; - strong_pos->width = 0; - strong_pos->height = run_rect.height; - } - - if (weak_pos) - { - weak_pos->x = line_rect.x; - - if (dir1 == line->direction && - (dir2 != dir1 || level1 < level2)) - weak_pos->x += x2; - else - weak_pos->x += x1_trailing; - - weak_pos->y = run_rect.y; - weak_pos->width = 0; - weak_pos->height = run_rect.height; - } -} - -/** - * pango_layout_line_get_caret_pos: - * @line: a `PangoLayoutLine` - * @idx: the byte index of the cursor - * @strong_pos: (out) (optional): location to store the strong cursor position - * @weak_pos: (out) (optional): location to store the weak cursor position - * - * Given an index within @line, determines the positions of the - * strong and weak cursors if the insertion point is at that index. - * - * Note that @idx is allowed to be @line->start_index + @line->length. - * - * This is a variant of [method@Pango.LayoutLine.get_cursor_pos] that applies - * font metric information about caret slope and offset to the positions - * it returns. - * - * - * - * Caret metrics - * - */ -void -pango_layout_line_get_caret_pos (PangoLayoutLine *line, - int idx, - PangoRectangle *strong_pos, - PangoRectangle *weak_pos) -{ - PangoRun *run = NULL; - PangoGlyphItem *glyph_item; - hb_font_t *hb_font; - hb_position_t caret_offset, caret_run, caret_rise, descender; - - pango_layout_line_get_cursor_pos (line, idx, strong_pos, weak_pos); - - if (idx >= line->start_index + line->length) - { - if (line->runs) - run = g_slist_last (line->runs)->data; - } - else - pango_layout_line_index_to_run (line, idx, &run); - - if (!run) - return; - - glyph_item = pango_run_get_glyph_item (run); - hb_font = pango_font_get_hb_font (glyph_item->item->analysis.font); - - if (hb_ot_metrics_get_position (hb_font, HB_OT_METRICS_TAG_HORIZONTAL_CARET_RISE, &caret_rise) && - hb_ot_metrics_get_position (hb_font, HB_OT_METRICS_TAG_HORIZONTAL_CARET_RUN, &caret_run) && - hb_ot_metrics_get_position (hb_font, HB_OT_METRICS_TAG_HORIZONTAL_CARET_OFFSET, &caret_offset) && - hb_ot_metrics_get_position (hb_font, HB_OT_METRICS_TAG_HORIZONTAL_DESCENDER, &descender)) - { - double slope_inv; - int x_scale, y_scale; - - if (strong_pos) - strong_pos->x += caret_offset; - - if (weak_pos) - weak_pos->x += caret_offset; - - if (caret_rise == 0) - return; - - hb_font_get_scale (hb_font, &x_scale, &y_scale); - slope_inv = (caret_run * y_scale) / (double) (caret_rise * x_scale); - - if (strong_pos) - { - strong_pos->x += descender * slope_inv; - strong_pos->width = strong_pos->height * slope_inv; - if (slope_inv < 0) - strong_pos->x -= strong_pos->width; - } - - if (weak_pos) - { - weak_pos->x += descender * slope_inv; - weak_pos->width = weak_pos->height * slope_inv; - if (slope_inv < 0) - weak_pos->x -= weak_pos->width; - } - } -} - -/* }}} */ -/* }}} */ - -/* vim:set foldmethod=marker expandtab: */ diff --git a/pango/pango-layout-line.h b/pango/pango-layout-line.h deleted file mode 100644 index 6c080c23..00000000 --- a/pango/pango-layout-line.h +++ /dev/null @@ -1,107 +0,0 @@ -#pragma once - -#include - -#include -#include - -G_BEGIN_DECLS - -PANGO_AVAILABLE_IN_ALL -GType pango_layout_line_get_type (void) G_GNUC_CONST; - -PANGO_AVAILABLE_IN_ALL -PangoLayoutLine * pango_layout_line_copy (PangoLayoutLine *line); - -PANGO_AVAILABLE_IN_ALL -void pango_layout_line_free (PangoLayoutLine *line); - -PANGO_AVAILABLE_IN_ALL -PangoLayoutLine * pango_layout_line_justify (PangoLayoutLine *line, - int width); - -PANGO_AVAILABLE_IN_ALL -GSList * pango_layout_line_get_runs (PangoLayoutLine *line); - -PANGO_AVAILABLE_IN_ALL -const char * pango_layout_line_get_text (PangoLayoutLine *line, - int *start_index, - int *length); - -PANGO_AVAILABLE_IN_ALL -int pango_layout_line_get_start_index (PangoLayoutLine *line); - -PANGO_AVAILABLE_IN_ALL -int pango_layout_line_get_length (PangoLayoutLine *line); - -PANGO_AVAILABLE_IN_ALL -const PangoLogAttr * pango_layout_line_get_log_attrs (PangoLayoutLine *line, - int *start_offset, - int *n_attrs); - -PANGO_AVAILABLE_IN_ALL -gboolean pango_layout_line_is_wrapped (PangoLayoutLine *line); - -PANGO_AVAILABLE_IN_ALL -gboolean pango_layout_line_is_ellipsized (PangoLayoutLine *line); - -PANGO_AVAILABLE_IN_ALL -gboolean pango_layout_line_is_hyphenated (PangoLayoutLine *line); - -PANGO_AVAILABLE_IN_ALL -gboolean pango_layout_line_is_justified (PangoLayoutLine *line); - -PANGO_AVAILABLE_IN_ALL -gboolean pango_layout_line_is_paragraph_start - (PangoLayoutLine *line); - -PANGO_AVAILABLE_IN_ALL -gboolean pango_layout_line_is_paragraph_end - (PangoLayoutLine *line); - -PANGO_AVAILABLE_IN_ALL -PangoDirection pango_layout_line_get_resolved_direction - (PangoLayoutLine *line); - -PANGO_AVAILABLE_IN_ALL -void pango_layout_line_get_extents (PangoLayoutLine *line, - PangoRectangle *ink_rect, - PangoRectangle *logical_rect); - -PANGO_AVAILABLE_IN_ALL -void pango_layout_line_get_trimmed_extents - (PangoLayoutLine *line, - PangoLeadingTrim trim, - PangoRectangle *logical_rect); - -PANGO_AVAILABLE_IN_ALL -void pango_layout_line_index_to_pos (PangoLayoutLine *line, - int idx, - PangoRectangle *pos); - -PANGO_AVAILABLE_IN_ALL -void pango_layout_line_index_to_x (PangoLayoutLine *line, - int idx, - int trailing, - int *x_pos); - -PANGO_AVAILABLE_IN_ALL -gboolean pango_layout_line_x_to_index (PangoLayoutLine *line, - int x, - int *idx, - int *trailing); - -PANGO_AVAILABLE_IN_ALL -void pango_layout_line_get_cursor_pos - (PangoLayoutLine *line, - int idx, - PangoRectangle *strong_pos, - PangoRectangle *weak_pos); - -PANGO_AVAILABLE_IN_ALL -void pango_layout_line_get_caret_pos (PangoLayoutLine *line, - int idx, - PangoRectangle *strong_pos, - PangoRectangle *weak_pos); - -G_END_DECLS diff --git a/pango/pango-layout.c b/pango/pango-layout.c index 619dcad9..bdae079b 100644 --- a/pango/pango-layout.c +++ b/pango/pango-layout.c @@ -2,7 +2,7 @@ #include "pango-layout.h" #include "pango-line-breaker.h" -#include "pango-layout-line-private.h" +#include "pango-line-private.h" #include "pango-enum-types.h" #include "pango-markup.h" #include "pango-context.h" @@ -649,7 +649,7 @@ ensure_lines (PangoLayout *layout) line_no = 0; while (pango_line_breaker_has_line (breaker)) { - PangoLayoutLine *line; + PangoLine *line; PangoRectangle ext; int offset; PangoEllipsizeMode ellipsize = PANGO_ELLIPSIZE_NONE; @@ -670,7 +670,7 @@ ensure_lines (PangoLayout *layout) retry: line = pango_line_breaker_next_line (breaker, x, width, layout->wrap, ellipsize); - pango_layout_line_get_extents (line, NULL, &ext); + pango_line_get_extents (line, NULL, &ext); if (layout->height >= 0 && y + 2 * ext.height >= layout->height && ellipsize != layout->ellipsize) @@ -697,21 +697,21 @@ retry: break; case PANGO_ALIGN_JUSTIFY: - if (!pango_layout_line_is_paragraph_end (line)) + if (!pango_line_is_paragraph_end (line)) { - line = pango_layout_line_justify (line, width); + line = pango_line_justify (line, width); break; } G_GNUC_FALLTHROUGH; case PANGO_ALIGN_NATURAL: { - PangoLayoutLine *first_line; + PangoLine *first_line; if (pango_lines_get_line_count (layout->lines) > 0) first_line = pango_lines_get_line (layout->lines, 0, NULL, NULL); else first_line = line; - if (pango_layout_line_get_resolved_direction (first_line) == PANGO_DIRECTION_LTR) + if (pango_line_get_resolved_direction (first_line) == PANGO_DIRECTION_LTR) break; } G_GNUC_FALLTHROUGH; @@ -740,12 +740,12 @@ retry: int start_index; int start_offset; int offset; - PangoLayoutLine *line; + PangoLine *line; PangoRectangle ext; if (pango_lines_get_line_count (layout->lines) > 0) { - PangoLayoutLine *last; + PangoLine *last; last = pango_lines_get_line (layout->lines, pango_lines_get_line_count (layout->lines) - 1, @@ -768,7 +768,7 @@ retry: offset = 0; } - line = pango_layout_line_new (layout->context, data); + line = pango_line_new (layout->context, data); line->starts_paragraph = TRUE; line->ends_paragraph = TRUE; line->start_index = start_index; @@ -776,7 +776,7 @@ retry: line->start_offset = start_offset; line->n_chars = 0; - pango_layout_line_get_extents (line, NULL, &ext); + pango_line_get_extents (line, NULL, &ext); pango_lines_add_line (layout->lines, line, x + offset, y - ext.y); @@ -1633,7 +1633,7 @@ pango_layout_set_markup (PangoLayout *layout, int pango_layout_get_character_count (PangoLayout *layout) { - PangoLayoutLine *line; + PangoLine *line; g_return_val_if_fail (PANGO_IS_LAYOUT (layout), 0); @@ -1688,7 +1688,7 @@ const PangoLogAttr * pango_layout_get_log_attrs (PangoLayout *layout, int *n_attrs) { - PangoLayoutLine *line; + PangoLine *line; g_return_val_if_fail (PANGO_IS_LAYOUT (layout), NULL); diff --git a/pango/pango-line-breaker.c b/pango/pango-line-breaker.c index 8a2a9bd9..3461e021 100644 --- a/pango/pango-line-breaker.c +++ b/pango/pango-line-breaker.c @@ -1,7 +1,7 @@ #include "config.h" #include "pango-line-breaker.h" -#include "pango-layout-line-private.h" +#include "pango-line-private.h" #include "pango-tabs.h" #include "pango-impl-utils.h" @@ -28,7 +28,7 @@ * to influence the formatting. * * Then you can call [method@Pango.LineBreaker.next_line] repeatedly to obtain - * `PangoLayoutLine` objects for the text, one by one. The parameters that are + * `PangoLine` objects for the text, one by one. The parameters that are * passed to `pango_line_breaker_next_line`, as well as properties of the * `PangoLineBreaker` can be changed from call to call. For example, you can * pass `PANGO_ELLIPSIZE_END` to consume the remaining text with a single, @@ -39,7 +39,7 @@ * is to add them to a [class@Pango.Lines] object, together with positioning * information. Before doing so, you can tweak the line or its offset, for * example to implement alignment and justification (for the latter, see - * [method@Pango.LayoutLine.justify]). + * [method@Pango.Line.justify]). * * `PangoLineBreaker` is meant to enable use cases like flowing text around * images, shaped paragraphs or multi-column layout. For simple formatting @@ -412,7 +412,7 @@ get_resolved_dir (PangoLineBreaker *self) static gboolean should_ellipsize_current_line (PangoLineBreaker *self, - PangoLayoutLine *line) + PangoLine *line) { return self->line_ellipsize != PANGO_ELLIPSIZE_NONE && self->line_width >= 0; } @@ -453,7 +453,7 @@ get_decimal_prefix_width (PangoItem *item, } static int -pango_line_compute_width (PangoLayoutLine *line) +pango_line_compute_width (PangoLine *line) { int width = 0; @@ -471,7 +471,7 @@ pango_line_compute_width (PangoLayoutLine *line) static inline int get_line_width (PangoLineBreaker *self, - PangoLayoutLine *line) + PangoLine *line) { if (self->remaining_width > -1) return self->line_width - self->remaining_width; @@ -610,7 +610,7 @@ pad_glyphstring_left (PangoLineBreaker *self, } static gboolean -is_tab_run (PangoLayoutLine *line, +is_tab_run (PangoLine *line, PangoGlyphItem *run) { return line->data->text[run->item->offset] == '\t'; @@ -686,7 +686,7 @@ reorder_runs_recurse (GSList *items, } static void -pango_line_reorder (PangoLayoutLine *line) +pango_line_reorder (PangoLine *line) { GSList *logical_runs = line->runs; GSList *tmp_list; @@ -724,7 +724,7 @@ pango_line_reorder (PangoLayoutLine *line) } static int -compute_n_chars (PangoLayoutLine *line) +compute_n_chars (PangoLine *line) { int n_chars = 0; @@ -742,7 +742,7 @@ compute_n_chars (PangoLayoutLine *line) static void get_tab_pos (PangoLineBreaker *self, - PangoLayoutLine *line, + PangoLine *line, int index, int *tab_pos, PangoTabAlign *alignment, @@ -818,7 +818,7 @@ get_tab_pos (PangoLineBreaker *self, static void shape_tab (PangoLineBreaker *self, - PangoLayoutLine *line, + PangoLine *line, int current_width, PangoItem *item, PangoGlyphString *glyphs) @@ -921,7 +921,7 @@ distribute_letter_spacing (int letter_spacing, static PangoGlyphString * shape_run (PangoLineBreaker *self, - PangoLayoutLine *line, + PangoLine *line, PangoItem *item) { PangoGlyphString *glyphs = pango_glyph_string_new (); @@ -1010,7 +1010,7 @@ free_run (PangoGlyphItem *run, } static PangoItem * -uninsert_run (PangoLayoutLine *line) +uninsert_run (PangoLine *line) { PangoGlyphItem *run; PangoItem *item; @@ -1031,7 +1031,7 @@ uninsert_run (PangoLayoutLine *line) static void insert_run (PangoLineBreaker *self, - PangoLayoutLine *line, + PangoLine *line, PangoItem *run_item, PangoGlyphString *glyphs, gboolean last_run) @@ -1250,10 +1250,10 @@ typedef enum static BreakResult process_item (PangoLineBreaker *self, - PangoLayoutLine *line, - gboolean force_fit, - gboolean no_break_at_end, - gboolean is_last_item) + PangoLine *line, + gboolean force_fit, + gboolean no_break_at_end, + gboolean is_last_item) { PangoItem *item = self->items->data; gboolean shape_set = FALSE; @@ -1596,7 +1596,7 @@ retry_break: static void process_line (PangoLineBreaker *self, - PangoLayoutLine *line) + PangoLine *line) { gboolean have_break = FALSE; /* If we've seen a possible break yet */ int break_remaining_width = 0; /* Remaining width before adding run with break */ @@ -1711,7 +1711,7 @@ done: static void add_missing_hyphen (PangoLineBreaker *self, - PangoLayoutLine *line) + PangoLine *line) { PangoGlyphItem *run; PangoItem *item; @@ -1754,7 +1754,7 @@ add_missing_hyphen (PangoLineBreaker *self, static void zero_line_final_space (PangoLineBreaker *self, - PangoLayoutLine *line) + PangoLine *line) { PangoGlyphItem *run; PangoItem *item; @@ -1813,7 +1813,7 @@ zero_line_final_space (PangoLineBreaker *self, */ static void adjust_line_letter_spacing (PangoLineBreaker *self, - PangoLayoutLine *line) + PangoLine *line) { gboolean reversed; PangoGlyphItem *last_run; @@ -2024,7 +2024,7 @@ collect_baseline_shift (PangoLineBreaker *self, static void apply_baseline_shift (PangoLineBreaker *self, - PangoLayoutLine *line) + PangoLine *line) { int y_offset = 0; PangoItem *prev = NULL; @@ -2052,7 +2052,7 @@ apply_baseline_shift (PangoLineBreaker *self, static void apply_render_attributes (PangoLineBreaker *self, - PangoLayoutLine *line) + PangoLine *line) { GSList *runs; @@ -2079,7 +2079,7 @@ apply_render_attributes (PangoLineBreaker *self, static void postprocess_line (PangoLineBreaker *self, - PangoLayoutLine *line) + PangoLine *line) { add_missing_hyphen (self, line); @@ -2092,7 +2092,7 @@ postprocess_line (PangoLineBreaker *self, apply_baseline_shift (self, line); if (should_ellipsize_current_line (self, line)) - pango_layout_line_ellipsize (line, self->context, self->line_ellipsize, self->line_width); + pango_line_ellipsize (line, self->context, self->line_ellipsize, self->line_width); /* Now convert logical to visual order */ pango_line_reorder (line); @@ -2485,14 +2485,14 @@ pango_line_breaker_has_line (PangoLineBreaker *self) * Returns: (transfer full) (nullable): the next line, or `NULL` * if @self has no more input */ -PangoLayoutLine * +PangoLine * pango_line_breaker_next_line (PangoLineBreaker *self, int x, int width, PangoWrapMode wrap, PangoEllipsizeMode ellipsize) { - PangoLayoutLine *line; + PangoLine *line; g_return_val_if_fail (PANGO_IS_LINE_BREAKER (self), NULL); @@ -2501,7 +2501,7 @@ pango_line_breaker_next_line (PangoLineBreaker *self, if (!self->items) return NULL; - line = pango_layout_line_new (self->context, self->data); + line = pango_line_new (self->context, self->data); line->start_index = self->line_start_index; line->start_offset = self->line_start_offset; @@ -2544,7 +2544,7 @@ pango_line_breaker_next_line (PangoLineBreaker *self, g_clear_pointer (&self->render_attrs, pango_attr_list_unref); } - pango_layout_line_check_invariants (line); + pango_line_check_invariants (line); return line; } @@ -2570,7 +2570,7 @@ pango_line_breaker_next_line (PangoLineBreaker *self, */ gboolean pango_line_breaker_undo_line (PangoLineBreaker *self, - PangoLayoutLine *line) + PangoLine *line) { if (self->data == NULL && line->start_index == 0 && line->length == line->data->length) diff --git a/pango/pango-line-breaker.h b/pango/pango-line-breaker.h index ef8c82b4..30da8c5e 100644 --- a/pango/pango-line-breaker.h +++ b/pango/pango-line-breaker.h @@ -4,7 +4,7 @@ #include #include #include -#include +#include G_BEGIN_DECLS @@ -44,7 +44,7 @@ PANGO_AVAILABLE_IN_ALL gboolean pango_line_breaker_has_line (PangoLineBreaker *self); PANGO_AVAILABLE_IN_ALL -PangoLayoutLine * pango_line_breaker_next_line (PangoLineBreaker *self, +PangoLine * pango_line_breaker_next_line (PangoLineBreaker *self, int x, int width, PangoWrapMode wrap, @@ -52,6 +52,6 @@ PangoLayoutLine * pango_line_breaker_next_line (PangoLineBreaker * PANGO_AVAILABLE_IN_ALL gboolean pango_line_breaker_undo_line (PangoLineBreaker *self, - PangoLayoutLine *line); + PangoLine *line); G_END_DECLS diff --git a/pango/pango-line-private.h b/pango/pango-line-private.h new file mode 100644 index 00000000..2ea21aa9 --- /dev/null +++ b/pango/pango-line-private.h @@ -0,0 +1,65 @@ +#pragma once + +#include "pango-line.h" +#include "pango-break.h" +#include "pango-attributes.h" +#include "pango-glyph-item.h" + +typedef struct _LineData LineData; +struct _LineData { + char *text; + int length; + int n_chars; + PangoDirection direction; + + PangoAttrList *attrs; + PangoLogAttr *log_attrs; +}; + +LineData * line_data_new (void); +LineData * line_data_ref (LineData *data); +void line_data_unref (LineData *data); +void line_data_clear (LineData *data); + +struct _PangoLine +{ + PangoContext *context; + LineData *data; + + int start_index; + int length; + int start_offset; + int n_chars; + GSList *runs; + + guint wrapped : 1; + guint ellipsized : 1; + guint hyphenated : 1; + guint justified : 1; + guint starts_paragraph : 1; + guint ends_paragraph : 1; + guint has_extents : 1; + + PangoDirection direction; + + PangoRectangle ink_rect; + PangoRectangle logical_rect; +}; + +PangoLine * pango_line_new (PangoContext *context, + LineData *data); + +void pango_line_ellipsize (PangoLine *line, + PangoContext *context, + PangoEllipsizeMode ellipsize, + int goal_width); + +void pango_line_index_to_run (PangoLine *line, + int idx, + PangoRun **run); + +void pango_line_get_empty_extents (PangoLine *line, + PangoLeadingTrim trim, + PangoRectangle *logical_rect); + +void pango_line_check_invariants (PangoLine *line); diff --git a/pango/pango-line.c b/pango/pango-line.c new file mode 100644 index 00000000..61258956 --- /dev/null +++ b/pango/pango-line.c @@ -0,0 +1,1575 @@ +#include "config.h" + +#include "pango-line-private.h" + +#include "pango-tabs.h" +#include "pango-impl-utils.h" +#include "pango-attributes-private.h" +#include "pango-item-private.h" +#include "pango-run-private.h" + +#include +#include + +/** + * PangoLine: + * + * A `PangoLine` is an immutable object which represents a line resulting + * from laying out text via `PangoLayout` or `PangoLineBreaker`. + * + * A line consists of a number of runs (i.e. ranges of text with uniform + * script, font and attributes that are shaped as a unit). Runs are + * represented as [struct@Pango.Run] objects. + * + * A `PangoLine` always has its origin at the leftmost point of its + * baseline. To position lines in an entire paragraph of text (i.e. in layout + * coordinates), the `PangoLines` object stores X and Y coordinates to + * 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. + */ + +/* {{{ LineData */ + +void +line_data_clear (LineData *data) +{ + g_free (data->text); + g_clear_pointer (&data->attrs, pango_attr_list_unref); + g_free (data->log_attrs); +} + +LineData * +line_data_new (void) +{ + return g_rc_box_new0 (LineData); +} + +LineData * +line_data_ref (LineData *data) +{ + return g_rc_box_acquire (data); +} + +void +line_data_unref (LineData *data) +{ + g_rc_box_release_full (data, (GDestroyNotify) line_data_clear); +} + +/* }}} */ +/* {{{ PangoLine implementation */ + +G_DEFINE_BOXED_TYPE (PangoLine, pango_line, + pango_line_copy, pango_line_free); + +/* }}} */ +/* {{{ Justification */ + +static inline void +distribute_letter_spacing (int letter_spacing, + int *space_left, + int *space_right) +{ + *space_left = letter_spacing / 2; + + /* hinting */ + if ((letter_spacing & (PANGO_SCALE - 1)) == 0) + *space_left = PANGO_UNITS_ROUND (*space_left); + *space_right = letter_spacing - *space_left; +} + +static int +pango_line_compute_width (PangoLine *line) +{ + int width = 0; + + /* Compute the width of the line currently - inefficient, but easier + * than keeping the current width of the line up to date everywhere + */ + for (GSList *l = line->runs; l; l = l->next) + { + PangoGlyphItem *run = l->data; + width += pango_glyph_string_get_width (run->glyphs); + } + + return width; +} + +static void +justify_clusters (PangoLine *line, + int *remaining_width) +{ + int total_remaining_width, total_gaps = 0; + int added_so_far, gaps_so_far; + gboolean is_hinted; + GSList *run_iter; + enum { + MEASURE, + ADJUST + } mode; + + total_remaining_width = *remaining_width; + if (total_remaining_width <= 0) + return; + + /* hint to full pixel if total remaining width was so */ + is_hinted = (total_remaining_width & (PANGO_SCALE - 1)) == 0; + + for (mode = MEASURE; mode <= ADJUST; mode++) + { + gboolean leftedge = TRUE; + PangoGlyphString *rightmost_glyphs = NULL; + int rightmost_space = 0; + int residual = 0; + + added_so_far = 0; + gaps_so_far = 0; + + for (run_iter = line->runs; run_iter; run_iter = run_iter->next) + { + PangoGlyphItem *run = run_iter->data; + PangoGlyphString *glyphs = run->glyphs; + PangoGlyphItemIter cluster_iter; + gboolean have_cluster; + int dir; + int offset; + + dir = run->item->analysis.level % 2 == 0 ? +1 : -1; + /* Note: we simply assert here, since our items are all internally + * created. If that ever changes, we need to add a fallback here. + */ + g_assert (run->item->analysis.flags & PANGO_ANALYSIS_FLAG_HAS_CHAR_OFFSET); + offset = ((PangoItemPrivate *)run->item)->char_offset; + for (have_cluster = dir > 0 ? + pango_glyph_item_iter_init_start (&cluster_iter, run, line->data->text) : + pango_glyph_item_iter_init_end (&cluster_iter, run, line->data->text); + have_cluster; + have_cluster = dir > 0 ? + pango_glyph_item_iter_next_cluster (&cluster_iter) : + pango_glyph_item_iter_prev_cluster (&cluster_iter)) + { + int i; + int width = 0; + + /* don't expand in the middle of graphemes */ + if (!line->data->log_attrs[offset + cluster_iter.start_char].is_cursor_position) + continue; + + for (i = cluster_iter.start_glyph; i != cluster_iter.end_glyph; i += dir) + width += glyphs->glyphs[i].geometry.width; + + /* also don't expand zero-width clusters. */ + if (width == 0) + continue; + + gaps_so_far++; + + if (mode == ADJUST) + { + int leftmost, rightmost; + int adjustment, space_left, space_right; + + adjustment = total_remaining_width / total_gaps + residual; + if (is_hinted) + { + int old_adjustment = adjustment; + adjustment = PANGO_UNITS_ROUND (adjustment); + residual = old_adjustment - adjustment; + } + /* distribute to before/after */ + distribute_letter_spacing (adjustment, &space_left, &space_right); + + if (cluster_iter.start_glyph < cluster_iter.end_glyph) + { + /* LTR */ + leftmost = cluster_iter.start_glyph; + rightmost = cluster_iter.end_glyph - 1; + } + else + { + /* RTL */ + leftmost = cluster_iter.end_glyph + 1; + rightmost = cluster_iter.start_glyph; + } + /* Don't add to left-side of left-most glyph of left-most non-zero run. */ + if (leftedge) + leftedge = FALSE; + else + { + glyphs->glyphs[leftmost].geometry.width += space_left ; + glyphs->glyphs[leftmost].geometry.x_offset += space_left ; + added_so_far += space_left; + } + /* Don't add to right-side of right-most glyph of right-most non-zero run. */ + { + /* Save so we can undo later. */ + rightmost_glyphs = glyphs; + rightmost_space = space_right; + + glyphs->glyphs[rightmost].geometry.width += space_right; + added_so_far += space_right; + } + } + } + } + + if (mode == MEASURE) + { + total_gaps = gaps_so_far - 1; + + if (total_gaps == 0) + { + /* a single cluster, can't really justify it */ + return; + } + } + else /* mode == ADJUST */ + { + if (rightmost_glyphs) + { + rightmost_glyphs->glyphs[rightmost_glyphs->num_glyphs - 1].geometry.width -= rightmost_space; + added_so_far -= rightmost_space; + } + } + } + + *remaining_width -= added_so_far; +} + +static void +justify_words (PangoLine *line, + int *remaining_width) +{ + int total_remaining_width, total_space_width = 0; + int added_so_far, spaces_so_far; + gboolean is_hinted; + GSList *run_iter; + enum { + MEASURE, + ADJUST + } mode; + + total_remaining_width = *remaining_width; + if (total_remaining_width <= 0) + return; + + /* hint to full pixel if total remaining width was so */ + is_hinted = (total_remaining_width & (PANGO_SCALE - 1)) == 0; + + for (mode = MEASURE; mode <= ADJUST; mode++) + { + added_so_far = 0; + spaces_so_far = 0; + + for (run_iter = line->runs; run_iter; run_iter = run_iter->next) + { + PangoGlyphItem *run = run_iter->data; + PangoGlyphString *glyphs = run->glyphs; + PangoGlyphItemIter cluster_iter; + gboolean have_cluster; + int offset; + + /* Note: we simply assert here, since our items are all internally + * created. If that ever changes, we need to add a fallback here. + */ + g_assert (run->item->analysis.flags & PANGO_ANALYSIS_FLAG_HAS_CHAR_OFFSET); + offset = ((PangoItemPrivate *)run->item)->char_offset; + + for (have_cluster = pango_glyph_item_iter_init_start (&cluster_iter, run, line->data->text); + have_cluster; + have_cluster = pango_glyph_item_iter_next_cluster (&cluster_iter)) + { + int i; + int dir; + + if (!line->data->log_attrs[offset + cluster_iter.start_char].is_expandable_space) + continue; + dir = (cluster_iter.start_glyph < cluster_iter.end_glyph) ? 1 : -1; + for (i = cluster_iter.start_glyph; i != cluster_iter.end_glyph; i += dir) + { + int glyph_width = glyphs->glyphs[i].geometry.width; + + if (glyph_width == 0) + continue; + + spaces_so_far += glyph_width; + + if (mode == ADJUST) + { + int adjustment; + + adjustment = ((guint64) spaces_so_far * total_remaining_width) / total_space_width - added_so_far; + if (is_hinted) + adjustment = PANGO_UNITS_ROUND (adjustment); + + glyphs->glyphs[i].geometry.width += adjustment; + added_so_far += adjustment; + } + } + } + } + + if (mode == MEASURE) + { + total_space_width = spaces_so_far; + + if (total_space_width == 0) + { + justify_clusters (line, remaining_width); + return; + } + } + } + + *remaining_width -= added_so_far; +} + +/* }}} */ +/* {{{ Extents */ + +static void +compute_extents (PangoLine *line, + PangoLeadingTrim trim, + PangoRectangle *ink, + PangoRectangle *logical) +{ + int x_pos = 0; + + if (!line->runs) + { + memset (ink, 0, sizeof (PangoRectangle)); + pango_line_get_empty_extents (line, trim, logical); + return; + } + + for (GSList *l = line->runs; l; l = l->next) + { + PangoRun *run = l->data; + PangoRectangle run_ink; + PangoRectangle run_logical; + int new_pos; + + pango_run_get_extents (run, trim, &run_ink, &run_logical); + + if (ink->width == 0 || ink->height == 0) + { + *ink = run_ink; + ink->x += x_pos; + } + else if (run_ink.width != 0 && run_ink.height != 0) + { + new_pos = MIN (ink->x, x_pos + run_ink.x); + ink->width = MAX (ink->x + ink->width, + x_pos + run_ink.x + run_ink.width) - new_pos; + ink->x = new_pos; + + new_pos = MIN (ink->y, run_ink.y); + ink->height = MAX (ink->y + ink->height, + run_ink.y + run_ink.height) - new_pos; + ink->y = new_pos; + } + + if (l == line->runs) + { + *logical = run_logical; + logical->x += x_pos; + } + else + { + new_pos = MIN (logical->x, x_pos + run_logical.x); + logical->width = MAX (logical->x + logical->width, + x_pos + run_logical.x + run_logical.width) - new_pos; + logical->x = new_pos; + + new_pos = MIN (logical->y, run_logical.y); + logical->height = MAX (logical->y + logical->height, + run_logical.y + run_logical.height) - new_pos; + logical->y = new_pos; + } + + x_pos += run_logical.width; + } +} + +/* }}} */ +/* {{{ Private API */ + +void +pango_line_check_invariants (PangoLine *line) +{ + /* Check that byte and char positions agree */ + g_assert (g_utf8_strlen (line->data->text + line->start_index, line->length) == line->n_chars); + g_assert (g_utf8_offset_to_pointer (line->data->text + line->start_index, line->n_chars) == line->data->text + line->start_index + line->length); + + /* Check that runs are sane */ + if (line->runs) + { + int run_min, run_max; + int n_chars; + + run_min = G_MAXINT; + run_max = 0; + n_chars = 0; + for (GSList *l = line->runs; l; l = l->next) + { + PangoGlyphItem *run = l->data; + + run_min = MIN (run_min, run->item->offset); + run_max = MAX (run_max, run->item->offset + run->item->length); + n_chars += run->item->num_chars; + } + + g_assert (run_min == line->start_index); + g_assert (run_max == line->start_index + line->length); + g_assert (n_chars == line->n_chars); + } +} + +void +pango_line_get_empty_extents (PangoLine *line, + PangoLeadingTrim trim, + PangoRectangle *logical_rect) +{ + PangoFontDescription *font_desc = NULL; + gboolean free_font_desc = FALSE; + double line_height_factor = 0.0; + int absolute_line_height = 0; + PangoFont *font; + + font_desc = pango_context_get_font_description (line->context); + + if (line->data->attrs) + { + PangoAttrIterator iter; + int start, end; + + _pango_attr_list_get_iterator (line->data->attrs, &iter); + + do + { + pango_attr_iterator_range (&iter, &start, &end); + + if (start <= line->start_index && line->start_index < end) + { + PangoAttribute *attr; + + if (!free_font_desc) + { + font_desc = pango_font_description_copy_static (font_desc); + free_font_desc = TRUE; + } + + pango_attr_iterator_get_font (&iter, font_desc, NULL, NULL); + + attr = pango_attr_iterator_get (&iter, PANGO_ATTR_LINE_HEIGHT); + if (attr) + line_height_factor = ((PangoAttrFloat *)attr)->value; + + attr = pango_attr_iterator_get (&iter, PANGO_ATTR_ABSOLUTE_LINE_HEIGHT); + if (attr) + absolute_line_height = ((PangoAttrInt *)attr)->value; + + break; + } + } + while (pango_attr_iterator_next (&iter)); + + _pango_attr_iterator_destroy (&iter); + } + + memset (logical_rect, 0, sizeof (PangoRectangle)); + + font = pango_context_load_font (line->context, font_desc); + if (font) + { + PangoFontMetrics *metrics; + + metrics = pango_font_get_metrics (font, pango_context_get_language (line->context)); + if (metrics) + { + logical_rect->y = - pango_font_metrics_get_ascent (metrics); + logical_rect->height = - logical_rect->y + pango_font_metrics_get_descent (metrics); + + if (trim != PANGO_LEADING_TRIM_BOTH) + { + int leading; + + if (absolute_line_height != 0 || line_height_factor != 0.0) + { + int line_height; + + line_height = MAX (absolute_line_height, ceilf (line_height_factor * logical_rect->height)); + + leading = line_height - logical_rect->height; + } + else + { + leading = MAX (metrics->height - (metrics->ascent + metrics->descent), 0); + } + + if ((trim & PANGO_LEADING_TRIM_START) == 0) + logical_rect->y -= leading / 2; + if (trim == PANGO_LEADING_TRIM_NONE) + logical_rect->height += leading; + else + logical_rect->height += (leading - leading / 2); + } + + pango_font_metrics_unref (metrics); + } + + g_object_unref (font); + } + + if (free_font_desc) + pango_font_description_free (font_desc); +} + +/*< private > + * pango_line_new: + * @context: the `PangoContext` + * @data: the `LineData` + * + * Creates a new `PangoLine`. + * + * The line shares the immutable `LineData` with other lines. + * + * The @context is needed for shape rendering. + * + * Returns: new `PangoLine` + */ +PangoLine * +pango_line_new (PangoContext *context, + LineData *data) +{ + PangoLine *line; + + line = g_new0 (PangoLine, 1); + line->context = g_object_ref (context); + line->data = line_data_ref (data); + + return line; +} + +/*< private > + * pango_line_index_to_run: + * @line: a `PangoLine` + * @idx: a byte offset in the line + * @run: (out): return location for the run + * + * Finds the run in @line which contains @idx. + */ +void +pango_line_index_to_run (PangoLine *line, + int idx, + PangoRun **run) +{ + *run = NULL; + + for (GSList *l = line->runs; l; l = l->next) + { + PangoRun *r = l->data; + PangoItem *item; + + item = pango_run_get_glyph_item (r)->item; + if (item->offset <= idx && idx < item->offset + item->length) + { + *run = r; + break; + } + } +} + +/* }}} */ +/* {{{ Public API */ + +PangoLine * +pango_line_copy (PangoLine *line) +{ + PangoLine *copy; + + if (line == NULL) + return NULL; + + copy = g_new0 (PangoLine, 1); + copy->context = g_object_ref (line->context); + copy->data = line_data_ref (line->data); + copy->start_index = line->start_index; + copy->length = line->length; + copy->start_offset = line->start_offset; + copy->n_chars = line->n_chars; + copy->wrapped = line->wrapped; + copy->ellipsized = line->ellipsized; + copy->hyphenated = line->hyphenated; + copy->justified = TRUE; + copy->starts_paragraph = line->starts_paragraph; + copy->ends_paragraph = line->ends_paragraph; + copy->has_extents = FALSE; + copy->direction = line->direction; + copy->runs = g_slist_copy_deep (line->runs, (GCopyFunc) pango_glyph_item_copy, NULL); + + return copy; +} + +void +pango_line_free (PangoLine *line) +{ + g_object_unref (line->context); + line_data_unref (line->data); + g_slist_free_full (line->runs, (GDestroyNotify)pango_glyph_item_free); + g_free (line); +} + +/* {{{ Simple getters */ + +/** + * pango_line_get_runs: + * @line: a `PangoLine` + * + * Gets the runs of the line. + * + * Note that the returned list and its contents + * are owned by Pango and must not be modified. + * + * Returns: (transfer none) (element-type PangoGlyphItem): a list of `PangoGlyphItem` + */ +GSList * +pango_line_get_runs (PangoLine *line) +{ + g_return_val_if_fail (line != NULL, NULL); + + return line->runs; +} + +/** + * pango_line_get_text: + * @line: a `PangoLine` + * @start_index: the byte index of the first byte of @line + * @length: the number of bytes in @line + * + * Gets the text that @line presents. + * + * The `PangoLine` represents the slice from @start_index + * to @start_index + @length of the returned string. + * + * The returned string is owned by @line and must not + * be modified. + * + * Returns: the text + */ +const char * +pango_line_get_text (PangoLine *line, + int *start_index, + int *length) +{ + g_return_val_if_fail (line != NULL, NULL); + g_return_val_if_fail (start_index != NULL, NULL); + g_return_val_if_fail (length != NULL, NULL); + + *start_index = line->start_index; + *length = line->length; + + return line->data->text; +} + +/** + * pango_line_get_start_index: + * @line: a `PangoLine` + * + * Returns the start index of the line, as byte index + * into the text of the layout. + * + * Returns: the start index of the line + */ +int +pango_line_get_start_index (PangoLine *line) +{ + g_return_val_if_fail (line != NULL, 0); + + return line->start_index; +} + +/** + * pango_line_get_length: + * @line: a `PangoLine` + * + * Returns the length of the line, in bytes. + * + * Returns: the length of the line + */ +int +pango_line_get_length (PangoLine *line) +{ + g_return_val_if_fail (line != NULL, 0); + + return line->length; +} + +/** + * pango_line_get_log_attrs: + * @line: a `PangoLine` + * @start_offset: the character offset of the first character of @line + * @n_attrs: the number of attributes that apply to @line + * + * Gets the `PangoLogAttr` array for the line. + * + * The `PangoLogAttrs` for @line are the slice from @start_offset + * to @start_offset+@n_attrs of the returned array. @n_attrs is + * be the number of characters plus one. + * + * The returned array is owned by @line and must not be modified. + * + * Returns: the `PangoLogAttr` array + */ +const PangoLogAttr * +pango_line_get_log_attrs (PangoLine *line, + int *start_offset, + int *n_attrs) +{ + g_return_val_if_fail (line != NULL, NULL); + g_return_val_if_fail (start_offset != NULL, NULL); + g_return_val_if_fail (n_attrs != NULL, NULL); + + *start_offset = line->start_offset; + *n_attrs = line->n_chars + 1; + + return line->data->log_attrs; +} + +/** + * pango_line_is_wrapped: + * @line: a `PangoLine` + * + * Gets whether the line is wrapped. + * + * Returns: `TRUE` if @line has been wrapped + */ +gboolean +pango_line_is_wrapped (PangoLine *line) +{ + g_return_val_if_fail (line != NULL, FALSE); + + return line->wrapped; +} + +/** + * pango_line_is_ellipsized: + * @line: a `PangoLine` + * + * Gets whether the line is ellipsized. + * + * Returns: `TRUE` if @line has been ellipsized + */ +gboolean +pango_line_is_ellipsized (PangoLine *line) +{ + g_return_val_if_fail (line != NULL, FALSE); + + return line->ellipsized; +} + +/** + * pango_line_is_hyphenated: + * @line: a `PangoLine` + * + * Gets whether the line is hyphenated. + * + * Returns: `TRUE` if @line has been hyphenated + */ +gboolean +pango_line_is_hyphenated (PangoLine *line) +{ + g_return_val_if_fail (line != NULL, FALSE); + + return line->hyphenated; +} + +/** + * pango_line_is_justified: + * @line: a `PangoLine` + * + * Gets whether the line is justified. + * + * See [method@Pango.Line.justify]. + * + * Returns: `TRUE` if @line has been justified + */ +gboolean +pango_line_is_justified (PangoLine *line) +{ + g_return_val_if_fail (line != NULL, FALSE); + + return line->justified; +} + +/** + * pango_line_is_paragraph_start: + * @line: a `PangoLine` + * + * Gets whether the line is the first of a paragraph. + * + * Returns: `TRUE` if @line starts a paragraph + */ +gboolean +pango_line_is_paragraph_start (PangoLine *line) +{ + g_return_val_if_fail (line != NULL, FALSE); + + return line->starts_paragraph; +} + +/** + * pango_line_ends_paragraph: + * @line: a `PangoLine` + * + * Gets whether the line is the last of a paragraph. + * + * Returns: `TRUE` if @line ends a paragraph + */ +gboolean +pango_line_is_paragraph_end (PangoLine *line) +{ + g_return_val_if_fail (line != NULL, FALSE); + + return line->ends_paragraph; +} + +/** + * pango_line_get_resolved_direction: + * @line: a `PangoLine` + * + * Gets the resolved direction of the line. + * + * Returns: the resolved direction of @line + */ +PangoDirection +pango_line_get_resolved_direction (PangoLine *line) +{ + g_return_val_if_fail (line != NULL, PANGO_DIRECTION_LTR); + + return line->direction; +} + +/* }}} */ +/* {{{ Justification */ + +/** + * pango_line_justify: + * @line: (transfer full): a `PangoLine` + * @width: the width to justify @line to + * + * Creates a new `PangoLine` that is justified + * copy of @line. + * + * The content of the returned line is justified + * to fill the given width, by modifying inter-word + * spaces (and possibly intra-word spaces too). + * + * Note that this function consumes @line. + * + * Returns: (transfer full): a new `PangoLine` + */ +PangoLine * +pango_line_justify (PangoLine *line, + int width) +{ + int remaining_width; + PangoLine *copy; + + g_return_val_if_fail (line != NULL, NULL); + + remaining_width = width - pango_line_compute_width (line); + if (remaining_width <= 0) + return line; + + copy = pango_line_new (line->context, line->data); + copy->start_index = line->start_index; + copy->length = line->length; + copy->start_offset = line->start_offset; + copy->n_chars = line->n_chars; + copy->wrapped = line->wrapped; + copy->ellipsized = line->ellipsized; + copy->hyphenated = line->hyphenated; + copy->justified = TRUE; + copy->starts_paragraph = line->starts_paragraph; + copy->ends_paragraph = line->ends_paragraph; + copy->has_extents = FALSE; + copy->direction = line->direction; + copy->runs = line->runs; + line->runs = NULL; + + justify_words (copy, &remaining_width); + + pango_line_free (line); + + return copy; +} + +/* }}} */ +/* {{{ Extents */ + +/** + * pango_line_get_extents: + * @line: a `PangoLine` + * @ink_rect: (out) (optional): rectangle that will be filled with ink extents + * @logical_rect: (out) (optional): rectangle that will be filled with the logical extents + * + * Gets the extents of the line. + * + * The logical extents returned by this function always include leading. + * If you need extents with trimmed leading, use [method@Pango.Line.get_trimmed_extents]. + * + * Note that the origin is at the left end of the baseline. + * + * Pango is following CSS in splitting the external leading, and giving one half of it + * to the line above, and the other half the the line below. Unless the line height is set + * via attributes, the external leading is determined as the difference between the + * height and ascent + descent in font metrics: + * + * + * + * Pango Font Metrics + * + * + * If spacing is set, it also gets split, for the purpose of determining the + * logical extents. + * + * + * + * Pango Extents and Spacing + * + * + * If line height is set, it determines the logical extents. + * + * + * + * Pango Extents and Line Height + * + */ +void +pango_line_get_extents (PangoLine *line, + PangoRectangle *ink_rect, + PangoRectangle *logical_rect) +{ + PangoRectangle ink = { 0, }; + PangoRectangle logical = { 0, }; + + if (line->has_extents) + goto cached; + + compute_extents (line, PANGO_LEADING_TRIM_NONE, &ink, &logical); + + line->ink_rect = ink; + line->logical_rect = logical; + line->has_extents = TRUE; + +cached: + if (ink_rect) + *ink_rect = line->ink_rect; + if (logical_rect) + *logical_rect = line->logical_rect; +} + +/** + * pango_line_get_trimmed_extents: + * @line: a `PangoLine` + * @trim: `PangoLeadingTrim` flags + * @logical_rect: (out): rectangle that will be filled with the logical extents + * + * Gets trimmed logical extents of the line. + * + * The @trim flags specify if line-height attributes are taken + * into consideration for determining the logical height. See the + * [CSS inline layout](https://www.w3.org/TR/css-inline-3/#inline-height) + * specification for details. + * + * Note that the origin is at the left end of the baseline. + */ +void +pango_line_get_trimmed_extents (PangoLine *line, + PangoLeadingTrim trim, + PangoRectangle *logical_rect) +{ + PangoRectangle ink = { 0, }; + + if (line->has_extents && trim == PANGO_LEADING_TRIM_NONE) + { + *logical_rect = line->logical_rect; + return; + } + + compute_extents (line, trim, &ink, logical_rect); +} + +/* }}} */ +/* {{{ Editing API */ + +/** + * pango_line_layout_index_to_pos: + * @line: a `PangoLine` + * @idx: byte index within @line + * @pos: (out): rectangle in which to store the position of the grapheme + * + * Converts from an index within a `PangoLine` to the + * position corresponding to the grapheme at that index. + * + * The return value is represented as rectangle. Note that `pos->x` is + * always the leading edge of the grapheme and `pos->x + pos->width` the + * trailing edge of the grapheme. If the directionality of the grapheme + * is right-to-left, then `pos->width` will be negative. + * + * Note that @idx is allowed to be @line->start_index + @line->length. + */ +void +pango_line_index_to_pos (PangoLine *line, + int idx, + PangoRectangle *pos) +{ + PangoRectangle run_logical; + PangoRectangle line_logical; + PangoRun *run = NULL; + int x_pos; + + pango_line_get_extents (line, NULL, &line_logical); + + if (!line->runs) + { + *pos = line_logical; + return; + } + + if (idx == line->start_index + line->length) + run = g_slist_last (line->runs)->data; + else + pango_line_index_to_run (line, idx, &run); + + pango_run_get_extents (run, PANGO_LEADING_TRIM_BOTH, NULL, &run_logical); + + pos->y = run_logical.y; + pos->height = run_logical.height; + + /* FIXME: avoid iterating through the runs multiple times */ + + pango_line_index_to_x (line, idx, 0, &x_pos); + pos->x = line_logical.x + x_pos; + + if (idx < line->start_index + line->length) + { + pango_line_index_to_x (line, idx, 1, &x_pos); + pos->width = (line_logical.x + x_pos) - pos->x; + } + else + pos->width = 0; +} + +/** + * pango_line_index_to_x: + * @line: a `PangoLine` + * @idx: byte index within @line + * @trailing: an integer indicating the edge of the grapheme to retrieve + * the position of. If > 0, the trailing edge of the grapheme, + * if 0, the leading of the grapheme + * @x_pos: (out): location to store the x_offset (in Pango units) + * + * Converts an index within a `PangoLine` to a X position. + * + * Note that @idx is allowed to be @line->start_index + @line->length. + */ +void +pango_line_index_to_x (PangoLine *line, + int index, + int trailing, + int *x_pos) +{ + GSList *run_list = line->runs; + int width = 0; + + while (run_list) + { + PangoGlyphItem *run = run_list->data; + + if (run->item->offset <= index && run->item->offset + run->item->length > index) + { + int offset = g_utf8_pointer_to_offset (line->data->text, line->data->text + index); + int attr_offset; + + if (trailing) + { + while (index < line->start_index + line->length && + offset + 1 < line->data->n_chars && + !line->data->log_attrs[offset + 1].is_cursor_position) + { + offset++; + index = g_utf8_next_char (line->data->text + index) - line->data->text; + } + } + else + { + while (index > line->start_index && + !line->data->log_attrs[offset].is_cursor_position) + { + offset--; + index = g_utf8_prev_char (line->data->text + index) - line->data->text; + } + } + + /* Note: we simply assert here, since our items are all internally + * created. If that ever changes, we need to add a fallback here. + */ + g_assert (run->item->analysis.flags & PANGO_ANALYSIS_FLAG_HAS_CHAR_OFFSET); + attr_offset = ((PangoItemPrivate *)run->item)->char_offset; + pango_glyph_string_index_to_x_full (run->glyphs, + line->data->text + run->item->offset, + run->item->length, + &run->item->analysis, + line->data->log_attrs + attr_offset, + index - run->item->offset, trailing, x_pos); + if (x_pos) + *x_pos += width; + + return; + } + + width += pango_glyph_string_get_width (run->glyphs); + + run_list = run_list->next; + } + + if (x_pos) + *x_pos = width; +} + +/** + * pango_line_x_to_index: + * @line: a `PangoLine` + * @x: the X offset (in Pango units) from the left edge of the line + * @idx: (out): location to store calculated byte index for the grapheme + * in which the user clicked + * @trailing: (out): location to store an integer indicating where in the + * grapheme the user clicked. It will either be zero, or the number of + * characters in the grapheme. 0 represents the leading edge of the grapheme. + * + * Converts from x offset to the byte index of the corresponding character + * within the text of the line. + * + * If @x is outside the line, @idx and @trailing will point to the very + * first or very last position in the line. This determination is based on the + * resolved direction of the paragraph; for example, if the resolved direction + * is right-to-left, then an X position to the right of the line (after it) + * results in 0 being stored in @idx and @trailing. An X position to the + * left of the line results in @idx pointing to the (logical) last grapheme + * in the line and @trailing being set to the number of characters in that + * grapheme. The reverse is true for a left-to-right line. + * + * Return value: %FALSE if @x_pos was outside the line, %TRUE if inside + */ +gboolean +pango_line_x_to_index (PangoLine *line, + int x_pos, + int *index, + int *trailing) +{ + GSList *tmp_list; + gint start_pos = 0; + gint first_index = 0; /* line->start_index */ + gint first_offset; + gint last_index; /* start of last grapheme in line */ + gint last_offset; + gint end_index; /* end iterator for line */ + gint end_offset; /* end iterator for line */ + gint last_trailing; + gboolean suppress_last_trailing; + + /* Find the last index in the line */ + first_index = line->start_index; + + if (line->length == 0) + { + if (index) + *index = first_index; + if (trailing) + *trailing = 0; + + return FALSE; + } + + g_assert (line->length > 0); + + first_offset = g_utf8_pointer_to_offset (line->data->text, line->data->text + line->start_index); + + end_index = first_index + line->length; + end_offset = first_offset + g_utf8_pointer_to_offset (line->data->text + first_index, line->data->text + end_index); + + last_index = end_index; + last_offset = end_offset; + last_trailing = 0; + do + { + last_index = g_utf8_prev_char (line->data->text + last_index) - line->data->text; + last_offset--; + last_trailing++; + } + while (last_offset > first_offset && !line->data->log_attrs[last_offset].is_cursor_position); + + /* This is a HACK. If a program only keeps track of cursor (etc) + * indices and not the trailing flag, then the trailing index of the + * last character on a wrapped line is identical to the leading + * index of the next line. So, we fake it and set the trailing flag + * to zero. + * + * That is, if the text is "now is the time", and is broken between + * 'now' and 'is' + * + * Then when the cursor is actually at: + * + * n|o|w| |i|s| + * ^ + * we lie and say it is at: + * + * n|o|w| |i|s| + * ^ + * + * So the cursor won't appear on the next line before 'the'. + * + * Actually, any program keeping cursor + * positions with wrapped lines should distinguish leading and + * trailing cursors. + */ + if (line->wrapped) + suppress_last_trailing = TRUE; + else + suppress_last_trailing = FALSE; + + if (x_pos < 0) + { + /* pick the leftmost char */ + if (index) + *index = (line->direction == PANGO_DIRECTION_LTR) ? first_index : last_index; + /* and its leftmost edge */ + if (trailing) + *trailing = (line->direction == PANGO_DIRECTION_LTR || suppress_last_trailing) ? 0 : last_trailing; + + return FALSE; + } + + tmp_list = line->runs; + while (tmp_list) + { + PangoGlyphItem *run = tmp_list->data; + int logical_width; + + logical_width = pango_glyph_string_get_width (run->glyphs); + + if (x_pos >= start_pos && x_pos < start_pos + logical_width) + { + int offset; + gboolean char_trailing; + int grapheme_start_index; + int grapheme_start_offset; + int grapheme_end_offset; + int pos; + int char_index; + + pango_glyph_string_x_to_index (run->glyphs, + line->data->text + run->item->offset, run->item->length, + &run->item->analysis, + x_pos - start_pos, + &pos, &char_trailing); + + char_index = run->item->offset + pos; + + /* Convert from characters to graphemes */ + + offset = g_utf8_pointer_to_offset (line->data->text, line->data->text + char_index); + + grapheme_start_offset = offset; + grapheme_start_index = char_index; + while (grapheme_start_offset > first_offset && + !line->data->log_attrs[grapheme_start_offset].is_cursor_position) + { + grapheme_start_index = g_utf8_prev_char (line->data->text + grapheme_start_index) - line->data->text; + grapheme_start_offset--; + } + + grapheme_end_offset = offset; + do + { + grapheme_end_offset++; + } + + while (grapheme_end_offset < end_offset && + !line->data->log_attrs[grapheme_end_offset].is_cursor_position); + + if (index) + *index = grapheme_start_index; + if (trailing) + { + if ((grapheme_end_offset == end_offset && suppress_last_trailing) || + offset + char_trailing <= (grapheme_start_offset + grapheme_end_offset) / 2) + *trailing = 0; + else + *trailing = grapheme_end_offset - grapheme_start_offset; + } + + return TRUE; + } + + start_pos += logical_width; + tmp_list = tmp_list->next; + } + + /* pick the rightmost char */ + if (index) + *index = (line->direction == PANGO_DIRECTION_LTR) ? last_index : first_index; + + /* and its rightmost edge */ + if (trailing) + *trailing = (line->direction == PANGO_DIRECTION_LTR && !suppress_last_trailing) ? last_trailing : 0; + + return FALSE; +} + +/* }}} */ +/* {{{ Cursor positioning */ + +/** + * pango_line_get_cursor_pos: + * @line: a `PangoLine` + * @idx: the byte index of the cursor + * @strong_pos: (out) (optional): location to store the strong cursor position + * @weak_pos: (out) (optional): location to store the weak cursor position + * + * Given an index within @line, determines the positions that of the + * strong and weak cursors if the insertion point is at that index. + * + * Note that @idx is allowed to be @line->start_index + @line->length. + * + * The position of each cursor is stored as a zero-width rectangle + * with the height of the run extents. + * + * + * + * Cursor positions + * + * + * 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. + * + * The following example shows text with both a strong and a weak cursor. + * + * + * + * Strong and weak cursors + * + * + * The strong cursor has a little arrow pointing to the right, the weak + * cursor to the left. Typing a 'c' in this situation will insert the + * character after the 'b', and typing another Hebrew character, like 'ג', + * will insert it at the end. + */ +void +pango_line_get_cursor_pos (PangoLine *line, + int idx, + PangoRectangle *strong_pos, + PangoRectangle *weak_pos) +{ + PangoRectangle line_rect = { 666, }; + PangoRectangle run_rect = { 666, }; + PangoDirection dir1, dir2; + int level1, level2; + PangoRun *run = NULL; + int x1_trailing; + int x2; + + if (idx >= line->start_index + line->length) + { + if (line->runs) + run = g_slist_last (line->runs)->data; + } + else + pango_line_index_to_run (line, idx, &run); + + pango_line_get_extents (line, NULL, &line_rect); + if (run) + pango_run_get_extents (run, PANGO_LEADING_TRIM_BOTH, NULL, &run_rect); + else + { + run_rect = line_rect; + x1_trailing = x2 = line_rect.width; + goto done; + } + + /* Examine the trailing edge of the character before the cursor */ + if (idx == line->start_index) + { + dir1 = line->direction; + level1 = dir1 == PANGO_DIRECTION_LTR ? 0 : 1; + if (line->direction == PANGO_DIRECTION_LTR) + x1_trailing = 0; + else + x1_trailing = line_rect.width; + } + else + { + int prev_index = g_utf8_prev_char (line->data->text + idx) - line->data->text; + + if (prev_index >= line->start_index + line->length) + { + dir1 = line->direction; + level1 = dir1 == PANGO_DIRECTION_LTR ? 0 : 1; + x1_trailing = line_rect.width; + } + else + { + PangoRun *prev_run; + + pango_line_index_to_run (line, prev_index, &prev_run); + level1 = pango_run_get_glyph_item (prev_run)->item->analysis.level; + dir1 = level1 % 2 ? PANGO_DIRECTION_RTL : PANGO_DIRECTION_LTR; + pango_line_index_to_x (line, prev_index, TRUE, &x1_trailing); + } + } + + /* Examine the leading edge of the character after the cursor */ + if (idx >= line->start_index + line->length) + { + dir2 = line->direction; + level2 = dir2 == PANGO_DIRECTION_LTR ? 0 : 1; + if (line->direction == PANGO_DIRECTION_LTR) + x2 = line_rect.width; + else + x2 = 0; + } + else + { + pango_line_index_to_x (line, idx, FALSE, &x2); + level2 = pango_run_get_glyph_item (run)->item->analysis.level; + dir2 = level2 % 2 ? PANGO_DIRECTION_RTL : PANGO_DIRECTION_LTR; + } + +done: + if (strong_pos) + { + strong_pos->x = line_rect.x; + + if (dir1 == line->direction && + (dir2 != dir1 || level1 < level2)) + strong_pos->x += x1_trailing; + else + strong_pos->x += x2; + + strong_pos->y = run_rect.y; + strong_pos->width = 0; + strong_pos->height = run_rect.height; + } + + if (weak_pos) + { + weak_pos->x = line_rect.x; + + if (dir1 == line->direction && + (dir2 != dir1 || level1 < level2)) + weak_pos->x += x2; + else + weak_pos->x += x1_trailing; + + weak_pos->y = run_rect.y; + weak_pos->width = 0; + weak_pos->height = run_rect.height; + } +} + +/** + * pango_line_get_caret_pos: + * @line: a `PangoLine` + * @idx: the byte index of the cursor + * @strong_pos: (out) (optional): location to store the strong cursor position + * @weak_pos: (out) (optional): location to store the weak cursor position + * + * Given an index within @line, determines the positions of the + * strong and weak cursors if the insertion point is at that index. + * + * Note that @idx is allowed to be @line->start_index + @line->length. + * + * This is a variant of [method@Pango.Line.get_cursor_pos] that applies + * font metric information about caret slope and offset to the positions + * it returns. + * + * + * + * Caret metrics + * + */ +void +pango_line_get_caret_pos (PangoLine *line, + int idx, + PangoRectangle *strong_pos, + PangoRectangle *weak_pos) +{ + PangoRun *run = NULL; + PangoGlyphItem *glyph_item; + hb_font_t *hb_font; + hb_position_t caret_offset, caret_run, caret_rise, descender; + + pango_line_get_cursor_pos (line, idx, strong_pos, weak_pos); + + if (idx >= line->start_index + line->length) + { + if (line->runs) + run = g_slist_last (line->runs)->data; + } + else + pango_line_index_to_run (line, idx, &run); + + if (!run) + return; + + glyph_item = pango_run_get_glyph_item (run); + hb_font = pango_font_get_hb_font (glyph_item->item->analysis.font); + + if (hb_ot_metrics_get_position (hb_font, HB_OT_METRICS_TAG_HORIZONTAL_CARET_RISE, &caret_rise) && + hb_ot_metrics_get_position (hb_font, HB_OT_METRICS_TAG_HORIZONTAL_CARET_RUN, &caret_run) && + hb_ot_metrics_get_position (hb_font, HB_OT_METRICS_TAG_HORIZONTAL_CARET_OFFSET, &caret_offset) && + hb_ot_metrics_get_position (hb_font, HB_OT_METRICS_TAG_HORIZONTAL_DESCENDER, &descender)) + { + double slope_inv; + int x_scale, y_scale; + + if (strong_pos) + strong_pos->x += caret_offset; + + if (weak_pos) + weak_pos->x += caret_offset; + + if (caret_rise == 0) + return; + + hb_font_get_scale (hb_font, &x_scale, &y_scale); + slope_inv = (caret_run * y_scale) / (double) (caret_rise * x_scale); + + if (strong_pos) + { + strong_pos->x += descender * slope_inv; + strong_pos->width = strong_pos->height * slope_inv; + if (slope_inv < 0) + strong_pos->x -= strong_pos->width; + } + + if (weak_pos) + { + weak_pos->x += descender * slope_inv; + weak_pos->width = weak_pos->height * slope_inv; + if (slope_inv < 0) + weak_pos->x -= weak_pos->width; + } + } +} + +/* }}} */ +/* }}} */ + +/* vim:set foldmethod=marker expandtab: */ diff --git a/pango/pango-line.h b/pango/pango-line.h new file mode 100644 index 00000000..665ced7e --- /dev/null +++ b/pango/pango-line.h @@ -0,0 +1,106 @@ +#pragma once + +#include + +#include +#include + +G_BEGIN_DECLS + +PANGO_AVAILABLE_IN_ALL +GType pango_line_get_type (void) G_GNUC_CONST; + +PANGO_AVAILABLE_IN_ALL +PangoLine * pango_line_copy (PangoLine *line); + +PANGO_AVAILABLE_IN_ALL +void pango_line_free (PangoLine *line); + +PANGO_AVAILABLE_IN_ALL +PangoLine * pango_line_justify (PangoLine *line, + int width); + +PANGO_AVAILABLE_IN_ALL +GSList * pango_line_get_runs (PangoLine *line); + +PANGO_AVAILABLE_IN_ALL +const char * pango_line_get_text (PangoLine *line, + int *start_index, + int *length); + +PANGO_AVAILABLE_IN_ALL +int pango_line_get_start_index (PangoLine *line); + +PANGO_AVAILABLE_IN_ALL +int pango_line_get_length (PangoLine *line); + +PANGO_AVAILABLE_IN_ALL +const PangoLogAttr * pango_line_get_log_attrs (PangoLine *line, + int *start_offset, + int *n_attrs); + +PANGO_AVAILABLE_IN_ALL +gboolean pango_line_is_wrapped (PangoLine *line); + +PANGO_AVAILABLE_IN_ALL +gboolean pango_line_is_ellipsized (PangoLine *line); + +PANGO_AVAILABLE_IN_ALL +gboolean pango_line_is_hyphenated (PangoLine *line); + +PANGO_AVAILABLE_IN_ALL +gboolean pango_line_is_justified (PangoLine *line); + +PANGO_AVAILABLE_IN_ALL +gboolean pango_line_is_paragraph_start + (PangoLine *line); + +PANGO_AVAILABLE_IN_ALL +gboolean pango_line_is_paragraph_end + (PangoLine *line); + +PANGO_AVAILABLE_IN_ALL +PangoDirection pango_line_get_resolved_direction + (PangoLine *line); + +PANGO_AVAILABLE_IN_ALL +void pango_line_get_extents (PangoLine *line, + PangoRectangle *ink_rect, + PangoRectangle *logical_rect); + +PANGO_AVAILABLE_IN_ALL +void pango_line_get_trimmed_extents + (PangoLine *line, + PangoLeadingTrim trim, + PangoRectangle *logical_rect); + +PANGO_AVAILABLE_IN_ALL +void pango_line_index_to_pos (PangoLine *line, + int idx, + PangoRectangle *pos); + +PANGO_AVAILABLE_IN_ALL +void pango_line_index_to_x (PangoLine *line, + int idx, + int trailing, + int *x_pos); + +PANGO_AVAILABLE_IN_ALL +gboolean pango_line_x_to_index (PangoLine *line, + int x, + int *idx, + int *trailing); + +PANGO_AVAILABLE_IN_ALL +void pango_line_get_cursor_pos (PangoLine *line, + int idx, + PangoRectangle *strong_pos, + PangoRectangle *weak_pos); + +PANGO_AVAILABLE_IN_ALL +void pango_line_get_caret_pos (PangoLine *line, + int idx, + PangoRectangle *strong_pos, + PangoRectangle *weak_pos); + +G_END_DECLS diff --git a/pango/pango-lines.c b/pango/pango-lines.c index ac447e91..26b408ed 100644 --- a/pango/pango-lines.c +++ b/pango/pango-lines.c @@ -1,7 +1,7 @@ #include "config.h" #include "pango-lines-private.h" -#include "pango-layout-line-private.h" +#include "pango-line-private.h" #include "pango-item-private.h" #include "pango-layout-iter-private.h" @@ -11,7 +11,7 @@ * A `PangoLines` object represents the result of formatting an * entire paragraph (or more) of text. * - * A `PangoLines` object contains a list of `PangoLayoutLine` objects, + * A `PangoLines` object contains a list of `PangoLine` objects, * together with information about where to position each line * in layout coordinates. * @@ -43,7 +43,7 @@ typedef struct _Line Line; struct _Line { - PangoLayoutLine *line; + PangoLine *line; int x, y; }; @@ -69,7 +69,7 @@ pango_lines_finalize (GObject *object) for (int i = 0; i < lines->lines->len; i++) { Line *line = &g_array_index (lines->lines, Line, i); - pango_layout_line_free (line->line); + pango_line_free (line->line); } g_array_free (lines->lines, TRUE); @@ -104,10 +104,10 @@ compare_cursor (gconstpointer v1, } static void -pango_layout_line_get_cursors (PangoLines *lines, - PangoLayoutLine *line, - gboolean strong, - GArray *cursors) +pango_line_get_cursors (PangoLines *lines, + PangoLine *line, + gboolean strong, + GArray *cursors) { const char *start, *end; int start_offset; @@ -144,7 +144,7 @@ pango_layout_line_get_cursors (PangoLines *lines, { CursorPos cursor; - pango_layout_line_get_cursor_pos (line, idx, + pango_line_get_cursor_pos (line, idx, strong ? &pos : NULL, strong ? NULL : &pos); @@ -200,7 +200,7 @@ pango_lines_get_serial (PangoLines *lines) /** * pango_lines_add_line: * @lines: a `PangoLines` - * @line: (transfer full): the `PangoLayoutLine` to add + * @line: (transfer full): the `PangoLine` to add * @line_x: X coordinate of the position * @line_y: Y coordinate of the position * @@ -212,10 +212,10 @@ pango_lines_get_serial (PangoLines *lines) * Note that this function takes ownership of the line. */ void -pango_lines_add_line (PangoLines *lines, - PangoLayoutLine *line, - int x_line, - int y_line) +pango_lines_add_line (PangoLines *lines, + PangoLine *line, + int x_line, + int y_line) { Line l; @@ -275,11 +275,11 @@ pango_lines_get_line_count (PangoLines *lines) * * Returns: (transfer none) (nullable): the line that was found */ -PangoLayoutLine * -pango_lines_get_line (PangoLines *lines, - int num, - int *line_x, - int *line_y) +PangoLine * +pango_lines_get_line (PangoLines *lines, + int num, + int *line_x, + int *line_y) { Line *l; @@ -351,7 +351,7 @@ pango_lines_is_wrapped (PangoLines *lines) for (int i = 0; i < lines->lines->len; i++) { Line *l = &g_array_index (lines->lines, Line, i); - if (pango_layout_line_is_wrapped (l->line)) + if (pango_line_is_wrapped (l->line)) return TRUE; } @@ -372,7 +372,7 @@ pango_lines_is_ellipsized (PangoLines *lines) for (int i = 0; i < lines->lines->len; i++) { Line *l = &g_array_index (lines->lines, Line, i); - if (pango_layout_line_is_ellipsized (l->line)) + if (pango_line_is_ellipsized (l->line)) return TRUE; } @@ -393,7 +393,7 @@ pango_lines_is_hyphenated (PangoLines *lines) for (int i = 0; i < lines->lines->len; i++) { Line *l = &g_array_index (lines->lines, Line, i); - if (pango_layout_line_is_hyphenated (l->line)) + if (pango_line_is_hyphenated (l->line)) return TRUE; } @@ -437,8 +437,8 @@ pango_lines_get_extents (PangoLines *lines, if (l->line->ends_paragraph) trim |= PANGO_LEADING_TRIM_END; - pango_layout_line_get_extents (l->line, &line_ink, NULL); - pango_layout_line_get_trimmed_extents (l->line, trim, &line_logical); + pango_line_get_extents (l->line, &line_ink, NULL); + pango_line_get_trimmed_extents (l->line, trim, &line_logical); line_ink.x += l->x; line_ink.y += l->y; @@ -531,16 +531,16 @@ pango_lines_get_baseline (PangoLines *lines) } /** - * pango_layout_lines_get_x_ranges: + * pango_lines_get_x_ranges: * @lines: a `PangoLines` object - * @line: the `PangoLayoutLine` in @lines whose x ranges will be reported - * @start_line: (nullable): `PangoLayoutLine` wrt to which @start_index is + * @line: the `PangoLine` in @lines whose x ranges will be reported + * @start_line: (nullable): `PangoLine` wrt to which @start_index is * interpreted or `NULL` for the first matching line * @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_line: (nullable): `PangoLayoutLine` wrt to which @end_index is + * @end_line: (nullable): `PangoLine` wrt to which @end_index is * interpreted or `NULL` for the first matching line * @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 @@ -562,14 +562,14 @@ pango_lines_get_baseline (PangoLines *lines) * layout, not with respect to the line. */ void -pango_lines_get_x_ranges (PangoLines *lines, - PangoLayoutLine *line, - PangoLayoutLine *start_line, - int start_index, - PangoLayoutLine *end_line, - int end_index, - int **ranges, - int *n_ranges) +pango_lines_get_x_ranges (PangoLines *lines, + PangoLine *line, + PangoLine *start_line, + int start_index, + PangoLine *end_line, + int end_index, + int **ranges, + int *n_ranges) { int x_offset; int line_no, start_line_no, end_line_no; @@ -608,7 +608,7 @@ pango_lines_get_x_ranges (PangoLines *lines, *ranges = g_new (int, 2 * (2 + g_slist_length (line->runs))); range_count = 0; - dir = pango_layout_line_get_resolved_direction (line); + dir = pango_line_get_resolved_direction (line); if (x_offset > 0 && ((dir == PANGO_DIRECTION_LTR && start_line_no < line_no) || @@ -621,7 +621,7 @@ pango_lines_get_x_ranges (PangoLines *lines, } accumulated_width = 0; - for (GSList *l = pango_layout_line_get_runs (line); l; l = l->next) + for (GSList *l = pango_line_get_runs (line); l; l = l->next) { PangoGlyphItem *run = l->data; @@ -672,7 +672,7 @@ pango_lines_get_x_ranges (PangoLines *lines, accumulated_width += pango_glyph_string_get_width (run->glyphs); } - pango_layout_line_get_extents (line, NULL, &ext); + pango_line_get_extents (line, NULL, &ext); pango_lines_get_size (lines, &width, NULL); if (x_offset + ext.width < width && @@ -714,12 +714,12 @@ pango_lines_get_x_ranges (PangoLines *lines, * as *@line and use this function to find the line at @idx. */ void -pango_lines_index_to_line (PangoLines *lines, - int idx, - PangoLayoutLine **line, - int *line_no, - int *x_offset, - int *y_offset) +pango_lines_index_to_line (PangoLines *lines, + int idx, + PangoLine **line, + int *line_no, + int *x_offset, + int *y_offset) { Line *found = NULL; int num; @@ -775,7 +775,7 @@ pango_lines_index_to_line (PangoLines *lines, * Returns: (transfer none) (nullable): the line that was found */ -PangoLayoutLine * +PangoLine * pango_lines_pos_to_line (PangoLines *lines, int x, int y, @@ -789,7 +789,7 @@ pango_lines_pos_to_line (PangoLines *lines, Line *l = &g_array_index (lines->lines, Line, i); PangoRectangle ext; - pango_layout_line_get_extents (l->line, NULL, &ext); + pango_line_get_extents (l->line, NULL, &ext); ext.x += l->x; ext.y += l->y; @@ -817,12 +817,12 @@ pango_lines_pos_to_line (PangoLines *lines, /** * pango_lines_index_to_pos: * @lines: a `PangoLines` object - * @line: (nullable): `PangoLayoutLine` wrt to which @idx is interpreted + * @line: (nullable): `PangoLine` wrt to which @idx is interpreted * or `NULL` for the first matching line * @idx: byte index within @line * @pos: (out): rectangle in which to store the position of the grapheme * - * Converts from an index within a `PangoLayoutLine` to the + * Converts from an index within a `PangoLine` to the * position corresponding to the grapheme at that index. * * The return value is represented as rectangle. Note that `pos->x` @@ -834,10 +834,10 @@ pango_lines_pos_to_line (PangoLines *lines, * for the position off the end of the last line. */ void -pango_lines_index_to_pos (PangoLines *lines, - PangoLayoutLine *line, - int idx, - PangoRectangle *pos) +pango_lines_index_to_pos (PangoLines *lines, + PangoLine *line, + int idx, + PangoRectangle *pos) { int x_offset, y_offset; @@ -849,7 +849,7 @@ pango_lines_index_to_pos (PangoLines *lines, g_return_if_fail (line != NULL); - pango_layout_line_index_to_pos (line, idx, pos); + pango_line_index_to_pos (line, idx, pos); pos->x += x_offset; pos->y += y_offset; } @@ -870,14 +870,14 @@ pango_lines_index_to_pos (PangoLines *lines, * * Returns: (transfer none) (nullable): the line that was found */ -PangoLayoutLine * +PangoLine * pango_lines_pos_to_index (PangoLines *lines, int x, int y, int *idx, int *trailing) { - PangoLayoutLine *line; + PangoLine *line; int x_offset; g_return_val_if_fail (PANGO_IS_LINES (lines), FALSE); @@ -886,7 +886,7 @@ pango_lines_pos_to_index (PangoLines *lines, line = pango_lines_pos_to_line (lines, x, y, &x_offset, NULL); if (line) - pango_layout_line_x_to_index (line, x - x_offset, idx, trailing); + pango_line_x_to_index (line, x - x_offset, idx, trailing); return line; } @@ -897,7 +897,7 @@ pango_lines_pos_to_index (PangoLines *lines, /** * pango_lines_get_cursor_pos: * @lines: a `PangoLines` object - * @line: (nullable): `PangoLayoutLine` wrt to which @idx is interpreted + * @line: (nullable): `PangoLine` wrt to which @idx is interpreted * or `NULL` for the first matching line * @idx: the byte index of the cursor * @strong_pos: (out) (optional): location to store the strong cursor position @@ -936,13 +936,13 @@ pango_lines_pos_to_index (PangoLines *lines, */ void pango_lines_get_cursor_pos (PangoLines *lines, - PangoLayoutLine *line, + PangoLine *line, int idx, PangoRectangle *strong_pos, PangoRectangle *weak_pos) { int x_offset, y_offset; - PangoLayoutLine *l; + PangoLine *l; g_return_if_fail (PANGO_IS_LINES (lines)); @@ -954,7 +954,7 @@ pango_lines_get_cursor_pos (PangoLines *lines, line = l; - pango_layout_line_get_cursor_pos (line, idx, strong_pos, weak_pos); + pango_line_get_cursor_pos (line, idx, strong_pos, weak_pos); if (strong_pos) { @@ -971,7 +971,7 @@ pango_lines_get_cursor_pos (PangoLines *lines, /** * pango_lines_get_caret_pos: * @lines: a `PangoLines` object - * @line: (nullable): `PangoLayoutLine` wrt to which @idx is interpreted + * @line: (nullable): `PangoLine` wrt to which @idx is interpreted * or `NULL` for the first matching line * @idx: the byte index of the cursor * @strong_pos: (out) (optional): location to store the strong cursor position @@ -994,7 +994,7 @@ pango_lines_get_cursor_pos (PangoLines *lines, */ void pango_lines_get_caret_pos (PangoLines *lines, - PangoLayoutLine *line, + PangoLine *line, int idx, PangoRectangle *strong_pos, PangoRectangle *weak_pos) @@ -1007,7 +1007,7 @@ pango_lines_get_caret_pos (PangoLines *lines, g_return_if_fail (line != NULL); - pango_layout_line_get_caret_pos (line, idx, strong_pos, weak_pos); + pango_line_get_caret_pos (line, idx, strong_pos, weak_pos); if (strong_pos) { @@ -1027,7 +1027,7 @@ pango_lines_get_caret_pos (PangoLines *lines, * @strong: whether the moving cursor is the strong cursor or the * weak cursor. The strong cursor is the cursor corresponding * to text insertion in the base direction for the layout. - * @line: (nullable): `PangoLayoutLine` wrt to which @idx is interpreted + * @line: (nullable): `PangoLine` wrt to which @idx is interpreted * or `NULL` for the first matching line * @idx: the byte index of the current cursor position * @trailing: if 0, the cursor was at the leading edge of the @@ -1035,7 +1035,7 @@ pango_lines_get_caret_pos (PangoLines *lines, * was at the trailing edge. * @direction: direction to move cursor. A negative * value indicates motion to the left - * @new_line: (nullable): `PangoLayoutLine` wrt to which @new_idx is interpreted + * @new_line: (nullable): `PangoLine` wrt to which @new_idx is interpreted * @new_idx: (out): location to store the new cursor byte index * A value of -1 indicates that the cursor has been moved off the * beginning of the layout. A value of %G_MAXINT indicates that @@ -1064,15 +1064,15 @@ pango_lines_get_caret_pos (PangoLines *lines, * when multiple characters combine to form a single grapheme. */ void -pango_lines_move_cursor (PangoLines *lines, - gboolean strong, - PangoLayoutLine *line, - int idx, - int trailing, - int direction, - PangoLayoutLine **new_line, - int *new_idx, - int *new_trailing) +pango_lines_move_cursor (PangoLines *lines, + gboolean strong, + PangoLine *line, + int idx, + int trailing, + int direction, + PangoLine **new_line, + int *new_idx, + int *new_trailing) { int line_no; GArray *cursors; @@ -1104,7 +1104,7 @@ pango_lines_move_cursor (PangoLines *lines, idx = line->start_index + line->length; cursors = g_array_new (FALSE, FALSE, sizeof (CursorPos)); - pango_layout_line_get_cursors (lines, line, strong, cursors); + pango_line_get_cursors (lines, line, strong, cursors); pango_lines_get_cursor_pos (lines, line, idx, strong ? &pos : NULL, strong ? NULL : &pos); @@ -1156,7 +1156,7 @@ pango_lines_move_cursor (PangoLines *lines, if (off_start) { - PangoLayoutLine *prev_line; + PangoLine *prev_line; prev_line = pango_lines_get_line (lines, line_no - 1, NULL, NULL); if (!prev_line) @@ -1175,7 +1175,7 @@ pango_lines_move_cursor (PangoLines *lines, } else { - PangoLayoutLine *next_line; + PangoLine *next_line; next_line = pango_lines_get_line (lines, line_no + 1, NULL, NULL); if (!next_line) @@ -1193,7 +1193,7 @@ pango_lines_move_cursor (PangoLines *lines, } g_array_set_size (cursors, 0); - pango_layout_line_get_cursors (lines, line, strong, cursors); + pango_line_get_cursors (lines, line, strong, cursors); n_vis = cursors->len; diff --git a/pango/pango-lines.h b/pango/pango-lines.h index 97f50384..1e3ec82f 100644 --- a/pango/pango-lines.h +++ b/pango/pango-lines.h @@ -3,7 +3,7 @@ #include #include -#include +#include G_BEGIN_DECLS @@ -22,7 +22,7 @@ guint pango_lines_get_serial (PangoLines *lines); PANGO_AVAILABLE_IN_ALL void pango_lines_add_line (PangoLines *lines, - PangoLayoutLine *line, + PangoLine *line, int line_x, int line_y); @@ -30,7 +30,7 @@ PANGO_AVAILABLE_IN_ALL int pango_lines_get_line_count (PangoLines *lines); PANGO_AVAILABLE_IN_ALL -PangoLayoutLine * pango_lines_get_line (PangoLines *lines, +PangoLine * pango_lines_get_line (PangoLines *lines, int num, int *line_x, int *line_y); @@ -53,10 +53,10 @@ int pango_lines_get_baseline (PangoLines *lines); PANGO_AVAILABLE_IN_ALL void pango_lines_get_x_ranges (PangoLines *lines, - PangoLayoutLine *line, - PangoLayoutLine *start_line, + PangoLine *line, + PangoLine *start_line, int start_index, - PangoLayoutLine *end_line, + PangoLine *end_line, int end_index, int **ranges, int *n_ranges); @@ -77,13 +77,13 @@ gboolean pango_lines_is_hyphenated (PangoLines *lines); PANGO_AVAILABLE_IN_ALL void pango_lines_index_to_line (PangoLines *lines, int idx, - PangoLayoutLine **line, + PangoLine **line, int *line_no, int *x_offset, int *y_offset); PANGO_AVAILABLE_IN_ALL -PangoLayoutLine * pango_lines_pos_to_line (PangoLines *lines, +PangoLine * pango_lines_pos_to_line (PangoLines *lines, int x, int y, int *line_x, @@ -91,12 +91,12 @@ PangoLayoutLine * pango_lines_pos_to_line (PangoLines *lines, PANGO_AVAILABLE_IN_ALL void pango_lines_index_to_pos (PangoLines *lines, - PangoLayoutLine *line, + PangoLine *line, int idx, PangoRectangle *pos); PANGO_AVAILABLE_IN_ALL -PangoLayoutLine * pango_lines_pos_to_index (PangoLines *lines, +PangoLine * pango_lines_pos_to_index (PangoLines *lines, int x, int y, int *idx, @@ -104,14 +104,14 @@ PangoLayoutLine * pango_lines_pos_to_index (PangoLines *lines, PANGO_AVAILABLE_IN_ALL void pango_lines_get_cursor_pos (PangoLines *lines, - PangoLayoutLine *line, + PangoLine *line, int idx, PangoRectangle *strong_pos, PangoRectangle *weak_pos); PANGO_AVAILABLE_IN_ALL void pango_lines_get_caret_pos (PangoLines *lines, - PangoLayoutLine *line, + PangoLine *line, int idx, PangoRectangle *strong_pos, PangoRectangle *weak_pos); @@ -119,11 +119,11 @@ void pango_lines_get_caret_pos (PangoLines *lines, PANGO_AVAILABLE_IN_ALL void pango_lines_move_cursor (PangoLines *lines, gboolean strong, - PangoLayoutLine *line, + PangoLine *line, int idx, int trailing, int direction, - PangoLayoutLine **new_line, + PangoLine **new_line, int *new_idx, int *new_trailing); diff --git a/pango/pango-renderer.c b/pango/pango-renderer.c index fc0dc4c2..6fbbd12f 100644 --- a/pango/pango-renderer.c +++ b/pango/pango-renderer.c @@ -26,7 +26,7 @@ #include "pango-impl-utils.h" #include "pango-layout.h" #include "pango-run-private.h" -#include "pango-layout-line-private.h" +#include "pango-line-private.h" #define N_RENDER_PARTS 5 @@ -65,7 +65,7 @@ struct _PangoRendererPrivate guint16 alpha[N_RENDER_PARTS]; PangoLines *lines; - PangoLayoutLine *line; + PangoLine *line; LineState *line_state; PangoOverline overline; }; @@ -511,9 +511,9 @@ static void pango_renderer_draw_runs (PangoRenderer *renderer, int y); /** - * pango_renderer_draw_layout_line: + * pango_renderer_draw_line: * @renderer: a `PangoRenderer` - * @line: a `PangoLayoutLine` + * @line: a `PangoLine` * @x: X position of left edge of baseline, in user space coordinates * in Pango units. * @y: Y position of left edge of baseline, in user space coordinates @@ -526,10 +526,10 @@ static void pango_renderer_draw_runs (PangoRenderer *renderer, * of those items. */ void -pango_renderer_draw_layout_line (PangoRenderer *renderer, - PangoLayoutLine *line, - int x, - int y) +pango_renderer_draw_line (PangoRenderer *renderer, + PangoLine *line, + int x, + int y) { LineState state = { 0, }; @@ -576,7 +576,7 @@ pango_renderer_draw_lines (PangoRenderer *renderer, int y) { int n; - PangoLayoutLine *line; + PangoLine *line; int line_x, line_y; g_return_if_fail (PANGO_IS_RENDERER_FAST (renderer)); @@ -589,7 +589,7 @@ pango_renderer_draw_lines (PangoRenderer *renderer, if (n == 0) pango_renderer_activate_with_context (renderer, line->context); - pango_renderer_draw_layout_line (renderer, line, x + line_x, y + line_y); + pango_renderer_draw_line (renderer, line, x + line_x, y + line_y); n++; } @@ -681,7 +681,7 @@ pango_renderer_draw_runs (PangoRenderer *renderer, if (!got_overall) { #ifdef EXTENTS - pango_layout_line_get_extents (line, NULL, &overall_rect); + pango_line_get_extents (line, NULL, &overall_rect); #endif got_overall = TRUE; } @@ -814,7 +814,7 @@ pango_renderer_default_draw_glyphs (PangoRenderer *renderer, * * Note that this method does not handle attributes in @glyph_item. * If you want colors, shapes and lines handled automatically according - * to those attributes, you need to use [method@Pango.Renderer.draw_layout_line] + * to those attributes, you need to use [method@Pango.Renderer.draw_line] * or [method@Pango.Renderer.draw_lines]. * * Note that @text is the start of the text for layout, which is then @@ -1616,7 +1616,7 @@ pango_renderer_get_lines (PangoRenderer *renderer) } /** - * pango_renderer_get_layout_line: + * pango_renderer_get_line: * @renderer: a `PangoRenderer` * * Gets the layout line currently being rendered using @renderer. @@ -1630,8 +1630,8 @@ pango_renderer_get_lines (PangoRenderer *renderer) * Return value: (transfer none) (nullable): the layout line, or %NULL * if no layout line is being rendered using @renderer at this time. */ -PangoLayoutLine * -pango_renderer_get_layout_line (PangoRenderer *renderer) +PangoLine * +pango_renderer_get_line (PangoRenderer *renderer) { return renderer->priv->line; } diff --git a/pango/pango-renderer.h b/pango/pango-renderer.h index 116f8c78..927460e6 100644 --- a/pango/pango-renderer.h +++ b/pango/pango-renderer.h @@ -207,8 +207,8 @@ void pango_renderer_draw_lines (PangoRenderer *renderer, int y); PANGO_AVAILABLE_IN_ALL -void pango_renderer_draw_layout_line (PangoRenderer *renderer, - PangoLayoutLine *line, +void pango_renderer_draw_line (PangoRenderer *renderer, + PangoLine *line, int x, int y); PANGO_AVAILABLE_IN_1_8 @@ -287,7 +287,7 @@ PANGO_AVAILABLE_IN_ALL PangoLines * pango_renderer_get_lines (PangoRenderer *renderer); PANGO_AVAILABLE_IN_ALL -PangoLayoutLine * pango_renderer_get_layout_line (PangoRenderer *renderer); +PangoLine * pango_renderer_get_line (PangoRenderer *renderer); PANGO_AVAILABLE_IN_ALL PangoContext * pango_renderer_get_context (PangoRenderer *renderer); diff --git a/pango/pango-run.c b/pango/pango-run.c index a011395d..401666f6 100644 --- a/pango/pango-run.c +++ b/pango/pango-run.c @@ -9,7 +9,7 @@ /** * PangoRun: * - * A `PangoRun` represents a single run within a `PangoLayoutLine`. + * A `PangoRun` represents a single run within a `PangoLine`. * * A run is a range of text with uniform script, font and attributes that * is shaped as a unit. diff --git a/pango/pango-types.h b/pango/pango-types.h index bca88069..6c44314e 100644 --- a/pango/pango-types.h +++ b/pango/pango-types.h @@ -53,9 +53,9 @@ typedef struct _PangoLanguage PangoLanguage; */ typedef guint32 PangoGlyph; -typedef struct _PangoLines PangoLines; typedef struct _PangoRun PangoRun; -typedef struct _PangoLayoutLine PangoLayoutLine; +typedef struct _PangoLine PangoLine; +typedef struct _PangoLines PangoLines; typedef struct _PangoLayoutIter PangoLayoutIter; /** diff --git a/pango/pango.h b/pango/pango.h index f7851bf7..4f4782d0 100644 --- a/pango/pango.h +++ b/pango/pango.h @@ -42,7 +42,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/pango/pangocairo-font.c b/pango/pangocairo-font.c index 0374971a..d2454328 100644 --- a/pango/pangocairo-font.c +++ b/pango/pangocairo-font.c @@ -195,9 +195,9 @@ max_glyph_width (PangoLayout *layout) lines = pango_layout_get_lines (layout); for (int i = 0; i < pango_lines_get_line_count (lines); i++) { - PangoLayoutLine *line = pango_lines_get_line (lines, i, NULL, NULL); + PangoLine *line = pango_lines_get_line (lines, i, NULL, NULL); - for (r = pango_layout_line_get_runs (line); r; r = r->next) + for (r = pango_line_get_runs (line); r; r = r->next) { PangoGlyphString *glyphs = ((PangoGlyphItem *)r->data)->glyphs; int i; diff --git a/pango/pangocairo-render.c b/pango/pangocairo-render.c index e5417825..d226b389 100644 --- a/pango/pangocairo-render.c +++ b/pango/pangocairo-render.c @@ -973,9 +973,9 @@ _pango_cairo_do_glyph_item (cairo_t *cr, } static void -_pango_cairo_do_layout_line (cairo_t *cr, - PangoLayoutLine *line, - gboolean do_path) +_pango_cairo_do_line (cairo_t *cr, + PangoLine *line, + gboolean do_path) { PangoCairoRenderer *crenderer = acquire_renderer (); PangoRenderer *renderer = (PangoRenderer *) crenderer; @@ -984,7 +984,7 @@ _pango_cairo_do_layout_line (cairo_t *cr, crenderer->do_path = do_path; save_current_point (crenderer); - pango_renderer_draw_layout_line (renderer, line, 0, 0); + pango_renderer_draw_line (renderer, line, 0, 0); restore_current_point (crenderer); @@ -1116,21 +1116,21 @@ pango_cairo_show_glyph_item (cairo_t *cr, /** * pango_cairo_show_line: * @cr: a Cairo context - * @line: a `PangoLayoutLine` + * @line: a `PangoLine` * - * Draws a `PangoLayoutLine` in the specified cairo context. + * Draws a `PangoLine` in the specified cairo context. * * The origin of the glyphs (the left edge of the line) will * be drawn at the current point of the cairo context. */ void -pango_cairo_show_layout_line (cairo_t *cr, - PangoLayoutLine *line) +pango_cairo_show_line (cairo_t *cr, + PangoLine *line) { g_return_if_fail (cr != NULL); g_return_if_fail (line != NULL); - _pango_cairo_do_layout_line (cr, line, FALSE); + _pango_cairo_do_line (cr, line, FALSE); } /** @@ -1232,23 +1232,23 @@ pango_cairo_glyph_string_path (cairo_t *cr, } /** - * pango_cairo_layout_line_path: + * pango_cairo_line_path: * @cr: a Cairo context - * @line: a `PangoLayoutLine` + * @line: a `PangoLine` * - * Adds the text in `PangoLayoutLine` to the current path in the + * Adds the text in `PangoLine` to the current path in the * specified cairo context. * * The origin of the glyphs (the left edge of the line) will be * at the current point of the cairo context. */ void -pango_cairo_layout_line_path (cairo_t *cr, - PangoLayoutLine *line) +pango_cairo_line_path (cairo_t *cr, + PangoLine *line) { g_return_if_fail (cr != NULL); - _pango_cairo_do_layout_line (cr, line, TRUE); + _pango_cairo_do_line (cr, line, TRUE); } /** diff --git a/pango/pangocairo.h b/pango/pangocairo.h index d42b9258..e418240f 100644 --- a/pango/pangocairo.h +++ b/pango/pangocairo.h @@ -85,7 +85,7 @@ typedef struct _PangoCairoFontMap PangoCairoFontMap; * @do_path: whether only the shape path should be appended to current * path of @cr and no filling/stroking done. This will be set * to %TRUE when called from pango_cairo_layout_path() and - * pango_cairo_layout_line_path() rendering functions. + * pango_cairo_line_path() rendering functions. * @data: (closure): user data passed to pango_cairo_context_set_shape_renderer() * * Function type for rendering attributes of type %PANGO_ATTR_SHAPE @@ -181,8 +181,8 @@ void pango_cairo_show_glyph_item (cairo_t *cr, const char *text, PangoGlyphItem *glyph_item); PANGO_AVAILABLE_IN_ALL -void pango_cairo_show_layout_line (cairo_t *cr, - PangoLayoutLine *line); +void pango_cairo_show_line (cairo_t *cr, + PangoLine *line); PANGO_AVAILABLE_IN_ALL void pango_cairo_show_lines (cairo_t *cr, PangoLines *lines); @@ -209,8 +209,8 @@ PANGO_AVAILABLE_IN_1_10 void pango_cairo_layout_path (cairo_t *cr, PangoLayout *layout); PANGO_AVAILABLE_IN_ALL -void pango_cairo_layout_line_path (cairo_t *cr, - PangoLayoutLine *line); +void pango_cairo_line_path (cairo_t *cr, + PangoLine *line); PANGO_AVAILABLE_IN_ALL void pango_cairo_lines_path (cairo_t *cr, PangoLines *lines); diff --git a/pango/pangofc-font.c b/pango/pangofc-font.c index 4f0ad457..8a774cbb 100644 --- a/pango/pangofc-font.c +++ b/pango/pangofc-font.c @@ -426,9 +426,9 @@ max_glyph_width (PangoLayout *layout) lines = pango_layout_get_lines (layout); for (int i = 0; i < pango_lines_get_line_count (lines); i++) { - PangoLayoutLine *line = pango_lines_get_line (lines, i, NULL, NULL); + PangoLine *line = pango_lines_get_line (lines, i, NULL, NULL); - for (r = pango_layout_line_get_runs (line); r; r = r->next) + for (r = pango_line_get_runs (line); r; r = r->next) { PangoGlyphString *glyphs = ((PangoGlyphItem *)r->data)->glyphs; int i; diff --git a/pango/pangoft2-render.c b/pango/pangoft2-render.c index 902f7d6f..ed093921 100644 --- a/pango/pangoft2-render.c +++ b/pango/pangoft2-render.c @@ -26,7 +26,7 @@ #include "pango-font-private.h" #include "pangoft2-private.h" #include "pango-impl-utils.h" -#include "pango-layout-line-private.h" +#include "pango-line-private.h" /* for compatibility with older freetype versions */ #ifndef FT_LOAD_TARGET_MONO @@ -636,13 +636,13 @@ pango_ft2_render_layout (FT_Bitmap *bitmap, } /** - * pango_ft2_render_layout_line_subpixel: + * pango_ft2_render_line_subpixel: * @bitmap: a FT_Bitmap to render the line onto - * @line: a `PangoLayoutLine` + * @line: a `PangoLine` * @x: the x position of start of string (in Pango units) * @y: the y position of baseline (in Pango units) * - * Render a `PangoLayoutLine` onto a FreeType2 bitmap, with he + * Render a `PangoLine` onto a FreeType2 bitmap, with he * location specified in fixed-point Pango units rather than * pixels. * @@ -653,10 +653,10 @@ pango_ft2_render_layout (FT_Bitmap *bitmap, * Since: 1.6 */ void -pango_ft2_render_layout_line_subpixel (FT_Bitmap *bitmap, - PangoLayoutLine *line, - int x, - int y) +pango_ft2_render_line_subpixel (FT_Bitmap *bitmap, + PangoLine *line, + int x, + int y) { PangoFontMap *fontmap; PangoRenderer *renderer; @@ -669,25 +669,25 @@ pango_ft2_render_layout_line_subpixel (FT_Bitmap *bitmap, pango_ft2_renderer_set_bitmap (PANGO_FT2_RENDERER (renderer), bitmap); - pango_renderer_draw_layout_line (renderer, line, x, y); + pango_renderer_draw_line (renderer, line, x, y); } /** - * pango_ft2_render_layout_line: + * pango_ft2_render_line: * @bitmap: a FT_Bitmap to render the line onto - * @line: a `PangoLayoutLine` + * @line: a `PangoLine` * @x: the x position of start of string (in pixels) * @y: the y position of baseline (in pixels) * - * Render a `PangoLayoutLine` onto a FreeType2 bitmap + * Render a `PangoLine` onto a FreeType2 bitmap */ void -pango_ft2_render_layout_line (FT_Bitmap *bitmap, - PangoLayoutLine *line, - int x, - int y) +pango_ft2_render_line (FT_Bitmap *bitmap, + PangoLine *line, + int x, + int y) { - pango_ft2_render_layout_line_subpixel (bitmap, line, x * PANGO_SCALE, y * PANGO_SCALE); + pango_ft2_render_line_subpixel (bitmap, line, x * PANGO_SCALE, y * PANGO_SCALE); } /** diff --git a/pango/pangoft2.h b/pango/pangoft2.h index 3610a125..409b3af6 100644 --- a/pango/pangoft2.h +++ b/pango/pangoft2.h @@ -87,15 +87,15 @@ void pango_ft2_render_transformed (FT_Bitmap *bitmap, int y); PANGO_AVAILABLE_IN_ALL -void pango_ft2_render_layout_line (FT_Bitmap *bitmap, - PangoLayoutLine *line, +void pango_ft2_render_line (FT_Bitmap *bitmap, + PangoLine *line, int x, int y); PANGO_AVAILABLE_IN_1_6 -void pango_ft2_render_layout_line_subpixel (FT_Bitmap *bitmap, - PangoLayoutLine *line, - int x, - int y); +void pango_ft2_render_line_subpixel (FT_Bitmap *bitmap, + PangoLine *line, + int x, + int y); PANGO_AVAILABLE_IN_ALL void pango_ft2_render_layout (FT_Bitmap *bitmap, diff --git a/pango/pangoxft-render.c b/pango/pangoxft-render.c index 714bc5c3..ace4bbd4 100644 --- a/pango/pangoxft-render.c +++ b/pango/pangoxft-render.c @@ -24,7 +24,7 @@ #include "pangoxft-render.h" #include "pangoxft-private.h" -#include "pango-layout-line-private.h" +#include "pango-line-private.h" enum { PROP_0, @@ -746,20 +746,20 @@ pango_xft_render_layout (XftDraw *draw, * @draw: an XftDraw * @color: the foreground color in which to draw the layout line * (may be overridden by color attributes) - * @line: a `PangoLayoutLine` + * @line: a `PangoLine` * @x: the x position of start of string (in Pango units) * @y: the y position of baseline (in Pango units) * - * Render a `PangoLayoutLine` onto a XftDraw + * Render a `Pangoine` onto a XftDraw * * Since: 1.8 */ void -pango_xft_render_layout_line (XftDraw *draw, - XftColor *color, - PangoLayoutLine *line, - int x, - int y) +pango_xft_render_line (XftDraw *draw, + XftColor *color, + PangoLine *line, + int x, + int y) { PangoFontMap *fontmap; PangoRenderer *renderer; @@ -771,7 +771,7 @@ pango_xft_render_layout_line (XftDraw *draw, fontmap = pango_context_get_font_map (line->context); renderer = get_renderer (fontmap, draw, color); - pango_renderer_draw_layout_line (renderer, line, x, y); + pango_renderer_draw_line (renderer, line, x, y); release_renderer (renderer); } diff --git a/pango/pangoxft-render.h b/pango/pangoxft-render.h index 8e0316c2..7cae0f31 100644 --- a/pango/pangoxft-render.h +++ b/pango/pangoxft-render.h @@ -141,9 +141,9 @@ void pango_xft_render_transformed (XftDraw *draw, int x, int y); PANGO_AVAILABLE_IN_1_8 -void pango_xft_render_layout_line (XftDraw *draw, +void pango_xft_render_line (XftDraw *draw, XftColor *color, - PangoLayoutLine *line, + PangoLine *line, int x, int y); PANGO_AVAILABLE_IN_1_8 diff --git a/pango/serializer.c b/pango/serializer.c index cd39f921..a2870362 100644 --- a/pango/serializer.c +++ b/pango/serializer.c @@ -25,7 +25,7 @@ #include #include #include -#include +#include #include #include @@ -711,7 +711,7 @@ add_run (GtkJsonPrinter *printer, static void line_to_json (GtkJsonPrinter *printer, - PangoLayoutLine *line, + PangoLine *line, int x, int y) { @@ -770,7 +770,7 @@ lines_to_json (GtkJsonPrinter *printer, for (int i = 0; i < pango_lines_get_line_count (lines); i++) { - PangoLayoutLine *line; + PangoLine *line; int x, y; line = pango_lines_get_line (lines, i, &x, &y); line_to_json (printer, line, x, y); diff --git a/tests/test-bidi.c b/tests/test-bidi.c index f8b05588..fe74cac2 100644 --- a/tests/test-bidi.c +++ b/tests/test-bidi.c @@ -159,7 +159,7 @@ test_bidi_embedding_levels (void) } /* Some basic tests for pango_layout_move_cursor inside - * a single PangoLayoutLine: + * a single PangoLine: * - check that we actually move the cursor in the right direction * - check that we get through the line with at most n steps * - check that we don't skip legitimate cursor positions @@ -189,8 +189,8 @@ test_move_cursor_line (void) PangoRectangle s_pos, old_s_pos; PangoRectangle w_pos, old_w_pos; PangoLines *lines; - PangoLayoutLine *line; - PangoLayoutLine *new_line; + PangoLine *line; + PangoLine *new_line; struct { int direction; gboolean strong; @@ -242,7 +242,7 @@ test_move_cursor_line (void) params[j].direction > 0 ? "->" : "<-", params[j].strong ? "strong" : "weak"); - if ((pango_layout_line_get_resolved_direction (line) == PANGO_DIRECTION_LTR) == (params[j].direction > 0)) + if ((pango_line_get_resolved_direction (line) == PANGO_DIRECTION_LTR) == (params[j].direction > 0)) start_index = 0; else start_index = strlen (text); @@ -359,11 +359,11 @@ test_move_cursor_para (void) int index; int trailing; const char *text; - PangoLayoutLine *line; + PangoLine *line; PangoRectangle ext; PangoLines *lines; PangoLayoutIter *iter; - PangoLayoutLine *new_line; + PangoLine *new_line; layout = pango_layout_new (context); diff --git a/tests/testiter.c b/tests/testiter.c index 6547865c..062cd3b9 100644 --- a/tests/testiter.c +++ b/tests/testiter.c @@ -176,7 +176,7 @@ iter_cluster_test (PangoLayout *layout) PangoLayoutIter *iter; int index; gboolean iter_next_ok; - PangoLayoutLine *last_line = NULL; + PangoLine *last_line = NULL; int expected_next_x = 0; iter = pango_lines_get_iter (pango_layout_get_lines (layout)); @@ -184,7 +184,7 @@ iter_cluster_test (PangoLayout *layout) while (iter_next_ok) { - PangoLayoutLine *line = pango_layout_iter_get_line (iter); + PangoLine *line = pango_layout_iter_get_line (iter); /* Every cluster is part of a run */ g_assert (pango_layout_iter_get_run (iter)); @@ -259,7 +259,7 @@ test_glyphitem_iter (void) PangoContext *context; PangoFontDescription *font_desc; PangoLayout *layout; - PangoLayoutLine *line; + PangoLine *line; const char *text; GSList *l; @@ -274,7 +274,7 @@ test_glyphitem_iter (void) text = pango_layout_get_text (layout); line = pango_lines_get_line (pango_layout_get_lines (layout), 0, NULL, NULL); - for (l = pango_layout_line_get_runs (line); l; l = l->next) + for (l = pango_line_get_runs (line); l; l = l->next) { PangoGlyphItem *run = l->data; int direction; diff --git a/tests/testmisc.c b/tests/testmisc.c index 98e022cd..f1e892e8 100644 --- a/tests/testmisc.c +++ b/tests/testmisc.c @@ -92,14 +92,14 @@ test_line_height (void) { PangoContext *context; PangoLayout *layout; - PangoLayoutLine *line; + PangoLine *line; PangoRectangle ext; context = pango_font_map_create_context (pango_cairo_font_map_get_default ()); layout = pango_layout_new (context); pango_layout_set_text (layout, "one\ttwo", -1); line = pango_lines_get_line (pango_layout_get_lines (layout), 0, NULL, NULL); - pango_layout_line_get_extents (line, NULL, &ext); + pango_line_get_extents (line, NULL, &ext); g_assert_cmpint (ext.height, >, 0); @@ -112,7 +112,7 @@ test_line_height2 (void) { PangoContext *context; PangoLayout *layout; - PangoLayoutLine *line; + PangoLine *line; PangoRectangle ext1, ext2; context = pango_font_map_create_context (pango_cairo_font_map_get_default ()); @@ -121,7 +121,7 @@ test_line_height2 (void) line = pango_lines_get_line (pango_layout_get_lines (layout), 0, NULL, NULL); g_assert_nonnull (line); - pango_layout_line_get_extents (line, NULL, &ext1); + pango_line_get_extents (line, NULL, &ext1); pango_layout_write_to_file (layout, "one.layout"); @@ -129,7 +129,7 @@ test_line_height2 (void) line = pango_lines_get_line (pango_layout_get_lines (layout), 0, NULL, NULL); g_assert_nonnull (line); - pango_layout_line_get_extents (line, NULL, &ext2); + pango_line_get_extents (line, NULL, &ext2); pango_layout_write_to_file (layout, "empty.layout"); @@ -144,7 +144,7 @@ test_line_height3 (void) { PangoContext *context; PangoLayout *layout; - PangoLayoutLine *line; + PangoLine *line; PangoAttrList *attrs; PangoRectangle ext1; PangoRectangle ext2; @@ -159,13 +159,13 @@ test_line_height3 (void) line = pango_lines_get_line (pango_layout_get_lines (layout), 0, NULL, NULL); g_assert_cmpint (pango_lines_get_line_count (pango_layout_get_lines (layout)), ==, 1); - pango_layout_line_get_extents (line, NULL, &ext1); + pango_line_get_extents (line, NULL, &ext1); pango_layout_set_text (layout, "", -1); g_assert_cmpint (pango_lines_get_line_count (pango_layout_get_lines (layout)), ==, 1); line = pango_lines_get_line (pango_layout_get_lines (layout), 0, NULL, NULL); - pango_layout_line_get_extents (line, NULL, &ext2); + pango_line_get_extents (line, NULL, &ext2); g_assert_cmpint (ext1.height, ==, ext2.height); @@ -523,7 +523,7 @@ test_index_to_x (void) for (p = text; *p; p = g_utf8_next_char (p)) { int index = p - text; - PangoLayoutLine *line; + PangoLine *line; int x; int index2, trailing; gunichar ch; @@ -533,8 +533,8 @@ test_index_to_x (void) pango_lines_index_to_line (pango_layout_get_lines (layout), index, &line, NULL, NULL, NULL); g_assert_nonnull (line); - pango_layout_line_index_to_x (line, index, 0, &x); - pango_layout_line_x_to_index (line, x, &index2, &trailing); + pango_line_index_to_x (line, index, 0, &x); + pango_line_x_to_index (line, x, &index2, &trailing); if (!pango_is_zero_width (ch)) g_assert_cmpint (index, ==, index2); } diff --git a/utils/viewer-pangocairo.c b/utils/viewer-pangocairo.c index 9c041879..631c2a7d 100644 --- a/utils/viewer-pangocairo.c +++ b/utils/viewer-pangocairo.c @@ -282,7 +282,7 @@ render_callback (PangoLayout *layout, iter = pango_layout_get_iter (layout); do { - PangoLayoutLine *line = pango_layout_iter_get_line (iter); + PangoLine *line = pango_layout_iter_get_line (iter); double width = (double)logical.width / PANGO_SCALE; y = pango_layout_iter_get_line_baseline (iter); @@ -290,7 +290,7 @@ render_callback (PangoLayout *layout, cairo_translate (cr, (double)logical.x / PANGO_SCALE + width * 0.5, (double)y / PANGO_SCALE); - if (pango_layout_line_get_resolved_direction (line)) + if (pango_line_get_resolved_direction (line)) cairo_scale (cr, -1, 1); cairo_move_to (cr, -width * .5, -lw*0.2); cairo_rel_line_to (cr, +width * .9, -lw*0.3); -- cgit v1.2.1