@@ -64,15 +64,72 @@ public extension CGContext {
6464 for r in 0 ..< rows {
6565 for c in 0 ..< cols {
6666 let tile = CGRect (
67- x: rect. minX + CGFloat( r ) * svg. size. width,
68- y: rect. minY + CGFloat( c ) * svg. size. height,
67+ x: rect. minX + CGFloat( c ) * svg. size. width,
68+ y: rect. minY + CGFloat( r ) * svg. size. height,
6969 width: svg. size. width,
7070 height: svg. size. height
7171 )
7272 draw ( svg, in: tile)
7373 }
7474 }
7575 }
76+
77+ func draw(
78+ _ svg: SVG ,
79+ in rect: CGRect ,
80+ capInsets: ( top: CGFloat , left: CGFloat , bottom: CGFloat , right: CGFloat ) ,
81+ byTiling: Bool
82+ ) {
83+ guard capInsets != ( 0 , 0 , 0 , 0 ) else {
84+ draw ( svg, in: rect, byTiling: byTiling)
85+ return
86+ }
87+
88+ let source = Slice9 ( source: CGRect ( origin: . zero, size: svg. size) , capInsets: capInsets)
89+ let dest = Slice9 ( source: rect, capInsets: capInsets)
90+
91+ draw ( svg, from: source. topLeft, in: dest. topLeft, byTiling: false )
92+ draw ( svg, from: source. topMid, in: dest. topMid, byTiling: byTiling)
93+ draw ( svg, from: source. topRight, in: dest. topRight, byTiling: false )
94+ draw ( svg, from: source. midLeft, in: dest. midLeft, byTiling: byTiling)
95+ draw ( svg, from: source. center, in: dest. center, byTiling: byTiling)
96+ draw ( svg, from: source. midRight, in: dest. midRight, byTiling: byTiling)
97+ draw ( svg, from: source. bottomLeft, in: dest. bottomLeft, byTiling: false )
98+ draw ( svg, from: source. bottomMid, in: dest. bottomMid, byTiling: byTiling)
99+ draw ( svg, from: source. bottomRight, in: dest. bottomRight, byTiling: false )
100+ }
101+
102+ private func draw( _ svg: SVG , from source: CGRect , in rect: CGRect , byTiling: Bool = false ) {
103+ saveGState ( )
104+ clip ( to: [ rect] )
105+
106+ if byTiling {
107+ let cols = Int ( ceil ( rect. width / source. width) )
108+ let rows = Int ( ceil ( rect. height / source. height) )
109+ for r in 0 ..< rows {
110+ for c in 0 ..< cols {
111+ let tile = CGRect (
112+ x: rect. minX + source. width * CGFloat( c) ,
113+ y: rect. minY + source. height * CGFloat( r) ,
114+ width: source. width,
115+ height: source. height
116+ )
117+ draw ( svg, from: source, in: tile)
118+ }
119+ }
120+ } else {
121+ // stretch
122+ translateBy ( x: rect. origin. x, y: rect. origin. y)
123+ scaleBy (
124+ x: rect. width / source. width,
125+ y: rect. height / source. height
126+ )
127+ translateBy ( x: - source. minX, y: - source. minY)
128+ CGRenderer ( context: self ) . perform ( svg. commands)
129+ }
130+
131+ restoreGState ( )
132+ }
76133}
77134
78135public extension SVG {
@@ -142,4 +199,45 @@ private extension LayerTree.Size {
142199 }
143200}
144201
202+ struct Slice9 {
203+ var source : CGRect
204+ var capInsets : ( top: CGFloat , left: CGFloat , bottom: CGFloat , right: CGFloat )
205+
206+ var topLeft : CGRect {
207+ CGRect ( x: source. minX, y: source. minY, width: capInsets. left, height: capInsets. top)
208+ }
209+
210+ var bottomLeft : CGRect {
211+ CGRect ( x: source. minX, y: source. height - capInsets. bottom, width: capInsets. left, height: capInsets. bottom)
212+ }
213+
214+ var topRight : CGRect {
215+ CGRect ( x: source. maxX - capInsets. right, y: source. minY, width: capInsets. right, height: capInsets. top)
216+ }
217+
218+ var bottomRight : CGRect {
219+ CGRect ( x: source. maxX - capInsets. right, y: source. maxY - capInsets. bottom, width: capInsets. right, height: capInsets. bottom)
220+ }
221+
222+ var midLeft : CGRect {
223+ CGRect ( x: source. minX, y: capInsets. top, width: capInsets. left, height: source. maxY - capInsets. top - capInsets. bottom)
224+ }
225+
226+ var midRight : CGRect {
227+ CGRect ( x: source. maxX - capInsets. right, y: capInsets. top, width: capInsets. right, height: source. maxY - capInsets. top - capInsets. bottom)
228+ }
229+
230+ var topMid : CGRect {
231+ CGRect ( x: capInsets. left, y: source. minY, width: source. maxX - capInsets. left - capInsets. right, height: capInsets. top)
232+ }
233+
234+ var bottomMid : CGRect {
235+ CGRect ( x: capInsets. left, y: source. maxY - capInsets. bottom, width: source. maxX - capInsets. left - capInsets. right, height: capInsets. bottom)
236+ }
237+
238+ var center : CGRect {
239+ CGRect ( x: capInsets. left, y: capInsets. top, width: source. maxX - capInsets. left - capInsets. right, height: source. maxY - capInsets. top - capInsets. bottom)
240+ }
241+ }
242+
145243#endif
0 commit comments