mirror of
https://github.com/Cockatrice/Cockatrice.git
synced 2026-11-07 10:33:24 -08:00
The pre-#7595 add, remove and delete icons were filled shapes with a black outline and no disc. A tint cannot bring that back, and the badge disc is a different icon language, so add a third value to the existing style axis. IconStyle::Sticker draws the sentinel glyph twice: a near-black rim at the band width plus one rim on each side, then the tone pass clipped to the glyph and filled with a vertical gradient. Both treatments keep the disabled fallback to the line glyph. The fill rule moves into theme_icon_fill: the semantic tones are tuned for text, so a filled shape gives its tone a saturation floor, and a dark-scheme tone is pulled down rather than up. IconTint::resolve() applies the same floor to line glyphs, and the badge disc uses the same fill, so a line, a badge and a sticker next to each other carry the same green or red instead of a pale line beside a saturated glyph. The badge's glyph ink follows the scheme: white on light-scheme tones, as in the pre-#7595 art, and the saturated tone darkened to an outline-dark ink on dark-scheme tones, where the shared saturated disc is light enough that white would sit near 2.7:1. The new test pins both cases so the glyph cannot silently flip. resolveSvgStrokeWidth() moves the stroke-width rewrite into libcockatrice_utility so the badge and the sticker share it; the badge's local copy is gone. The sticker is opted into at 17 call sites: increment, decrement and remove_row in the deck editor, settings pages, token dialog, server dialogs and replay/deck storage tabs. The visual database's clear-filter button keeps its trash can (icons/delete) in the line treatment: that glyph is new in #7595, but it is the clearer metaphor, and a sticker rim closes its lid gap at toolbar sizes. The preview generators also gain a semantic-tint sheet for #7775 and a line/badge/sticker family strip, so the three PR descriptions can show the same rendered colors.
84 lines
3.4 KiB
C++
84 lines
3.4 KiB
C++
/**
|
|
* @file theme_icon_badge.h
|
|
* @ingroup Interface
|
|
*/
|
|
|
|
#ifndef THEME_ICON_BADGE_H
|
|
#define THEME_ICON_BADGE_H
|
|
|
|
#include <QByteArray>
|
|
#include <QColor>
|
|
#include <QPixmap>
|
|
#include <QSize>
|
|
|
|
/**
|
|
* @brief Paints the badge treatment of a `currentColor` glyph.
|
|
*
|
|
* A tint alone can say "positive" or "negative", but a 2px line at 16px reads as
|
|
* a different thing from the filled badge art the UI used before the one-glyph
|
|
* cutover. The badge treatment keeps that shape: a filled disc, a dark ring, and
|
|
* a contrast glyph, all derived from the one tone the tint resolves to. So the
|
|
* theme still owns the color, and callers only choose between a line and a
|
|
* badge.
|
|
*
|
|
* The trade-off is fidelity against contrast. A badge is a small picture: it
|
|
* survives a busy toolbar and a tinted row better than a hairline, and it can
|
|
* carry a light or dark glyph independent of the surrounding text. In exchange
|
|
* it costs more pixels of attention per control, and its glyph color follows the
|
|
* scheme it is drawn for rather than the window's text color, so it is
|
|
* deliberately not the palette's foreground.
|
|
*
|
|
* Everything here works in device pixels. The icon engine renders at the
|
|
* device-pixel size it already computed and sets the pixmap's device pixel ratio
|
|
* afterwards, so badge geometry must not assume logical pixels.
|
|
*/
|
|
namespace ThemeIconBadge
|
|
{
|
|
/**
|
|
* @brief WCAG relative luminance, used to test a color against a background.
|
|
*
|
|
* Used by IconTint::resolve()'s selected-row contrast test.
|
|
*/
|
|
double relativeLuminance(const QColor &color);
|
|
|
|
/** @brief WCAG contrast ratio between two opaque colors, from 1.0 to 21.0. */
|
|
double contrastRatio(const QColor &first, const QColor &second);
|
|
|
|
/**
|
|
* @brief Glyph color for a badge disc.
|
|
*
|
|
* White on the light scheme, the saturated tone darkened to an outline-dark ink
|
|
* on the dark scheme. The dark-scheme tones fill the disc light enough that
|
|
* white would sit near 2.7:1 at its top, so that scheme keeps the darkened ink
|
|
* the badge had before the filled treatments shared a fill. The dark ink is
|
|
* derived from the tone, so the theme keeps control of both ends.
|
|
*/
|
|
QColor glyphColor(const QColor &tone);
|
|
|
|
/** @brief Size of the engraved glyph for a badge of @p pixelSize, in device pixels. */
|
|
QSize glyphSize(const QSize &pixelSize);
|
|
|
|
/**
|
|
* @brief Renders a sentinel-carrying SVG as a badge.
|
|
*
|
|
* The disc fills the square canvas minus the ring with the same gradient the
|
|
* sticker fill uses, the ring darkens the tone, and the sentinel is resolved to
|
|
* the contrast glyph. The SVG is scaled to nearly the whole disc, because the
|
|
* sentinel paths are padded inside their viewBox and a smaller box loses the
|
|
* stroke at 16px.
|
|
*
|
|
* This treatment reproduces the pre-#7595 ready/not-ready art, which was a
|
|
* filled disc. It is not a generic replacement for every semantic glyph: the
|
|
* old add/remove icons were filled glyphs with an outline and no disc, so
|
|
* badging them would invent a look the UI never had.
|
|
*
|
|
* @param svg Sentinel-carrying SVG source; `currentColor` is resolved internally.
|
|
* @param tone Disc color, already resolved for the icon mode.
|
|
* @param pixelSize Canvas size in device pixels; a non-square canvas centers
|
|
* the badge and leaves the remaining area transparent.
|
|
* @return The composited badge, or a null pixmap for empty or invalid input.
|
|
*/
|
|
QPixmap renderBadge(const QByteArray &svg, const QColor &tone, const QSize &pixelSize);
|
|
} // namespace ThemeIconBadge
|
|
|
|
#endif // THEME_ICON_BADGE_H
|