mirror of
https://github.com/Cockatrice/Cockatrice.git
synced 2026-11-10 12:03:25 -08:00
[Icons] Add a sticker icon treatment
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.
This commit is contained in:
parent
717f64a88b
commit
876d66ffc9
25 changed files with 1027 additions and 127 deletions
|
|
@ -42,3 +42,46 @@ QByteArray resolveSvgColorSentinel(const QByteArray &svg, const QByteArray &colo
|
|||
}
|
||||
return resolved;
|
||||
}
|
||||
|
||||
QByteArray resolveSvgStrokeWidth(const QByteArray &svg, double width)
|
||||
{
|
||||
constexpr QByteArrayView ATTRIBUTE = "stroke-width";
|
||||
constexpr QByteArrayView DOUBLE_QUOTE = "\"";
|
||||
constexpr QByteArrayView SINGLE_QUOTE = "'";
|
||||
const QByteArray value = QByteArray::number(width, 'f', 2);
|
||||
|
||||
QByteArray resolved;
|
||||
resolved.reserve(svg.size());
|
||||
|
||||
qsizetype cursor = 0;
|
||||
while (true) {
|
||||
const qsizetype start = svg.indexOf(ATTRIBUTE, cursor);
|
||||
if (start < 0) {
|
||||
resolved.append(svg.sliced(cursor));
|
||||
return resolved;
|
||||
}
|
||||
|
||||
// Only an XML attribute is rewritten. A CSS declaration such as
|
||||
// `style="stroke-width:2"` has no `=` right after the name, so it stays
|
||||
// untouched and the scan moves past it.
|
||||
qsizetype nameEnd = start + ATTRIBUTE.size();
|
||||
while (nameEnd < svg.size() && svg.at(nameEnd) == ' ') {
|
||||
++nameEnd;
|
||||
}
|
||||
const bool isAttribute = nameEnd < svg.size() && svg.at(nameEnd) == '=' && nameEnd + 1 < svg.size();
|
||||
const char quoteChar = isAttribute ? svg.at(nameEnd + 1) : '\0';
|
||||
const bool quoted = quoteChar == '"' || quoteChar == '\'';
|
||||
const qsizetype close = quoted ? svg.indexOf(quoteChar == '"' ? DOUBLE_QUOTE : SINGLE_QUOTE, nameEnd + 2) : -1;
|
||||
if (close < 0) {
|
||||
resolved.append(svg.sliced(cursor, start + ATTRIBUTE.size() - cursor));
|
||||
cursor = start + ATTRIBUTE.size();
|
||||
continue;
|
||||
}
|
||||
|
||||
// Keep the opening quote, replace the value, and resume at the closing
|
||||
// quote so the rest of the document is copied verbatim.
|
||||
resolved.append(svg.sliced(cursor, nameEnd + 2 - cursor));
|
||||
resolved.append(value);
|
||||
cursor = close;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -28,4 +28,21 @@
|
|||
*/
|
||||
QByteArray resolveSvgColorSentinel(const QByteArray &svg, const QByteArray &color);
|
||||
|
||||
/**
|
||||
* @brief Rewrites the value of every `stroke-width` attribute in authored SVG.
|
||||
*
|
||||
* A treatment can need a heavier or lighter stroke than the one authored for a
|
||||
* line icon at text size. Like the sentinel resolver, this rewriter works on the
|
||||
* bytes and understands only the XML attribute form, in either quote style
|
||||
* (`stroke-width="2"` or `stroke-width='2'`): a CSS declaration such as
|
||||
* `style="stroke-width:2"` is left untouched. Documents without the attribute
|
||||
* are returned unchanged.
|
||||
*
|
||||
* @param svg SVG source bytes, expected to be UTF-8. Invalid UTF-8 is preserved
|
||||
* byte-for-byte.
|
||||
* @param width Replacement width in the document's user units.
|
||||
* @return The rewritten SVG source; the input is left untouched.
|
||||
*/
|
||||
QByteArray resolveSvgStrokeWidth(const QByteArray &svg, double width);
|
||||
|
||||
#endif // SVG_RECOLOR_H
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue