antialiasing-and-blending · git:20261026.79a684e · 2026-10-26 · sha256 f4d7cec8a350341c

antialiasing-and-blending git:20261026.79a684eA

Immutable. This exact content never changes and is served at /api/v1/blob/f4d7cec8a350341c.

---
name: antialiasing-and-blending
description: How map engines smooth edges (MSAA, analytic coverage in the shader, post-process, none), pay for resolution, blend translucent layers without darkened overlaps, keep one alpha convention, and avoid seams between tiles and shapes, with what each choice cost them. Load it when a map-from-scratch request has translucent fills or lines, layer opacity, fades, thin strokes or points on a target without MSAA (offscreen framebuffer, WebGPU, another engine's context, Canvas 2D hit canvas), a devicePixelRatio or frame-time budget on a phone, or when output shows jaggies, darker overlaps, dark or white fringes, hairline seams, blurry icons, or colour-ID picks that return wrong ids.
---

# Antialiasing and blending: edges, alpha, overlaps and seams

Every map edge is a partial-coverage problem, and every partial-coverage
pixel is a blending problem. A general engine must antialias any shape on
any render target, blend any number of translucent layers in any order,
composite over any page, and accept tiles from any producer, so it carries
MSAA, shader coverage, offscreen passes, stencil tricks and alpha
bookkeeping, and still ships bugs where two of them meet: darker overlaps,
fringes at transparent edges, hairline seams between tiles, ids that do not
exist. A renderer made for one request knows its targets, its layers and
whether any of them is translucent, so most of this machinery becomes a
bake-time decision or disappears. This skill collects what the engines
decided and why. Line geometry (joins, the ±0.5 px outset) is in the
line-tessellation skill, glyph halos in text-rendering, icon snapping in
symbols-and-icons, fallback tiles in tile-lod-and-overzoom; only the
coverage and blending side is here [108]. Per-engine detail is in
[references/engines.md](references/engines.md).

## First decision: where does edge coverage come from?

| The target and shapes | Edge coverage from | Evidence |
| --- | --- | --- |
| default WebGL2 canvas you own, mixed shapes, desktop | `antialias: true` (MSAA), nothing in the shader | the repo's 02, 03, 07 do this [107]; MSAA gave 1,361 partial pixels on a 2 px diagonal but only 3 alpha levels [1] |
| offscreen framebuffer, WebGPU canvas, another engine's context (MapLibre, Google Maps) | analytic coverage in the shader: `fwidth`, half-pixel outset | no MSAA reaches these targets [1][2]; 0 partial pixels without it, 1,572 with >40 levels with it [1] |
| lines, circles, SDF glyphs, procedural patterns | analytic coverage, even with MSAA available | +2.0% GPU for 100K 1 px paths [1]; Cesium antialiases draped lines in the shader [8][9]; walkers feathers half a pixel instead of MSAA [20]; Organic Maps draws hatches with `fwidth` instead of mask textures [102] |
| stencil-filled polygons (07's even-odd fill) | MSAA only | the stencil test has no coverage value; the land edge in 07 is smoothed only because the canvas is multisampled [107] |
| id buffer, count buffer, exact-colour mask | none | antialiased hit-canvas edges decode to ids that do not exist [52]; the repo's 04 counts into a canvas with `antialias: false` and additive `ONE, ONE` [107]; MapServer added per-style aliased lines for exact colours [96] |
| a whole frame, weak mobile GPU | not FXAA | Organic Maps stopped enabling its post-process AA because it 'destroys performance on some Android devices' [103]; FXAA/TAA cannot recover coverage and break shared depth [1] |
| Canvas 2D | the browser's own AA | it cannot be turned off on a hit canvas [52]; antialiased clip paths leave gaps between tiles [17] |

Write the choice and the rejected rows into `architecture_selection`.

## Decisions the engines made

### Analytic edge coverage

- **The ramp is centred on the edge, ±0.5 px, and the geometry is widened
  by half a pixel.** OpenLayers' first ramp ran 0 to -1 px and every line
  came out 1 px thinner than asked [14]. deck.gl computes
  `clamp((1 - coord) / fwidth(coord) + 0.5, 0, 1)` and extends the strip by
  half a device pixel so the outer half of the ramp is rasterised [1];
  maplibre-rs adds a 0.5 px outset in clip space, multiplied by `w` [21];
  Cesium fades draped lines over a half-pixel band [9]; tangram enlarges
  point quads in the vertex shader for the same reason, and removed a
  '+1 px to balance antialiasing' that made outlines oversized [60].
- **Feather across the width, never along the length.** Segmented strokes
  abut lengthwise, so feathering their ends seams at every vertex; deck.gl
  leaves flat caps hard [1][2].
- **Coverage multiplies alpha before premultiplication.** Moving the
  multiply after it raised deck.gl's worst overshoot from 2 to 126 [2].
  Compute coverage before any `discard` [2].
- **Compile it as a variant, not a uniform branch**, so the default pays
  nothing; deck.gl replaced a uniform flag with GLSL/WGSL variants [2][3].
  Cost on an M1 Max at 3840x2160: +2.0% for 100K 1 px paths, +10.8% for
  256 overlapping 64 px strokes, +21.2% for 10K arcs, +6.6% for 100K points
  [1]. Cesium keeps an opt-out because 'disabling this is faster but leaves
  the edges aliased' [8][9].
- **Analytic AA on top of MSAA is a different picture**: deck.gl's WebGL
  golden dropped to a 98.28% match, so it is chosen per target [2].
- **Self-overlaps composite twice** with shader coverage; deck.gl documents
  it as a known artefact [1][3].
- **Dashes are prefiltered**: integrating the dash square wave over the
  pixel footprint fixed a 0.2 px period from mean/stdev 107.7/125.9 to
  127.5/0.5 (target 127.5), for +0.10 ms in an overdraw-heavy pass and
  nothing in a sparse one; rounded dash ends intersect the line's AA
  envelope once, not twice (double ramps gave dark shoulders) [4].
- **Points and fill+outline in one pass**: tangram composites stroke over
  fill in the shader with one `length()` and no branch [60]. The repo's 07
  does the same with a 1 px rim [107].
- **highp for SDF edge maths on mobile**: lowp gamma aliased large text on
  mobile in MapLibre [28].
- **Shader patterns beat mask textures**: Organic Maps replaced 13 mask PNGs
  (every DPI/theme) and their mipmaps with `fwidth`-antialiased patterns on a
  world-anchored lattice; thin lines stopped shimmering during zoom [102].

### Paying for pixels: resolution and when to antialias

- **Device pixel ratio is a budget, not a given.** Retina is 4x the
  fragments; deck.gl defaults `useDevicePixelRatio` to false and picking
  must follow the same ratio [6]. Cesium flipped its default three times
  (1.18 CSS px, 1.61 native, 1.62 flag off, 1.66 flag on) and settled on
  CSS pixels because weak laptop and phone GPUs ran 'at an unusable FPS'
  [10].
- **No MSAA while moving, one 4x frame when still.** ortho-earth's WebGPU
  path measured MSAA store/load/resolve as the largest fixed frame cost; it
  renders 1x during motion and one 4x frame after 500 ms still. Every
  animation source must count as motion: shadow-time replay counted as
  'still' doubled the main pass (10 to 21 ms) [39].
- **Measure GPU time, not wall clock, when adapting quality**: a 30 Hz
  monitor always read 33 ms and sank resolution to 0.55 at 3.7 ms of GPU
  time [40].
- **Turn MSAA off only after measuring it.** tangram-es on an iPhone 6S Plus
  went from ~6.3 to ~3.8 ms per frame with MSAA and stencil off plus shader
  work moved to vertices; the MSAA share was not separated [64].
- **Dropping AA is a visible quality cut.** QGIS measured 2%, 12% and 30%
  from disabling AA on three data sets, but the difference showed, so it is
  limited to about-one-pixel geometry and only when the user raises the
  simplification factor [44]. For dense 2D point clouds QGIS draws
  `fillRect` squares with AA off, 'orders of magnitude faster' [46].
- **Do not composite empty full-screen layers**: Marble's transparent
  routing overlay, repainted, uploaded and blended every frame, held a
  tablet at 3 fps; hiding it gave ~30 fps [48].

### Translucent overlaps: the darkening problem

Per-fragment alpha blending darkens wherever a layer overlaps itself:
crossing routes, line joins, buffered tile edges, polygons with several
styles. The engines found four ways out.

- **Draw the layer opaque offscreen, composite once with the layer
  opacity.** OpenLayers does this only when layer opacity < 1 [15].
  MapLibre GL JS did it for constant `line-opacity` in (0,1) [25]: a bench
  of 50 line layers at 0.5 was 3x slower at first, 1.95x later; the
  standard benches never reached the path because their opacities
  interpolate to 0 or 1. 6.0 reverted the automatic trigger and moved the
  fix behind a separate `line-layer-opacity` property [26]. Mapbox GL had
  removed the same approach long ago for performance [25]. A per-layer fill
  opacity PR stayed open 2022-2026 and was closed stale; a screen-size
  framebuffer did not fit terrain [27].
- **Write each pixel once with depth or stencil.** vtm clears depth and
  draws each translucent line style with depth test and writes, first as a
  global flag, then per style; reporters called it 'MUCH better' [104].
  tangram-es draws translucent polygons as a depth pre-pass plus `EQUAL`
  depth with a stencil `EQUAL 0, INCR`, so coplanar overlaps do not
  z-fight, at two passes and an 8-bit stencil [65]. MapLibre Native clips
  fill AA outlines with `LEQUAL` depth so they do not double-blend with
  neighbours [30]. MapLibre's own stencil attempt for lines failed: the
  first-drawn feature won, transparent pattern pixels wrote stencil, SDF
  edges showed artefacts [25].
- **Use commutative blend modes and no depth writes.** tangram draws add and
  multiply styles after opaque ones as order-independent approximations, and
  refused depth write with alpha because it regroups draws by tile and
  shader, so translucent geometry drawn first would hide what lies behind
  [61][62]. tangram-es turns depth writes off for add and multiply [66].
  Additive suits only a known dark background: globe.gl's additive arcs
  vanished on white and switched to normal blending [72].
- **Order-independent transparency only for intersecting 3D volumes.**
  Cesium's weighted blended OIT needs no sorting, but two layers looked
  almost opaque and three opaque, and an FBO bind typo cost every draw [11].
  maplibre-rs removed all transparency until OIT exists [22]. navara left
  translucent instances inside one InstancedMesh unsolved: CPU sorting is
  per mesh, and depth-then-colour dual pass doubles GPU work [35].
- **Batching merges overlaps.** OpenLayers fills up to 200 polygons in one
  path only when the source declares `overlaps: false`; sniffing alpha in
  the style was tried and dropped as an 'opacity guessing game' [16].

### One alpha convention, end to end

- **Premultiplied for anything filtered or composited.** Mapnik's grey
  fringes under bilinear scaling came from premultiplying twice; AGG filters
  require premultiplied input [85]. It moved the whole rasteriser to
  premultiplied buffers, premultiplies markers once before caching, and
  added a `premultiplied` flag to images after a string of bugs (#1489,
  #1541, #1995, #2011) [84]. iTowns removed white fringes on transparent
  raster layers with premultiplied textures and shader [73]. GRASS fixed
  transparent-over-opaque cells by matching cairo's premultiplied surfaces
  [47]. WorldWindJava premultiplies symbol textures and alpha-tests
  `> 0` so transparent texels stay out of the pick frame [79].
- **When resolving MSAA into a texture, un-premultiply on the copy**, or
  edges darken (or brighten by 1/alpha); navara bakes all draped features
  through one shared multisampled target because per-tile multisampling
  quintupled every drape target's memory [34]. MapLibre Native uploads
  decoded premultiplied images as-is and un-premultiplies in the shader
  [32].
- **Separate alpha blend when the canvas is composited over something.**
  deck.gl's `blendFuncSeparate(..., ONE, ONE_MINUS_SRC_ALPHA)` was reverted
  the same day for compatibility and left opt-in, so overlay alpha stays
  wrong by default [5]. The repo's WebGL canvases are `alpha: false`, which
  avoids the question [107].
- **One colour space**: galileo dropped sRGB textures and surface because
  images are decoded as plain RGBA bytes; blending then happens in gamma
  space [106].
- **Fix the convention in test readback**: maplibre-rs's premultiplied PR
  converts readback to straight alpha before comparing with PNG fixtures
  [24].

### Seams between tiles and shapes

- **Snap tile placement to device pixels at rest.** Fractional positions
  leave antialiased, partly transparent edges on both sides: Leaflet snaps
  drag positions by `round(x * dpr) / dpr` [58] and rounds offsets in the
  drawing step, not in stored geometry [54]; QGIS expands integer tile rects
  outwards [41]; modestmaps makes scale × width an integer and rounds only
  when stopped [70]; polymaps rounds only at integer zoom without rotation,
  and seams at fractional zoom stayed open for years [71].
- **Compositor seams are not fixable from DOM tiles.** Leaflet's seam issue
  ran from 2015 with 200+ comments; 1 px oversize blurred tiles and broke
  overzoom, stitching to one canvas was 'really slow', and the 2023 fix is
  `mix-blend-mode: plus-lighter` on tile images, narrowed to `img` within
  two weeks [55]. TerriaJS draws tiles 0.5 px larger [77]; Leaflet called
  its zoom-animation seams 'not possible to fix on the Leaflet side' [57].
  modestmaps' one-transform-per-level was reverted over Safari seams [69].
- **Do not clip with antialiased paths at tile edges.** OpenLayers renders
  each vector tile into its own canvas instead [17]; on iOS 12 a rotated
  clip made `drawImage` up to 93x slower [19].
- **Clip at bake time with a buffer, and do not stroke the clip edge.**
  MapServer pads polygon clipping by 2 px so degenerate clipper edges fall
  off-image, and sizes the buffer from every style's width and offset [93];
  GeoServer clips vector tiles 12 px outside the tile [97]; TerriaJS's
  Tippecanoe polygon splitting drew stray lines until `--no-polygon-splitting`
  [74].
- **Clip each tile to its square when tiles carry buffers.** RustGIS's
  stencil per tile fixed see-through double-blended fills (48k outlier
  pixels) [37]; tangram draws unclipped and accepts doubled translucent
  polygons at tile edges, advising bake-time clipping [61].
- **Adjacent faces of one mesh must not blend twice.** Mapnik warps
  transparent rasters with `src` compositing instead of `src-over` because
  antialiased face edges seamed [89]. MapServer stopped drawing a hidden
  same-colour outline around every polygon; coverages that need continuity
  add it explicitly [91].
- **Atlas and texture edges**: deck.gl uses `lodMaxClamp: 0` so pattern
  cells do not bleed at minification [7]; Cesium tolerates texcoords 1/10
  texel outside [0,1] [13]. Clear pooled bitmaps before drawing transparent
  content: osmdroid showed stale tiles over empty sea [105].

### Fades and translucent stand-ins

- **A fade multiplies with layer opacity.** WebWorldWind needed three fixes
  (flashing, failed-load fallbacks fading, double opacity) and then disabled
  fading on translucent layers [78]. OpenLayers 2 discouraged back-buffer
  transitions on transparent layers [51]; harp.gl offers
  `allowOverlappingTiles=false` because overlapping transparent tiles
  flickered [67]; tangram stencil-masks translucent proxy tiles but not
  points or text, where transparent pixels write stencil and cut out [59].
- **Cross-fades with coverage (A2C/MSAA) bring the new one to full first**:
  osgearth uses min(1, 2(1-t)) and min(1, 2t); complementary ramps kept
  about 68% of reference coverage at the midpoint [80].
- **Never make correctness depend on a fade's completion event**: OL2's
  `transitionend` never fired without a CSS rule, so old tiles stayed [49];
  Leaflet's fade states made pruning racy [56].

### Pixel snapping and filtering

- Snap only when idle: OpenLayers removed per-style `snapToPixel` and snaps
  when no interaction or animation runs [18]; tangram's always-on snapping
  shimmered during slow pans [60]. MapLibre Native tried nearest icon
  sampling during pure pans and reverted it without a stated reason [33].
  OL2, Mapnik and OsmAnd round icon positions to whole pixels at native
  size [53][88][101]; tangram found CPU rounding of label positions
  useless because the view matrix moves them off the grid again, so it
  snaps in the vertex shader [63]. Icon and glyph specifics:
  symbols-and-icons, text-rendering [108].
- Resample data, not colours, and on the target's pixel grid: QGIS moved
  raster resampling to read time so layers stop shifting by a subpixel,
  at the price of harder edges and a visible look change [45]; OL2's tile
  seams came from sub-pixel CSS positions [50].
- Round points come from the fragment shader, not driver point smoothing:
  osgEarth's smooth points vanished in a Qt-hosted context until a 3.3
  context was requested [81]. Mip level on a pitched raster map can be
  computed per vertex to save fragment work [100].
- Halos are a coverage problem too: one-pass SDF halo+fill cut MapLibre's
  symbol time by about 40% [29]; Mapnik's 'fast' halo rasteriser doubled
  its text benchmark for 1-2 px halos [82]; MapServer replaced 8 offset
  redraws with a stroked outline [94]. Details: text-rendering [108].
- Knock-out masks (labels cutting roads) are a second pass or a stencil;
  QGIS's version cost about 8k lines and forced rasterised PDF until mask
  shapes were recorded as clip paths [42].

### Palette output

- Keep a few alpha levels, not binary transparency: Mapnik's png256 builds
  one octree per alpha range (4 levels by default, ~10% more encode time and
  size) [87]; GeoServer uses an RGBA median cut when transparent [98];
  MapServer pre-allocates semantic colours before AA eats the palette [92].
  Composite lossless layers, not palette ones: GeoServer's png8 member
  tiles lost antialiased edges when stacked [99].

## Tried and reverted

- MapLibre GL JS: offscreen pass tied to `line-opacity` (#7490) reverted in
  6.0 for a separate property [25][26]; stencil masking of line overdraw
  [25]; per-layer fill opacity PR closed stale [27].
- MapLibre Native: nearest icon filtering during pans, reverted [33].
- deck.gl: separate alpha blending as default, reverted the same day [5];
  uniform AA branch replaced by compiled variants [2].
- Cesium: render resolution default flipped 1.18 → 1.61 → 1.62 → 1.66 [10];
  an SDF distance texture for clipping polygons, replaced by per-tile
  vector lookups because a fixed-resolution SDF ran out across distance
  scales [12].
- OpenLayers: fill batching landed, reverted within a week, re-landed with
  alpha sniffing, replaced by `overlaps` [16]; fractional overlay positions
  reverted in 4.3.3 [18].
- QGIS: always disabling AA for tiny features as part of fast drawing [44].
- Leaflet: 1 px oversize, NoGap, `L_DISABLE_3D`, then `mix-blend-mode`
  narrowed to images [55]. modestmaps: per-level transform reverted from
  master [69]. polymaps: a Firefox rounding tweak rolled back [71].
- MapServer: cleaning degenerate clipped edges caused polygon flooding [93];
  GD backend removed after years beside AGG [91]; GD halo stroker route
  closed [94].
- maplibre-rs: tile stencil by x/y parity abandoned [23]; all transparency
  removed pending OIT [22].
- navara: forked UnrealBloomPass replaced by a mip blur (square halos,
  threshold flicker) [36].

## Guidance for a renderer in this repo

1. **List the targets and say where coverage comes from on each** (table
   above). The repo's browser examples own their canvas, so `antialias:
   true` is the start [107]; any offscreen, float, id or count target is
   single-sample, and shapes drawn there need analytic coverage or none
   [1][52]. A stencil fill gets edges only from MSAA [107].
2. **Analytic AA for lines, points and patterns**: ±0.5 px ramp from
   `fwidth`, quad widened by half a device pixel, width-wise only, coverage
   before premultiplication, highp on mobile [14][1][2][28]. If MSAA is also
   on, decide which one owns the edge and check the picture [2].
3. **Budget the pixel ratio and MSAA in `spec.yaml`.** Bench frame GPU time
   at DPR 1, 2 and the device's, with and without MSAA [6][10][39]. If the
   map animates and MSAA is expensive, render moving frames at 1x and one
   MSAA frame when still, and count every animation as motion [39]. On weak
   phones avoid full-screen post-process AA [103].
4. **Bake translucency away when you can.** Most map layers are not seen
   through each other: mix the colour with the background at bake time and
   draw opaque. If a layer must stay translucent, decide its overlap rule
   at bake time: a non-overlapping coverage can be one path or one mesh
   [16]; overlapping routes or tracks need write-once (stencil or depth per
   layer) [104][65]; an offscreen composite is affordable for one or two
   layers, not dozens [25]. If overlaps are supposed to add up (track
   density), say so: write-once removes that [25].
5. **Premultiplied alpha everywhere** in textures, sprites and blending,
   converted once in `bake.ts`; `blendFunc(ONE, ONE_MINUS_SRC_ALPHA)` then
   matches [84][85][73]. The repo's examples blend untextured vertex
   colours with `SRC_ALPHA, ONE_MINUS_SRC_ALPHA` [107]; that is exact while
   nothing is filtered, resolved or composited, so switch when the first
   texture, sprite or offscreen layer arrives. Keep `alpha: false` unless
   the map is composited over the page; then set the alpha channel's blend separately [5][107].
6. **No seams by construction**: clip at bake time to the tile or view plus
   max stroke width + offset + 1 px, and never stroke a clip edge [93][97]
   [74]; draw a level of tiles as one mesh in one surface rather than as
   separately antialiased quads [55][17]; snap at rest, not in motion
   [18][58].
7. **Leave out what the purpose excludes**: OIT, fade machinery, proxy
   stencils, palette quantisers and dirty-rect compositors all exist for
   inputs a general engine cannot predict [11][78][59][87][83].
8. **Check edges in `verification.checks`.** Count partial-coverage pixels
   on a known diagonal like deck.gl's RFC (0 means no AA reached the
   target) [1]; sample an overlap of two translucent features against the
   single-feature colour; compare screenshots with per-pixel tolerance
   masks, not exact matches [43].

## Sources

Local paths are relative to the repository; `rr/` is `ref-repos/`.

1. https://github.com/visgl/deck.gl/blob/master/dev-docs/RFCs/v9.4/analytic-antialiasing-rfc.md ; `rr/visgl__deck.gl/dev-docs/RFCs/v9.4/analytic-antialiasing-rfc.md`
2. https://github.com/visgl/deck.gl/pull/10520
3. https://github.com/visgl/deck.gl/commit/427df1b0 ; https://github.com/visgl/deck.gl/commit/9846e044
4. https://github.com/visgl/deck.gl/pull/10581
5. https://github.com/visgl/deck.gl/commit/925a0fa9 ; https://github.com/visgl/deck.gl/commit/2cc1b8fc ; https://github.com/visgl/deck.gl/commit/e01e5b73
6. https://github.com/visgl/deck.gl/commit/376ccfdb ; https://github.com/visgl/deck.gl/commit/32f92341 ; https://github.com/visgl/deck.gl/commit/2645c8e6
7. https://github.com/visgl/deck.gl/commit/14d5aa0f
8. `rr/CesiumGS__cesium/CHANGES.md` ; https://github.com/CesiumGS/cesium/pull/13675 ; https://github.com/CesiumGS/cesium/pull/13703
9. https://github.com/CesiumGS/cesium/commit/d14b301dc06b54f6d994f2cfd353aad7c96160b7 ; https://github.com/CesiumGS/cesium/commit/09a5810776d8bbc41ea029eca8a5f1a2aa6b404d ; https://github.com/CesiumGS/cesium/commit/b470ad5241a2860792f92364f9f22b376258323a
10. `rr/CesiumGS__cesium/CHANGES.md` ; https://github.com/CesiumGS/cesium/pull/8548 ; https://github.com/CesiumGS/cesium/issues/8082 ; https://github.com/CesiumGS/cesium/issues/8215 ; https://github.com/CesiumGS/cesium/commit/7f2dd38a7 ; https://github.com/CesiumGS/cesium/commit/6a9520fef
11. https://github.com/CesiumGS/cesium/pull/1412
12. https://github.com/CesiumGS/cesium/commit/1a74c94654ed16e99f6a13b7da1059f1c6b41520 ; https://github.com/CesiumGS/cesium/commit/dd17f1037609ce24d5c93cb63dbbae81b1219c6a ; https://github.com/CesiumGS/cesium/commit/8862ae50335a5ef8bbcd25ead626a3281084caa9 ; https://github.com/CesiumGS/cesium/commit/e1c238f1c67562f31e879086e49ad5de3b87550f
13. https://github.com/CesiumGS/cesium/commit/048416a30 ; https://github.com/CesiumGS/cesium/commit/3014ae331
14. https://github.com/openlayers/openlayers/commit/dea2bab81
15. https://github.com/openlayers/openlayers/commit/645e359cd
16. https://github.com/openlayers/openlayers/pull/5196 ; https://github.com/openlayers/openlayers/issues/4232 ; https://github.com/openlayers/openlayers/commit/18f3d7243 ; https://github.com/openlayers/openlayers/commit/880d4b89a ; https://github.com/openlayers/openlayers/commit/eed52552a ; https://github.com/openlayers/openlayers/commit/7e940e618
17. https://github.com/openlayers/openlayers/commit/c1b16217f ; https://github.com/openlayers/openlayers/commit/44764ec1d
18. `rr/openlayers__openlayers/changelog/upgrade-notes.md` ; `rr/openlayers__openlayers/changelog/v4.3.3.md`
19. https://github.com/openlayers/openlayers/issues/8531
20. https://github.com/podusowski/walkers/commit/a79e4dd
21. https://github.com/maplibre/maplibre-rs/commit/0de294e
22. https://github.com/maplibre/maplibre-rs/issues/252
23. https://github.com/maplibre/maplibre-rs/blob/main/docs/src/development-documents/stencil-masking.md ; `rr/maplibre__maplibre-rs/docs/src/development-documents/stencil-masking.md` ; `rr/maplibre__maplibre-rs/maplibre/src/render/tile_view_pattern/pattern.rs`
24. https://github.com/maplibre/maplibre-rs/pull/340
25. https://github.com/maplibre/maplibre-gl-js/pull/7490 ; https://github.com/mapbox/mapbox-gl-js/issues/4090
26. `rr/maplibre__maplibre-gl-js/CHANGELOG.md` ; https://github.com/maplibre/maplibre-gl-js/pull/7764
27. https://github.com/maplibre/maplibre-gl-js/pull/1191
28. https://github.com/maplibre/maplibre-gl-js/commit/10315c051 ; https://github.com/maplibre/maplibre-gl-js/commit/a72aab768 ; https://github.com/maplibre/maplibre-gl-js/commit/293c80c69
29. https://github.com/maplibre/maplibre-gl-js/commit/018c3a089
30. https://github.com/maplibre/maplibre-native/commit/31a3d3603
31. https://github.com/maplibre/maplibre-native/commit/893c97f20 ; https://github.com/maplibre/maplibre-native/commit/8264a1c86 ; `rr/maplibre__maplibre-native/src/mln/renderer/buckets/fill_bucket.hpp`
32. https://github.com/maplibre/maplibre-native/commit/8ae701054
33. https://github.com/maplibre/maplibre-native/commit/e2981c890 ; https://github.com/maplibre/maplibre-native/commit/a70bfd891
34. https://github.com/maplibre/navara/blob/main/guide/TILE_TEXTURE_COMPOSITING.md ; `rr/maplibre__navara/guide/TILE_TEXTURE_COMPOSITING.md`
35. https://github.com/maplibre/navara/pull/656 ; https://github.com/maplibre/navara/pull/816 ; https://github.com/maplibre/navara/pull/833
36. https://github.com/maplibre/navara/pull/832
37. https://github.com/opengeos/RustGIS/pull/611
38. https://github.com/opengeos/RustGIS/commit/f2ae8c0
39. https://github.com/kenjiyoshidahome2026-bit/ortho-earth/blob/main/packages/ortho-core/fallback-ladder.md ; `rr/kenjiyoshidahome2026-bit__ortho-earth/packages/ortho-core/fallback-ladder.md` ; `rr/kenjiyoshidahome2026-bit__ortho-earth/packages/ortho-core/webgpu port.md` ; https://github.com/kenjiyoshidahome2026-bit/ortho-earth/commit/06462fba
40. https://github.com/kenjiyoshidahome2026-bit/ortho-earth/commit/b06368cd ; https://github.com/kenjiyoshidahome2026-bit/ortho-earth/commit/9afc6f21
41. `rr/qgis__QGIS/ChangeLog` (line 53370, 2025-04-22 'Fix visible gaps in between xyz tiles')
42. `rr/qgis__QGIS/doc/design/selective_masking/README.md` ; `rr/qgis__QGIS/doc/design/selective_masking/p4/README.md` ; https://github.com/qgis/QGIS/pull/30747 ; https://github.com/qgis/QGIS-Enhancement-Proposals/issues/63 ; https://github.com/qgis/QGIS/pull/47459 ; https://github.com/qgis/QGIS-Enhancement-Proposals/issues/186
43. `rr/qgis__QGIS/ChangeLog` (line 527784, 2015-02-18 'Allow use of masks for unit test control images')
44. https://github.com/qgis/QGIS/issues/17441 ; https://github.com/qgis/QGIS/pull/980 ; https://github.com/qgis/QGIS/commit/3ddcdac57f ; https://github.com/qgis/QGIS/commit/95cabe5711
45. https://github.com/qgis/QGIS/pull/37044 ; https://github.com/qgis/QGIS/issues/36820 ; https://github.com/qgis/QGIS/issues/40746
46. https://github.com/qgis/QGIS/commit/f68e3ae5fa ; https://github.com/qgis/QGIS/commit/47a6e36ee0
47. https://github.com/OSGeo/grass/commit/314d2a35b
48. https://github.com/KDE/marble/commit/e2091b15c ; https://github.com/KDE/marble/commit/9d90adc92
49. https://github.com/openlayers/ol2/issues/127
50. https://github.com/openlayers/ol2/issues/458 ; https://github.com/openlayers/ol2/issues/513
51. https://github.com/openlayers/ol2/commit/4d2fb886 ; https://github.com/openlayers/ol2/commit/5879a71f ; https://github.com/openlayers/ol2/commit/8c6466bf ; https://github.com/openlayers/ol2/commit/da3dc76a ; https://github.com/openlayers/ol2/commit/1e5f8359
52. https://github.com/openlayers/ol2/commit/3ef0b059 ; https://github.com/openlayers/ol2/commit/11191464
53. https://github.com/openlayers/ol2/commit/6ce9feed
54. `rr/Leaflet__Leaflet/CHANGELOG.md` ; https://github.com/Leaflet/Leaflet/issues/1085 ; https://github.com/Leaflet/Leaflet/pull/5148
55. https://github.com/Leaflet/Leaflet/issues/3575 ; https://github.com/Leaflet/Leaflet/pull/8891 ; https://github.com/Leaflet/Leaflet/commit/0392b7f4 ; https://github.com/Leaflet/Leaflet/commit/8483bfa6
56. https://github.com/Leaflet/Leaflet/issues/3765 ; https://github.com/Leaflet/Leaflet/pull/4193
57. https://github.com/Leaflet/Leaflet/issues/1066
58. https://github.com/Leaflet/Leaflet/commit/cf6d32fc ; `rr/Leaflet__Leaflet/src/dom/Draggable.js`
59. https://github.com/tangrams/tangram/blob/master/src/scene/scene.js ; `rr/tangrams__tangram/src/scene/scene.js` ; https://github.com/tangrams/tangram/blob/master/src/styles/points/points.js ; https://github.com/tangrams/tangram/blob/master/src/styles/style.js
60. https://github.com/tangrams/tangram/issues/453 ; https://github.com/tangrams/tangram/pull/583 ; https://github.com/tangrams/tangram/pull/472
61. https://github.com/tangrams/tangram/pull/455
62. https://github.com/tangrams/tangram/commit/acd35493 ; https://github.com/tangrams/tangram/commit/77e436c6
63. https://github.com/tangrams/tangram/pull/454
64. https://github.com/tangrams/tangram-es/pull/1385
65. https://github.com/tangrams/tangram-es/commit/7259be83 ; https://github.com/tangrams/tangram-es/commit/a77e1193 ; https://github.com/tangrams/tangram-es/commit/464d8881
66. https://github.com/tangrams/tangram-es/commit/dbb6420b
67. `rr/heremaps__harp.gl/docs/@docs/fallback/README.md` ; https://github.com/heremaps/harp.gl/commit/0ea1a7ae ; https://github.com/heremaps/harp.gl/commit/0f8617bf
68. https://github.com/maptalks/maptalks.js/commit/a24ef1f82
69. https://github.com/stamen/modestmaps-js/issues/109 ; https://github.com/stamen/modestmaps-js/issues/103 ; https://github.com/stamen/modestmaps-js/commit/96da436 ; https://github.com/stamen/modestmaps-js/commit/dfec3cf ; https://github.com/stamen/modestmaps-js/commit/5ea22cb
70. https://github.com/stamen/modestmaps-js/commit/f03067d ; https://github.com/stamen/modestmaps-js/commit/18d251d ; `rr/stamen__modestmaps-js/src/utils.js`
71. https://github.com/simplegeo/polymaps/commit/86a1b8a ; https://github.com/simplegeo/polymaps/commit/65c6e96 ; https://github.com/simplegeo/polymaps/issues/36 ; https://github.com/simplegeo/polymaps/issues/65
72. https://github.com/vasturiano/globe.gl/issues/35 ; https://github.com/vasturiano/globe.gl/commit/7029fbe
73. https://github.com/iTowns/itowns/pull/584
74. https://github.com/TerriaJS/terriajs/issues/1211
75. https://github.com/TerriaJS/terriajs/pull/7209
76. https://github.com/TerriaJS/terriajs/commit/b456ee2e3
77. https://github.com/TerriaJS/terriajs/commit/479f32bef ; https://github.com/TerriaJS/terriajs/commit/16f82fce8
78. https://github.com/NASAWorldWind/WebWorldWind/commit/2d589d1 ; https://github.com/NASAWorldWind/WebWorldWind/commit/0be0d26 ; https://github.com/NASAWorldWind/WebWorldWind/commit/2043407 ; https://github.com/NASAWorldWind/WebWorldWind/commit/117e9d6 ; https://github.com/NASAWorldWind/WebWorldWind/commit/487a91d
79. https://github.com/NASAWorldWind/WorldWindJava/blob/2543c23/src/gov/nasa/worldwind/symbology/AbstractTacticalSymbol.java ; `rr/NASAWorldWind__WorldWindJava/src/gov/nasa/worldwind/symbology/AbstractTacticalSymbol.java`
80. https://github.com/pelicanmapping/osgearth/blob/master/docs/design/procedural2-plan-history.md ; `rr/pelicanmapping__osgearth/docs/design/procedural2-plan-history.md`
81. https://github.com/pelicanmapping/osgearth/issues/2783
82. https://github.com/mapnik/mapnik/blob/master/CHANGELOG.md (2.0, 2.2, 4.0.6 halo entries) ; https://github.com/mapnik/mapnik/issues/1781 ; https://github.com/mapnik/mapnik/issues/1298 ; https://github.com/mapnik/mapnik/commit/e66d00762 ; https://github.com/mapnik/mapnik/commit/e313b5ba6
83. https://github.com/mapnik/mapnik/blob/master/CHANGELOG.md (2.1, 4.3.2) ; https://github.com/mapnik/mapnik/issues/1409 ; https://github.com/mapnik/mapnik/commit/49c1c15c4 ; https://github.com/mapnik/mapnik/commit/73cfc6e66 ; https://github.com/mapnik/mapnik/commit/d4564c85e
84. https://github.com/mapnik/mapnik/blob/master/CHANGELOG.md (3.0 'premultiplied') ; https://github.com/mapnik/mapnik/issues/1489 ; https://github.com/mapnik/mapnik/issues/1995 ; https://github.com/mapnik/mapnik/commit/751d246f3 ; https://github.com/mapnik/mapnik/commit/327270754 ; https://github.com/mapnik/mapnik/commit/8674e463a
85. https://github.com/mapnik/mapnik/issues/1508 ; https://github.com/mapnik/mapnik/issues/1512
86. https://github.com/mapnik/mapnik/blob/master/docs/line-dashoffset.md ; `rr/mapnik__mapnik/docs/line-dashoffset.md`
87. https://github.com/mapnik/mapnik/issues/477
88. https://github.com/mapnik/mapnik/issues/1316 ; https://github.com/mapnik/mapnik/issues/1866
89. https://github.com/mapnik/mapnik/commit/8b27aba0c
90. https://github.com/mapnik/mapnik/commit/cba876537
91. `rr/MapServer__MapServer/HISTORY.md` (5.0 RFC 32, 5.4.0-beta1 polygon outline, 7.0 RFC 99) ; https://mapserver.org/development/rfc/ms-rfc-32.html ; https://mapserver.org/development/rfc/ms-rfc-99.html
92. https://github.com/MapServer/MapServer/issues/306
93. https://github.com/MapServer/MapServer/issues/179 ; https://github.com/MapServer/MapServer/commit/cbc029d4 ; https://github.com/MapServer/MapServer/commit/f5e1bec9 ; https://github.com/MapServer/MapServer/commit/8b61e099 ; https://github.com/MapServer/MapServer/commit/6a4adf69 ; https://github.com/MapServer/MapServer/commit/d231a752
94. https://github.com/MapServer/MapServer/issues/1243
95. https://github.com/MapServer/MapServer/commit/962fff7a ; https://github.com/MapServer/MapServer/commit/2ab44080 ; https://github.com/MapServer/MapServer/commit/4ceca4cc
96. https://github.com/MapServer/MapServer/commit/212f9794 ; https://github.com/MapServer/MapServer/commit/8d8bcfd6
97. https://github.com/geoserver/geoserver/commit/f4eeb55439 ; `rr/geoserver__geoserver/src/community/vectortiles/src/main/java/org/geoserver/wms/vector/PipelineBuilder.java`
98. https://github.com/geoserver/geoserver/commit/fc024126cb ; https://github.com/geoserver/geoserver/commit/46d2e41946
99. https://github.com/geoserver/geoserver/commit/4b2a4821ba ; https://github.com/geoserver/geoserver/commit/273d6f947d
100. https://github.com/osmandapp/OsmAnd-core/commit/624e907e ; https://github.com/osmandapp/OsmAnd-core/commit/86225532 ; https://github.com/osmandapp/OsmAnd-core/commit/773dbc16
101. https://github.com/osmandapp/OsmAnd-core/commit/a4fbac07
102. https://github.com/organicmaps/organicmaps/commit/173be8d27d90ece935fe3b5a61ec80b1e345f933 ; https://github.com/organicmaps/organicmaps/commit/6af516698e37f6db45fa52879bee3470c2cdb880
103. https://github.com/organicmaps/organicmaps/commit/5c68eefafa1478c497e60408b7f739ad0af1442d
104. https://github.com/mapsforge/vtm/issues/1082 ; https://github.com/mapsforge/vtm/pull/1084 ; https://github.com/mapsforge/vtm/pull/1100
105. https://github.com/osmdroid/osmdroid/issues/1509 ; https://github.com/osmdroid/osmdroid/commit/2424d879
106. https://github.com/galileo-map/galileo/commit/fb02c8a ; https://github.com/galileo-map/galileo/commit/0012cec
107. `examples/02-world-population-mobile/map.ts` ; `examples/03-quake-timeline/quake.ts` ; `examples/04-osm-node-density/density.ts` ; `examples/07-world-cities-hover/cities.ts` (context flags, blend functions, the stencil land fill and the antialiased point rim)
108. `.agents/skills/line-tessellation/SKILL.md` ; `.agents/skills/text-rendering/SKILL.md` ; `.agents/skills/symbols-and-icons/SKILL.md` ; `.agents/skills/tile-lod-and-overzoom/SKILL.md`