summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMatthias Clasen <mclasen@redhat.com>2022-02-17 19:49:58 +0000
committerMatthias Clasen <mclasen@redhat.com>2022-02-17 19:49:58 +0000
commit6aec701eeb49d6f583c4c1f060d0a72d61ec95e6 (patch)
tree2984568ec10fcc5b556bb418d686ca3eeab96a05
parent0c77a45c1d03864ddd8f6bb656457eca590a8fdd (diff)
parent539ca68c7725f9d7bfb6ba8ad3c94f354a6c1142 (diff)
downloadpango-6aec701eeb49d6f583c4c1f060d0a72d61ec95e6.tar.gz
Merge branch 'baseline-handling' into 'main'
Handle baselines See merge request GNOME/pango!589
-rw-r--r--pango/pango-layout.c66
-rw-r--r--utils/viewer-pangocairo.c118
2 files changed, 181 insertions, 3 deletions
diff --git a/pango/pango-layout.c b/pango/pango-layout.c
index 9167883c..6e4bb357 100644
--- a/pango/pango-layout.c
+++ b/pango/pango-layout.c
@@ -85,6 +85,7 @@
#include <locale.h>
#include <hb-ot.h>
+#include <hb-glib.h>
#include "pango-layout-private.h"
#include "pango-attributes-private.h"
@@ -6694,6 +6695,12 @@ apply_baseline_shift (PangoLayoutLine *line,
{
int y_offset = 0;
PangoItem *prev = NULL;
+ hb_position_t baseline_adjustment = 0;
+#if HB_VERSION_ATLEAST(4,0,0)
+ hb_ot_layout_baseline_tag_t baseline_tag = 0;
+ hb_position_t baseline;
+ hb_position_t run_baseline;
+#endif
for (GSList *l = line->runs; l; l = l->next)
{
@@ -6701,16 +6708,71 @@ apply_baseline_shift (PangoLayoutLine *line,
PangoItem *item = run->item;
int start_x_offset, end_x_offset;
int start_y_offset, end_y_offset;
+#if HB_VERSION_ATLEAST(4,0,0)
+ hb_font_t *hb_font;
+ hb_script_t script;
+ hb_language_t language;
+ hb_direction_t direction;
+ hb_tag_t script_tags[HB_OT_MAX_TAGS_PER_SCRIPT];
+ hb_tag_t lang_tags[HB_OT_MAX_TAGS_PER_LANGUAGE];
+ unsigned int script_count = HB_OT_MAX_TAGS_PER_SCRIPT;
+ unsigned int lang_count = HB_OT_MAX_TAGS_PER_LANGUAGE;
+
+ hb_font = pango_font_get_hb_font (item->analysis.font);
+
+ script = hb_glib_script_to_script (item->analysis.script);
+ language = hb_language_from_string (pango_language_to_string (item->analysis.language), -1);
+ hb_ot_tags_from_script_and_language (script, language,
+ &script_count, script_tags,
+ &lang_count, lang_tags);
+
+ if (item->analysis.flags & PANGO_ANALYSIS_FLAG_CENTERED_BASELINE)
+ direction = HB_DIRECTION_TTB;
+ else
+ direction = HB_DIRECTION_LTR;
+
+ if (baseline_tag == 0)
+ {
+ if (item->analysis.flags & PANGO_ANALYSIS_FLAG_CENTERED_BASELINE)
+ baseline_tag = HB_OT_LAYOUT_BASELINE_TAG_IDEO_EMBOX_CENTRAL;
+ else
+ baseline_tag = hb_ot_layout_get_horizontal_baseline_tag_for_script (script);
+ hb_ot_layout_get_baseline_with_fallback (hb_font,
+ baseline_tag,
+ direction,
+ script_tags[script_count - 1],
+ lang_count ? lang_tags[lang_count - 1] : HB_TAG_NONE,
+ &run_baseline);
+ baseline = run_baseline;
+ }
+ else
+ {
+ hb_ot_layout_get_baseline_with_fallback (hb_font,
+ baseline_tag,
+ direction,
+ script_tags[script_count - 1],
+ lang_count ? lang_tags[lang_count - 1] : HB_TAG_NONE,
+ &run_baseline);
+ }
+
+ /* Don't do baseline adjustment in vertical, since the renderer
+ * is still doing its own baseline shifting there
+ */
+ if (item->analysis.flags & PANGO_ANALYSIS_FLAG_CENTERED_BASELINE)
+ baseline_adjustment = 0;
+ else
+ baseline_adjustment = baseline - run_baseline;
+#endif
collect_baseline_shift (state, item, prev, &start_x_offset, &start_y_offset, &end_x_offset, &end_y_offset);
- y_offset += start_y_offset;
+ y_offset += start_y_offset + baseline_adjustment;
run->y_offset = y_offset;
run->start_x_offset = start_x_offset;
run->end_x_offset = end_x_offset;
- y_offset += end_y_offset;
+ y_offset += end_y_offset - baseline_adjustment;
prev = item;
}
diff --git a/utils/viewer-pangocairo.c b/utils/viewer-pangocairo.c
index 8fe9db59..2cfe2cee 100644
--- a/utils/viewer-pangocairo.c
+++ b/utils/viewer-pangocairo.c
@@ -26,6 +26,9 @@
#include <pango/pangocairo.h>
+#include <hb-ot.h>
+#include <hb-glib.h>
+
static int opt_annotate = 0;
typedef struct
@@ -158,7 +161,8 @@ enum {
ANNOTATE_GLYPH_EXTENTS = 256,
ANNOTATE_CARET_POSITIONS = 512,
ANNOTATE_CARET_SLOPE = 1024,
- ANNOTATE_LAST = 2048,
+ ANNOTATE_RUN_BASELINES = 2048,
+ ANNOTATE_LAST = 4096,
};
static struct {
@@ -169,6 +173,7 @@ static struct {
{ ANNOTATE_GRAVITY_ROOF, "gravity-roof", "gravity" },
{ ANNOTATE_BLOCK_PROGRESSION, "block-progression", "progression" },
{ ANNOTATE_BASELINES, "baselines", "baselines" },
+ { ANNOTATE_RUN_BASELINES, "run-baselines", "run-baselines" },
{ ANNOTATE_LAYOUT_EXTENTS, "layout-extents", "layout" },
{ ANNOTATE_LINE_EXTENTS, "line-extents", "line" },
{ ANNOTATE_RUN_EXTENTS, "run-extents", "run" },
@@ -308,6 +313,117 @@ render_callback (PangoLayout *layout,
cairo_restore (cr);
}
+#if HB_VERSION_ATLEAST(4,0,0)
+ if (annotate & ANNOTATE_RUN_BASELINES)
+ {
+ hb_ot_layout_baseline_tag_t baseline_tag = 0;
+ /* draw baselines for runs in blue */
+ cairo_save (cr);
+ cairo_set_source_rgba (cr, 0.0, 0.0, 1.0, 0.5);
+
+ iter = pango_layout_get_iter (layout);
+ do
+ {
+ PangoLayoutRun *run;
+ PangoRectangle rect;
+ hb_font_t *hb_font;
+ hb_ot_layout_baseline_tag_t baselines[] = {
+ HB_OT_LAYOUT_BASELINE_TAG_ROMAN,
+ HB_OT_LAYOUT_BASELINE_TAG_HANGING,
+ HB_OT_LAYOUT_BASELINE_TAG_IDEO_FACE_BOTTOM_OR_LEFT,
+ HB_OT_LAYOUT_BASELINE_TAG_IDEO_FACE_TOP_OR_RIGHT,
+ HB_OT_LAYOUT_BASELINE_TAG_IDEO_EMBOX_BOTTOM_OR_LEFT,
+ HB_OT_LAYOUT_BASELINE_TAG_IDEO_EMBOX_CENTRAL,
+ HB_OT_LAYOUT_BASELINE_TAG_IDEO_EMBOX_TOP_OR_RIGHT,
+ HB_OT_LAYOUT_BASELINE_TAG_MATH
+ };
+ hb_direction_t dir;
+ hb_tag_t script, lang;
+ hb_position_t coord;
+
+ run = pango_layout_iter_get_run (iter);
+ if (!run)
+ {
+ baseline_tag = 0;
+ continue;
+ }
+
+ if (baseline_tag == 0)
+ {
+ hb_script_t script = hb_glib_script_to_script (run->item->analysis.script);
+
+ if (run->item->analysis.flags & PANGO_ANALYSIS_FLAG_CENTERED_BASELINE)
+ baseline_tag = HB_OT_LAYOUT_BASELINE_TAG_IDEO_EMBOX_CENTRAL;
+ else
+ baseline_tag = hb_ot_layout_get_horizontal_baseline_tag_for_script (script);
+ }
+
+ y = pango_layout_iter_get_run_baseline (iter);
+ pango_layout_iter_get_run_extents (iter, NULL, &rect);
+
+ hb_font = pango_font_get_hb_font (run->item->analysis.font);
+ if (run->item->analysis.flags & PANGO_ANALYSIS_FLAG_CENTERED_BASELINE)
+ dir = HB_DIRECTION_TTB;
+ else
+ dir = HB_DIRECTION_LTR;
+ script = hb_glib_script_to_script (run->item->analysis.script);
+ lang = HB_TAG_NONE;
+
+ for (int i = 0; i < G_N_ELEMENTS (baselines); i++)
+ {
+ char buf[5] = { 0, };
+
+ cairo_save (cr);
+
+ if (baselines[i] == baseline_tag)
+ cairo_set_source_rgba (cr, 1.0, 0.0, 0.0, 0.5);
+ else
+ cairo_set_source_rgba (cr, 0.0, 0.0, 1.0, 0.5);
+
+ if (hb_ot_layout_get_baseline (hb_font,
+ baselines[i],
+ dir,
+ script,
+ lang,
+ &coord))
+ cairo_set_dash (cr, NULL, 0, 0);
+ else
+ {
+ double dashes[] = { 4 * lw, 4 * lw };
+
+ hb_ot_layout_get_baseline_with_fallback (hb_font,
+ baselines[i],
+ dir,
+ script,
+ lang,
+ &coord);
+
+ cairo_set_dash (cr, dashes, 2, 0);
+ cairo_set_line_cap (cr, CAIRO_LINE_CAP_SQUARE);
+ }
+ cairo_move_to (cr,
+ (double)rect.x / PANGO_SCALE,
+ (double)(y - coord) / PANGO_SCALE);
+ cairo_rel_line_to (cr, (double)rect.width / PANGO_SCALE, 0);
+ cairo_stroke (cr);
+ cairo_set_source_rgb (cr, 0, 0, 0);
+ cairo_move_to (cr,
+ (double)rect.x / PANGO_SCALE - 5,
+ (double)(y - coord) / PANGO_SCALE - 5);
+ hb_tag_to_string (baselines[i], buf);
+ if (baselines[i] == baseline_tag)
+ g_print ("dominant %s\n", buf);
+ cairo_show_text (cr, buf);
+
+ cairo_restore (cr);
+ }
+ }
+ while (pango_layout_iter_next_run (iter));
+ pango_layout_iter_free (iter);
+ cairo_restore (cr);
+ }
+#endif
+
if (annotate & ANNOTATE_LAYOUT_EXTENTS)
{
/* draw the logical rect in red */