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] 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 - 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`) 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; 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 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) { 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 // 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); CTLineGetTypographicBounds(line, &typographic_ascent, &typographic_descent, &typographic_leading);
*cell_height = MAX(4u, (unsigned int)ceilf(line_height)); *cell_height = MAX(4u, (unsigned int)ceilf(line_height));
CGFloat bounds_ascent = bounds_without_leading.size.height + bounds_without_leading.origin.y; 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); int baseline_offset = 0;
if (OPT(adjust_baseline_frac) != 0) bounds_ascent -= *cell_height * OPT(adjust_baseline_frac); 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); *baseline = (unsigned int)floor(bounds_ascent + 0.5);
// Not sure if we should add this to bounds ascent and then round it or add // Not sure if we should add this to bounds ascent and then round it or add
// it to already rounded baseline and round again. // 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("\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("\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); 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); CFRelease(test_frame); CFRelease(path); CFRelease(framesetter);

View File

@ -302,6 +302,14 @@ calc_cell_width(Face *self) {
return ans; 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 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) { 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; 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); *cell_height = calc_cell_height(self, true);
int baseline_offset = 0; int baseline_offset = 0;
if (OPT(adjust_baseline_px) != 0) baseline_offset = OPT(adjust_baseline_px); 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)); 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) - baseline_offset; *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)) - 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))));
*underline_thickness = MAX(1, font_units_to_pixels_y(self, self->underline_thickness)); *underline_thickness = MAX(1, font_units_to_pixels_y(self, self->underline_thickness));
if (self->strikethrough_position != 0) { 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 { } else {
*strikethrough_position = (unsigned int)floor(*baseline * 0.65); *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 { } else {
*strikethrough_thickness = *underline_thickness; *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 unsigned int

View File

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