diff --git a/Sources/LibMakeColors/Model/Scanner+ColorParser.swift b/Sources/LibMakeColors/Model/Scanner+ColorParser.swift index 84957cd..c0d54d2 100644 --- a/Sources/LibMakeColors/Model/Scanner+ColorParser.swift +++ b/Sources/LibMakeColors/Model/Scanner+ColorParser.swift @@ -31,9 +31,58 @@ extension Scanner { return Color(white: arguments) } + if string("hsva") { + return readHSV(alpha: true) + } + + if string("hsv") { + return readHSV(alpha: false) + } + return nil } + private func readHSV(alpha readAlpha: Bool) -> Color? { + guard + string("("), + let hue = degrees(), + string(","), + let saturation = component(), + string(","), + let value = component() + else { return nil } + + let alpha: UInt8 + + if readAlpha { + guard + string(","), + let value = component() + else { return nil } + alpha = value + } else { + alpha = 0xFF + } + + guard string(")") else { return nil } + + return Color(hue: hue, saturation: saturation, value: value, alpha: alpha) + } + + func degrees() -> Int? { + guard let int = scanInt() else { return nil } + + if string("%") { + guard 0...100 ~= int else { return nil } + return (360 * int) / 100 + } else if string("°") || string("deg") { + return int + } else { + guard 0...0xFF ~= int else { return nil } + return (360 * int) / 0xFF + } + } + func colorReference() -> String? { guard string("@") else { return nil } return name() diff --git a/Tests/MakeColorsTests/ColorParserTest.swift b/Tests/MakeColorsTests/ColorParserTest.swift index edcb587..075c72d 100644 --- a/Tests/MakeColorsTests/ColorParserTest.swift +++ b/Tests/MakeColorsTests/ColorParserTest.swift @@ -86,8 +86,38 @@ final class ColorParserTest: XCTestCase { XCTAssertTrue(scanner.isAtEnd) } + func testScanningDegreesAsByte() throws { + let scanner = Scanner(string: "128") + XCTAssertEqual(scanner.degrees(), 180) + } + + func testScanningDegreesAsPercentage() throws { + let scanner = Scanner(string: "50%") + XCTAssertEqual(scanner.degrees(), 180) + } + + func testScanningDegrees() throws { + let scanner = Scanner(string: "120°") + XCTAssertEqual(scanner.degrees(), 120) + } + + func testScanningDegreesWithDegSuffix() throws { + let scanner = Scanner(string: "120 deg") + XCTAssertEqual(scanner.degrees(), 120) + } + + func testScanningHSVColor() throws { + XCTAssertEqual(scanColor("hsv(60°, 255, 100%)"), Color(red: 0xFF, green: 0xFF, blue: 0)) + } + + func testScanningHSVAColor() throws { + XCTAssertEqual(scanColor("hsva(60°, 50%, 255, 99)"), Color(red: 0xFF, green: 0xFF, blue: 128, alpha: 99)) + } + private func scanColor(_ input: String) -> Color? { let scanner = Scanner(string: input) - return scanner.color() + let result = scanner.color() + XCTAssertTrue(result == nil || scanner.isAtEnd) + return result } }