Skip to main content

Label placement and collision fades

Shared point and line symbol history, target queries, and actual frame scheduling

Stage 74 passed local public acceptance and matching development-SDK validation. This page describes the frozen contract. Formal publication and external/device acceptance remain pending as recorded below.

fadeDuration controls opacity when collision placement admits or withholds labels. Paint transitions, raster tile fades, and the pattern window configured by materialFadeDuration have separate clocks. This batch covers existing legal GeoJSON/MVT point and line symbols. It does not add globe or terrain labels, complex shaping, or cross-tile line stitching.

Standalone browser SDK creation accepts fadeDuration. Retained Native scripts, the desktop app, main-thread scripts, and Worker scripts use the same extension getter and setter. The extension lives under sqs; it is not presented as a standard MapLibre Map method.

// Standalone SDK initialization:
const map = await MapView.create(container, { fadeDuration: 1200 });
// These calls also work in the shared script environment:
map.sqs.setLabelFadeDuration(1200);
const milliseconds = await map.sqs.getLabelFadeDuration();

The capability commonSymbolPlacementHistory must be true for this contract. Check capabilities before using older versions.

The default is 300 ms. Zero selects the target on the next actual frame. Values must be finite, nonnegative, and at most 3600000 ms. Negative or nonfinite input yields INVALID_ARGUMENT; excessive duration yields RESOURCE_LIMIT. Rejection preserves configuration, identities, history, and the prior frame. Configuration survives full style replacement and clearing.

Opacity follows the real render clock at one full alpha unit per configured window. Reversal samples the current alpha and continues without a jump; fading from 0.4 to 0 takes about 0.4 windows. A duration change first samples the previous trajectory, then uses the new speed. This continuity is an explicit SqsMap policy. The observed reference zoom reversal also changed tile placement and scheduling, so that combined trajectory is not evidence for pure scalar continuity.

The first successful nonempty placement in a new map is immediately visible. This is not a rule for every style.load: a full replacement in an existing map introduces new resource identities and fades new labels in. An exact compatible no-op diff preserves identities and clocks. Layer/source/image removal, clearing, and destruction cannot retain invalid atlas references or ghost labels. Resource lifecycle and limits follow the frozen implementation.

Queries and rendering serve different purposes. queryRenderedFeatures follows target placement and retains original feature IDs, sources, and layers. A collision-withheld target leaves query results while its prior pixels can still fade out. Newly placed targets participate in queries as they begin fading in. Retiring geometry follows its original world anchor and the camera; it is not a frozen screenshot or a rewrite of source coordinates.

Existing optional-component and collision decisions still apply. A blocked required icon withholds the default icon/text group; icon-optional allows text to place independently. Placement opacity and paint opacity are each applied once. Curved glyphs, RGBA/SDF images, and stretch patches share the same clock. Dynamic image callbacks remain deduplicated by their shared owner per actual frame; retiring labels do not create a second callback loop.

flush({render:true}) still confirms one actual frame. Subscribe to idle before changing the target when waiting for a finite fade to finish. Other animation and resource requests also affect idle. Reading lifecycle state, queries, or configuration must not advance the clock.

DLL/SO clients use UTF-8 {method,args} through the existing sqsm_map_source_json channel. The getter returns a JSON number. Callers still release returned buffers with sqsm_map_bytes_free(out.allocation).

{"method":"sqs.setLabelFadeDuration","args":[1200]}
{"method":"sqs.getLabelFadeDuration","args":[]}

History is limited to 16384 groups. Current records, resource snapshots, both captures, the complete candidate, and ordering containers share an 8 MiB metadata budget. Old and new draw candidates together allow at most 65536 quads; old/new draw geometry, templates, and targets together allow at most 64 MiB. A string feature ID allows at most 2048 bytes; a retained identity key allows at most 4096 bytes. These are SqsMap safety limits, not separate pools per resource generation. Rejected candidates preserve prior state and pixels.

Complete HTML/CSS/JS and all four button handlers · One shared cross-platform script. The example includes original image/glyph resources and event handling. Serve it over HTTP beside the matching SDK dist directory.

Core 5576072e946eb146bb77f923fa3d5adbee3b84aa, development SDK 0.3.0-dev.5576072e. Shared label placement history and collision fades passed local public acceptance: the same 84-check/13-phase script passed Native, main-thread, and Worker at DPR1/2, with 845 actual observed frames. Coverage includes target queries, required/optional groups, real linear timing, reversal, full style replacement, and original identity/anchor continuity across MVT parent/child handoff with a nonzero 2400ms fade window. The raw C ABI passed 16 steps. Complete HTML passed four real buttons, four phases/30 frames, an original ID74 click, and 200ms stable-idle checks. The integrated CPU and final software-Vulkan case passed, together with relevant APP/native/script typing, dependency, generated-contract, and WASM checks.

Archive SqsMap-SDK-0.3.0-dev.5576072e-fixed74.tar.gz: 624 inventory files plus bundle.json, 38224421 bytes, SHA256 b74d766d98aa3f881efdd925efedc32ff27aa8707fed94a6225529c3dadabf2c. The tar was independently reopened to verify every size/SHA and exact Native/Android libraries, examples, and declarations. Linux Native, core/application/script WASM, and Android API24 ARM64/JNI match this core. Android is build/link verified, not device accepted. Bilingual production HTTP and four-repository Git synchronization are the final delivery steps. Full style/vector/DEM, mobile GIS/iOS, phone/hardware GPU, external Windows/macOS acceptance, formal publication, and deployment remain incomplete.