diff --git a/TheNoiseClock/Core/Utilities/FontUtils.swift b/TheNoiseClock/Core/Utilities/FontUtils.swift index b52fe9f..d51bede 100644 --- a/TheNoiseClock/Core/Utilities/FontUtils.swift +++ b/TheNoiseClock/Core/Utilities/FontUtils.swift @@ -11,25 +11,25 @@ import UIKit /// Font sizing and typography utilities struct FontUtils { - + static func weightedFontName( name: String, weight: Font.Weight, design: Font.Design ) -> String { let weightSuffix = weight.uiFontWeightSuffix - + switch design { case .rounded: if name.lowercased() == "system" { return "System" } return name - + (weightSuffix.isEmpty ? "-Rounded" : weightSuffix + "Rounded") + + (weightSuffix.isEmpty ? "-Rounded" : weightSuffix + "Rounded") case .monospaced: if name.lowercased() == "system" { return "Courier" } return name == "Courier" - ? name + weightSuffix - : name - + (weightSuffix.isEmpty ? "-Mono" : weightSuffix + "Mono") + ? name + weightSuffix + : name + + (weightSuffix.isEmpty ? "-Mono" : weightSuffix + "Mono") case .serif: if name.lowercased() == "system" { return "TimesNewRomanPS" } return name + weightSuffix @@ -37,7 +37,7 @@ struct FontUtils { return name + weightSuffix } } - + static func calculateOptimalFontSize( digit: String, fontName: FontFamily, @@ -47,7 +47,7 @@ struct FontUtils { ) -> CGFloat { var low: CGFloat = 1.0 var high: CGFloat = 2000.0 - + while high - low > 0.01 { let mid = (low + high) / 2 let testFont = createUIFont( @@ -57,17 +57,17 @@ struct FontUtils { size: mid ) let textSize = tightBoundingBox(for: digit, withFont: testFont) - + if textSize.width <= size.width && textSize.height <= size.height { low = mid } else { high = mid } } - + return low } - + private static func tightBoundingBox( for text: String, withFont font: UIFont @@ -86,7 +86,7 @@ struct FontUtils { ) return CGSize(width: ceil(rect.width), height: ceil(rect.height)) } - + static func createUIFont( name: FontFamily, weight: Font.Weight, @@ -100,7 +100,7 @@ struct FontUtils { width: design.uiFontWidth ) } - + if let font = UIFont( name: weightedFontName( name: name.rawValue, @@ -111,30 +111,28 @@ struct FontUtils { ) { return font } - + return UIFont.systemFont( ofSize: size, weight: weight.uiFontWeight, width: design.uiFontWidth ) } - + static func createFont( name: FontFamily, weight: Font.Weight, design: Font.Design, size: CGFloat ) -> Font { - let fontName = weightedFontName( - name: name.rawValue, - weight: weight, - design: design - ) - print(fontName) if name == .system { return .system(size: size, weight: weight, design: design) } else { - return .custom(fontName, size: size) + return .custom(weightedFontName( + name: name.rawValue, + weight: weight, + design: design + ), size: size) } } } diff --git a/TheNoiseClock/Views/Clock/Components/DigitView.swift b/TheNoiseClock/Views/Clock/Components/DigitView.swift index 9e9e2c9..4104319 100644 --- a/TheNoiseClock/Views/Clock/Components/DigitView.swift +++ b/TheNoiseClock/Views/Clock/Components/DigitView.swift @@ -20,6 +20,9 @@ struct DigitView: View { @State var glowIntensity: Double @Binding var fontSize: CGFloat + @State private var lastCalculatedSize: CGSize = .zero + @State private var isCalculating: Bool = false + init(digit: String, fontName: FontFamily, weight: Font.Weight = .regular, @@ -85,37 +88,43 @@ struct DigitView: View { .padding(.horizontal, 0) .baselineOffset(0) .onAppear { - let optimalSize = FontUtils.calculateOptimalFontSize(digit: digit, - fontName: fontName, - weight: weight, - design: design, - for: geometry.size) - if optimalSize != fontSize { - fontSize = optimalSize - } + calculateOptimalFontSize(for: geometry.size) } .onChange(of: geometry.size) { _, newSize in - let optimalSize = FontUtils.calculateOptimalFontSize(digit: digit, - fontName: fontName, - weight: weight, - design: design, - for: newSize) - if optimalSize != fontSize { - fontSize = optimalSize - } + calculateOptimalFontSize(for: newSize) } .onChange(of: sizeCategory) { _, _ in - let optimalSize = FontUtils.calculateOptimalFontSize(digit: digit, - fontName: fontName, - weight: weight, - design: design, - for: geometry.size) - if optimalSize != fontSize { - fontSize = optimalSize - } + calculateOptimalFontSize(for: geometry.size) } } } + + private func calculateOptimalFontSize(for size: CGSize) { + // Prevent multiple calculations for the same size + guard size != lastCalculatedSize && !isCalculating else { return } + + // Prevent multiple updates per frame + guard !isCalculating else { return } + isCalculating = true + + let optimalSize = FontUtils.calculateOptimalFontSize(digit: digit, + fontName: fontName, + weight: weight, + design: design, + for: size) + + // Only update if the size is significantly different to prevent micro-adjustments + if abs(optimalSize - fontSize) > 0.1 { + fontSize = optimalSize + } + + lastCalculatedSize = size + + // Reset calculation flag after a brief delay to allow for frame completion + DispatchQueue.main.asyncAfter(deadline: .now() + 0.016) { // ~60fps + isCalculating = false + } + } } // MARK: - Preview diff --git a/TheNoiseClock/Views/Clock/Components/TimeDisplayView.swift b/TheNoiseClock/Views/Clock/Components/TimeDisplayView.swift index c6bc28e..e3a5a8c 100644 --- a/TheNoiseClock/Views/Clock/Components/TimeDisplayView.swift +++ b/TheNoiseClock/Views/Clock/Components/TimeDisplayView.swift @@ -107,7 +107,7 @@ struct TimeDisplayView: View { .minimumScaleFactor(0.1) .clipped() // Prevent overflow beyond bounds } - .border(.yellow, width: 1) + //.border(.yellow, width: 1) .frame(maxWidth: .infinity, maxHeight: .infinity) .onOrientationChange() // Force updates on orientation changes } @@ -135,5 +135,6 @@ struct TimeDisplayView: View { fontWeight: style.fontWeight, fontDesign: style.fontDesign, forceHorizontalMode: style.forceHorizontalMode - ) .background(Color.black) + ) + .background(Color.black) } diff --git a/TheNoiseClock/Views/Clock/Components/TimeSegment.swift b/TheNoiseClock/Views/Clock/Components/TimeSegment.swift index 6c03938..e05a5fa 100644 --- a/TheNoiseClock/Views/Clock/Components/TimeSegment.swift +++ b/TheNoiseClock/Views/Clock/Components/TimeSegment.swift @@ -32,10 +32,10 @@ struct TimeSegment: View { glowIntensity: glowIntensity, fontSize: $fontSize ) - .border(.red, width: 1) + //.border(.red, width: 1) } } - .border(Color.green, width: 1) + //.border(Color.green, width: 1) .frame(maxHeight: .infinity) }