Skip to content

Commit 7f794c1

Browse files
Mark Pospeselmpospese
authored andcommitted
[Issue-60] Add HelveticaNeue font family
1 parent 0751c92 commit 7f794c1

File tree

4 files changed

+160
-1
lines changed

4 files changed

+160
-1
lines changed

Sources/YMatterType/Typography/FontFamily/FontFamily.swift

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,12 @@ extension FontFamily {
108108
let useBoldFont = isBoldTextEnabled(compatibleWith: traitCollection)
109109
let actualWeight = useBoldFont ? accessibilityBoldWeight(for: weight) : weight
110110
let weightName = weightName(for: actualWeight)
111-
return "\(familyName)-\(weightName)\(fontNameSuffix)"
111+
let suffix = fontNameSuffix
112+
if weightName.isEmpty && suffix.isEmpty {
113+
// don't use "-" if nothing will follow it
114+
return familyName
115+
}
116+
return "\(familyName)-\(weightName)\(suffix)"
112117
}
113118

114119
/// Returns default name for each weight
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
//
2+
// HelveticaNeueFontFamily.swift
3+
// YMatterType
4+
//
5+
// Created by Mark Pospesel on 3/2/23.
6+
// Copyright © 2023 Y Media Labs. All rights reserved.
7+
//
8+
9+
import UIKit
10+
11+
public extension Typography {
12+
/// HelveticaNeue font family
13+
static let helveticaNeue = HelveticaNeueFontFamily(style: .regular)
14+
/// HelveticaNeue Italic font family
15+
static let helveticaNeueItalic = HelveticaNeueFontFamily(style: .italic)
16+
}
17+
18+
/// Information about the Helvetica Neue family of fonts
19+
public struct HelveticaNeueFontFamily: FontFamily {
20+
/// Font family root name
21+
public let familyName: String = "HelveticaNeue"
22+
23+
/// Font style, e.g. regular or italic
24+
public let style: Typography.FontStyle
25+
26+
/// Initialize a `HelveticaNeueFontFamily` object
27+
/// - Parameter style: font style (default = `.regular`)
28+
public init(style: Typography.FontStyle = .regular) {
29+
self.style = style
30+
}
31+
32+
/// HelveticaNeue supports 6 font weights (nothing heavier than bold)
33+
public var supportedWeights: [Typography.FontWeight] {
34+
[.ultralight, .thin, .light, .regular, .medium, .bold]
35+
}
36+
37+
public func weightName(for weight: Typography.FontWeight) -> String {
38+
// Default font name suffix by weight
39+
switch weight {
40+
case .ultralight:
41+
return "UltraLight"
42+
case .thin:
43+
return "Thin"
44+
case .light:
45+
return "Light"
46+
case .regular:
47+
return "" // HelveticaNeue skips the weight name for regular
48+
case .medium:
49+
return "Medium"
50+
case .bold:
51+
return "Bold"
52+
case .semibold, .heavy, .black:
53+
return "" // HelveticaNeue does not support these weights
54+
}
55+
}
56+
57+
/// Optional suffix to use for the font name.
58+
///
59+
/// Used by `FontFamily.fontName(for:compatibleWith:)`
60+
/// e.g. "Italic" is a typical suffix for italic fonts.
61+
/// default = ""
62+
public var fontNameSuffix: String {
63+
(style == .italic) ? DefaultFontFamily.italicSuffix : ""
64+
}
65+
}

Tests/YMatterTypeTests/Typography/FontFamily/FontFamilyTests.swift

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,30 @@ final class FontFamilyTests: XCTestCase {
112112
// given traitCollection is nil, it should return the system setting
113113
XCTAssertEqual(sut.isBoldTextEnabled(compatibleWith: nil), UIAccessibility.isBoldTextEnabled)
114114
}
115+
116+
func test_fontNameWithoutWeightOrSuffix_isFamilyName() {
117+
let sut = WeightlessFontFamily()
118+
var name: String
119+
120+
// If there's a weight name then we will append it
121+
sut.weightName = "Regular"
122+
name = sut.fontName(for: .regular, compatibleWith: nil)
123+
XCTAssertNotEqual(name, sut.familyName)
124+
XCTAssertTrue(name.hasSuffix("-" + sut.weightName))
125+
126+
// If there's a suffix then we will append it
127+
sut.weightName = ""
128+
sut.fontNameSuffix = "Italic"
129+
name = sut.fontName(for: .regular, compatibleWith: nil)
130+
XCTAssertNotEqual(name, sut.familyName)
131+
XCTAssertTrue(name.hasSuffix("-" + sut.fontNameSuffix))
132+
133+
// If there's neither then we just return the family name
134+
sut.fontNameSuffix = ""
135+
name = sut.fontName(for: .regular, compatibleWith: nil)
136+
XCTAssertEqual(name, sut.familyName)
137+
XCTAssertNil(name.firstIndex(of: "-"))
138+
}
115139
}
116140

117141
// We use large tuples in makeSUT()
@@ -146,3 +170,11 @@ final class MockFontFamily: FontFamily {
146170

147171
var supportedWeights: [Typography.FontWeight] = Typography.FontWeight.allCases
148172
}
173+
174+
final class WeightlessFontFamily: FontFamily {
175+
let familyName: String = "Weightless"
176+
var weightName: String = ""
177+
var fontNameSuffix: String = ""
178+
179+
func weightName(for weight: Typography.FontWeight) -> String { weightName }
180+
}
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
//
2+
// HelveticaNeueFontFamilyTests.swift
3+
// YMatterTypeTests
4+
//
5+
// Created by Mark Pospesel on 3/2/23.
6+
// Copyright © 2023 Y Media Labs. All rights reserved.
7+
//
8+
9+
import XCTest
10+
@testable import YMatterType
11+
12+
final class HelveticaNeueFontFamilyTests: XCTestCase {
13+
func testFont() {
14+
let (families, traitCollections) = makeSUT()
15+
for family in families {
16+
for weight in family.supportedWeights {
17+
for traitCollection in traitCollections {
18+
let pointSize = CGFloat(Int.random(in: 10...32))
19+
let font = family.font(for: weight, pointSize: pointSize, compatibleWith: traitCollection)
20+
XCTAssertEqual(font.familyName, "Helvetica Neue")
21+
XCTAssertEqual(font.pointSize, pointSize)
22+
}
23+
}
24+
}
25+
}
26+
27+
func testRegular() {
28+
let (families, _) = makeSUT()
29+
for family in families {
30+
XCTAssertTrue(family.weightName(for: .regular).isEmpty)
31+
}
32+
}
33+
34+
func testUnsupportedWeights() {
35+
let (families, _) = makeSUT()
36+
for family in families {
37+
let unsupported = Typography.FontWeight.allCases.filter { !family.supportedWeights.contains($0) }
38+
for weight in unsupported {
39+
XCTAssertTrue(family.weightName(for: weight).isEmpty)
40+
}
41+
}
42+
}
43+
}
44+
45+
private extension HelveticaNeueFontFamilyTests {
46+
func makeSUT() -> ([FontFamily], [UITraitCollection?]) {
47+
super.setUp()
48+
let families: [FontFamily] = [Typography.helveticaNeue, Typography.helveticaNeueItalic]
49+
let traitCollections: [UITraitCollection?] = [
50+
nil,
51+
UITraitCollection(legibilityWeight: .unspecified),
52+
UITraitCollection(legibilityWeight: .regular),
53+
UITraitCollection(legibilityWeight: .bold)
54+
]
55+
return (families, traitCollections)
56+
}
57+
}

0 commit comments

Comments
 (0)