Skip to content

Commit c862633

Browse files
committed
Radial Gradient Support
1 parent 658b2e1 commit c862633

10 files changed

+976
-709
lines changed

Samples/avocado.svg

Lines changed: 36 additions & 0 deletions
Loading

Samples/gradient-linear.swift

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
extension UIImage {
2+
static func svgGradientRadial(size: CGSize = CGSize(width: 480.0, height: 352.0)) -> UIImage {
3+
let f = UIGraphicsImageRendererFormat.preferred()
4+
f.opaque = false
5+
let scale = CGSize(width: size.width / 480.0, height: size.height / 352.0)
6+
return UIGraphicsImageRenderer(size: size, format: f).image {
7+
drawSVG(in: $0.cgContext, scale: scale)
8+
}
9+
}
10+
11+
private static func drawSVG(in ctx: CGContext, scale: CGSize) {
12+
let baseCTM = ctx.ctm
13+
ctx.scaleBy(x: scale.width, y: scale.height)
14+
let patternDraw: CGPatternDrawPatternCallback = { _, ctx in
15+
let rgb = CGColorSpaceCreateDeviceRGB()
16+
let color1 = CGColor(colorSpace: rgb, components: [0.2509804, 0.2509804, 0.2509804, 1.0])!
17+
ctx.setFillColor(color1)
18+
ctx.fill(CGRect(x: 0.0, y: 0.0, width: 32.0, height: 32.0))
19+
let color2 = CGColor(colorSpace: rgb, components: [0.16078432, 0.16078432, 0.16078432, 1.0])!
20+
ctx.setFillColor(color2)
21+
ctx.fill(CGRect(x: 32.0, y: 0.0, width: 32.0, height: 32.0))
22+
ctx.fill(CGRect(x: 0.0, y: 32.0, width: 32.0, height: 32.0))
23+
ctx.setFillColor(color1)
24+
ctx.fill(CGRect(x: 32.0, y: 32.0, width: 32.0, height: 32.0))
25+
}
26+
var patternCallback = CGPatternCallbacks(version: 0, drawPattern: patternDraw, releaseInfo: nil)
27+
let pattern = CGPattern(
28+
info: nil,
29+
bounds: CGRect(x: 0.0, y: 0.0, width: 64.0, height: 64.0),
30+
matrix: ctx.ctm.concatenating(baseCTM.inverted()),
31+
xStep: 64.0,
32+
yStep: 64.0,
33+
tiling: .constantSpacing,
34+
isColored: true,
35+
callbacks: &patternCallback
36+
)!
37+
ctx.setFillColorSpace(CGColorSpace(patternBaseSpace: nil)!)
38+
var patternAlpha : CGFloat = 1.0
39+
ctx.setFillPattern(pattern, colorComponents: &patternAlpha)
40+
ctx.fill(CGRect(x: 0.0, y: 0.0, width: 480.0, height: 352.0))
41+
ctx.saveGState()
42+
let path = CGPath(
43+
ellipseIn: CGRect(x: 160.0, y: 96.0, width: 160.0, height: 160.0),
44+
transform: nil
45+
)
46+
ctx.addPath(path)
47+
ctx.clip()
48+
ctx.setAlpha(1.0)
49+
let rgb = CGColorSpaceCreateDeviceRGB()
50+
let color1 = CGColor(colorSpace: rgb, components: [1.0, 0.84313726, 0.0, 1.0])!
51+
let color2 = CGColor(colorSpace: rgb, components: [1.0, 0.0, 0.0, 1.0])!
52+
var locations: [CGFloat] = [0.1, 0.95]
53+
let gradient = CGGradient(
54+
colorsSpace: rgb,
55+
colors: [color1, color2] as CFArray,
56+
locations: &locations
57+
)!
58+
ctx.drawLinearGradient(gradient,
59+
start: CGPoint(x: 160.0, y: 256.0),
60+
end: CGPoint(x: 320.0, y: 256.0),
61+
options: [.drawsAfterEndLocation, .drawsBeforeStartLocation])
62+
ctx.restoreGState()
63+
}
64+
}

Samples/gradient-radial.svg

Lines changed: 29 additions & 0 deletions
Loading

Samples/mouth-open.svg

Lines changed: 73 additions & 0 deletions
Loading

SwiftDraw/DOM.RadialGradient.swift

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -62,9 +62,7 @@ extension DOM {
6262

6363
extension DOM.RadialGradient: Equatable {
6464
static func ==(lhs: DOM.RadialGradient, rhs: DOM.RadialGradient) -> Bool {
65-
return
66-
lhs.id == rhs.id &&
67-
lhs.stops == rhs.stops
65+
return lhs.id == rhs.id && lhs.stops == rhs.stops
6866
}
6967
}
7068

SwiftDraw/LayerTree.Builder.Shape.swift

Lines changed: 48 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -32,50 +32,53 @@
3232
import Foundation
3333

3434
extension LayerTree.Builder {
35-
36-
static func makeShape(from element: DOM.GraphicsElement) -> LayerTree.Shape? {
37-
if let line = element as? DOM.Line {
38-
let from = Point(line.x1, line.y1)
39-
let to = Point(line.x2, line.y2)
40-
return .line(between: [from, to])
41-
} else if let circle = element as? DOM.Circle {
42-
return .ellipse(within: makeRect(from: circle))
43-
} else if let ellipse = element as? DOM.Ellipse {
44-
return .ellipse(within: makeRect(from: ellipse))
45-
} else if let rect = element as? DOM.Rect {
46-
let radii = LayerTree.Size(rect.rx ?? 0, rect.ry ?? 0)
47-
return .rect(within: makeRect(from: rect), radii: radii)
48-
} else if let polyline = element as? DOM.Polyline {
49-
return .line(between: polyline.points.map{ Point($0.x, $0.y) })
50-
} else if let polygon = element as? DOM.Polygon {
51-
return .polygon(between: polygon.points.map{ Point($0.x, $0.y) })
52-
} else if let domPath = element as? DOM.Path,
53-
let path = try? createPath(from: domPath) {
54-
return .path(path)
35+
36+
static func makeShape(from element: DOM.GraphicsElement) -> LayerTree.Shape? {
37+
if let line = element as? DOM.Line {
38+
let from = Point(line.x1, line.y1)
39+
let to = Point(line.x2, line.y2)
40+
return .line(between: [from, to])
41+
} else if let circle = element as? DOM.Circle {
42+
return .ellipse(within: makeRect(from: circle))
43+
} else if let ellipse = element as? DOM.Ellipse {
44+
return .ellipse(within: makeRect(from: ellipse))
45+
} else if let rect = element as? DOM.Rect {
46+
let radii = makeRadii(rx: rect.rx, ry: rect.ry)
47+
return .rect(within: makeRect(from: rect), radii: radii)
48+
} else if let polyline = element as? DOM.Polyline {
49+
return .line(between: polyline.points.map{ Point($0.x, $0.y) })
50+
} else if let polygon = element as? DOM.Polygon {
51+
return .polygon(between: polygon.points.map{ Point($0.x, $0.y) })
52+
} else if let domPath = element as? DOM.Path,
53+
let path = try? createPath(from: domPath) {
54+
return .path(path)
55+
}
56+
57+
return nil;
58+
}
59+
60+
static func makeRect(from rect: DOM.Rect) -> LayerTree.Rect {
61+
return LayerTree.Rect(x: rect.x ?? 0,
62+
y: rect.y ?? 0,
63+
width: rect.width,
64+
height: rect.height)
65+
}
66+
67+
static func makeRect(from ellipse: DOM.Ellipse) -> LayerTree.Rect {
68+
return LayerTree.Rect(x: ellipse.cx - ellipse.rx,
69+
y: ellipse.cy - ellipse.ry,
70+
width: ellipse.rx * 2,
71+
height: ellipse.ry * 2)
72+
}
73+
74+
static func makeRect(from circle: DOM.Circle) -> LayerTree.Rect {
75+
return LayerTree.Rect(x: circle.cx - circle.r,
76+
y: circle.cy - circle.r,
77+
width: circle.r * 2,
78+
height: circle.r * 2)
79+
}
80+
81+
static func makeRadii(rx: DOM.Float?, ry: DOM.Float?) -> LayerTree.Size {
82+
LayerTree.Size(rx ?? ry ?? 0, ry ?? rx ?? 0)
5583
}
56-
57-
return nil;
58-
}
59-
60-
static func makeRect(from rect: DOM.Rect) -> LayerTree.Rect {
61-
return LayerTree.Rect(x: rect.x ?? 0,
62-
y: rect.y ?? 0,
63-
width: rect.width,
64-
height: rect.height)
65-
}
66-
67-
static func makeRect(from ellipse: DOM.Ellipse) -> LayerTree.Rect {
68-
return LayerTree.Rect(x: ellipse.cx - ellipse.rx,
69-
y: ellipse.cy - ellipse.ry,
70-
width: ellipse.rx * 2,
71-
height: ellipse.ry * 2)
72-
}
73-
74-
static func makeRect(from circle: DOM.Circle) -> LayerTree.Rect {
75-
return LayerTree.Rect(x: circle.cx - circle.r,
76-
y: circle.cy - circle.r,
77-
width: circle.r * 2,
78-
height: circle.r * 2)
79-
}
80-
8184
}

0 commit comments

Comments
 (0)