-
Notifications
You must be signed in to change notification settings - Fork 1.3k
[ios, macos] Add to-rgba expression operator. #11725
Conversation
@@ -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')` |
There was a problem hiding this comment.
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]; |
There was a problem hiding this comment.
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.
6aabfc0
to
38623c8
Compare
There was a problem hiding this 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')` |
There was a problem hiding this comment.
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]; |
There was a problem hiding this comment.
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]; |
There was a problem hiding this comment.
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]; |
There was a problem hiding this comment.
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.
80e63e8
to
40564fd
Compare
XCTAssertEqualObjects(expression.mgl_jsonExpressionObject, jsonExpression); | ||
} | ||
{ | ||
NSExpression *expression = [NSExpression expressionWithFormat:@"CAST(noindex(x), 'NSArray')"]; |
There was a problem hiding this comment.
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
.
There was a problem hiding this comment.
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]]; |
There was a problem hiding this comment.
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.
40564fd
to
78cd0b2
Compare
@@ -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')`. |
There was a problem hiding this comment.
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
orUIColor
object to an array, useCAST(noindex(color), 'NSArray')
.
platform/ios/CHANGELOG.md
Outdated
@@ -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)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit: NSExpression
s. (×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')`. |
There was a problem hiding this comment.
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 andCAST(key, 'NSColor')
on macOS.
78cd0b2
to
1f8d266
Compare
Fixes #11011