diff --git a/platform/darwin/src/NSExpression+MGLAdditions.mm b/platform/darwin/src/NSExpression+MGLAdditions.mm index 48c783798..78a21152a 100644 --- a/platform/darwin/src/NSExpression+MGLAdditions.mm +++ b/platform/darwin/src/NSExpression+MGLAdditions.mm @@ -308,7 +308,7 @@ const MGLExpressionInterpolationMode MGLExpressionInterpolationModeCubicBezier = return { (int64_t)number.longLongValue }; } } else if ([value isKindOfClass:[MGLColor class]]) { - auto hexString = [(MGLColor *)value mgl_color].stringify(); + auto hexString = [(MGLColor *)value mgl_colorForPremultipliedValue].stringify(); return { hexString }; } else if (value && value != [NSNull null]) { [NSException raise:NSInvalidArgumentException @@ -481,7 +481,7 @@ const MGLExpressionInterpolationMode MGLExpressionInterpolationModeCubicBezier = @implementation MGLColor (MGLExpressionAdditions) - (id)mgl_jsonExpressionObject { - auto color = [self mgl_color]; + auto color = [self mgl_colorForPremultipliedValue]; if (color.a == 1) { return @[@"rgb", @(color.r * 255), @(color.g * 255), @(color.b * 255)]; } @@ -1019,7 +1019,7 @@ NSArray *MGLSubexpressionsWithJSONObjects(NSArray *objects) { return @[@"literal", collection]; } if ([constantValue isKindOfClass:[MGLColor class]]) { - auto color = [constantValue mgl_color]; + auto color = [constantValue mgl_colorForPremultipliedValue]; if (color.a == 1) { return @[@"rgb", @(color.r * 255), @(color.g * 255), @(color.b * 255)]; } diff --git a/platform/darwin/test/MGLExpressionTests.mm b/platform/darwin/test/MGLExpressionTests.mm index 4ccd7adb6..cc3c37b83 100644 --- a/platform/darwin/test/MGLExpressionTests.mm +++ b/platform/darwin/test/MGLExpressionTests.mm @@ -296,10 +296,23 @@ using namespace std::string_literals; float blue = (213.0 * alpha) / 255; MGLColor *color = [MGLColor mgl_colorWithColor:{ red, green, blue, alpha }]; // papayawhip NSExpression *expression = [NSExpression expressionForConstantValue:color]; - NSArray *jsonExpression = @[@"rgba", @127.5, @119.5, @106.5, @0.5]; + NSArray *jsonExpression = @[@"rgba", @255.0, @239.0, @213.0, @0.5]; XCTAssertEqualObjects(expression.mgl_jsonExpressionObject, jsonExpression); XCTAssertEqualObjects([expression expressionValueWithObject:nil context:nil], color); } + { + // Transform color components to non-premultiplied values + NSArray *jsonExpression = @[@"rgba", @255.0, @239.0, @213.0, @0.5]; + NSExpression *papayawhipExpression = [NSExpression expressionWithMGLJSONObject:jsonExpression]; + MGLColor *papayaWhipColor = [papayawhipExpression expressionValueWithObject:nil context:nil]; + CGFloat convertedRed = 0.0, convertedGreen = 0.0, convertedBlue = 0.0, convertedAlpha = 0.0; + [papayaWhipColor getRed:&convertedRed green:&convertedGreen blue:&convertedBlue alpha:&convertedAlpha]; + + XCTAssertEqualWithAccuracy(convertedRed, 255.0/255.0, 0.0000001); + XCTAssertEqualWithAccuracy(convertedGreen, 239.0/255.0, 0.0000001); + XCTAssertEqualWithAccuracy(convertedBlue, 213.0/255.0, 0.0000001); + XCTAssertEqual(convertedAlpha, 0.5); + } { NSExpression *expression = [NSExpression expressionWithFormat:@"noindex(513)"]; XCTAssertEqualObjects(expression.mgl_jsonExpressionObject, @513); diff --git a/platform/ios/CHANGELOG.md b/platform/ios/CHANGELOG.md index ff34a959b..eb6385f7f 100644 --- a/platform/ios/CHANGELOG.md +++ b/platform/ios/CHANGELOG.md @@ -2,6 +2,12 @@ Mapbox welcomes participation and contributions from everyone. Please read [CONTRIBUTING.md](../../CONTRIBUTING.md) to get started. +## 5.9.0 + +### Styles and rendering + +* Fixed an issue where properties such as `MGLFillStyleLayer.fillColor` and `MGLLineStyleLayer.lineColor` misinterpreted non-opaque `UIColor`s. ([#266](https://github.com/mapbox/mapbox-gl-native-ios/pull/266)) + ## 5.8.0 ### Styles and rendering diff --git a/platform/ios/src/UIColor+MGLAdditions.h b/platform/ios/src/UIColor+MGLAdditions.h index 19702fa10..be356fe61 100644 --- a/platform/ios/src/UIColor+MGLAdditions.h +++ b/platform/ios/src/UIColor+MGLAdditions.h @@ -9,6 +9,8 @@ - (mbgl::style::PropertyValue)mgl_colorPropertyValue; +- (mbgl::Color)mgl_colorForPremultipliedValue; + + (UIColor *)mgl_colorWithColor:(mbgl::Color)color; @end diff --git a/platform/ios/src/UIColor+MGLAdditions.mm b/platform/ios/src/UIColor+MGLAdditions.mm index 68e77f5b1..95c86409d 100644 --- a/platform/ios/src/UIColor+MGLAdditions.mm +++ b/platform/ios/src/UIColor+MGLAdditions.mm @@ -12,6 +12,14 @@ return { static_cast(r*a), static_cast(g*a), static_cast(b*a), static_cast(a) }; } +// Intended to be used when providing colors on the basis of an NSExpression +- (mbgl::Color)mgl_colorForPremultipliedValue +{ + CGFloat r, g, b, a; + [self getRed:&r green:&g blue:&b alpha:&a]; + return { static_cast(r), static_cast(g), static_cast(b), static_cast(a) }; +} + - (mbgl::style::PropertyValue)mgl_colorPropertyValue { mbgl::Color color = self.mgl_color; diff --git a/platform/macos/CHANGELOG.md b/platform/macos/CHANGELOG.md index 873f382c1..ae14d0a32 100644 --- a/platform/macos/CHANGELOG.md +++ b/platform/macos/CHANGELOG.md @@ -23,6 +23,7 @@ * Fixed an issue where style layers backed by a shape source could flicker when transitioning between styles. ([#15907](https://github.com/mapbox/mapbox-gl-native/pull/15907), [#15941](https://github.com/mapbox/mapbox-gl-native/pull/15941)) * Improved the performance of loading a style that has many style images. ([#16187](https://github.com/mapbox/mapbox-gl-native/pull/16187)) * Updated “map ID” to the more accurate term “tileset ID” in documentation; updated “style's Map ID” to the more accurate term “style URL”. ([#15116](https://github.com/mapbox/mapbox-gl-native/pull/15116)) +* Fixed an issue where properties such as `MGLFillStyleLayer.fillColor` and `MGLLineStyleLayer.lineColor` misinterpreted non-opaque `NSColor`s. ([#266](https://github.com/mapbox/mapbox-gl-native-ios/pull/266)) ### Camera diff --git a/platform/macos/src/NSColor+MGLAdditions.h b/platform/macos/src/NSColor+MGLAdditions.h index a3c5aba63..7de843362 100644 --- a/platform/macos/src/NSColor+MGLAdditions.h +++ b/platform/macos/src/NSColor+MGLAdditions.h @@ -10,6 +10,8 @@ */ - (mbgl::Color)mgl_color; +- (mbgl::Color)mgl_colorForPremultipliedValue; + /** Instantiates `NSColor` from an `mbgl::Color` */ diff --git a/platform/macos/src/NSColor+MGLAdditions.mm b/platform/macos/src/NSColor+MGLAdditions.mm index 6df3d750c..8029d8912 100644 --- a/platform/macos/src/NSColor+MGLAdditions.mm +++ b/platform/macos/src/NSColor+MGLAdditions.mm @@ -21,6 +21,22 @@ return { static_cast(r*a), static_cast(g*a), static_cast(b*a), static_cast(a) }; } +- (mbgl::Color)mgl_colorForPremultipliedValue { + CGFloat r, g, b, a; + + // The Mapbox Style Specification does not specify a color space, but it is + // assumed to be sRGB for consistency with CSS. + NSColor *srgbColor = self; + if ([NSColor redColor].colorSpaceName == NSCalibratedRGBColorSpace) { + srgbColor = [srgbColor colorUsingColorSpaceName:NSCalibratedRGBColorSpace]; + } else { + srgbColor = [srgbColor colorUsingColorSpace:[NSColorSpace sRGBColorSpace]]; + } + [srgbColor getRed:&r green:&g blue:&b alpha:&a]; + + return { static_cast(r), static_cast(g), static_cast(b), static_cast(a) }; +} + + (NSColor *)mgl_colorWithColor:(mbgl::Color)color { // If there is no alpha value, return original color values. if (color.a == 0.0f) {