@craft-native/ios 0.0.141 → 0.0.142

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@craft-native/ios",
3
- "version": "0.0.141",
3
+ "version": "0.0.142",
4
4
  "homepage": "https://github.com/craft-native/craft/tree/main/packages/ios#readme",
5
5
  "repository": {
6
6
  "type": "git",
@@ -1789,14 +1789,36 @@ private final class CraftNativeSvgView: UIView {
1789
1789
  }
1790
1790
  }
1791
1791
 
1792
+ /// viewBox units to the view's points, set by each draw.
1793
+ private var viewTransform = CGAffineTransform.identity
1794
+
1795
+ /// viewBox to view: centred at one scale (SVG's default, `xMidYMid meet`),
1796
+ /// or each axis stretched to fill (`preserveAspectRatio="none"`), as a
1797
+ /// chart a page sizes to its width and a fixed height asks for.
1798
+ static func transform(box: CGRect, bounds: CGSize, preserveAspectRatio: String?) -> CGAffineTransform? {
1799
+ var sx = bounds.width / box.width
1800
+ var sy = bounds.height / box.height
1801
+ var dx: CGFloat = 0
1802
+ var dy: CGFloat = 0
1803
+ if preserveAspectRatio?.trimmingCharacters(in: .whitespaces) != "none" {
1804
+ let scale = min(sx, sy)
1805
+ sx = scale
1806
+ sy = scale
1807
+ dx = (bounds.width - box.width * scale) / 2
1808
+ dy = (bounds.height - box.height * scale) / 2
1809
+ }
1810
+ guard sx.isFinite, sy.isFinite, sx > 0, sy > 0 else { return nil }
1811
+ return CGAffineTransform(translationX: dx, y: dy).scaledBy(x: sx, y: sy).translatedBy(x: -box.minX, y: -box.minY)
1812
+ }
1813
+
1792
1814
  override func draw(_ rect: CGRect) {
1793
1815
  guard let context = UIGraphicsGetCurrentContext() else { return }
1816
+ viewTransform = .identity
1794
1817
  if let box = viewBox {
1795
- let scale = min(bounds.width / box.width, bounds.height / box.height)
1796
- guard scale.isFinite, scale > 0 else { return }
1797
- context.translateBy(x: (bounds.width - box.width * scale) / 2, y: (bounds.height - box.height * scale) / 2)
1798
- context.scaleBy(x: scale, y: scale)
1799
- context.translateBy(x: -box.minX, y: -box.minY)
1818
+ let props = drawing["props"] as? [String: Any] ?? [:]
1819
+ guard let transform = CraftNativeSvgView.transform(box: box, bounds: bounds.size, preserveAspectRatio: props["preserveAspectRatio"] as? String) else { return }
1820
+ viewTransform = transform
1821
+ context.concatenate(transform)
1800
1822
  }
1801
1823
  draw(children: drawing["children"] as? [Any] ?? [], paint: Paint().merged(drawing), in: context)
1802
1824
  }
@@ -1820,12 +1842,25 @@ private final class CraftNativeSvgView: UIView {
1820
1842
  path.fill()
1821
1843
  }
1822
1844
  if let stroke = own.resolve(own.stroke), own.strokeWidth > 0 {
1845
+ // `vector-effect="non-scaling-stroke"`: the stroke is in the
1846
+ // view's points, so a stretched chart's line keeps its width
1847
+ // and a round cap stays a round dot.
1848
+ let nonScaling = (shape["props"] as? [String: Any])?["vectorEffect"] as? String == "non-scaling-stroke"
1849
+ let line: UIBezierPath
1850
+ if nonScaling, let copy = path.copy() as? UIBezierPath {
1851
+ copy.apply(viewTransform)
1852
+ context.concatenate(viewTransform.inverted())
1853
+ line = copy
1854
+ }
1855
+ else {
1856
+ line = path
1857
+ }
1823
1858
  stroke.setStroke()
1824
- path.lineWidth = own.strokeWidth
1825
- path.lineCapStyle = own.linecap == "round" ? .round : own.linecap == "square" ? .square : .butt
1826
- path.lineJoinStyle = own.linejoin == "round" ? .round : own.linejoin == "bevel" ? .bevel : .miter
1827
- if let dashes = own.dashes, !dashes.isEmpty { path.setLineDash(dashes, count: dashes.count, phase: 0) }
1828
- path.stroke()
1859
+ line.lineWidth = own.strokeWidth
1860
+ line.lineCapStyle = own.linecap == "round" ? .round : own.linecap == "square" ? .square : .butt
1861
+ line.lineJoinStyle = own.linejoin == "round" ? .round : own.linejoin == "bevel" ? .bevel : .miter
1862
+ if let dashes = own.dashes, !dashes.isEmpty { line.setLineDash(dashes, count: dashes.count, phase: 0) }
1863
+ line.stroke()
1829
1864
  }
1830
1865
  context.restoreGState()
1831
1866
  }