@@ -4,6 +4,7 @@ import Display
44import ComponentFlow
55import ComponentDisplayAdapters
66import UIKitRuntimeUtils
7+ import CoreImage
78
89private final class ContentContainer : UIView {
910 private let maskContentView : UIView
@@ -406,7 +407,7 @@ public class GlassBackgroundView: UIView {
406407 context. clear ( CGRect ( origin: CGPoint ( ) , size: size) )
407408
408409 context. setFillColor ( UIColor . black. cgColor)
409- context. setShadow ( offset: CGSize ( width: 0.0 , height: 1.0 ) , blur: 40.0 , color: UIColor ( white: 0.0 , alpha: 0.09 ) . cgColor)
410+ context. setShadow ( offset: CGSize ( width: 0.0 , height: 1.0 ) , blur: 40.0 , color: UIColor ( white: 0.0 , alpha: 0.065 ) . cgColor)
410411 context. fillEllipse ( in: CGRect ( origin: CGPoint ( x: shadowInset + shadowInnerInset, y: shadowInset + shadowInnerInset) , size: CGSize ( width: size. width - shadowInset * 2.0 - shadowInnerInset * 2.0 , height: size. height - shadowInset * 2.0 - shadowInnerInset * 2.0 ) ) )
411412
412413 context. setFillColor ( UIColor . clear. cgColor)
@@ -567,11 +568,57 @@ public final class VariableBlurView: UIVisualEffectView {
567568 }
568569}
569570
571+ private extension CGContext {
572+ func addBadgePath( in rect: CGRect ) {
573+ saveGState ( )
574+ translateBy ( x: rect. minX, y: rect. minY)
575+ scaleBy ( x: rect. width / 78.0 , y: rect. height / 78.0 )
576+
577+ // M 0 39
578+ move ( to: CGPoint ( x: 0 , y: 39 ) )
579+
580+ // C 0 17.4609 17.4609 0 39 0
581+ addCurve ( to: CGPoint ( x: 39 , y: 0 ) ,
582+ control1: CGPoint ( x: 0 , y: 17.4609 ) ,
583+ control2: CGPoint ( x: 17.4609 , y: 0 ) )
584+
585+ // H 42
586+ addLine ( to: CGPoint ( x: 42 , y: 0 ) )
587+
588+ // C 61.8823 0 78 16.1177 78 36
589+ addCurve ( to: CGPoint ( x: 78 , y: 36 ) ,
590+ control1: CGPoint ( x: 61.8823 , y: 0 ) ,
591+ control2: CGPoint ( x: 78 , y: 16.1177 ) )
592+
593+ // V 39
594+ addLine ( to: CGPoint ( x: 78 , y: 39 ) )
595+
596+ // C 78 60.5391 60.5391 78 39 78
597+ addCurve ( to: CGPoint ( x: 39 , y: 78 ) ,
598+ control1: CGPoint ( x: 78 , y: 60.5391 ) ,
599+ control2: CGPoint ( x: 60.5391 , y: 78 ) )
600+
601+ // H 36
602+ addLine ( to: CGPoint ( x: 36 , y: 78 ) )
603+
604+ // C 16.1177 78 0 61.8823 0 42
605+ addCurve ( to: CGPoint ( x: 0 , y: 42 ) ,
606+ control1: CGPoint ( x: 16.1177 , y: 78 ) ,
607+ control2: CGPoint ( x: 0 , y: 61.8823 ) )
608+
609+ // V 39 / Z
610+ addLine ( to: CGPoint ( x: 0 , y: 39 ) )
611+ closePath ( )
612+
613+ restoreGState ( )
614+ }
615+ }
616+
570617public extension GlassBackgroundView {
571618 static func generateLegacyGlassImage( size: CGSize , inset: CGFloat , isDark: Bool , fillColor: UIColor ) -> UIImage {
572619 var size = size
573620 if size == . zero {
574- size = CGSize ( width: 1 .0, height: 1 .0)
621+ size = CGSize ( width: 2 .0, height: 2 .0)
575622 }
576623 let innerSize = size
577624 size. width += inset * 2.0
@@ -581,45 +628,13 @@ public extension GlassBackgroundView {
581628 let context = ctx. cgContext
582629
583630 context. clear ( CGRect ( origin: CGPoint ( ) , size: size) )
584-
585- func pathApplyingSpread( _ path: CGPath , spread: CGFloat ) -> CGPath {
586- guard spread != 0 else { return path }
587- let result = CGMutablePath ( )
588- result. addPath ( path)
589631
590- // Copy a stroked outline centered on the original path boundary.
591- // Filling it plus the original path approximates an outward "spread".
592- let outline = path. copy (
593- strokingWithWidth: abs ( spread) * 2 ,
594- lineCap: . butt,
595- lineJoin: . miter,
596- miterLimit: 10 ,
597- transform: . identity
598- )
599- result. addPath ( outline)
600-
601- // For negative spread (tighten), use even-odd to carve inside:
602- if spread < 0 {
603- let carve = CGMutablePath ( )
604- carve. addPath ( path)
605- carve. addPath ( outline)
606- // even-odd: outline - original ≈ outer ring; union with original earlier keeps overall stable
607- // For "tightening" effect we rely on clipping in inner shadow branch below.
608- }
609- return result
610- }
611-
612- let maskImage = UIGraphicsImageRenderer ( size: size) . image { ctx in
613- let context = ctx. cgContext
614- context. setFillColor ( UIColor . black. cgColor)
615- context. fillEllipse ( in: CGRect ( origin: CGPoint ( x: inset, y: inset) , size: innerSize) )
616- }
617-
618- let addShadow : ( Bool , CGPoint , CGFloat , CGFloat , UIColor , CGBlendMode ) -> Void = { isOuter, position, blur, spread, shadowColor, blendMode in
632+ let addShadow : ( CGContext , Bool , CGPoint , CGFloat , CGFloat , UIColor , CGBlendMode ) -> Void = { context, isOuter, position, blur, spread, shadowColor, blendMode in
619633 var blur = blur
620- blur += abs ( spread)
621634
622635 if isOuter {
636+ blur += abs ( spread)
637+
623638 context. beginTransparencyLayer ( auxiliaryInfo: nil )
624639 context. saveGState ( )
625640 defer {
@@ -653,20 +668,14 @@ public extension GlassBackgroundView {
653668 let context = ctx. cgContext
654669
655670 context. clear ( CGRect ( origin: CGPoint ( ) , size: size) )
656- let spreadRect = CGRect ( origin: CGPoint ( x: inset, y: inset) , size: innerSize) . insetBy ( dx: - spread - 1.0 , dy: - spread - 1.0 )
657- let spreadPath = UIBezierPath (
658- roundedRect: spreadRect,
659- cornerRadius: min ( spreadRect. width, spreadRect. height) * 0.5
660- ) . cgPath
671+ let spreadRect = CGRect ( origin: CGPoint ( x: inset, y: inset) , size: innerSize) . insetBy ( dx: - spread - 0.33 , dy: - spread - 0.33 )
661672
662673 context. setShadow ( offset: CGSize ( width: position. x, height: position. y) , blur: blur, color: shadowColor. cgColor)
663- context. setFillColor ( UIColor . red . cgColor)
674+ context. setFillColor ( shadowColor . cgColor)
664675 let enclosingRect = spreadRect. insetBy ( dx: - 10000.0 , dy: - 10000.0 )
665676 context. addPath ( UIBezierPath ( rect: enclosingRect) . cgPath)
666- context. addPath ( spreadPath )
677+ context. addBadgePath ( in : spreadRect )
667678 context. fillPath ( using: . evenOdd)
668-
669- maskImage. draw ( at: CGPoint ( ) , blendMode: . destinationIn, alpha: 1.0 )
670679 } )
671680
672681 UIGraphicsPushContext ( context)
@@ -675,92 +684,47 @@ public extension GlassBackgroundView {
675684 }
676685 }
677686
678- addShadow ( true , CGPoint ( ) , 16.0 , 0.0 , UIColor ( white: 0.0 , alpha: 0.08 ) , . normal)
679-
680- context. setFillColor ( fillColor. cgColor)
681- context. fillEllipse ( in: CGRect ( origin: CGPoint ( ) , size: size) . insetBy ( dx: inset, dy: inset) . insetBy ( dx: 0.1 , dy: 0.1 ) )
687+ addShadow ( context, true , CGPoint ( ) , 6.0 , 0.0 , UIColor ( white: 0.0 , alpha: 0.08 ) , . normal)
682688
683- /*
684- case normal = 0
685-
686- case multiply = 1
687-
688- case screen = 2
689-
690- case overlay = 3
691-
692- case darken = 4
693-
694- case lighten = 5
695-
696- case colorDodge = 6
697-
698- case colorBurn = 7
699-
700- case softLight = 8
701-
702- case hardLight = 9
703-
704- case difference = 10
705-
706- case exclusion = 11
707-
708- case hue = 12
709-
710- case saturation = 13
711-
712- case color = 14
713-
714- case luminosity = 15
715-
716- case clear = 16
717-
718- case copy = 17
719-
720- case sourceIn = 18
721-
722- case sourceOut = 19
723-
724- case sourceAtop = 20
725-
726- case destinationOver = 21
727-
728- case destinationIn = 22
729-
730- case destinationOut = 23
731-
732- case destinationAtop = 24
733-
734- case xor = 25
735-
736- case plusDarker = 26
737-
738- case plusLighter = 27
739- */
740-
741- var a : CGFloat = 0.0
742- var b : CGFloat = 0.0
743- fillColor. getHue ( nil , saturation: nil , brightness: & b, alpha: & a)
744-
745- addShadow ( true , CGPoint ( x: 0.0 , y: 0.0 ) , 20.0 , 0.0 , UIColor ( white: 0.0 , alpha: 0.04 ) , . normal)
746- addShadow ( true , CGPoint ( x: 0.0 , y: 0.0 ) , 5.0 , 0.0 , UIColor ( white: 0.0 , alpha: 0.04 ) , . normal)
747-
748- let edgeWidth : CGFloat = 0.5
749- let edgeAlpha : CGFloat = max ( 0.2 , min ( 0.8 , a * a * a) )
750-
751- if b >= 0.2 {
752- for _ in 0 ..< 3 {
753- addShadow ( false , CGPoint ( x: 0.0 , y: 0.0 ) , 1.0 , 0.0 , UIColor ( white: 1.0 , alpha: edgeAlpha) , . overlay)
754- addShadow ( false , CGPoint ( x: edgeWidth, y: edgeWidth) , 1.4 , 0.0 , UIColor ( white: 1.0 , alpha: edgeAlpha * 0.9 ) , . overlay)
755- addShadow ( false , CGPoint ( x: - edgeWidth, y: - edgeWidth) , 1.4 , 0.0 , UIColor ( white: 1.0 , alpha: edgeAlpha * 0.9 ) , . overlay)
756- }
757- } else {
758- for _ in 0 ..< 3 {
759- addShadow ( false , CGPoint ( x: 0.0 , y: 0.0 ) , 1.0 , 0.0 , UIColor ( white: 1.0 , alpha: edgeAlpha) , . normal)
760- addShadow ( false , CGPoint ( x: edgeWidth, y: edgeWidth) , 1.4 , 0.0 , UIColor ( white: 1.0 , alpha: edgeAlpha * 0.9 ) , . normal)
761- addShadow ( false , CGPoint ( x: - edgeWidth, y: - edgeWidth) , 1.4 , 0.0 , UIColor ( white: 1.0 , alpha: edgeAlpha * 0.9 ) , . normal)
689+ let innerImage = UIGraphicsImageRenderer ( size: size) . image { ctx in
690+ let context = ctx. cgContext
691+
692+ context. setFillColor ( fillColor. cgColor)
693+ context. fill ( CGRect ( origin: CGPoint ( ) , size: size) . insetBy ( dx: inset, dy: inset) . insetBy ( dx: 0.1 , dy: 0.1 ) )
694+
695+ var a : CGFloat = 0.0
696+ var b : CGFloat = 0.0
697+ var s : CGFloat = 0.0
698+ fillColor. getHue ( nil , saturation: & s, brightness: & b, alpha: & a)
699+
700+ addShadow ( context, true , CGPoint ( x: 0.0 , y: 0.0 ) , 20.0 , 0.0 , UIColor ( white: 0.0 , alpha: 0.04 ) , . normal)
701+ addShadow ( context, true , CGPoint ( x: 0.0 , y: 0.0 ) , 5.0 , 0.0 , UIColor ( white: 0.0 , alpha: 0.04 ) , . normal)
702+
703+ if s <= 0.3 && !isDark {
704+ addShadow ( context, false , CGPoint ( x: 0.0 , y: 0.0 ) , 8.0 , 0.0 , UIColor ( white: 0.0 , alpha: 0.4 ) , . overlay)
705+
706+ let edgeAlpha : CGFloat = max ( 0.8 , min ( 1.0 , a) )
707+
708+ for _ in 0 ..< 2 {
709+ addShadow ( context, false , CGPoint ( x: - 0.64 , y: - 0.64 ) , 0.8 , 0.0 , UIColor ( white: 1.0 , alpha: edgeAlpha) , . normal)
710+ addShadow ( context, false , CGPoint ( x: 0.64 , y: 0.64 ) , 0.8 , 0.0 , UIColor ( white: 1.0 , alpha: edgeAlpha) , . normal)
711+ }
712+ } else if b >= 0.2 {
713+ let edgeAlpha : CGFloat = max ( 0.2 , min ( isDark ? 0.7 : 0.8 , a * a * a) )
714+
715+ addShadow ( context, false , CGPoint ( x: - 0.64 , y: - 0.64 ) , 0.5 , 0.0 , UIColor ( white: 1.0 , alpha: edgeAlpha) , . plusLighter)
716+ addShadow ( context, false , CGPoint ( x: 0.64 , y: 0.64 ) , 0.5 , 0.0 , UIColor ( white: 1.0 , alpha: edgeAlpha) , . plusLighter)
717+ } else {
718+ let edgeAlpha : CGFloat = max ( 0.4 , min ( 1.0 , a * a * a) )
719+
720+ addShadow ( context, false , CGPoint ( x: - 0.64 , y: - 0.64 ) , 1.2 , 0.0 , UIColor ( white: 1.0 , alpha: edgeAlpha) , . normal)
721+ addShadow ( context, false , CGPoint ( x: 0.64 , y: 0.64 ) , 1.2 , 0.0 , UIColor ( white: 1.0 , alpha: edgeAlpha) , . normal)
762722 }
763723 }
724+
725+ context. addEllipse ( in: CGRect ( origin: CGPoint ( x: inset, y: inset) , size: innerSize) )
726+ context. clip ( )
727+ innerImage. draw ( in: CGRect ( origin: CGPoint ( ) , size: size) )
764728 } . stretchableImage ( withLeftCapWidth: Int ( size. width * 0.5 ) , topCapHeight: Int ( size. height * 0.5 ) )
765729 }
766730
0 commit comments