AtakPalette

Bidirectional lookup between ATAK's 14-color palette and the Meshtastic Team protobuf enum values. Used by the CoT parser/builder to encode stroke/fill/marker colors as a 1–2 byte enum on the wire when the source ARGB matches a palette entry, falling back to the exact _argb fixed32 field when it doesn't.

Provenance

The exact ARGB constants are taken from ATAK-CIV's com.atakmap.android.gui.ColorPalette source file at atak/ATAK/app/src/main/java/com/atakmap/android/gui/ColorPalette.java, specifically the COLOR1..COLOR14 class constants. ColorPalette's display names don't always line up with Meshtastic's Team enum names — ATAK labels position 6 "Brown" but the value 0xFF7F0000 is a dark red (maroon); Meshtastic calls it Maroon, which is actually more accurate. Position 14 is similarly misnamed: ATAK's 0xFF777777 is mid-gray and Meshtastic's Brown label is incorrect, but the numeric positions match and the enum tag is what rides on the wire, so the naming drift is cosmetic.

Wire-format contract

  • Every color field in the new typed payloads (DrawnShape.stroke_color, DrawnShape.fill_color, Marker.color, RangeAndBearing.stroke_color) is paired with a _argb fixed32 fallback.

  • On encode: parser extracts the exact ARGB from the source XML, calls argbToTeam — if non-null it populates the palette field with that Team value; either way it stores the exact bits in the _argb field so readers can recover them byte-for-byte.

  • On decode: builder reads the palette field first. If it is non-Unspecifed_Color (0), builder resolves the ARGB via teamToArgb and emits that as the <strokeColor value="..."> int. If the palette is Unspecifed_Color, builder uses the stored _argb bits.

This gives palette matches a 2-byte wire cost (tag + varint enum) and custom user-picked colors a 5-byte cost (tag + fixed32), with the exact bits always preserved for round-trip fidelity.

Bit patterns

The values below are the exact int bit patterns ATAK serializes in <strokeColor value="..."> / <fillColor value="..."> / <color argb="...">. 0xFFFFFFFF.toInt() == -1, 0xFFFF0000.toInt() == -65536, and so on. ATAK emits them as signed decimal ints so the parser reads them as such.

This object is immutable and safe to share across threads.

Properties

Link copied to clipboard
const val UNSPECIFIED: Int = 0

Meshtastic Team enum value for "no palette match" / "use the exact ARGB fallback". Mirrors the proto-generated Team.Unspecifed_Color = 0. Exposed here so parser/builder code can use a named constant instead of a magic zero.

Functions

Link copied to clipboard
fun argbToTeam(argb: Int): Int

Look up a Team enum value by its exact ARGB bit pattern.

Link copied to clipboard

True if the given Team value refers to one of the 14 named palette colors (i.e. not UNSPECIFIED and within the valid enum range).

Link copied to clipboard
fun teamToArgb(team: Int): Int?

Look up an exact ARGB bit pattern by Team enum value.