@orbat-mapper/tactical-map-sheet 0.5.0 → 0.6.1

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.
@@ -1,8 +1,8 @@
1
1
  import GeographicLibMgrs from "geographiclib-mgrs";
2
2
  import PolarStereographic from "geographiclib-mgrs/src/polar-stereographic.mjs";
3
3
  import opentype from "opentype.js";
4
- import { DEFAULT_LABEL_HEIGHT_CSS_PIXELS, DEFAULT_LABEL_SIZE_CLAMP_CSS_PIXELS, DEFAULT_LINE_CAP, DEFAULT_LINE_JOIN, DEFAULT_PORTRAYAL, DEFAULT_STROKE_DASH_CSS_PIXELS, DEFAULT_STROKE_WIDTH_CSS_PIXELS, getFillPatternDefinition, renderControlMeasure, resolveConstructionMetersPerCssPixel, resolveSymbolColor } from "@orbat-mapper/control-measures";
5
- import { effectivePointSymbolPixelSize, resolveHighlightCasing, resolvePointSymbolOffset, resolveTextAppearance, scalePointSymbolLayout } from "@orbat-mapper/tactical-draw";
4
+ import { DEFAULT_LABEL_HEIGHT_CSS_PIXELS, DEFAULT_LABEL_SIZE_BAND, DEFAULT_LINE_CAP, DEFAULT_LINE_JOIN, DEFAULT_PORTRAYAL, DEFAULT_STROKE_DASH_CSS_PIXELS, DEFAULT_STROKE_WIDTH_CSS_PIXELS, getFillPatternDefinition, renderControlMeasure, resolveConstructionMetersPerCssPixel, resolveSymbolColor } from "@orbat-mapper/control-measures";
5
+ import { effectivePointSymbolPixelSize, highlightBandsInPaintOrder, resolvePointSymbolOffset, resolveTextAppearance, scalePointSymbolLayout } from "@orbat-mapper/tactical-draw";
6
6
  import { SaxesParser } from "saxes";
7
7
  //#region src/projection/geographic-lib.ts
8
8
  const backend = GeographicLibMgrs.UTMUPS;
@@ -684,6 +684,7 @@ function serializeElement(element) {
684
684
  ].join(" ")}"`,
685
685
  ` stroke="${escapeXml(element.strokeColor)}"`,
686
686
  ` stroke-width="${formatDecimal(element.strokeWidthMm)}"`,
687
+ element.strokeOpacity !== void 0 ? ` stroke-opacity="${formatDecimal(element.strokeOpacity)}"` : "",
687
688
  ` stroke-linecap="${element.lineCap}" stroke-linejoin="${element.lineJoin}"`,
688
689
  element.strokeDashMm.length > 0 ? ` stroke-dasharray="${element.strokeDashMm.map(formatDecimal).join(" ")}"` : "",
689
690
  element.fillColor || element.fillPatternId ? ` paint-order="fill stroke"` : "",
@@ -1412,7 +1413,7 @@ function resolvePortrayal(input) {
1412
1413
  strokeDashCssPixels.forEach((value) => requireFiniteNonNegative(value, "Stroke dash"));
1413
1414
  const labelHeightCssPixels = input?.labelHeightCssPixels ?? DEFAULT_LABEL_HEIGHT_CSS_PIXELS;
1414
1415
  requirePositiveFinite(labelHeightCssPixels, "Label height");
1415
- const labelSizeClampCssPixels = input?.labelSizeClampCssPixels ?? DEFAULT_LABEL_SIZE_CLAMP_CSS_PIXELS;
1416
+ const labelSizeClampCssPixels = input?.labelSizeClampCssPixels ?? DEFAULT_LABEL_SIZE_BAND;
1416
1417
  requireFiniteNonNegative(labelSizeClampCssPixels.min, "Label clamp minimum");
1417
1418
  requireFiniteNonNegative(labelSizeClampCssPixels.max, "Label clamp maximum");
1418
1419
  const symbolColor = input?.symbolColor ?? DEFAULT_PORTRAYAL.symbolColor;
@@ -1424,7 +1425,12 @@ function resolvePortrayal(input) {
1424
1425
  lineCap: input?.lineCap ?? DEFAULT_LINE_CAP,
1425
1426
  lineJoin: input?.lineJoin ?? DEFAULT_LINE_JOIN,
1426
1427
  labelHeightCssPixels,
1427
- labelSizeClampCssPixels
1428
+ labelSizeClampCssPixels,
1429
+ labelSizeBand: {
1430
+ ...labelSizeClampCssPixels,
1431
+ belowMin: "pin"
1432
+ },
1433
+ highlightAppearance: input?.highlightAppearance
1428
1434
  };
1429
1435
  }
1430
1436
  function toScenePoint(position, context) {
@@ -1500,20 +1506,20 @@ function textFromFeature(feature, portrayal, context, constructionMetersPerCssPi
1500
1506
  };
1501
1507
  }
1502
1508
  /**
1503
- * The Highlight casing beneath each path a highlighted line or area part drew:
1504
- * the same geometry as one solid stroke in the resolved `highlightColor`,
1505
- * `highlightCasingWidth` wide and never filled, so an area is cased along its
1506
- * outline only and a transparent stroke is still cased.
1509
+ * One Highlight band stroked along each path a highlighted line or area part
1510
+ * drew: the same geometry as one solid stroke in the resolved
1511
+ * `highlightColor`, never filled, so an area is cased along its outline only
1512
+ * and a transparent stroke is still cased. Glow bands carry their opacity, so
1513
+ * SVG and PDF print them alike.
1507
1514
  */
1508
- function highlightCasings(feature, parts, portrayal) {
1509
- const casing = resolveHighlightCasing(feature, portrayal.strokeWidthCssPixels);
1510
- if (!casing) return [];
1515
+ function highlightBandPaths(band, parts) {
1511
1516
  return parts.flatMap((part) => part.kind === "path" ? [{
1512
1517
  kind: "path",
1513
1518
  points: part.points,
1514
1519
  ...part.closed ? { closed: true } : {},
1515
- strokeColor: casing.color,
1516
- strokeWidthMm: casing.width * MILLIMETRES_PER_CSS_PIXEL,
1520
+ strokeColor: band.color,
1521
+ strokeWidthMm: band.width * MILLIMETRES_PER_CSS_PIXEL,
1522
+ ...band.opacity < 1 ? { strokeOpacity: band.opacity } : {},
1517
1523
  strokeDashMm: [],
1518
1524
  lineCap: "round",
1519
1525
  lineJoin: "round"
@@ -1695,9 +1701,10 @@ function renderGraphic(layerId, authored, portrayal, context) {
1695
1701
  rendered = renderControlMeasure(graphic, {
1696
1702
  validationMode: "throw",
1697
1703
  graphicsStyle,
1704
+ highlightAppearance: portrayal.highlightAppearance,
1698
1705
  context: {
1699
1706
  groundMetersPerCssPixel: context.groundMetersPerCssPixel,
1700
- labelSizeClampCssPixels: portrayal.labelSizeClampCssPixels,
1707
+ labelSizeBand: portrayal.labelSizeBand,
1701
1708
  measureText: measureOpenSans
1702
1709
  }
1703
1710
  });
@@ -1726,7 +1733,7 @@ function renderGraphic(layerId, authored, portrayal, context) {
1726
1733
  throw new Error(`Cannot render Graphic "${graphic.id}": ${String(error)}`, { cause: error });
1727
1734
  }
1728
1735
  });
1729
- const elements = [...featureElements.flatMap((parts, index) => highlightCasings(rendered.features[index], parts, portrayal)), ...featureElements.flat()];
1736
+ const elements = [...highlightBandsInPaintOrder(rendered.features, portrayal.strokeWidthCssPixels).flatMap(({ feature, band }) => highlightBandPaths(band, featureElements[rendered.features.indexOf(feature)])), ...featureElements.flat()];
1730
1737
  if (elements.length === 0 && rendered.features.every((feature) => feature.properties.text !== void 0)) return { warnings: [{
1731
1738
  code: "graphic-hidden",
1732
1739
  layerId,
@@ -1,4 +1,4 @@
1
- import { ControlMeasure, PatternId, TextAmplifiers } from "@orbat-mapper/control-measures";
1
+ import { ControlMeasure, HighlightAppearance, PatternId, TextAmplifiers } from "@orbat-mapper/control-measures";
2
2
  import { PointSymbolOffset, PointSymbolRender } from "@orbat-mapper/tactical-draw";
3
3
 
4
4
  //#region ../../node_modules/.pnpm/@types+geojson@7946.0.16/node_modules/@types/geojson/index.d.ts
@@ -337,6 +337,11 @@ interface MapSheetPortrayalDefaults {
337
337
  readonly min: number;
338
338
  readonly max: number;
339
339
  };
340
+ /**
341
+ * How graphics with `style.highlight` print (ADR-0062). Pass the same value
342
+ * as the on-screen `TacticalDraw` so the sheet matches the map.
343
+ */
344
+ readonly highlightAppearance?: HighlightAppearance;
340
345
  }
341
346
  type MapSheetAuthoredGraphic = ControlMeasure | MapSheetPointSymbol | MapSheetCustomSymbol;
342
347
  interface AuthoredMapSheetGraphic {
package/dist/index.d.mts CHANGED
@@ -1,4 +1,4 @@
1
- import { $ as MapSheetPatternIdentity, A as PaperSizeName, B as TacticalMapSheetLayer, C as ResolvedMapSheetRasterTileMetadata, D as ResolvedRegistrationMark, E as MapSheetRegistrationRequest, F as GraphicOutsideFrameWarning, G as MapSheetSymbolSize, H as MapSheetCustomSymbol, I as GraphicRenderWarning, J as MapSheetMetadata, K as VectorSymbolAnchor, L as MapSheetPortrayalDefaults, M as AuthoredMapSheetGraphic, N as GraphicClippedWarning, O as PAPER_SIZES, P as GraphicHiddenWarning, Q as MgrsSnapInterval, R as PointSymbolFallbackWarning, S as ResolvedMapSheetRasterLayerMetadata, T as AuthoredRegistrationMark, U as MapSheetPointSymbol, V as ControlledVectorSymbol, W as MapSheetPointSymbolCapability, X as ResolvedMgrsGridMetadata, Y as MgrsGridOptions, Z as MgrsPrecision, _ as MapSheetRasterLayer, a as ResolvedMapSheetMetadata, b as RasterDpiAnisotropyWarning, c as TacticalMapSheetResources, d as UpsProjection, et as SceneRectangle, f as UtmProjection, g as MapSheetRasterBasemap, h as MapSheetRasterAttribution, i as MapSheetPageInput, it as UtmCrs, j as resolvePaperSize, k as PaperOrientation, l as TacticalMapSheetResult, m as LowRasterDpiWarning, n as CrossZoneFootprintWarning, nt as GridCrs, o as ScaleDeviationWarning, ot as Position, p as createTacticalMapSheet, q as MapSheetMarginaliaOptions, r as MapSheetFontIdentity, rt as UpsCrs, s as TacticalMapSheetRequest, t as CrossProjectionFootprintWarning, tt as GeographicPosition, u as TacticalMapSheetWarning, v as MapSheetRasterTile, w as PrinterCalibrationRequest, x as ResolvedMapSheetRasterBasemapMetadata, y as MapSheetRasterWarning, z as PointSymbolOffsetWarning } from "./create-tactical-map-sheet-ByCfDv0u.mjs";
1
+ import { $ as MapSheetPatternIdentity, A as PaperSizeName, B as TacticalMapSheetLayer, C as ResolvedMapSheetRasterTileMetadata, D as ResolvedRegistrationMark, E as MapSheetRegistrationRequest, F as GraphicOutsideFrameWarning, G as MapSheetSymbolSize, H as MapSheetCustomSymbol, I as GraphicRenderWarning, J as MapSheetMetadata, K as VectorSymbolAnchor, L as MapSheetPortrayalDefaults, M as AuthoredMapSheetGraphic, N as GraphicClippedWarning, O as PAPER_SIZES, P as GraphicHiddenWarning, Q as MgrsSnapInterval, R as PointSymbolFallbackWarning, S as ResolvedMapSheetRasterLayerMetadata, T as AuthoredRegistrationMark, U as MapSheetPointSymbol, V as ControlledVectorSymbol, W as MapSheetPointSymbolCapability, X as ResolvedMgrsGridMetadata, Y as MgrsGridOptions, Z as MgrsPrecision, _ as MapSheetRasterLayer, a as ResolvedMapSheetMetadata, b as RasterDpiAnisotropyWarning, c as TacticalMapSheetResources, d as UpsProjection, et as SceneRectangle, f as UtmProjection, g as MapSheetRasterBasemap, h as MapSheetRasterAttribution, i as MapSheetPageInput, it as UtmCrs, j as resolvePaperSize, k as PaperOrientation, l as TacticalMapSheetResult, m as LowRasterDpiWarning, n as CrossZoneFootprintWarning, nt as GridCrs, o as ScaleDeviationWarning, ot as Position, p as createTacticalMapSheet, q as MapSheetMarginaliaOptions, r as MapSheetFontIdentity, rt as UpsCrs, s as TacticalMapSheetRequest, t as CrossProjectionFootprintWarning, tt as GeographicPosition, u as TacticalMapSheetWarning, v as MapSheetRasterTile, w as PrinterCalibrationRequest, x as ResolvedMapSheetRasterBasemapMetadata, y as MapSheetRasterWarning, z as PointSymbolOffsetWarning } from "./create-tactical-map-sheet-CEQT11I-.mjs";
2
2
 
3
3
  //#region src/mgrs.d.ts
4
4
  interface ProjectedGridCoordinate {
package/dist/index.mjs CHANGED
@@ -1,4 +1,4 @@
1
- import { a as geographicToMgrs, c as normalizeMgrsReference, d as snapGeographicToMgrs, f as snapProjectedToMgrs, i as resolveMapSheetRasterPlan, l as parseMgrsReference, o as mgrsToGeographic, r as mapSheetRasterPointToGeographic, s as mgrsToProjected, t as createTacticalMapSheet, u as projectedToMgrs } from "./create-tactical-map-sheet-BJLUJ9b5.mjs";
1
+ import { a as geographicToMgrs, c as normalizeMgrsReference, d as snapGeographicToMgrs, f as snapProjectedToMgrs, i as resolveMapSheetRasterPlan, l as parseMgrsReference, o as mgrsToGeographic, r as mapSheetRasterPointToGeographic, s as mgrsToProjected, t as createTacticalMapSheet, u as projectedToMgrs } from "./create-tactical-map-sheet-BaTAm1Id.mjs";
2
2
  //#region src/paper.ts
3
3
  const A0 = Object.freeze({
4
4
  widthMm: 841,
package/dist/pdf.d.mts CHANGED
@@ -1,4 +1,4 @@
1
- import { a as ResolvedMapSheetMetadata, at as Polygon, c as TacticalMapSheetResources, l as TacticalMapSheetResult, s as TacticalMapSheetRequest, u as TacticalMapSheetWarning } from "./create-tactical-map-sheet-ByCfDv0u.mjs";
1
+ import { a as ResolvedMapSheetMetadata, at as Polygon, c as TacticalMapSheetResources, l as TacticalMapSheetResult, s as TacticalMapSheetRequest, u as TacticalMapSheetWarning } from "./create-tactical-map-sheet-CEQT11I-.mjs";
2
2
 
3
3
  //#region src/pdf.d.ts
4
4
  interface TacticalMapSheetPdfResult {
package/dist/pdf.mjs CHANGED
@@ -1,4 +1,4 @@
1
- import { _ as openSansMiddleBaselineOffset, g as openSansCentralBaselineOffset, h as POINTS_PER_MILLIMETRE, m as MILLIMETRES_PER_CSS_PIXEL, n as createTacticalMapSheetDocument, p as formatDecimal } from "./create-tactical-map-sheet-BJLUJ9b5.mjs";
1
+ import { _ as openSansMiddleBaselineOffset, g as openSansCentralBaselineOffset, h as POINTS_PER_MILLIMETRE, m as MILLIMETRES_PER_CSS_PIXEL, n as createTacticalMapSheetDocument, p as formatDecimal } from "./create-tactical-map-sheet-BaTAm1Id.mjs";
2
2
  import { jsPDF } from "jspdf";
3
3
  //#region src/pdf-transparency.ts
4
4
  const FORM_DICTIONARY_MARKER = new TextEncoder().encode("/Subtype /Form\n/BBox");
@@ -571,6 +571,7 @@ function renderElement(pdf, element, formIds) {
571
571
  fill: element.fillColor,
572
572
  stroke: element.strokeColor,
573
573
  strokeWidth: element.strokeWidthMm,
574
+ strokeOpacity: element.strokeOpacity ?? DEFAULT_VECTOR_PAINT.strokeOpacity,
574
575
  lineCap: element.lineCap,
575
576
  lineJoin: element.lineJoin,
576
577
  dash: element.strokeDashMm
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@orbat-mapper/tactical-map-sheet",
3
- "version": "0.5.0",
3
+ "version": "0.6.1",
4
4
  "description": "Scale-accurate projected vector tactical map-sheet renderer.",
5
5
  "license": "MIT",
6
6
  "author": "Orbat Mapper",
@@ -30,8 +30,8 @@
30
30
  "jspdf": "4.2.1",
31
31
  "opentype.js": "2.0.0",
32
32
  "saxes": "6.0.0",
33
- "@orbat-mapper/control-measures": "^0.37.0",
34
- "@orbat-mapper/tactical-draw": "^0.21.0"
33
+ "@orbat-mapper/control-measures": "^0.39.0",
34
+ "@orbat-mapper/tactical-draw": "^0.23.0"
35
35
  },
36
36
  "devDependencies": {
37
37
  "@napi-rs/canvas": "1.0.7",
@@ -45,7 +45,7 @@
45
45
  "typescript": "~5.9.3",
46
46
  "vite": "^8.0.16",
47
47
  "vitest": "^4.1.8",
48
- "@orbat-mapper/point-symbols": "0.2.19"
48
+ "@orbat-mapper/point-symbols": "0.2.21"
49
49
  },
50
50
  "inlinedDependencies": {
51
51
  "@types/geojson": "7946.0.16"