summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMatthias Clasen <mclasen@redhat.com>2021-08-07 21:02:36 -0400
committerMatthias Clasen <mclasen@redhat.com>2021-08-08 21:56:32 -0400
commite2def596629bd6e9499d6b455cd645b360a9b7aa (patch)
tree46c937c21032171717b431ff8d427aa7fa151b0e
parent5a20c4837a6d08ca2d4be46e33255fcd9d8fd575 (diff)
downloadpango-e2def596629bd6e9499d6b455cd645b360a9b7aa.tar.gz
Fix up logical rectangle reporting
Fix up the various apis that are reporting logical rects to follow these rules: Logical rectangles of lines are affected by the line-height attribute, logical rectangles of smaller units (runs, clusters, chars, cursors, etc) are not. This fixes the text cursors and block cursors in GTK to be 'normal' height, even when applying line-height for double-spacing.
-rw-r--r--pango/pango-layout.c100
1 files changed, 76 insertions, 24 deletions
diff --git a/pango/pango-layout.c b/pango/pango-layout.c
index 447bf890..2a3cb5a2 100644
--- a/pango/pango-layout.c
+++ b/pango/pango-layout.c
@@ -180,7 +180,8 @@ static void pango_layout_line_postprocess (PangoLayoutLine *line,
static void pango_layout_line_leaked (PangoLayoutLine *line);
/* doesn't leak line */
-static PangoLayoutLine* _pango_layout_iter_get_line (PangoLayoutIter *iter);
+static PangoLayoutLine * _pango_layout_iter_get_line (PangoLayoutIter *iter);
+static PangoLayoutRun * _pango_layout_iter_get_run (PangoLayoutIter *iter);
static void pango_layout_get_item_properties (PangoItem *item,
ItemProperties *properties);
@@ -1802,7 +1803,8 @@ pango_layout_index_to_line (PangoLayout *layout,
static PangoLayoutLine *
pango_layout_index_to_line_and_extents (PangoLayout *layout,
int index,
- PangoRectangle *line_rect)
+ PangoRectangle *line_rect,
+ PangoRectangle *run_rect)
{
PangoLayoutIter iter;
PangoLayoutLine *line = NULL;
@@ -1822,7 +1824,26 @@ pango_layout_index_to_line_and_extents (PangoLayout *layout,
pango_layout_iter_get_line_extents (&iter, NULL, line_rect);
if (line->start_index + line->length > index)
- break;
+ {
+ if (run_rect)
+ {
+ while (TRUE)
+ {
+ PangoLayoutRun *run = _pango_layout_iter_get_run (&iter);
+
+ if (run->item->offset <= index && index < run->item->offset + run->item->length)
+ {
+ pango_layout_iter_get_run_extents (&iter, NULL, run_rect);
+ break;
+ }
+
+ if (!pango_layout_iter_next_run (&iter))
+ break;
+ }
+ }
+
+ break;
+ }
if (!pango_layout_iter_next_line (&iter))
break; /* Use end of last line */
@@ -2300,10 +2321,24 @@ pango_layout_index_to_pos (PangoLayout *layout,
layout_line = tmp_line;
- pango_layout_iter_get_line_extents (&iter, NULL, &logical_rect);
-
if (layout_line->start_index + layout_line->length > index)
- break;
+ {
+ while (TRUE)
+ {
+ PangoLayoutRun *run = _pango_layout_iter_get_run (&iter);
+
+ if (run->item->offset <= index && index < run->item->offset + run->item->length)
+ {
+ pango_layout_iter_get_run_extents (&iter, NULL, &logical_rect);
+ break;
+ }
+
+ if (!pango_layout_iter_next_run (&iter))
+ break;
+ }
+
+ break;
+ }
if (!pango_layout_iter_next_line (&iter))
{
@@ -2376,7 +2411,7 @@ pango_layout_get_direction (PangoLayout *layout,
{
PangoLayoutLine *line;
- line = pango_layout_index_to_line_and_extents (layout, index, NULL);
+ line = pango_layout_index_to_line_and_extents (layout, index, NULL, NULL);
if (line)
return pango_layout_line_get_char_direction (line, index);
@@ -2409,6 +2444,7 @@ pango_layout_get_cursor_pos (PangoLayout *layout,
PangoDirection dir1, dir2;
int level1, level2;
PangoRectangle line_rect;
+ PangoRectangle run_rect;
PangoLayoutLine *layout_line = NULL; /* Quiet GCC */
int x1_trailing;
int x2;
@@ -2417,7 +2453,7 @@ pango_layout_get_cursor_pos (PangoLayout *layout,
g_return_if_fail (index >= 0 && index <= layout->length);
layout_line = pango_layout_index_to_line_and_extents (layout, index,
- &line_rect);
+ &line_rect, &run_rect);
g_assert (index >= layout_line->start_index);
@@ -2466,9 +2502,9 @@ pango_layout_get_cursor_pos (PangoLayout *layout,
else
strong_pos->x += x2;
- strong_pos->y = line_rect.y;
+ strong_pos->y = run_rect.y;
strong_pos->width = 0;
- strong_pos->height = line_rect.height;
+ strong_pos->height = run_rect.height;
}
if (weak_pos)
@@ -2481,9 +2517,9 @@ pango_layout_get_cursor_pos (PangoLayout *layout,
else
weak_pos->x += x1_trailing;
- weak_pos->y = line_rect.y;
+ weak_pos->y = run_rect.y;
weak_pos->width = 0;
- weak_pos->height = line_rect.height;
+ weak_pos->height = run_rect.height;
}
}
@@ -5022,6 +5058,7 @@ static void
pango_layout_run_get_extents_and_height (PangoLayoutRun *run,
PangoRectangle *run_ink,
PangoRectangle *run_logical,
+ PangoRectangle *line_logical,
int *height)
{
PangoRectangle logical;
@@ -5030,7 +5067,7 @@ pango_layout_run_get_extents_and_height (PangoLayoutRun *run,
gboolean has_underline;
gboolean has_overline;
- if (G_UNLIKELY (!run_ink && !run_logical && !height))
+ if (G_UNLIKELY (!run_ink && !run_logical && !line_logical && !height))
return;
pango_layout_get_item_properties (run->item, &properties);
@@ -5045,6 +5082,9 @@ pango_layout_run_get_extents_and_height (PangoLayoutRun *run,
if (!run_logical && (has_underline || has_overline || properties.strikethrough))
run_logical = &logical;
+ if (!run_logical && line_logical)
+ run_logical = &logical;
+
if (properties.shape_set)
_pango_shape_get_extents (run->item->num_chars,
properties.shape_ink_rect,
@@ -5119,16 +5159,6 @@ pango_layout_run_get_extents_and_height (PangoLayoutRun *run,
*height = pango_font_metrics_get_height (metrics);
}
- if (properties.absolute_line_height != 0 || properties.line_height != 0.0)
- {
- int line_height, leading;
-
- line_height = MAX (properties.absolute_line_height, ceilf (properties.line_height * run_logical->height));
- leading = line_height - run_logical->height;
- run_logical->y -= leading / 2;
- run_logical->height += leading;
- }
-
if (run->item->analysis.flags & PANGO_ANALYSIS_FLAG_CENTERED_BASELINE)
{
gboolean is_hinted = (run_logical->y & run_logical->height & (PANGO_SCALE - 1)) == 0;
@@ -5149,6 +5179,21 @@ pango_layout_run_get_extents_and_height (PangoLayoutRun *run,
run_logical->y -= properties.rise;
}
+ if (line_logical)
+ {
+ *line_logical = *run_logical;
+
+ if (properties.absolute_line_height != 0 || properties.line_height != 0.0)
+ {
+ int line_height, leading;
+
+ line_height = MAX (properties.absolute_line_height, ceilf (properties.line_height * line_logical->height));
+ leading = line_height - line_logical->height;
+ line_logical->y -= leading / 2;
+ line_logical->height += leading;
+ }
+ }
+
if (metrics)
pango_font_metrics_unref (metrics);
}
@@ -5228,6 +5273,7 @@ pango_layout_line_get_extents_and_height (PangoLayoutLine *line,
pango_layout_run_get_extents_and_height (run,
ink_rect ? &run_ink : NULL,
+ NULL,
&run_logical,
height ? &run_height : NULL);
@@ -6478,6 +6524,12 @@ _pango_layout_iter_get_line (PangoLayoutIter *iter)
return iter->line;
}
+static PangoLayoutRun *
+_pango_layout_iter_get_run (PangoLayoutIter *iter)
+{
+ return iter->run;
+}
+
/**
* pango_layout_iter_get_line:
* @iter: a `PangoLayoutIter`
@@ -6939,7 +6991,7 @@ pango_layout_iter_get_run_extents (PangoLayoutIter *iter,
if (iter->run)
{
- pango_layout_run_get_extents_and_height (iter->run, ink_rect, logical_rect, NULL);
+ pango_layout_run_get_extents_and_height (iter->run, ink_rect, logical_rect, NULL, NULL);
if (ink_rect)
{