Skip to content

Commit

Permalink
widgets: add PNG status badge (#11466)
Browse files Browse the repository at this point in the history
It is SVG rendered into PNG using rsvg, which is already pulled as a
dependency for Pango/Cairo stack.

Fixes #6221
  • Loading branch information
nijel authored Apr 23, 2024
1 parent c46d75a commit dbf4bfe
Show file tree
Hide file tree
Showing 6 changed files with 41 additions and 5 deletions.
2 changes: 1 addition & 1 deletion ci/apt-install
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@ apt-get purge git git-man

# Install dependencies
apt-get install -y \
gir1.2-pango-1.0 \
gettext \
git \
git-svn \
Expand All @@ -43,6 +42,7 @@ apt-get install -y \
libgirepository1.0-dev \
libcairo-dev \
liblz4-dev \
gir1.2-rsvg-2.0 \
gir1.2-pango-1.0

# Remove MySQL 8.x client, use older MariaDB one to ensure compatibility
Expand Down
3 changes: 3 additions & 0 deletions dev-docker/weblate-dev/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,9 @@ RUN apt-get update && apt-get install -y \
libz-dev \
libjpeg62-turbo-dev

# TODO: drop once weblate/weblate image has it
RUN apt-get install -y gir1.2-rsvg-2.0

COPY requirements.txt /tmp/
RUN . /app/venv/bin/activate && uv pip install -r /tmp/requirements.txt
# List should match weblate/weblate
Expand Down
2 changes: 1 addition & 1 deletion docs/admin/install/venv-debian.rst
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ Installing on Debian and Ubuntu
apt install -y \
libxml2-dev libxslt-dev libfreetype6-dev libjpeg-dev libz-dev libyaml-dev \
libffi-dev libcairo-dev gir1.2-pango-1.0 libgirepository1.0-dev \
libffi-dev libcairo-dev gir1.2-pango-1.0 gir1.2-rsvg-2.0 libgirepository1.0-dev \
libacl1-dev libssl-dev libpq-dev libjpeg-dev build-essential \
python3-gdbm python3-dev python3-pip python3-virtualenv virtualenv git
Expand Down
1 change: 1 addition & 0 deletions docs/changes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ Not yet released.
* Display more details on source string change in history.
* :ref:`mt-microsoft-translator` now supports using custom translators.
* Improved error handling in :ref:`invite-user`.
* Added PNG status badge.
* Added list of managed projects to the dashboard view.

**Bug fixes**
Expand Down
2 changes: 1 addition & 1 deletion weblate/trans/views/widgets.py
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down
36 changes: 34 additions & 2 deletions weblate/trans/widgets.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
from __future__ import annotations

import os.path
from io import StringIO
from typing import TYPE_CHECKING

import cairo
Expand Down Expand Up @@ -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),
Expand Down Expand Up @@ -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"
Expand Down Expand Up @@ -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")
Expand Down Expand Up @@ -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"
Expand Down

0 comments on commit dbf4bfe

Please sign in to comment.