@orbat-mapper/tactical-map-sheet 0.4.18 → 0.6.0

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,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 {
@@ -2,7 +2,7 @@ import GeographicLibMgrs from "geographiclib-mgrs";
2
2
  import PolarStereographic from "geographiclib-mgrs/src/polar-stereographic.mjs";
3
3
  import opentype from "opentype.js";
4
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, resolvePointSymbolOffset, resolveTextAppearance, scalePointSymbolLayout } from "@orbat-mapper/tactical-draw";
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"` : "",
@@ -1424,7 +1425,8 @@ 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
+ highlightAppearance: input?.highlightAppearance
1428
1430
  };
1429
1431
  }
1430
1432
  function toScenePoint(position, context) {
@@ -1499,6 +1501,26 @@ function textFromFeature(feature, portrayal, context, constructionMetersPerCssPi
1499
1501
  } : {}
1500
1502
  };
1501
1503
  }
1504
+ /**
1505
+ * One Highlight band stroked along each path a highlighted line or area part
1506
+ * drew: the same geometry as one solid stroke in the resolved
1507
+ * `highlightColor`, never filled, so an area is cased along its outline only
1508
+ * and a transparent stroke is still cased. Glow bands carry their opacity, so
1509
+ * SVG and PDF print them alike.
1510
+ */
1511
+ function highlightBandPaths(band, parts) {
1512
+ return parts.flatMap((part) => part.kind === "path" ? [{
1513
+ kind: "path",
1514
+ points: part.points,
1515
+ ...part.closed ? { closed: true } : {},
1516
+ strokeColor: band.color,
1517
+ strokeWidthMm: band.width * MILLIMETRES_PER_CSS_PIXEL,
1518
+ ...band.opacity < 1 ? { strokeOpacity: band.opacity } : {},
1519
+ strokeDashMm: [],
1520
+ lineCap: "round",
1521
+ lineJoin: "round"
1522
+ }] : []);
1523
+ }
1502
1524
  function elementsFromGeometry(feature, portrayal, context, constructionMetersPerCssPixel) {
1503
1525
  const text = textFromFeature(feature, portrayal, context, constructionMetersPerCssPixel);
1504
1526
  if (text) return [text];
@@ -1675,6 +1697,7 @@ function renderGraphic(layerId, authored, portrayal, context) {
1675
1697
  rendered = renderControlMeasure(graphic, {
1676
1698
  validationMode: "throw",
1677
1699
  graphicsStyle,
1700
+ highlightAppearance: portrayal.highlightAppearance,
1678
1701
  context: {
1679
1702
  groundMetersPerCssPixel: context.groundMetersPerCssPixel,
1680
1703
  labelSizeClampCssPixels: portrayal.labelSizeClampCssPixels,
@@ -1695,7 +1718,7 @@ function renderGraphic(layerId, authored, portrayal, context) {
1695
1718
  graphicId: graphic.id
1696
1719
  }] };
1697
1720
  const constructionMetersPerCssPixel = resolveConstructionMetersPerCssPixel(graphic.controlPoints, context.groundMetersPerCssPixel);
1698
- const elements = rendered.features.flatMap((feature, index) => {
1721
+ const featureElements = rendered.features.map((feature, index) => {
1699
1722
  try {
1700
1723
  const geometry = featureOutOfRange[index] ? clipGeometryToBounds(feature.geometry, frameBounds) : feature.geometry;
1701
1724
  return geometry ? elementsFromGeometry({
@@ -1706,6 +1729,7 @@ function renderGraphic(layerId, authored, portrayal, context) {
1706
1729
  throw new Error(`Cannot render Graphic "${graphic.id}": ${String(error)}`, { cause: error });
1707
1730
  }
1708
1731
  });
1732
+ const elements = [...highlightBandsInPaintOrder(rendered.features, portrayal.strokeWidthCssPixels).flatMap(({ feature, band }) => highlightBandPaths(band, featureElements[rendered.features.indexOf(feature)])), ...featureElements.flat()];
1709
1733
  if (elements.length === 0 && rendered.features.every((feature) => feature.properties.text !== void 0)) return { warnings: [{
1710
1734
  code: "graphic-hidden",
1711
1735
  layerId,
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-CjaUXinf.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-jY-O7aUB.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-CjaUXinf.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-jY-O7aUB.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.4.18",
3
+ "version": "0.6.0",
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.36.0",
34
- "@orbat-mapper/tactical-draw": "^0.20.0"
33
+ "@orbat-mapper/control-measures": "^0.38.0",
34
+ "@orbat-mapper/tactical-draw": "^0.22.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.18"
48
+ "@orbat-mapper/point-symbols": "0.2.20"
49
49
  },
50
50
  "inlinedDependencies": {
51
51
  "@types/geojson": "7946.0.16"