summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMatthias Clasen <mclasen@redhat.com>2021-08-29 17:26:52 -0400
committerMatthias Clasen <mclasen@redhat.com>2021-08-31 14:29:56 -0400
commit1f0b5d5b87b61a37bebd393c0d67cce0b4ccdcb9 (patch)
tree1d9e1e3586a1f3b907385aa1c22a4c3456f147e4
parent1b73eedc69bc15941f216bff11817b825adb51d8 (diff)
downloadpango-1f0b5d5b87b61a37bebd393c0d67cce0b4ccdcb9.tar.gz
Add horizontal displacement
Apply horizontal displacements for superscripts and subscripts that are provided in font metrics. This noticably improves the placement of superscripts in italics. Currently, we only apply these displacements in post-processing, and ignore the width changes during line-breaking. This could be improved by moving the baseline handling into the line-breaking proper.
-rw-r--r--pango/pango-glyph-item.c4
-rw-r--r--pango/pango-glyph-item.h10
-rw-r--r--pango/pango-layout-private.h5
-rw-r--r--pango/pango-layout.c94
-rw-r--r--pango/pango-renderer.c4
5 files changed, 78 insertions, 39 deletions
diff --git a/pango/pango-glyph-item.c b/pango/pango-glyph-item.c
index c64bfa13..7eb1737d 100644
--- a/pango/pango-glyph-item.c
+++ b/pango/pango-glyph-item.c
@@ -130,6 +130,8 @@ pango_glyph_item_split (PangoGlyphItem *orig,
pango_glyph_string_set_size (orig->glyphs, orig->glyphs->num_glyphs - num_glyphs);
new->y_offset = orig->y_offset;
+ new->start_x_offset = orig->start_x_offset;
+ new->end_x_offset = -orig->start_x_offset;
return new;
}
@@ -157,6 +159,8 @@ pango_glyph_item_copy (PangoGlyphItem *orig)
result->item = pango_item_copy (orig->item);
result->glyphs = pango_glyph_string_copy (orig->glyphs);
result->y_offset = orig->y_offset;
+ result->start_x_offset = orig->start_x_offset;
+ result->end_x_offset = orig->end_x_offset;
return result;
}
diff --git a/pango/pango-glyph-item.h b/pango/pango-glyph-item.h
index baea69fc..fd8951d2 100644
--- a/pango/pango-glyph-item.h
+++ b/pango/pango-glyph-item.h
@@ -33,8 +33,12 @@ G_BEGIN_DECLS
* PangoGlyphItem:
* @item: corresponding `PangoItem`
* @glyphs: corresponding `PangoGlyphString`
- * @baseline: shift of the baseline, relative to the
- * containing lines baseline. Positive values shift upwards
+ * @y_offset: shift of the baseline, relative to the baseline
+ * of the containing line. Positive values shift upwards
+ * @start_x_offset: horizontal displacement to apply before the
+ * glyph item. Positive values shift right
+ * @end_x_offset: horizontal displacement to apply after th
+ * glyph item. Positive values shift right
*
* A `PangoGlyphItem` is a pair of a `PangoItem` and the glyphs
* resulting from shaping the items text.
@@ -50,6 +54,8 @@ struct _PangoGlyphItem
PangoItem *item;
PangoGlyphString *glyphs;
int y_offset;
+ int start_x_offset;
+ int end_x_offset;
};
#define PANGO_TYPE_GLYPH_ITEM (pango_glyph_item_get_type ())
diff --git a/pango/pango-layout-private.h b/pango/pango-layout-private.h
index 1805e730..b9f9b137 100644
--- a/pango/pango-layout-private.h
+++ b/pango/pango-layout-private.h
@@ -112,11 +112,12 @@ struct _PangoLayoutIter
Extents *line_extents;
int line_index;
- /* X position of the current run */
+ /* Position of the current run */
int run_x;
- /* Width of the current run */
+ /* Width and end offset of the current run */
int run_width;
+ int end_x_offset;
/* this run is left-to-right */
gboolean ltr;
diff --git a/pango/pango-layout.c b/pango/pango-layout.c
index 6c1e2e5e..098e3a3e 100644
--- a/pango/pango-layout.c
+++ b/pango/pango-layout.c
@@ -6154,18 +6154,23 @@ justify_words (PangoLayoutLine *line,
typedef struct {
PangoAttribute *attr;
- int shift;
+ int x_offset;
+ int y_offset;
} BaselineItem;
static void
-collect_shifts (ParaBreakState *state,
- PangoItem *item,
- PangoItem *prev,
- int *start_shift,
- int *end_shift)
-{
- *start_shift = 0;
- *end_shift = 0;
+collect_baseline_shift (ParaBreakState *state,
+ PangoItem *item,
+ PangoItem *prev,
+ int *start_x_offset,
+ int *start_y_offset,
+ int *end_x_offset,
+ int *end_y_offset)
+{
+ *start_x_offset = 0;
+ *start_y_offset = 0;
+ *end_x_offset = 0;
+ *end_y_offset = 0;
for (GSList *l = item->analysis.extra_attrs; l; l = l->next)
{
@@ -6175,8 +6180,8 @@ collect_shifts (ParaBreakState *state,
{
int value = ((PangoAttrInt *)attr)->value;
- *start_shift += value;
- *end_shift -= value;
+ *start_y_offset += value;
+ *end_y_offset -= value;
}
else if (attr->klass->type == PANGO_ATTR_BASELINE_SHIFT)
{
@@ -6187,51 +6192,60 @@ collect_shifts (ParaBreakState *state,
entry = g_new0 (BaselineItem, 1);
entry->attr = attr;
+ state->baseline_shifts = g_list_prepend (state->baseline_shifts, entry);
value = ((PangoAttrInt *)attr)->value;
if (value > 1024 || value < -1024)
{
- entry->shift = value;
+ entry->y_offset = value;
+ /* FIXME: compute an x_offset from value to italic angle */
}
else
{
- int superscript_shift = 0;
- int subscript_shift = 0;
- hb_font_t *hb_font;
+ int superscript_x_offset = 0;
+ int superscript_y_offset = 0;
+ int subscript_x_offset = 0;
+ int subscript_y_offset = 0;
if (prev)
{
- hb_font = pango_font_get_hb_font (prev->analysis.font);
- hb_ot_metrics_get_position (hb_font, HB_OT_METRICS_TAG_SUPERSCRIPT_EM_Y_OFFSET, &superscript_shift);
- hb_ot_metrics_get_position (hb_font, HB_OT_METRICS_TAG_SUBSCRIPT_EM_Y_OFFSET, &subscript_shift);
+ hb_font_t *hb_font = pango_font_get_hb_font (prev->analysis.font);
+ hb_ot_metrics_get_position (hb_font, HB_OT_METRICS_TAG_SUPERSCRIPT_EM_Y_OFFSET, &superscript_y_offset);
+ hb_ot_metrics_get_position (hb_font, HB_OT_METRICS_TAG_SUPERSCRIPT_EM_X_OFFSET, &superscript_x_offset);
+ hb_ot_metrics_get_position (hb_font, HB_OT_METRICS_TAG_SUBSCRIPT_EM_Y_OFFSET, &subscript_y_offset);
+ hb_ot_metrics_get_position (hb_font, HB_OT_METRICS_TAG_SUBSCRIPT_EM_X_OFFSET, &subscript_x_offset);
}
- if (superscript_shift == 0)
- superscript_shift = 5000;
- if (subscript_shift == 0)
- subscript_shift = 5000;
+ if (superscript_y_offset == 0)
+ superscript_y_offset = 5000;
+ if (subscript_y_offset == 0)
+ subscript_y_offset = 5000;
switch (value)
{
case PANGO_BASELINE_SHIFT_NONE:
- entry->shift = 0;
+ entry->x_offset = 0;
+ entry->y_offset = 0;
break;
case PANGO_BASELINE_SHIFT_SUPERSCRIPT:
- entry->shift = superscript_shift;
+ entry->x_offset = superscript_x_offset;
+ entry->y_offset = superscript_y_offset;
break;
case PANGO_BASELINE_SHIFT_SUBSCRIPT:
- entry->shift = -subscript_shift;
+ entry->x_offset = subscript_x_offset;
+ entry->y_offset = -subscript_y_offset;
break;
default:
g_assert_not_reached ();
}
}
- *start_shift += entry->shift;
- state->baseline_shifts = g_list_prepend (state->baseline_shifts, entry);
+ *start_x_offset += entry->x_offset;
+ *start_y_offset += entry->y_offset;
}
+
if (attr->end_index == item->offset + item->length)
{
BaselineItem *entry = state->baseline_shifts->data;
@@ -6239,7 +6253,10 @@ collect_shifts (ParaBreakState *state,
if (attr->start_index == entry->attr->start_index &&
attr->end_index == entry->attr->end_index &&
((PangoAttrInt *)attr)->value == ((PangoAttrInt *)entry->attr)->value)
- *end_shift -= entry->shift;
+ {
+ *end_x_offset -= entry->x_offset;
+ *end_y_offset -= entry->y_offset;
+ }
else
g_warning ("Baseline attributes mismatch\n");
@@ -6251,7 +6268,7 @@ collect_shifts (ParaBreakState *state,
}
static void
-apply_baseline_shifts (PangoLayoutLine *line,
+apply_baseline_shift (PangoLayoutLine *line,
ParaBreakState *state)
{
int y_offset = 0;
@@ -6261,13 +6278,16 @@ apply_baseline_shifts (PangoLayoutLine *line,
{
PangoLayoutRun *run = l->data;
PangoItem *item = run->item;
+ int start_x_offset, end_x_offset;
int start_y_offset, end_y_offset;
- collect_shifts (state, item, prev, &start_y_offset, &end_y_offset);
+ collect_baseline_shift (state, item, prev, &start_x_offset, &start_y_offset, &end_x_offset, &end_y_offset);
y_offset += start_y_offset;
run->y_offset = y_offset;
+ run->start_x_offset = start_x_offset;
+ run->end_x_offset = end_x_offset;
y_offset += end_y_offset;
@@ -6295,7 +6315,7 @@ pango_layout_line_postprocess (PangoLayoutLine *line,
*/
line->runs = g_slist_reverse (line->runs);
- apply_baseline_shifts (line, state);
+ apply_baseline_shift (line, state);
/* Ellipsize the line if necessary
*/
@@ -6543,16 +6563,22 @@ update_run (PangoLayoutIter *iter,
if (iter->run_list_link == iter->line->runs)
iter->run_x = line_ext->logical_rect.x;
else
- iter->run_x += iter->run_width;
+ {
+ iter->run_x += iter->end_x_offset + iter->run_width;
+ if (iter->run)
+ iter->run_x += iter->run->start_x_offset;
+ }
if (iter->run)
{
iter->run_width = pango_glyph_string_get_width (iter->run->glyphs);
+ iter->end_x_offset = iter->run->end_x_offset;
}
else
{
/* The empty run at the end of a line */
iter->run_width = 0;
+ iter->end_x_offset = 0;
}
if (iter->run)
@@ -7256,7 +7282,7 @@ pango_layout_iter_get_cluster_extents (PangoLayoutIter *iter,
if (ink_rect)
{
- ink_rect->x += iter->cluster_x;
+ ink_rect->x += iter->cluster_x + iter->run->start_x_offset;
ink_rect->y -= iter->run->y_offset;
offset_y (iter, &ink_rect->y);
}
@@ -7264,7 +7290,7 @@ pango_layout_iter_get_cluster_extents (PangoLayoutIter *iter,
if (logical_rect)
{
g_assert (logical_rect->width == iter->cluster_width);
- logical_rect->x += iter->cluster_x;
+ logical_rect->x += iter->cluster_x + iter->run->start_x_offset;
logical_rect->y -= iter->run->y_offset;
offset_y (iter, &logical_rect->y);
}
diff --git a/pango/pango-renderer.c b/pango/pango-renderer.c
index 231ebe7d..d47ba13a 100644
--- a/pango/pango-renderer.c
+++ b/pango/pango-renderer.c
@@ -580,7 +580,6 @@ pango_renderer_draw_layout_line (PangoRenderer *renderer,
gboolean got_overall = FALSE;
PangoRectangle overall_rect;
const char *text;
- int y_off;
g_return_if_fail (PANGO_IS_RENDERER_FAST (renderer));
@@ -612,6 +611,7 @@ pango_renderer_draw_layout_line (PangoRenderer *renderer,
PangoAttrShape *shape_attr;
PangoRectangle ink_rect, *ink = NULL;
PangoRectangle logical_rect, *logical = NULL;
+ int y_off;
if (run->item->analysis.flags & PANGO_ANALYSIS_FLAG_CENTERED_BASELINE)
logical = &logical_rect;
@@ -651,6 +651,7 @@ pango_renderer_draw_layout_line (PangoRenderer *renderer,
state.logical_rect_end = x + x_off + glyph_string_width;
+ x_off += run->start_x_offset;
y_off = run->y_offset;
if (run->item->analysis.flags & PANGO_ANALYSIS_FLAG_CENTERED_BASELINE)
@@ -730,6 +731,7 @@ pango_renderer_draw_layout_line (PangoRenderer *renderer,
draw_strikethrough (renderer, &state);
x_off += glyph_string_width;
+ x_off += run->end_x_offset;
}
/* Finish off any remaining underlines