Clean up the baseline adjustment PR

This commit is contained in:
Kovid Goyal 2021-06-16 20:39:00 +05:30
parent 5d0eb1d330
commit 0fb2f383ac
No known key found for this signature in database
GPG Key ID: 06BC317B515ACE7C
4 changed files with 41 additions and 11 deletions

View File

@ -7,6 +7,9 @@ To update |kitty|, :doc:`follow the instructions <binary>`.
0.21.2 [future]
----------------------
- A new :opt:`adjust_baseline` option to adjust the vertical alignment of text
inside a line (:pull:`3734`)
- Fix a regression in 0.21.0 that broke rendering of private use unicode symbols followed
by spaces, when they also exist not followed by spaces (:iss:`3729`)

View File

@ -323,6 +323,13 @@ harfbuzz_font_for_face(PyObject* s) {
return self->hb_font;
}
static unsigned int
adjust_ypos(unsigned int pos, unsigned int cell_height, int adjustment) {
if (adjustment >= 0) adjustment = MIN(adjustment, (int)pos - 1);
else adjustment = MAX(adjustment, (int)pos - (int)cell_height + 1);
return pos - adjustment;
}
void
cell_metrics(PyObject *s, unsigned int* cell_width, unsigned int* cell_height, unsigned int* baseline, unsigned int* underline_position, unsigned int* underline_thickness, unsigned int* strikethrough_position, unsigned int* strikethrough_thickness) {
// See https://developer.apple.com/library/content/documentation/StringsTextFonts/Conceptual/TextAndWebiPhoneOS/TypoFeatures/TextSystemFeatures.html
@ -368,8 +375,9 @@ cell_metrics(PyObject *s, unsigned int* cell_width, unsigned int* cell_height, u
CTLineGetTypographicBounds(line, &typographic_ascent, &typographic_descent, &typographic_leading);
*cell_height = MAX(4u, (unsigned int)ceilf(line_height));
CGFloat bounds_ascent = bounds_without_leading.size.height + bounds_without_leading.origin.y;
if (OPT(adjust_baseline_px) != 0) bounds_ascent -= OPT(adjust_baseline_px);
if (OPT(adjust_baseline_frac) != 0) bounds_ascent -= *cell_height * OPT(adjust_baseline_frac);
int baseline_offset = 0;
if (OPT(adjust_baseline_px) != 0) baseline_offset = OPT(adjust_baseline_px);
else if (OPT(adjust_baseline_frac) != 0) baseline_offset = *cell_height * OPT(adjust_baseline_frac);
*baseline = (unsigned int)floor(bounds_ascent + 0.5);
// Not sure if we should add this to bounds ascent and then round it or add
// it to already rounded baseline and round again.
@ -384,6 +392,11 @@ cell_metrics(PyObject *s, unsigned int* cell_width, unsigned int* cell_height, u
debug("\tline metrics: ascent: %f descent: %f leading: %f\n", typographic_ascent, typographic_descent, typographic_leading);
debug("\tfont metrics: ascent: %f descent: %f leading: %f underline_position: %f\n", self->ascent, self->descent, self->leading, self->underline_position);
debug("\tcell_height: %u baseline: %u underline_position: %u strikethrough_position: %u\n", *cell_height, *baseline, *underline_position, *strikethrough_position);
if (baseline_offset) {
*baseline = adjust_ypos(*baseline, *cell_height, baseline_offset);
*underline_position = adjust_ypos(*underline_position, *cell_height, baseline_offset);
*strikethrough_position = adjust_ypos(*strikethrough_position, *cell_height, baseline_offset);
}
CFRelease(test_frame); CFRelease(path); CFRelease(framesetter);

View File

@ -302,6 +302,14 @@ calc_cell_width(Face *self) {
return ans;
}
static unsigned int
adjust_ypos(unsigned int pos, unsigned int cell_height, int adjustment) {
if (adjustment >= 0) adjustment = MIN(adjustment, (int)pos - 1);
else adjustment = MAX(adjustment, (int)pos - (int)cell_height + 1);
return pos - adjustment;
}
void
cell_metrics(PyObject *s, unsigned int* cell_width, unsigned int* cell_height, unsigned int* baseline, unsigned int* underline_position, unsigned int* underline_thickness, unsigned int* strikethrough_position, unsigned int* strikethrough_thickness) {
Face *self = (Face*)s;
@ -309,13 +317,13 @@ cell_metrics(PyObject *s, unsigned int* cell_width, unsigned int* cell_height, u
*cell_height = calc_cell_height(self, true);
int baseline_offset = 0;
if (OPT(adjust_baseline_px) != 0) baseline_offset = OPT(adjust_baseline_px);
if (OPT(adjust_baseline_frac) != 0) baseline_offset = (int)(*cell_height * OPT(adjust_baseline_frac));
*baseline = font_units_to_pixels_y(self, self->ascender) - baseline_offset;
*underline_position = MIN(*cell_height - 1, (unsigned int)MAX(0, font_units_to_pixels_y(self, MAX(0, self->ascender - self->underline_position)) - baseline_offset));
else if (OPT(adjust_baseline_frac) != 0) baseline_offset = (int)(*cell_height * OPT(adjust_baseline_frac));
*baseline = font_units_to_pixels_y(self, self->ascender);
*underline_position = MIN(*cell_height - 1, (unsigned int)MAX(0, font_units_to_pixels_y(self, MAX(0, self->ascender - self->underline_position))));
*underline_thickness = MAX(1, font_units_to_pixels_y(self, self->underline_thickness));
if (self->strikethrough_position != 0) {
*strikethrough_position = MIN(*cell_height - 1, (unsigned int)MAX(0, font_units_to_pixels_y(self, MAX(0, self->ascender - self->strikethrough_position)) - baseline_offset));
*strikethrough_position = MIN(*cell_height - 1, (unsigned int)MAX(0, font_units_to_pixels_y(self, MAX(0, self->ascender - self->strikethrough_position))));
} else {
*strikethrough_position = (unsigned int)floor(*baseline * 0.65);
}
@ -324,6 +332,11 @@ cell_metrics(PyObject *s, unsigned int* cell_width, unsigned int* cell_height, u
} else {
*strikethrough_thickness = *underline_thickness;
}
if (baseline_offset) {
*baseline = adjust_ypos(*baseline, *cell_height, baseline_offset);
*underline_position = adjust_ypos(*underline_position, *cell_height, baseline_offset);
*strikethrough_position = adjust_ypos(*strikethrough_position, *cell_height, baseline_offset);
}
}
unsigned int

View File

@ -98,11 +98,12 @@ opt('adjust_baseline', '0',
option_type='adjust_baseline', ctype='!adjust_baseline',
add_to_default=False,
long_text='''
Adjust the baseline position of each character. You can use either
a number, which is interpreted as pixels or a percentage (number followed by %),
which is interpreted as the percentage of the line height. A positive
value moves all characters up, and a negative value moves them down.
The underline and strikethrough positions are adjusted accordingly.
Adjust the vertical alignment of text (the height in the cell at which text is
positioned). You can use either numbers, which are interpreted as pixels or a
percentages (number followed by %), which are interpreted as the percentage of
the line height. A positive value moves the baseline up, and a negative value
moves them down. The underline and strikethrough positions are adjusted
accordingly.
'''
)