From 3ae03c68a98cd6b5afee16c3a832efd02463bec5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michal=20=C4=8Ciha=C5=99?= Date: Tue, 23 Apr 2024 12:13:02 +0200 Subject: [PATCH] widgets: add PNG status badge It is SVG rendered into PNG using rsvg, which is already pulled as a dependency for Pango/Cairo stack. Fixes #6221 --- weblate/trans/views/widgets.py | 2 +- weblate/trans/widgets.py | 36 ++++++++++++++++++++++++++++++++-- 2 files changed, 35 insertions(+), 3 deletions(-) diff --git a/weblate/trans/views/widgets.py b/weblate/trans/views/widgets.py index 2ee22acebf03..361463668c5b 100644 --- a/weblate/trans/views/widgets.py +++ b/weblate/trans/views/widgets.py @@ -116,7 +116,7 @@ def get_redirect_url( path.append("-") path.append(lang) # Redirect no longer supported badge styles to svg - if widget in {"status", "shields"}: + if widget == "shields": widget = "svg" return reverse( "widget-image", diff --git a/weblate/trans/widgets.py b/weblate/trans/widgets.py index c7db34f53d9d..f1d050f99c7c 100644 --- a/weblate/trans/widgets.py +++ b/weblate/trans/widgets.py @@ -5,6 +5,7 @@ from __future__ import annotations import os.path +from io import StringIO from typing import TYPE_CHECKING import cairo @@ -34,8 +35,9 @@ gi.require_version("PangoCairo", "1.0") gi.require_version("Pango", "1.0") +gi.require_version("Rsvg", "2.0") -from gi.repository import Pango, PangoCairo # noqa: E402 +from gi.repository import Pango, PangoCairo, Rsvg # noqa: E402 COLOR_DATA = { "grey": (0, 0, 0), @@ -210,6 +212,30 @@ def render(self, response) -> None: raise NotImplementedError +class PNGWidget(SVGWidget): + extension = "png" + content_type = "image/png" + + def render(self, response) -> None: + with StringIO() as output: + super().render(output) + svgdata = output.getvalue() + + handle = Rsvg.Handle.new_from_data(svgdata.encode()) + dimensions = handle.get_dimensions() + viewport = Rsvg.Rectangle() + viewport.x = 0 + viewport.y = 0 + viewport.width = dimensions.width + viewport.height = dimensions.height + surface = cairo.ImageSurface( + cairo.FORMAT_ARGB32, int(dimensions.width), int(dimensions.height) + ) + context = cairo.Context(surface) + handle.render_document(context, viewport) + surface.write_to_png(response) + + @register_widget class NormalWidget(BitmapWidget): name = "287x66" @@ -340,7 +366,7 @@ class SVGBadgeWidget(SVGWidget): colors: tuple[str, ...] = ("badge",) order = 80 template_name = "svg/badge.svg" - verbose = gettext_lazy("Status badge") + verbose = gettext_lazy("SVG status badge") def render(self, response) -> None: translated_text = gettext("translated") @@ -375,6 +401,12 @@ def render(self, response) -> None: ) +@register_widget +class PNGBadgeWidget(PNGWidget, SVGBadgeWidget): + name = "status" + verbose = gettext_lazy("PNG status badge") + + @register_widget class MultiLanguageWidget(SVGWidget): name = "multi"