+/* This takes a display_block and its containing line and corrects the yoffset
+ of each glyph in the block to cater for the ascent of the line as a
+ whole. Must be called *after* the line-ascent is known! */
+
+static void
+calculate_yoffset (struct display_line *dl, struct display_block *fixup)
+{
+ int i;
+ for (i=0; i<Dynarr_length (fixup->runes); i++)
+ {
+ struct rune *r = Dynarr_atp (fixup->runes,i);
+ if (r->type == RUNE_DGLYPH)
+ {
+ if (r->object.dglyph.ascent < dl->ascent)
+ r->object.dglyph.yoffset = dl->ascent - r->object.dglyph.ascent +
+ r->object.dglyph.descent;
+ }
+ }
+}
+
+/* Calculate the textual baseline (the ascent and descent values for the
+ display_line as a whole).
+
+ If the baseline is completely blank, or contains no manually positioned
+ glyphs, then the textual baseline is simply the baseline of the default font.
+ (The `contains no manually positioned glyphs' part is actually done for
+ us by `add_emchar_rune'.)
+
+ If the baseline contains pixmaps, and they're all manually positioned, then
+ the textual baseline location is constrained that way, and we need do no
+ work.
+
+ If the baseline contains pixmaps, and at least one is automatically
+ positioned, then the textual ascent is the largest ascent on the line, and
+ the textual descent is the largest descent (which is how things are set up at
+ entry to this function anyway): except that if the max_ascent + max_descent
+ is too small for the height of the line (say you've adjusted the baseline of
+ a short glyph, and there's a tall one next to it), then take the ascent and
+ descent for the line individually from the largest of the explicitly set
+ ascent/descent, and the rescaled ascent/descent of the default font, scaled
+ such that the largest glyph will fit.
+
+ This means that if you have a short glyph (but taller than the default
+ font's descent) forced right under the baseline, and a really tall
+ automatically positioned glyph, that the descent for the line is just big
+ enough for the manually positioned short glyph, and the tall one uses as
+ much of that space as the default font would were it as tall as the tall
+ glyph; but that the ascent is big enough for the tall glyph to fit.
+
+ This behaviour means that under no circumstances will changing the baseline
+ of a short glyph cause a tall glyph to move around; nor will it move the
+ textual baseline more than necessary. (Changing a tall glyph's baseline
+ might move the text's baseline arbitrarily, of course.) */
+
+static void
+calculate_baseline (pos_data *data)
+{
+ /* Blank line: baseline is default font's baseline. */
+
+ if (!data->new_ascent && !data->new_descent)
+ {
+ /* We've got a blank line so initialize these values from the default
+ face. */
+ default_face_font_info (data->window, &data->new_ascent,
+ &data->new_descent, 0, 0, 0);
+ }
+
+ /* No automatically positioned glyphs? Return at once. */
+ if (!data->need_baseline_computation)
+ return;
+
+ /* Is the tallest glyph on the line automatically positioned?
+ If it's manually positioned, or it's automatically positioned
+ and there's enough room for it anyway, we need do no more work. */
+ if (data->max_pixmap_height > data->new_ascent + data->new_descent)
+ {
+ int default_font_ascent, default_font_descent, default_font_height;
+ int scaled_default_font_ascent, scaled_default_font_descent;
+
+ default_face_font_info (data->window, &default_font_ascent,
+ &default_font_descent, &default_font_height,
+ 0, 0);
+
+ scaled_default_font_ascent = data->max_pixmap_height *
+ default_font_ascent / default_font_height;
+
+ data->new_ascent = max (data->new_ascent, scaled_default_font_ascent);
+
+ /* The ascent may have expanded now. Do we still need to grow the descent,
+ or are things big enough?
+
+ The +1 caters for the baseline row itself. */
+ if (data->max_pixmap_height > data->new_ascent + data->new_descent)
+ {
+ scaled_default_font_descent = (data->max_pixmap_height *
+ default_font_descent / default_font_height) + 1;
+
+ data->new_descent = max (data->new_descent, scaled_default_font_descent);
+ }
+ }
+}
+