Summary
When a custom frameColor object is passed to Symbol() (e.g. for no-fill rendering), Joker and Faker symbols always stroke in the Hostile (red) color instead of the expected orange/joker color. The root cause is that getcolors.js applies baseFrameColor.Friend = baseFrameColor.Hostile on the raw frameColor object without going through any color-mode redirect.
Affected file
src/ms/symbol/getcolors.js lines 31–34
What happens
The joker/faker branch does:
if (this.metadata.joker || this.metadata.faker) {
baseFillColor.Friend = baseFillColor.Hostile;
baseFrameColor.Friend = baseFrameColor.Hostile; // ← uses raw Hostile
baseIconColor.Friend = baseIconColor.Hostile;
}
When style.colorMode is an object (e.g. a custom color-mode table that remaps Hostile → orange), baseFillColor.Hostile resolves to orange and the fill is correct. But baseFrameColor is resolved independently from style.frameColor, which is a separate object that still holds the raw Hostile (red) value. The fill and stroke therefore disagree.
Reproduction
import ms from 'milsymbol';
const orangeMode = { ...ms.getColorMode('Light'), Hostile: '#FF6600' };
const frameColor = { ...ms.getColorMode('FrameColor') }; // Hostile = red
// Joker SIDC (standard identity digit = 4 → 'J')
const sidc = '10034000001101000000';
new ms.Symbol(sidc, {
fill: false,
colorMode: orangeMode, // fill uses Hostile → orange ✓
frameColor, // stroke uses Hostile → red ✗
}).asSVG();
The symbol's stroke is red even though the color mode specifies orange for joker/hostile affiliations.
Fix
In the joker/faker branch, resolve the stroke color through the same color-mode mapping used for the fill, rather than reading baseFrameColor.Hostile directly:
if (this.metadata.joker || this.metadata.faker) {
baseFillColor.Friend = baseFillColor.Hostile;
baseFrameColor.Friend = baseFrameColor.Hostile;
baseIconColor.Friend = baseIconColor.Hostile;
}
One approach is to apply the joker mapping after resolving the effective Hostile color from the active color mode, so both frameColor and colorMode branches use a consistent value. Alternatively, accept a jokerColor style property (analogous to the modifierColor proposal in #PR) so callers can explicitly override it.
Related
This bug is compounded by the in-place mutation issue described in [issue #351 ] — the frameColor object is mutated as a side-effect, which can corrupt shared objects across renders.
Summary
When a custom frameColor object is passed to Symbol() (e.g. for no-fill rendering), Joker and Faker symbols always stroke in the Hostile (red) color instead of the expected orange/joker color. The root cause is that getcolors.js applies baseFrameColor.Friend = baseFrameColor.Hostile on the raw frameColor object without going through any color-mode redirect.
Affected file
src/ms/symbol/getcolors.js lines 31–34
What happens
The joker/faker branch does:
if (this.metadata.joker || this.metadata.faker) {
baseFillColor.Friend = baseFillColor.Hostile;
baseFrameColor.Friend = baseFrameColor.Hostile; // ← uses raw Hostile
baseIconColor.Friend = baseIconColor.Hostile;
}
When style.colorMode is an object (e.g. a custom color-mode table that remaps Hostile → orange), baseFillColor.Hostile resolves to orange and the fill is correct. But baseFrameColor is resolved independently from style.frameColor, which is a separate object that still holds the raw Hostile (red) value. The fill and stroke therefore disagree.
Reproduction
import ms from 'milsymbol';
const orangeMode = { ...ms.getColorMode('Light'), Hostile: '#FF6600' };
const frameColor = { ...ms.getColorMode('FrameColor') }; // Hostile = red
// Joker SIDC (standard identity digit = 4 → 'J')
const sidc = '10034000001101000000';
new ms.Symbol(sidc, {
fill: false,
colorMode: orangeMode, // fill uses Hostile → orange ✓
frameColor, // stroke uses Hostile → red ✗
}).asSVG();
The symbol's stroke is red even though the color mode specifies orange for joker/hostile affiliations.
Fix
In the joker/faker branch, resolve the stroke color through the same color-mode mapping used for the fill, rather than reading baseFrameColor.Hostile directly:
if (this.metadata.joker || this.metadata.faker) {
baseFillColor.Friend = baseFillColor.Hostile;
baseFrameColor.Friend = baseFrameColor.Hostile;
baseIconColor.Friend = baseIconColor.Hostile;
}
One approach is to apply the joker mapping after resolving the effective Hostile color from the active color mode, so both frameColor and colorMode branches use a consistent value. Alternatively, accept a jokerColor style property (analogous to the modifierColor proposal in #PR) so callers can explicitly override it.
Related
This bug is compounded by the in-place mutation issue described in [issue #351 ] — the frameColor object is mutated as a side-effect, which can corrupt shared objects across renders.