@chrtco/sdk 0.10.47 → 0.10.48

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -25392,7 +25392,23 @@ function getLabelConfig(layerName, opts = {}) {
25392
25392
  "text-variable-anchor": ["top-left", "bottom-left", "top-right", "bottom-right"],
25393
25393
  "text-radial-offset": 0.9,
25394
25394
  "text-justify": "auto",
25395
- "text-allow-overlap": false,
25395
+ // ⚠ A DANGER DEPTH IS NEVER DROPPED (owner, 2026-10-06). Before,
25396
+ // a callout with no free corner was culled and the rock, wreck or
25397
+ // obstruction drew with no depth beside it: 15 of 136 at Boston
25398
+ // z12.3. ALLOW-OVERLAP ONLY, and that is the whole point:
25399
+ // - the variable anchors still fan out first — MapLibre 5.24
25400
+ // tries every corner without overlap and overlaps, at the
25401
+ // first corner, only when none is free (`placement.ts`,
25402
+ // `placementPasses`), so only the callouts that used to vanish
25403
+ // draw over something;
25404
+ // - `text-ignore-placement` stays false, so a callout keeps its
25405
+ // collision space and blocks what it blocked before. Ignoring
25406
+ // placement as well freed that space for buoy and place names,
25407
+ // which then pushed shallow soundings off: 11 shoals uncovered
25408
+ // at z12.3 on the bench. This form: 0.
25409
+ // The census and its numbers: `scripts/chart-bench/
25410
+ // danger-depth-census.ts` and `.chrt/standards/s-52.md` §8a.
25411
+ "text-allow-overlap": true,
25396
25412
  "text-optional": true,
25397
25413
  "text-padding": 2,
25398
25414
  "symbol-sort-key": labelSortKey(100, ["*", 10, valsou])
@@ -28678,65 +28694,364 @@ function iconExpressionForFamily(objectClass2, family) {
28678
28694
  }
28679
28695
  }
28680
28696
 
28681
- // src/atlas/depth-label-size.ts
28682
- var DEPTH_LABEL_SIZES = ["standard", "large"];
28683
- var DEFAULT_DEPTH_LABEL_SIZE = "standard";
28684
- function parseDepthLabelSize(raw) {
28685
- if (!raw) return null;
28686
- const lower = raw.toLowerCase();
28687
- return DEPTH_LABEL_SIZES.find((s) => s === lower) ?? null;
28688
- }
28689
- var DEPTH_LABEL_CLASSES = /* @__PURE__ */ new Set([
28690
- "SOUNDG",
28691
- "DEPCNT",
28692
- "UWTROC",
28693
- "OBSTRN",
28694
- "WRECKS"
28695
- ]);
28696
- var SEMIBOLD = ["Open Sans Semibold"];
28697
- var HAZARD_DEPTH = {
28698
- textSize: ["interpolate", ["linear"], ["zoom"], 12, 12, 16, 15],
28699
- haloWidth: 1.4,
28700
- font: SEMIBOLD
28697
+ // src/atlas/chart-symbol-sizing.ts
28698
+ var CHART_SYMBOL_SIZES = ["landLabels", "waterLabels", "depthNumbers", "waypoints", "chartIcons"];
28699
+ var CHART_SYMBOL_SIZE_WIRE = {
28700
+ landLabels: "chart.landLabelScale",
28701
+ waterLabels: "chart.waterLabelScale",
28702
+ /** Proposed for CHRTKit; aligned with sail's ChartSymbolSizing before release. */
28703
+ depthNumbers: "chart.depthNumberScale",
28704
+ waypoints: "chart.waypointScale",
28705
+ chartIcons: "chart.chartIconScale"
28701
28706
  };
28702
- var LARGE = {
28703
- // Standard: 7 / 8 / 10 / 12 at z8 / 11 / 14 / 16, halo 1.0, Semibold.
28704
- SOUNDG: {
28705
- textSize: ["interpolate", ["linear"], ["zoom"], 8, 10, 11, 11, 14, 14, 16, 17],
28706
- haloWidth: 1.2,
28707
- font: SEMIBOLD
28708
- },
28709
- // Standard: 8 / 10 at z10 / 14, halo 1.2, Regular.
28710
- //
28711
- // ⚠ ~1.2x, NOT 1.4x, AND SEMIBOLD CARRIES THE REST. A contour value rides
28712
- // its line (`symbol-placement: line`) and needs a straight-enough run to fit;
28713
- // it also shares rank 300 with the soundings, which place first. At 1.4x the
28714
- // Boston harbour view kept 15 of Standard's 20 contour labels; at 1.2x, 18.
28715
- DEPCNT: {
28716
- textSize: ["interpolate", ["linear"], ["zoom"], 10, 10, 14, 12],
28717
- haloWidth: 1.2,
28718
- font: SEMIBOLD
28719
- },
28720
- UWTROC: HAZARD_DEPTH,
28721
- OBSTRN: HAZARD_DEPTH,
28722
- WRECKS: HAZARD_DEPTH
28707
+ var CHART_SYMBOL_SIZE_LABELS = {
28708
+ landLabels: "Land labels",
28709
+ waterLabels: "Water labels",
28710
+ depthNumbers: "Depth numbers",
28711
+ waypoints: "Waypoints",
28712
+ chartIcons: "Chart icons"
28723
28713
  };
28724
- var LARGE_SOUNDING_PADDING_PX = 3.5;
28725
- function applyDepthLabelSize(objectClass2, layer, size) {
28726
- if (size !== "large") return layer;
28727
- const large = LARGE[objectClass2];
28728
- if (large === void 0) return layer;
28729
- const layout = {
28730
- ...layer.layout ?? {},
28731
- "text-size": large.textSize,
28732
- "text-font": [...large.font]
28733
- };
28734
- if (objectClass2 === "SOUNDG") layout["text-padding"] = LARGE_SOUNDING_PADDING_PX;
28735
- return {
28736
- ...layer,
28737
- layout,
28738
- paint: { ...layer.paint, "text-halo-width": large.haloWidth }
28739
- };
28714
+ var CHART_SYMBOL_SIZE_REACH = {
28715
+ landLabels: "Towns, landmarks, buildings and land areas.",
28716
+ waterLabels: "Sea, channel, lake and river names, and clearances.",
28717
+ depthNumbers: "Soundings, contour values, and the depths beside rocks, wrecks and obstructions.",
28718
+ waypoints: "Your waypoints and route marks, and how far a tap reaches them.",
28719
+ chartIcons: "Buoys, beacons, lights, wrecks, rocks and their names."
28720
+ };
28721
+ var CHART_SYMBOL_SCALE = {
28722
+ min: 50,
28723
+ max: 200,
28724
+ standard: 100,
28725
+ /** The − / + step. */
28726
+ buttonStep: 10,
28727
+ /** The slider's snap. */
28728
+ sliderStep: 5
28729
+ };
28730
+ var STANDARD_CHART_SYMBOL_SCALES = {
28731
+ landLabels: 100,
28732
+ waterLabels: 100,
28733
+ depthNumbers: 100,
28734
+ waypoints: 100,
28735
+ chartIcons: 100
28736
+ };
28737
+ function clampChartSymbolScale(percent) {
28738
+ if (!Number.isFinite(percent)) return CHART_SYMBOL_SCALE.standard;
28739
+ return Math.min(Math.max(Math.round(percent), CHART_SYMBOL_SCALE.min), CHART_SYMBOL_SCALE.max);
28740
+ }
28741
+ function snapChartSymbolScale(value) {
28742
+ if (!Number.isFinite(value)) return CHART_SYMBOL_SCALE.standard;
28743
+ const step = CHART_SYMBOL_SCALE.sliderStep;
28744
+ return clampChartSymbolScale(Math.round(value / step) * step);
28745
+ }
28746
+ function stepChartSymbolScale(percent, presses) {
28747
+ return clampChartSymbolScale(percent + presses * CHART_SYMBOL_SCALE.buttonStep);
28748
+ }
28749
+ function decodeChartSymbolScale(raw) {
28750
+ if (typeof raw === "number") return Number.isFinite(raw) ? clampChartSymbolScale(raw) : null;
28751
+ if (typeof raw === "string" && /^\s*-?\d+(\.\d+)?\s*$/.test(raw)) return clampChartSymbolScale(Number(raw));
28752
+ return null;
28753
+ }
28754
+ var LAND_TEXT_CLASSES = /* @__PURE__ */ new Set([
28755
+ "BUAARE",
28756
+ "LNDARE",
28757
+ "LNDRGN",
28758
+ "AIRARE",
28759
+ "PRDARE",
28760
+ "LNDMRK",
28761
+ "BUISGL",
28762
+ "SLCONS",
28763
+ "HRBFAC",
28764
+ "BRIDGE"
28765
+ ]);
28766
+ var WATER_TEXT_CLASSES = /* @__PURE__ */ new Set([
28767
+ "SEAARE",
28768
+ "DRGNOTE",
28769
+ "SBDARE",
28770
+ "WEDKLP",
28771
+ "ACHARE",
28772
+ "LAKARE",
28773
+ "RIVERS",
28774
+ "CANALS",
28775
+ "CBLOHD",
28776
+ "PIPOHD"
28777
+ ]);
28778
+ var SYMBOL_ANNOTATION_TEXT_CLASSES = /* @__PURE__ */ new Set([
28779
+ "LIGHTS",
28780
+ "FOGSIG",
28781
+ "BOYCAR",
28782
+ "BOYINB",
28783
+ "BOYISD",
28784
+ "BOYLAT",
28785
+ "BOYSAW",
28786
+ "BOYSPP",
28787
+ "BCNCAR",
28788
+ "BCNISD",
28789
+ "BCNLAT",
28790
+ "BCNSAW",
28791
+ "BCNSPP",
28792
+ "MORFAC",
28793
+ "PILPNT"
28794
+ ]);
28795
+ var BASEMAP_LAND_TEXT = /* @__PURE__ */ new Set([
28796
+ "CHRT_LAND/land_town",
28797
+ "CHRT_LAND/land_summit",
28798
+ "CHRT_LAND/land_poi",
28799
+ "CHRT_BASE/state_label"
28800
+ ]);
28801
+ var BASEMAP_WATER_TEXT = /* @__PURE__ */ new Set([
28802
+ "CHRT_BASE/inland_water_label",
28803
+ "CHRT_BASE/inland_water_label_detail"
28804
+ ]);
28805
+ var BASEMAP_SOURCES = /* @__PURE__ */ new Set(["CHRT_LAND", "CHRT_BASE"]);
28806
+ var HAZARD_LABEL_PRIORITY = 100;
28807
+ var DEPTH_FIGURE_CLASSES = /* @__PURE__ */ new Set(["SOUNDG", "DEPCNT", "UWTROC", "OBSTRN", "WRECKS"]);
28808
+ function contourValueFactor(depthNumbersFactor) {
28809
+ return 1 + (depthNumbersFactor - 1) / 2;
28810
+ }
28811
+ var SERVED_FONT_STACKS = ["Open Sans Regular", "Open Sans Italic", "Open Sans Semibold"];
28812
+ function semiboldFontStack(font) {
28813
+ if (!Array.isArray(font) || !font.every((face) => typeof face === "string")) return font;
28814
+ return font.map((face) => {
28815
+ const semibold = face.replace(/ Regular$/, " Semibold");
28816
+ return SERVED_FONT_STACKS.includes(semibold) ? semibold : face;
28817
+ });
28818
+ }
28819
+ function factsOf(layer) {
28820
+ const l = layer;
28821
+ const source = typeof l.source === "string" ? l.source : void 0;
28822
+ const sourceLayer = typeof l["source-layer"] === "string" ? l["source-layer"] : void 0;
28823
+ const meta = l.metadata ?? {};
28824
+ const isBasemap = source !== void 0 && BASEMAP_SOURCES.has(source);
28825
+ const cls = meta["s52:objectClass"];
28826
+ const objectClass2 = isBasemap ? void 0 : (typeof cls === "string" ? cls : sourceLayer)?.toUpperCase();
28827
+ const p = meta["chrt:labelPriority"];
28828
+ return { source, sourceLayer, objectClass: objectClass2, labelPriority: typeof p === "number" ? p : void 0 };
28829
+ }
28830
+ function textSliderFor(layer) {
28831
+ const f = factsOf(layer);
28832
+ if (f.source !== void 0 && BASEMAP_SOURCES.has(f.source)) {
28833
+ const key = `${f.source}/${f.sourceLayer ?? ""}`;
28834
+ if (BASEMAP_LAND_TEXT.has(key)) return "landLabels";
28835
+ if (BASEMAP_WATER_TEXT.has(key)) return "waterLabels";
28836
+ return null;
28837
+ }
28838
+ const cls = f.objectClass;
28839
+ if (cls === void 0) return null;
28840
+ if (DEPTH_FIGURE_CLASSES.has(cls)) return "depthNumbers";
28841
+ if (LAND_TEXT_CLASSES.has(cls)) return "landLabels";
28842
+ if (WATER_TEXT_CLASSES.has(cls)) return "waterLabels";
28843
+ if (SYMBOL_ANNOTATION_TEXT_CLASSES.has(cls)) return "chartIcons";
28844
+ return null;
28845
+ }
28846
+ function iconSliderFor(layer) {
28847
+ const f = factsOf(layer);
28848
+ if (f.source !== void 0 && BASEMAP_SOURCES.has(f.source)) return null;
28849
+ return f.objectClass === void 0 ? null : "chartIcons";
28850
+ }
28851
+ function mentionsZoom(v) {
28852
+ if (Array.isArray(v)) {
28853
+ if (v.length === 1 && v[0] === "zoom") return true;
28854
+ return v.some(mentionsZoom);
28855
+ }
28856
+ if (v !== null && typeof v === "object") return Object.values(v).some(mentionsZoom);
28857
+ return false;
28858
+ }
28859
+ function scaledOutput(v, factor) {
28860
+ return typeof v === "number" ? round(v * factor) : ["*", v, factor];
28861
+ }
28862
+ function round(n) {
28863
+ return Math.round(n * 1e3) / 1e3;
28864
+ }
28865
+ function scaleSizeExpression(value, factor, fallback) {
28866
+ if (!Number.isFinite(factor) || factor <= 0) return null;
28867
+ if (value === void 0) return round(fallback * factor);
28868
+ if (factor === 1) return value;
28869
+ if (typeof value === "number") return round(value * factor);
28870
+ if (Array.isArray(value)) {
28871
+ const op = value[0];
28872
+ if (typeof op !== "string") return null;
28873
+ if (op === "interpolate" || op === "interpolate-hcl" || op === "interpolate-lab") {
28874
+ if (value.length < 5 || value.length % 2 !== 1) return null;
28875
+ const out = [...value];
28876
+ for (let i = 4; i < out.length; i += 2) out[i] = scaledOutput(out[i], factor);
28877
+ return out;
28878
+ }
28879
+ if (op === "step") {
28880
+ if (value.length < 3 || value.length % 2 !== 1) return null;
28881
+ const out = [...value];
28882
+ for (let i = 2; i < out.length; i += 2) out[i] = scaledOutput(out[i], factor);
28883
+ return out;
28884
+ }
28885
+ return mentionsZoom(value) ? null : ["*", value, factor];
28886
+ }
28887
+ if (value !== null && typeof value === "object") {
28888
+ const stops = value.stops;
28889
+ if (!Array.isArray(stops)) return null;
28890
+ const outStops = [];
28891
+ for (const stop of stops) {
28892
+ if (!Array.isArray(stop) || stop.length !== 2 || typeof stop[1] !== "number") return null;
28893
+ outStops.push([stop[0], round(stop[1] * factor)]);
28894
+ }
28895
+ return { ...value, stops: outStops };
28896
+ }
28897
+ return null;
28898
+ }
28899
+ function haloFactor(factor) {
28900
+ return factor > 1 ? 1 + (factor - 1) / 2 : 1;
28901
+ }
28902
+ var SERVED_SOUNDING_PADDING_PX = 6;
28903
+ var SOUNDING_PADDING_PER_FACTOR = 6.25;
28904
+ function soundingPadding(factor, served = SERVED_SOUNDING_PADDING_PX) {
28905
+ if (factor <= 1) return served;
28906
+ return round(Math.max(0, served - SOUNDING_PADDING_PER_FACTOR * (factor - 1)));
28907
+ }
28908
+ var MAPLIBRE_DEFAULT_TEXT_PADDING_PX = 2;
28909
+ function soundingPaddingValue(served, factor) {
28910
+ if (factor <= 1) return served;
28911
+ if (served === void 0) return soundingPadding(factor, MAPLIBRE_DEFAULT_TEXT_PADDING_PX);
28912
+ if (typeof served === "number") return soundingPadding(factor, served);
28913
+ if (!Array.isArray(served) || typeof served[0] !== "string") return served;
28914
+ const first = served[0] === "interpolate" ? 4 : served[0] === "step" ? 2 : null;
28915
+ if (first === null) return served;
28916
+ const out = [...served];
28917
+ for (let i = first; i < out.length; i += 2) {
28918
+ if (typeof out[i] !== "number") return served;
28919
+ out[i] = soundingPadding(factor, out[i]);
28920
+ }
28921
+ return out;
28922
+ }
28923
+ function factorOf(scales, size) {
28924
+ return clampChartSymbolScale(scales[size]) / 100;
28925
+ }
28926
+ var OUTRANK_LABELS = { kind: "outrankLabels" };
28927
+ var CHART_SOUNDINGS_RULE = { kind: "zoomSplit", harbourFrom: 14 };
28928
+ var KEPT_ABOVE_SOUNDINGS_CLASSES = /* @__PURE__ */ new Set(["SEAARE", "LNDARE", "LNDRGN"]);
28929
+ function keptAboveSoundings(layer, splittingLights = false) {
28930
+ const facts = factsOf(layer);
28931
+ if (splittingLights && facts.objectClass === "LIGHTS") return false;
28932
+ if (facts.labelPriority === HAZARD_LABEL_PRIORITY) return true;
28933
+ if (facts.source !== void 0 && BASEMAP_SOURCES.has(facts.source)) return true;
28934
+ return KEPT_ABOVE_SOUNDINGS_CLASSES.has(facts.objectClass ?? "");
28935
+ }
28936
+ function fromZoom(z, value) {
28937
+ return ["step", ["zoom"], value ?? false, z, true];
28938
+ }
28939
+ function labelSlidersOffStandard(scales) {
28940
+ return ["landLabels", "waterLabels", "depthNumbers", "chartIcons"].some((s) => clampChartSymbolScale(scales[s]) !== 100);
28941
+ }
28942
+ function applyChartSymbolScalesToLayer(layer, scales, yieldText = false) {
28943
+ if (layer.type !== "symbol") return layer;
28944
+ const layout = layer.layout ?? {};
28945
+ const hasText = layout["text-field"] !== void 0;
28946
+ const hasIcon = layout["icon-image"] !== void 0;
28947
+ if (!hasText && !hasIcon) return layer;
28948
+ const facts = factsOf(layer);
28949
+ const nextLayout = { ...layout };
28950
+ let nextPaint = null;
28951
+ let touched = false;
28952
+ if (hasText) {
28953
+ const slider = textSliderFor(layer);
28954
+ const isDepthFigure = slider === "depthNumbers";
28955
+ const sliderFactor = slider === null ? 1 : factorOf(scales, slider);
28956
+ const f = isDepthFigure && facts.objectClass === "DEPCNT" ? contourValueFactor(sliderFactor) : sliderFactor;
28957
+ const size = f === 1 ? null : scaleSizeExpression(layout["text-size"], f, 16);
28958
+ if (size !== null) {
28959
+ touched = true;
28960
+ nextLayout["text-size"] = size;
28961
+ if (f > 1) {
28962
+ if (isDepthFigure) {
28963
+ const semibold = semiboldFontStack(layout["text-font"]);
28964
+ if (JSON.stringify(semibold) !== JSON.stringify(layout["text-font"])) nextLayout["text-font"] = semibold;
28965
+ if (facts.objectClass === "SOUNDG") {
28966
+ const padding = soundingPaddingValue(layout["text-padding"], f);
28967
+ if (padding !== void 0) nextLayout["text-padding"] = padding;
28968
+ } else if (facts.labelPriority === HAZARD_LABEL_PRIORITY) {
28969
+ nextLayout["text-ignore-placement"] = true;
28970
+ nextLayout["text-allow-overlap"] = true;
28971
+ }
28972
+ } else {
28973
+ nextLayout["text-ignore-placement"] = true;
28974
+ if (facts.labelPriority === HAZARD_LABEL_PRIORITY) nextLayout["text-allow-overlap"] = true;
28975
+ }
28976
+ const halo = layer.paint?.["text-halo-width"];
28977
+ if (isDepthFigure && halo !== void 0) {
28978
+ const wider = scaleSizeExpression(halo, haloFactor(sliderFactor), 0);
28979
+ if (wider !== null) nextPaint = { ...layer.paint ?? {}, "text-halo-width": wider };
28980
+ }
28981
+ }
28982
+ }
28983
+ if (yieldText && facts.objectClass !== "SOUNDG") {
28984
+ touched = true;
28985
+ nextLayout["text-ignore-placement"] = true;
28986
+ }
28987
+ }
28988
+ if (hasIcon) {
28989
+ const slider = iconSliderFor(layer);
28990
+ const f = slider === null ? 1 : factorOf(scales, slider);
28991
+ const size = f === 1 ? null : scaleSizeExpression(layout["icon-size"], f, 1);
28992
+ if (size !== null) {
28993
+ touched = true;
28994
+ nextLayout["icon-size"] = size;
28995
+ if (f > 1) nextLayout["icon-ignore-placement"] = true;
28996
+ }
28997
+ }
28998
+ if (!touched) return layer;
28999
+ return { ...layer, layout: nextLayout, ...nextPaint ? { paint: nextPaint } : {} };
29000
+ }
29001
+ var isSoundingText = (l) => l.type === "symbol" && l.layout?.["text-field"] !== void 0 && factsOf(l).objectClass === "SOUNDG";
29002
+ function applyChartSymbolScales(layers, scales, rule = CHART_SOUNDINGS_RULE) {
29003
+ if (scales === void 0 || ["landLabels", "waterLabels", "depthNumbers", "chartIcons"].every((s) => clampChartSymbolScale(scales[s]) === 100)) {
29004
+ return layers;
29005
+ }
29006
+ const outrank = labelSlidersOffStandard(scales);
29007
+ const soundingsAt = layers.findIndex(isSoundingText);
29008
+ const split = rule.kind === "zoomSplit" ? rule : null;
29009
+ const demoted = [];
29010
+ const kept = [];
29011
+ layers.forEach((l, i) => {
29012
+ const above = outrank && soundingsAt !== -1 && i > soundingsAt;
29013
+ const hasText = l.type === "symbol" && l.layout?.["text-field"] !== void 0;
29014
+ if (split !== null && above && hasText && !isSoundingText(l) && !keptAboveSoundings(l, split.splitLights === true)) {
29015
+ const own = applyChartSymbolScalesToLayer(l, scales, false);
29016
+ const layout = own.layout ?? {};
29017
+ demoted.push({
29018
+ ...own,
29019
+ layout: {
29020
+ ...layout,
29021
+ "text-allow-overlap": fromZoom(split.harbourFrom, layout["text-allow-overlap"]),
29022
+ "text-ignore-placement": fromZoom(split.harbourFrom, layout["text-ignore-placement"])
29023
+ }
29024
+ });
29025
+ return;
29026
+ }
29027
+ kept.push(applyChartSymbolScalesToLayer(l, scales, above));
29028
+ });
29029
+ if (demoted.length === 0) return kept;
29030
+ const at = kept.findIndex(isSoundingText);
29031
+ return [...kept.slice(0, at), ...demoted, ...kept.slice(at)];
29032
+ }
29033
+ function demotedBelowSoundings(layers, scales, rule = CHART_SOUNDINGS_RULE) {
29034
+ if (scales === void 0 || rule.kind !== "zoomSplit" || !labelSlidersOffStandard(scales)) return [];
29035
+ const soundingsAt = layers.findIndex(isSoundingText);
29036
+ if (soundingsAt === -1) return [];
29037
+ return layers.filter((l, i) => i > soundingsAt && l.type === "symbol" && l.layout?.["text-field"] !== void 0 && !isSoundingText(l) && !keptAboveSoundings(l, rule.splitLights === true)).map((l) => l.id);
29038
+ }
29039
+ function chartSymbolSizingCensus(layers) {
29040
+ const unclassified = [];
29041
+ const unscalable = [];
29042
+ for (const l of layers) {
29043
+ if (l.type !== "symbol") continue;
29044
+ const layout = l.layout ?? {};
29045
+ if (layout["text-field"] !== void 0) {
29046
+ if (textSliderFor(l) === null) unclassified.push(`${l.id} text`);
29047
+ else if (scaleSizeExpression(layout["text-size"], 2, 16) === null) unscalable.push(`${l.id} text`);
29048
+ }
29049
+ if (layout["icon-image"] !== void 0) {
29050
+ if (iconSliderFor(l) === null) unclassified.push(`${l.id} icon`);
29051
+ else if (scaleSizeExpression(layout["icon-size"], 2, 1) === null) unscalable.push(`${l.id} icon`);
29052
+ }
29053
+ }
29054
+ return { unclassified, unscalable };
28740
29055
  }
28741
29056
 
28742
29057
  // src/atlas/base-bundle.ts
@@ -30079,7 +30394,7 @@ function buildLabelLayer2(objectClass2, ct, sourceId = DEFAULT_REGION, depthUnit
30079
30394
  if (getLabelBehavior(objectClass2) === "orientation-cross-band") {
30080
30395
  layer.filter = LABEL_ANCHOR_FILTER;
30081
30396
  }
30082
- return applyDepthLabelSize(objectClass2, layer, labelOpts.depthLabelSize);
30397
+ return layer;
30083
30398
  }
30084
30399
  function getGeomTypesForClass(objectClass2, defaultType) {
30085
30400
  if (SYMBOL_MAP[objectClass2] && defaultType === "symbol") {
@@ -31234,8 +31549,7 @@ function generateStyle(palette = "DAY", opts = {}) {
31234
31549
  label: buildLabelLayer2(objectClass2, palette, sourceId, opts.depthUnits ?? "meters", {
31235
31550
  safetyContour: opts.safetyContour,
31236
31551
  twoShadeSoundings: opts.twoShadeSoundings,
31237
- soundingFontWeight: opts.soundingFontWeight,
31238
- depthLabelSize: opts.depthLabelSize
31552
+ soundingFontWeight: opts.soundingFontWeight
31239
31553
  })
31240
31554
  });
31241
31555
  }
@@ -31660,7 +31974,9 @@ function generateStyle(palette = "DAY", opts = {}) {
31660
31974
  layers: finalLayers
31661
31975
  };
31662
31976
  const familyStyle = symbolSet === "s101" ? applyS101SymbolSet(style) : symbolSet === "chrt" ? applyChrtSymbolSet(style, palette) : symbolSet === "raster" ? applyRasterSymbolSet(style) : style;
31663
- return applyEinkPortrayal(familyStyle, palette, { safetyContour: opts.safetyContour });
31977
+ const portrayed = applyEinkPortrayal(familyStyle, palette, { safetyContour: opts.safetyContour });
31978
+ const sized = applyChartSymbolScales(portrayed.layers, opts.symbolScales, opts.soundingsRule);
31979
+ return sized === portrayed.layers ? portrayed : { ...portrayed, layers: sized };
31664
31980
  }
31665
31981
  function generateStyleJSON(palette = "DAY", opts = {}) {
31666
31982
  return JSON.stringify(generateStyle(palette, opts), null, 2);
@@ -32566,6 +32882,12 @@ export {
32566
32882
  CHART_BAND_CODES,
32567
32883
  CHART_CASCADE_CODES,
32568
32884
  CHART_SECTIONS,
32885
+ CHART_SOUNDINGS_RULE,
32886
+ CHART_SYMBOL_SCALE,
32887
+ CHART_SYMBOL_SIZES,
32888
+ CHART_SYMBOL_SIZE_LABELS,
32889
+ CHART_SYMBOL_SIZE_REACH,
32890
+ CHART_SYMBOL_SIZE_WIRE,
32569
32891
  CHRTRASTER_REF_CROPS,
32570
32892
  CHRTRASTER_SVGS,
32571
32893
  CHRT_ATON_COLORS,
@@ -32579,7 +32901,6 @@ export {
32579
32901
  ChrtError,
32580
32902
  DEFAULT_CLICK_TOLERANCE,
32581
32903
  DEFAULT_CUSTOM_STYLE_CONFIG,
32582
- DEFAULT_DEPTH_LABEL_SIZE,
32583
32904
  DEFAULT_INSPECT_CLASS_RANK,
32584
32905
  DEFAULT_LABEL_SETTINGS,
32585
32906
  DEFAULT_NAV_AID_SETTINGS,
@@ -32591,14 +32912,14 @@ export {
32591
32912
  DEFAULT_WATER_BODY_SETTINGS,
32592
32913
  DEPARE_FILL_BRANCH_TOKENS,
32593
32914
  DEPARE_FILL_FALLBACK_TOKEN,
32594
- DEPTH_LABEL_CLASSES,
32595
- DEPTH_LABEL_SIZES,
32915
+ DEPTH_FIGURE_CLASSES,
32596
32916
  DRAPEABLE_LAYER_TYPES,
32597
32917
  EINK_COLOR_TABLES,
32598
32918
  EINK_DANGER_PATTERN,
32599
32919
  EINK_DOTS_PATTERN,
32600
32920
  EINK_HATCH_PATTERN,
32601
32921
  EINK_MONO_GREYS,
32922
+ HAZARD_LABEL_PRIORITY,
32602
32923
  INSPECT_CLASS_RANK,
32603
32924
  INSPECT_RANK_DEVIATIONS,
32604
32925
  InteractClient,
@@ -32614,7 +32935,8 @@ export {
32614
32935
  LAND_ATTRIBUTION,
32615
32936
  LAND_BUILD_MAXZOOM,
32616
32937
  LAND_REGION,
32617
- LARGE_SOUNDING_PADDING_PX,
32938
+ LAND_TEXT_CLASSES,
32939
+ MAPLIBRE_DEFAULT_TEXT_PADDING_PX,
32618
32940
  NAUTICAL_SYMBOLS,
32619
32941
  NAV_AID_LAYER_GROUPS,
32620
32942
  NAV_AID_QUERY_LAYERS,
@@ -32623,6 +32945,7 @@ export {
32623
32945
  NON_SOLAS_DISCLAIMER,
32624
32946
  NON_SOLAS_DISCLAIMER_SHORT,
32625
32947
  OPAQUE_SPLIT_OF,
32948
+ OUTRANK_LABELS,
32626
32949
  OfflineError,
32627
32950
  OfflineStyleError,
32628
32951
  PLACENAME_LAND_CLASSES,
@@ -32657,9 +32980,14 @@ export {
32657
32980
  S52_LOOKUP,
32658
32981
  S52_NIGHT,
32659
32982
  S52_PATTERN_SPRITE_PREFIX,
32983
+ SERVED_FONT_STACKS,
32984
+ SERVED_SOUNDING_PADDING_PX,
32660
32985
  SIGPER_TOLERANCE_SECONDS,
32661
32986
  SIGSEQ_MAX_TERMS,
32662
32987
  SOUNDING_LAYERS,
32988
+ SOUNDING_PADDING_PER_FACTOR,
32989
+ STANDARD_CHART_SYMBOL_SCALES,
32990
+ SYMBOL_ANNOTATION_TEXT_CLASSES,
32663
32991
  SYMBOL_FAMILIES,
32664
32992
  SYMBOL_FAMILY_META,
32665
32993
  SYMBOL_GROUPS,
@@ -32667,12 +32995,14 @@ export {
32667
32995
  TileAuth,
32668
32996
  TileTokenError,
32669
32997
  WATER_BODY_LAYER_GROUPS,
32998
+ WATER_TEXT_CLASSES,
32670
32999
  WeatherEndpoint,
32671
33000
  applyBaseBundle,
33001
+ applyChartSymbolScales,
33002
+ applyChartSymbolScalesToLayer,
32672
33003
  applyChrtSymbolSet,
32673
33004
  applyColorTheme,
32674
33005
  applyCustomStyleSettings,
32675
- applyDepthLabelSize,
32676
33006
  applyEinkPortrayal,
32677
33007
  applyRasterSymbolSet,
32678
33008
  applyS101SymbolSet,
@@ -32699,19 +33029,24 @@ export {
32699
33029
  capLuminance,
32700
33030
  cellBandCharacters,
32701
33031
  cellBandMatch,
33032
+ chartSymbolSizingCensus,
32702
33033
  chrtAtonTintExpression,
32703
33034
  chrtHouseColor,
32704
33035
  chrtLightTintExpression,
33036
+ clampChartSymbolScale,
32705
33037
  collectCandidates,
32706
33038
  collectClickCandidates,
32707
33039
  combineWithBandFilter,
33040
+ contourValueFactor,
32708
33041
  contrastRatio,
32709
33042
  daymarkColor,
32710
33043
  decimateFeatures,
32711
33044
  decodeAreaFeatureProps,
32712
33045
  decodeBridgeProps,
32713
33046
  decodeCandidate,
33047
+ decodeChartSymbolScale,
32714
33048
  decodeNavAidProps,
33049
+ demotedBelowSoundings,
32715
33050
  depareColor,
32716
33051
  depareFillExpression,
32717
33052
  depthAreaClassLayerId,
@@ -32721,6 +33056,7 @@ export {
32721
33056
  drapedFirst,
32722
33057
  extractNavAidDesignation,
32723
33058
  featureIdentity,
33059
+ fromZoom,
32724
33060
  generateCustomStyle,
32725
33061
  generateSpriteManifest,
32726
33062
  generateSpriteSheet,
@@ -32748,9 +33084,11 @@ export {
32748
33084
  getThemedS101Svg,
32749
33085
  getThemedS52Svg,
32750
33086
  getTopmarkMeaning,
33087
+ haloFactor,
32751
33088
  hazardColor,
32752
33089
  hazardFillExpression,
32753
33090
  iconExpressionForFamily,
33091
+ iconSliderFor,
32754
33092
  isDepthAreaClassLayerId,
32755
33093
  isDrapeable,
32756
33094
  isEinkColorTable,
@@ -32762,6 +33100,7 @@ export {
32762
33100
  isSoundingLayerVisible,
32763
33101
  isVisibleInMode,
32764
33102
  isWaterBodyLayerVisible,
33103
+ keptAboveSoundings,
32765
33104
  labelSortKey,
32766
33105
  lampRhythmColour,
32767
33106
  lampRhythmOpacity,
@@ -32774,7 +33113,6 @@ export {
32774
33113
  normalizeTheme,
32775
33114
  opaqueSplitBaseOf,
32776
33115
  paginate,
32777
- parseDepthLabelSize,
32778
33116
  parseListCodes,
32779
33117
  parseSigseqTerms,
32780
33118
  parseSymbolFamily,
@@ -32797,12 +33135,19 @@ export {
32797
33135
  safetyContourValues,
32798
33136
  sanitizeCustomStyleConfig,
32799
33137
  scaleLinearLight,
33138
+ scaleSizeExpression,
32800
33139
  scaleSizeValue,
32801
33140
  scaminToMinZoom,
32802
33141
  sectorLimitToArcBearing,
33142
+ semiboldFontStack,
33143
+ snapChartSymbolScale,
33144
+ soundingPadding,
33145
+ soundingPaddingValue,
32803
33146
  splitOpaqueDepthAreas,
33147
+ stepChartSymbolScale,
32804
33148
  styleModeBand,
32805
33149
  terrainStackCount,
33150
+ textSliderFor,
32806
33151
  themeChrtGlyph,
32807
33152
  tileTemplate,
32808
33153
  uncoveredSectorArcs,