From 03229db0bd1f5897a827efdfd502d56b75915000 Mon Sep 17 00:00:00 2001 From: BruebachL <44814898+BruebachL@users.noreply.github.com> Date: Sun, 23 Aug 2026 20:13:14 +0200 Subject: [PATCH] Fix cn and ss flags losing stars and clamp svg render sizes (#7168) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit cn.svg and ss.svg defined their star polygons with coordinates around plus/minus 5e5 compensated by tiny scale transforms. Qt drops shapes whose device space bounds exceed its rasterizer coordinate limit, so both flags silently lost their stars when rendered wider than roughly 76px. That threshold was always exceeded because loadSvg with expandOnly renders at the declared 640x480 native size before scaling down to the icon size. Fold the scale transforms into the polygon coordinates so the geometry is unchanged while bounds stay small at every render size. Also cap expandOnly and usericon render canvases at four times the requested size to bound memory use and keep pathological theme svgs away from the rasterizer limit. Took 8 minutes Took 57 seconds Took 3 minutes Co-authored-by: Lukas BrĂ¼bach --- cockatrice/resources/countries/cn.svg | 3 +- cockatrice/resources/countries/ss.svg | 2 +- .../src/interface/pixel_map_generator.cpp | 33 ++++++++++++++++++- 3 files changed, 34 insertions(+), 4 deletions(-) diff --git a/cockatrice/resources/countries/cn.svg b/cockatrice/resources/countries/cn.svg index f510cf049..45b608127 100644 --- a/cockatrice/resources/countries/cn.svg +++ b/cockatrice/resources/countries/cn.svg @@ -52,8 +52,7 @@ id="defs8"> - + diff --git a/cockatrice/src/interface/pixel_map_generator.cpp b/cockatrice/src/interface/pixel_map_generator.cpp index d3b0252a6..5bfba1c8a 100644 --- a/cockatrice/src/interface/pixel_map_generator.cpp +++ b/cockatrice/src/interface/pixel_map_generator.cpp @@ -14,6 +14,32 @@ #define DEFAULT_COLOR_MODERATOR_RIGHT "#000000"; #define DEFAULT_COLOR_ADMIN "#ff2701"; +/** + * Clamps an svg render size so that rendering does not exceed a multiple of the requested size. + * + * Rendering at the full native size of an svg just to scale it down afterwards wastes memory, + * and canvases with extreme coordinates can exceed Qt's rasterizer coordinate limit which makes + * Qt silently drop shapes from the rendered image. + * + * @param renderSize The size the svg would be rendered at. + * @param requestedSize The size that was actually requested. + * + * @return A size with the aspect ratio of renderSize whose longest side is at most four times + * the longest side of requestedSize. + */ +static QSize capRenderSize(const QSize &renderSize, const QSize &requestedSize) +{ + const int longestRequestedSide = qMax(requestedSize.width(), requestedSize.height()); + if (longestRequestedSide <= 0) { + return renderSize; + } + + const int longestRenderSide = qMax(renderSize.width(), renderSize.height()); + const qreal scale = qMin(1.0, static_cast(longestRequestedSide * 4) / longestRenderSide); + return QSize(qMax(1, static_cast(renderSize.width() * scale)), + qMax(1, static_cast(renderSize.height() * scale))); +} + /** * Loads in an svg from file and scales it without affecting image quality. * @@ -35,6 +61,9 @@ static QPixmap loadSvg(const QString &svgPath, const QSize &size, bool expandOnl // If expandOnly, make sure the pixmap is at least as large as the svg, so that we don't lose any detail. // QIcon.pixmap(size) will automatically scale down the image, but it won't scale it up. QSize pixmapSize = expandOnly ? svgRenderer.defaultSize().expandedTo(size) : size; + if (expandOnly) { + pixmapSize = capRenderSize(pixmapSize, size); + } QPixmap pix(pixmapSize); pix.fill(Qt::transparent); @@ -247,7 +276,9 @@ static QIcon loadAndColorSvg(const QString &iconPath, QSvgRenderer svgRenderer(doc.toByteArray()); - QPixmap pix(svgRenderer.defaultSize().expandedTo(QSize(minSize, minSize))); + const QSize pixmapSize = + capRenderSize(svgRenderer.defaultSize().expandedTo(QSize(minSize, minSize)), QSize(minSize, minSize)); + QPixmap pix(pixmapSize); pix.fill(Qt::transparent); QPainter pixPainter(&pix);