Shuffle code
Alpine 3.24 Success
Alpine 3.24 aarch64 Success

This commit is contained in:
2026-08-02 21:06:19 +02:00
parent 0ca431e4eb
commit 322d8af210
+99 -98
View File
@@ -759,27 +759,85 @@ void set_source(cairo_t *cr, const Color &color) {
cairo_set_source_rgb(cr, color.red, color.green, color.blue);
}
void rounded_rectangle(cairo_t *cr, double x, double y, double width,
double height, double radius) {
radius = min(radius, min(width, height) / 2.);
struct FontMetrics {
string family;
double em_size;
int cell_width;
int cell_height;
double baseline;
};
cairo_new_sub_path(cr);
cairo_move_to(cr, x + radius, y);
cairo_line_to(cr, x + width - radius, y);
cairo_arc(
cr, x + width - radius, y + radius, radius, -numbers::pi / 2., 0.);
cairo_line_to(cr, x + width, y + height - radius);
cairo_arc(cr, x + width - radius, y + height - radius, radius, 0.,
numbers::pi / 2.);
cairo_line_to(cr, x + radius, y + height);
cairo_arc(cr, x + radius, y + height - radius, radius, numbers::pi / 2.,
numbers::pi);
cairo_line_to(cr, x, y + radius);
cairo_arc(
cr, x + radius, y + radius, radius, numbers::pi, 3. * numbers::pi / 2.);
cairo_close_path(cr);
FontMetrics measure_font(const string &family, double point_size) {
SurfacePtr surface(cairo_image_surface_create(CAIRO_FORMAT_ARGB32, 1, 1),
cairo_surface_destroy);
if (cairo_surface_status(surface.get()) != CAIRO_STATUS_SUCCESS)
fail("cannot create Cairo font measurement surface");
CairoPtr cr(cairo_create(surface.get()), cairo_destroy);
cairo_select_font_face(cr.get(), family.c_str(), CAIRO_FONT_SLANT_NORMAL,
CAIRO_FONT_WEIGHT_NORMAL);
const double em_size = point_size * kRenderDpi / 72.;
cairo_set_font_size(cr.get(), em_size);
cairo_font_extents_t extents{};
cairo_font_extents(cr.get(), &extents);
cairo_text_extents_t em_glyph{};
cairo_text_extents(cr.get(), "M", &em_glyph);
if (cairo_status(cr.get()) != CAIRO_STATUS_SUCCESS ||
!isfinite(extents.height) || !isfinite(em_glyph.x_advance))
fail("cannot measure font " + family);
const int cell_width = max(1, int(lround(em_glyph.x_advance)));
const int cell_height = max(1, int(lround(extents.height)));
return {
family,
em_size,
cell_width,
cell_height,
(cell_height - extents.ascent - extents.descent) / 2. + extents.ascent,
};
}
// --- Rendering ---------------------------------------------------------------
int canvas_dimension(int cells, int cell_size, int border) {
const int64_t result = int64_t(cells) * cell_size + 2 * int64_t(border);
if (result > WEBP_MAX_DIMENSION)
fail("rendering options make the WebP canvas too large");
return int(result);
}
class Renderer {
FontMetrics font_;
const Theme &theme_;
BadgePosition badge_position_;
int border_;
int width_;
int height_;
void render_cell(cairo_t *cr, const Terminal &terminal,
const VTermPos &cursor, const VTermScreenCell &cell, int row, int col,
int cell_columns) const;
void render_key(cairo_t *cr, const string &key) const;
public:
Renderer(const Cast &cast, const Options &options);
[[nodiscard]] SurfacePtr render(
const Terminal &terminal, const string &key) const;
[[nodiscard]] int width() const { return width_; }
[[nodiscard]] int height() const { return height_; }
};
Renderer::Renderer(const Cast &cast, const Options &options)
: font_(measure_font(options.font_name, options.point_size)),
theme_(cast.header.theme), badge_position_(options.badge_position),
border_(options.border),
width_(canvas_dimension(cast.max_cols, font_.cell_width, border_)),
height_(canvas_dimension(cast.max_rows, font_.cell_height, border_)) {}
// These look better pixel-perfect and properly adjusted to cell boundaries.
bool add_block_element(cairo_t *cr, const VTermScreenCell &cell, double x,
double y, double width, double height) {
if (cell.chars[1])
@@ -862,84 +920,6 @@ bool add_block_element(cairo_t *cr, const VTermScreenCell &cell, double x,
return true;
}
struct FontMetrics {
string family;
double em_size;
int cell_width;
int cell_height;
double baseline;
};
FontMetrics measure_font(const string &family, double point_size) {
SurfacePtr surface(cairo_image_surface_create(CAIRO_FORMAT_ARGB32, 1, 1),
cairo_surface_destroy);
if (cairo_surface_status(surface.get()) != CAIRO_STATUS_SUCCESS)
fail("cannot create Cairo font measurement surface");
CairoPtr cr(cairo_create(surface.get()), cairo_destroy);
cairo_select_font_face(cr.get(), family.c_str(), CAIRO_FONT_SLANT_NORMAL,
CAIRO_FONT_WEIGHT_NORMAL);
const double em_size = point_size * kRenderDpi / 72.;
cairo_set_font_size(cr.get(), em_size);
cairo_font_extents_t extents{};
cairo_font_extents(cr.get(), &extents);
cairo_text_extents_t em_glyph{};
cairo_text_extents(cr.get(), "M", &em_glyph);
if (cairo_status(cr.get()) != CAIRO_STATUS_SUCCESS ||
!isfinite(extents.height) || !isfinite(em_glyph.x_advance))
fail("cannot measure font " + family);
const int cell_width = max(1, int(lround(em_glyph.x_advance)));
const int cell_height = max(1, int(lround(extents.height)));
return {
family,
em_size,
cell_width,
cell_height,
(cell_height - extents.ascent - extents.descent) / 2. + extents.ascent,
};
}
// --- Rendering ---------------------------------------------------------------
int canvas_dimension(int cells, int cell_size, int border) {
const int64_t result = int64_t(cells) * cell_size + 2 * int64_t(border);
if (result > WEBP_MAX_DIMENSION)
fail("rendering options make the WebP canvas too large");
return int(result);
}
class Renderer {
FontMetrics font_;
const Theme &theme_;
BadgePosition badge_position_;
int border_;
int width_;
int height_;
void render_cell(cairo_t *cr, const Terminal &terminal,
const VTermPos &cursor, const VTermScreenCell &cell, int row, int col,
int cell_columns) const;
void render_key(cairo_t *cr, const string &key) const;
public:
Renderer(const Cast &cast, const Options &options);
[[nodiscard]] SurfacePtr render(
const Terminal &terminal, const string &key) const;
[[nodiscard]] int width() const { return width_; }
[[nodiscard]] int height() const { return height_; }
};
Renderer::Renderer(const Cast &cast, const Options &options)
: font_(measure_font(options.font_name, options.point_size)),
theme_(cast.header.theme), badge_position_(options.badge_position),
border_(options.border),
width_(canvas_dimension(cast.max_cols, font_.cell_width, border_)),
height_(canvas_dimension(cast.max_rows, font_.cell_height, border_)) {}
void Renderer::render_cell(cairo_t *cr, const Terminal &terminal,
const VTermPos &cursor, const VTermScreenCell &cell, int row, int col,
int cell_columns) const {
@@ -993,6 +973,27 @@ double badge_coordinate(double offset, double canvas_size, double badge_size,
return border + offset * em_size;
}
void add_rounded_rectangle(cairo_t *cr, double x, double y, double width,
double height, double radius) {
radius = min(radius, min(width, height) / 2.);
cairo_new_sub_path(cr);
cairo_move_to(cr, x + radius, y);
cairo_line_to(cr, x + width - radius, y);
cairo_arc(
cr, x + width - radius, y + radius, radius, -numbers::pi / 2., 0.);
cairo_line_to(cr, x + width, y + height - radius);
cairo_arc(cr, x + width - radius, y + height - radius, radius, 0.,
numbers::pi / 2.);
cairo_line_to(cr, x + radius, y + height);
cairo_arc(cr, x + radius, y + height - radius, radius, numbers::pi / 2.,
numbers::pi);
cairo_line_to(cr, x, y + radius);
cairo_arc(
cr, x + radius, y + radius, radius, numbers::pi, 3. * numbers::pi / 2.);
cairo_close_path(cr);
}
void Renderer::render_key(cairo_t *cr, const string &key) const {
if (key.empty())
return;
@@ -1015,8 +1016,8 @@ void Renderer::render_key(cairo_t *cr, const string &key) const {
const double y = badge_coordinate(
badge_position_.top, height_, badge_height, border_, font.em_size);
rounded_rectangle(cr, x + 0.5, y + 0.5, badge_width - 1., badge_height - 1.,
font.em_size * 0.75);
add_rounded_rectangle(cr, x + 0.5, y + 0.5, badge_width - 1.,
badge_height - 1., font.em_size * 0.75);
set_source(cr, theme_.background);
cairo_fill_preserve(cr);
set_source(cr, theme_.foreground);