Skip to content
This repository has been archived by the owner on Aug 8, 2023. It is now read-only.

[ios, macos] Add to-rgba expression operator. #11725

Merged
merged 9 commits into from
May 7, 2018

Conversation

fabian-guerra
Copy link
Contributor

@fabian-guerra fabian-guerra commented Apr 18, 2018

Fixes #11011

  • to-color
  • to-rgba

@fabian-guerra fabian-guerra added GL JS parity For feature parity with Mapbox GL JS iOS Mapbox Maps SDK for iOS macOS Mapbox Maps SDK for macOS labels Apr 18, 2018
@fabian-guerra fabian-guerra added this to the ios-v4.0.0 milestone Apr 18, 2018
@fabian-guerra fabian-guerra self-assigned this Apr 18, 2018
@fabian-guerra fabian-guerra requested a review from 1ec5 April 18, 2018 17:14
@1ec5 1ec5 modified the milestones: ios-v4.0.0, ios-v4.0.1 Apr 18, 2018
@@ -372,7 +372,7 @@ In style specification | Method, function, or predicate type | Format string syn
`rgb` | `+[UIColor colorWithRed:green:blue:alpha:]` |
`rgba` | `+[UIColor colorWithRed:green:blue:alpha:]` |
<% } -%>
`to-rgba` | |
`to-rgba` | | `CAST(var, 'UIColor')` or `CAST(var, 'NSColor')`
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Within this particular .ejs file, you can use the cocoaPrefix variable to switch between “UI” and “NS” as appropriate:

const cocoaPrefix = iOS ? 'UI' : 'NS';

We don’t have the “Predicates and Expressions” guide set up this way yet, since the platform-specific content is so minimal in that guide.

@@ -1153,6 +1161,15 @@ - (id)mgl_jsonExpressionObject {
} else if ([type isEqualToString:@"NSNumber"]) {
return @[@"to-number", object];
}
#if TARGET_OS_IPHONE
else if ([type isEqualToString:@"UIColor"]) {
return @[@"to-rgba", object];
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I had things backwards in #11011. to-string turns its argument into a string, but oddly enough, to-rgba turns a color into an array, not the other way around. So CAST(…, 'UIColor') would more or less correspond to the rgba operator, and the to-rgba operator would correspond to CAST(…, 'NSArray'). Both coercions would be useful.

@fabian-guerra fabian-guerra force-pushed the fabian-to-color-11011 branch 3 times, most recently from 6aabfc0 to 38623c8 Compare April 24, 2018 18:40
Copy link
Contributor

@1ec5 1ec5 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In addition to the comments below, remember to add a blurb to the iOS and macOS changelogs about the newly supported casting types.

@@ -335,7 +335,11 @@ In style specification | Method, function, or predicate type | Format string syn
`number` | |
`string` | |
`to-boolean` | `boolValue` |
`to-color` | |
<% if (macOS) { -%>
`to-color` | | `CAST(var, 'NScolor')`
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Typo: NSColor, not NScolor. Also consider using the cocoaPrefix variable so you don’t have to duplicate the row with an if statement.

@@ -802,6 +802,17 @@ + (instancetype)expressionWithMGLJSONObject:(id)object {
} else if ([op isEqualToString:@"to-string"] || [op isEqualToString:@"string"]) {
NSExpression *operand = [NSExpression expressionWithMGLJSONObject:argumentObjects.firstObject];
return [NSExpression expressionWithFormat:@"CAST(%@, 'NSString')", operand];
} else if ([op isEqualToString:@"to-color"]) {
NSExpression *operand = [NSExpression expressionWithMGLJSONObject:argumentObjects.firstObject];
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

to-color can take multiple arguments, similar to to-number. I’m not a huge fan of mgl_numberWithFallbackValues:, so I won’t request an mgl_colorWithFallbackValues:. However, if there is more than one argument to this expression, we should at least fall back to MGL_FUNCTION() instead of losing all the fallback values in translation.

}
#endif
else if ([type isEqualToString:@"NSArray"]) {
return @[@"to-rgba", object];
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

to-rgba is only appropriate if the object is a color. If it’s a constant UIColor or NSColor, we can use to-rgba for sure. If it’s a different kind of constant value, such as an NSString, then we should raise an exception since that kind of conversion is currently unsupported. For non-constant expressions, we don’t know the resolved type for sure, so we can use to-rgba in that case.

}
#endif
else if ([type isEqualToString:@"NSArray"]) {
return @[@"to-rgba", object];
Copy link
Contributor

@1ec5 1ec5 Apr 26, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

NSExpression is a bit aggressive in evaluating a constant in a cast even during parsing, so just initializing an NSExpression with a format string of CAST(%@, 'NSArray') would crash. However, a format string of CAST(noindex(%@), 'NSArray') should convert to the expected JSON without crashing.

@fabian-guerra fabian-guerra force-pushed the fabian-to-color-11011 branch from 80e63e8 to 40564fd Compare April 30, 2018 21:11
XCTAssertEqualObjects(expression.mgl_jsonExpressionObject, jsonExpression);
}
{
NSExpression *expression = [NSExpression expressionWithFormat:@"CAST(noindex(x), 'NSArray')"];
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Developers won’t think to use noindex() for this purpose – I didn’t think of it until after much head-scratching. So let’s add a note to the “Predicates and Expressions” guide that points out the need to use noindex() when casting a constant expression to NSArray or NSColor/UIColor.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

noindex() is only required when using the operand to-rgba. I am adding the note for how to cast each:

* To cast a value to a color, use `CAST(key, 'UIColor')`.
* To cast a value to an rgba color, use `CAST(noindex(var), 'NSArray')`.

@@ -66,7 +66,7 @@ + (UIColor *)mgl_colorWithRGBComponents:(NSArray<NSExpression *> *)components {
return [UIColor colorWithRed:[components[0].constantValue doubleValue] / 255.0
green:[components[1].constantValue doubleValue] / 255.0
blue:[components[2].constantValue doubleValue] / 255.0
alpha:components.count == 3 ? [components[3].constantValue doubleValue] : 1.0];
alpha:components.count == 3 ? 1.0 : [components[3].constantValue doubleValue]];
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good catch! Let’s add a mention to the changelogs that this PR fixes an issue where certain colors were being misrepresented in NSExpressions obtained from MGLStyleLayer getters.

@fabian-guerra fabian-guerra force-pushed the fabian-to-color-11011 branch from 40564fd to 78cd0b2 Compare May 4, 2018 17:52
@@ -70,6 +70,8 @@ path or variable into a matching type:

* To cast a value to a number, use `CAST(key, 'NSNumber')`.
* To cast a value to a string, use `CAST(key, 'NSString')`.
* To cast a value to a color, use `CAST(key, 'UIColor')`.
* To cast a value to an rgba color, use `CAST(noindex(var), 'NSArray')`.
Copy link
Contributor

@1ec5 1ec5 May 5, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This doesn’t cast a value to a color, it casts a color to an array.

To cast an NSColor or UIColor object to an array, use CAST(noindex(color), 'NSArray').

@@ -22,6 +22,7 @@ Mapbox welcomes participation and contributions from everyone. Please read [CONT
* Reduce per-frame render CPU time ([#11811](https://github.com/mapbox/mapbox-gl-native/issues/11811))
* Fixed a crash when removing an `MGLOfflinePack`. ([#6092](https://github.com/mapbox/mapbox-gl-native/issues/6092))
* Fixed an issue where an `MGLOverlay` object straddling the antimeridian had an empty `MGLOverlay.overlayBounds` value. ([#11783](https://github.com/mapbox/mapbox-gl-native/pull/11783))
* Fixed an issue where certain colors were being misrepresented in `NSExpressions` obtained from `MGLStyleLayer` getters. ([#11725](https://github.com/mapbox/mapbox-gl-native/pull/11725))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: NSExpressions. (×2)

@@ -70,6 +70,8 @@ path or variable into a matching type:

* To cast a value to a number, use `CAST(key, 'NSNumber')`.
* To cast a value to a string, use `CAST(key, 'NSString')`.
* To cast a value to a color, use `CAST(key, 'UIColor')`.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To cast a value to a color, use CAST(key, 'UIColor') on iOS and CAST(key, 'NSColor') on macOS.

@fabian-guerra fabian-guerra force-pushed the fabian-to-color-11011 branch from 78cd0b2 to 1f8d266 Compare May 7, 2018 15:29
@fabian-guerra fabian-guerra merged commit a425995 into release-boba May 7, 2018
@fabian-guerra fabian-guerra deleted the fabian-to-color-11011 branch May 7, 2018 16:01
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
GL JS parity For feature parity with Mapbox GL JS iOS Mapbox Maps SDK for iOS macOS Mapbox Maps SDK for macOS
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants