1
1
mirror of https://github.com/exyte/Macaw.git synced 2024-09-21 01:47:44 +03:00
Macaw/Source/svg/SVGNodeLayout.swift
Alisa Mylnikova f6faa0e291 Add tests
2018-05-11 14:29:29 +07:00

82 lines
2.6 KiB
Swift

enum SVGLength {
case percent(Double)
case pixels(Double)
init(percent: Double) {
self = .percent(percent)
}
init(pixels: Double) {
self = .pixels(pixels)
}
}
class SVGSize {
let width: SVGLength
let height: SVGLength
public init(width: SVGLength, height: SVGLength) {
self.width = width
self.height = height
}
}
public protocol NodeLayout {
func layout(node: Node, in rect: Rect)
}
class SVGNodeLayout: NodeLayout {
let svgSize: SVGSize?
let viewBox: Rect?
let scalingMode: AspectRatio
let xAligningMode: Align
let yAligningMode: Align
init(svgSize: SVGSize? = .none, viewBox: Rect? = .none, scalingMode: AspectRatio? = .meet, xAligningMode: Align? = .mid, yAligningMode: Align? = .mid) {
self.svgSize = svgSize
self.viewBox = viewBox
self.scalingMode = scalingMode ?? .meet
self.xAligningMode = xAligningMode ?? .mid
self.yAligningMode = yAligningMode ?? .mid
}
func layout(node: Node, in rect: Rect) {
guard let size = svgSize else { return }
let width = svgLengthToPixels(size.width, framePixels: rect.w)
let height = svgLengthToPixels(size.height, framePixels: rect.h)
let svgSizeInPixels = Size(w: width, h: height)
if let viewBox = self.viewBox {
node.clip = viewBox
}
let viewBox = self.viewBox ?? Rect(x: 0, y: 0, w: svgSizeInPixels.w, h: svgSizeInPixels.h)
if scalingMode === AspectRatio.slice {
// setup new clipping to slice extra bits
let newSize = AspectRatio.meet.fit(size: svgSizeInPixels, into: viewBox)
let newX = viewBox.x + xAligningMode.align(outer: viewBox.w, inner: newSize.w)
let newY = viewBox.y + yAligningMode.align(outer: viewBox.h, inner: newSize.h)
node.clip = Rect(x: newX, y: newY, w: newSize.w, h: newSize.h)
}
let contentLayout = SVGContentLayout(scalingMode: scalingMode, xAligningMode: xAligningMode, yAligningMode: yAligningMode)
node.place = contentLayout.layout(rect: viewBox, into: Rect(x: 0, y: 0, w: svgSizeInPixels.w, h: svgSizeInPixels.h))
// move to (0, 0)
node.place = node.place.move(dx: -viewBox.x, dy: -viewBox.y)
}
}
fileprivate func svgLengthToPixels(_ svgLength: SVGLength, framePixels: Double) -> Double {
switch(svgLength) {
case let .percent(percent):
return framePixels * percent / 100.0
case let .pixels(pixels):
return pixels
}
}