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

Commit

Permalink
Merge branch 'release-ios-v3.4.0' into erw-note-map-load
Browse files Browse the repository at this point in the history
* release-ios-v3.4.0:
  [ios] Fixed crash on launch in iosapp
  [ios] Fix iosapp runtime styling examples (#7395)
  [ios, macos] handle duplicate layer error
  [core] guard against duplicate layer ids
  [core] use raii to guard backend deactivation
  [ios, macos] Override references to property names in property requirements lists (#7391)
  [ios, macos] Load features into shape source if possible (#7339)
  [ios, macos] Expanded source documentation
  [ios, macos] Rename MGLGeoJSONSource to MGLShapeSource (#7334)
  [ios, macos] Silence -Wc++11-narrowing warning in open gl layer (#7355)
  [ios, macos] Source-driven attribution (#5999)
  [ios, macos] renamed raster-hue-rotate
  • Loading branch information
ericrwolfe committed Dec 13, 2016
2 parents 170f4fd + 2d52dd8 commit d9b66f9
Show file tree
Hide file tree
Showing 72 changed files with 1,367 additions and 537 deletions.
31 changes: 25 additions & 6 deletions include/mbgl/map/backend.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ namespace gl {
class Context;
} // namespace gl

class BackendScope;

class Backend {
public:
Backend();
Expand All @@ -18,6 +20,14 @@ class Backend {
// Returns the backend's context which manages OpenGL state.
gl::Context& getContext();

// Called when the map needs to be rendered; the backend should call Map::render() at some point
// in the near future. (Not called for Map::renderStill() mode.)
virtual void invalidate() = 0;

// Notifies a watcher of map x/y/scale/rotation changes.
virtual void notifyMapChange(MapChange change);

protected:
// Called when the backend's GL context needs to be made active or inactive. These are called,
// as a matched pair, in four situations:
//
Expand All @@ -31,15 +41,24 @@ class Backend {
virtual void activate() = 0;
virtual void deactivate() = 0;

// Called when the map needs to be rendered; the backend should call Map::render() at some point
// in the near future. (Not called for Map::renderStill() mode.)
virtual void invalidate() = 0;
private:
const std::unique_ptr<gl::Context> context;

// Notifies a watcher of map x/y/scale/rotation changes.
virtual void notifyMapChange(MapChange change);
friend class BackendScope;
};

class BackendScope {
public:
BackendScope(Backend& backend_) : backend(backend_) {
backend.activate();
}

~BackendScope() {
backend.deactivate();
}

private:
const std::unique_ptr<gl::Context> context;
Backend& backend;
};

} // namespace mbgl
8 changes: 2 additions & 6 deletions platform/android/src/native_map_view.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -190,7 +190,7 @@ void NativeMapView::invalidate() {
}

void NativeMapView::render() {
activate();
BackendScope guard(*this);

updateViewBinding();
map->render(*this);
Expand Down Expand Up @@ -235,8 +235,6 @@ void NativeMapView::render() {
} else {
mbgl::Log::Info(mbgl::Event::Android, "Not swapping as we are not ready");
}

deactivate();
}

mbgl::Map &NativeMapView::getMap() { return *map; }
Expand Down Expand Up @@ -421,7 +419,7 @@ void NativeMapView::createSurface(ANativeWindow *window_) {
if (!firstTime) {
firstTime = true;

activate();
BackendScope guard(*this);

if (!eglMakeCurrent(display, surface, surface, context)) {
mbgl::Log::Error(mbgl::Event::OpenGL, "eglMakeCurrent() returned error %d",
Expand All @@ -442,8 +440,6 @@ void NativeMapView::createSurface(ANativeWindow *window_) {
mbgl::gl::InitializeExtensions([] (const char * name) {
return reinterpret_cast<mbgl::gl::glProc>(eglGetProcAddress(name));
});

deactivate();
}
}

Expand Down
6 changes: 4 additions & 2 deletions platform/android/src/native_map_view.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,6 @@ class NativeMapView : public mbgl::View, public mbgl::Backend {
void updateViewBinding();
void bind() override;

void activate() override;
void deactivate() override;
void invalidate() override;

void notifyMapChange(mbgl::MapChange) override;
Expand Down Expand Up @@ -53,6 +51,10 @@ class NativeMapView : public mbgl::View, public mbgl::Backend {

void scheduleTakeSnapshot();

protected:
void activate() override;
void deactivate() override;

private:
EGLConfig chooseConfig(const EGLConfig configs[], EGLint numConfigs);

Expand Down
17 changes: 17 additions & 0 deletions platform/darwin/scripts/generate-style-code.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,23 @@ _.forOwn(cocoaConventions, function (properties, kind) {
spec[kind][newName] = spec[kind][oldName];
spec[kind][newName].original = oldName;
delete spec[kind][oldName];

// Update requirements in other properties.
let updateRequirements = function (property, name) {
let requires = property.requires || [];
for (let i = 0; i < requires.length; i++) {
if (requires[i] in cocoaConventions[kind]) {
property.requires[i] = cocoaConventions[kind][requires[i]];
}
_.forOwn(requires[i], function (values, name, require) {
if (require in cocoaConventions[kind]) {
require[cocoaConventions[kind][name]] = values;
}
});
}
};
_.forOwn(spec[kind.replace(/^layout_/, 'paint_')], updateRequirements);
_.forOwn(spec[kind.replace(/^paint_/, 'layout_')], updateRequirements);
})
});

Expand Down
3 changes: 2 additions & 1 deletion platform/darwin/scripts/style-spec-cocoa-conventions-v8.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@
},
"paint_raster": {
"raster-brightness-min": "minimum-raster-brightness",
"raster-brightness-max": "maximum-raster-brightness"
"raster-brightness-max": "maximum-raster-brightness",
"raster-hue-rotate": "raster-hue-rotation"
},
"paint_line": {
"line-dasharray": "line-dash-pattern"
Expand Down
6 changes: 6 additions & 0 deletions platform/darwin/scripts/style-spec-overrides-v8.json
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,12 @@
}
},
"paint_symbol": {
"icon-color": {
"doc": "The tint color to apply to the icon. The `icon-image-name` property must be set to a template image."
},
"icon-halo-color": {
"doc": "The color of the icon’s halo. The `icon-image-name` property must be set to a template image."
},
"icon-translate": {
"doc": "Distance that the icon's anchor is moved from its original placement."
},
Expand Down
58 changes: 58 additions & 0 deletions platform/darwin/src/MGLAttributionInfo.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
#import <Foundation/Foundation.h>
#import <CoreGraphics/CoreGraphics.h>
#import <CoreLocation/CoreLocation.h>

#import "MGLTypes.h"

NS_ASSUME_NONNULL_BEGIN

/**
Information about an attribution statement, usually a copyright or trademark
statement, associated with a map content source.
*/
@interface MGLAttributionInfo : NSObject

/**
Parses and returns the attribution infos contained in the given HTML source
code string.
@param htmlString The HTML source code to parse.
@param fontSize The default text size in points.
@param linkColor The default link color.
*/
+ (NS_ARRAY_OF(MGLAttributionInfo *) *)attributionInfosFromHTMLString:(NSString *)htmlString fontSize:(CGFloat)fontSize linkColor:(nullable MGLColor *)linkColor;

- (instancetype)initWithTitle:(NSAttributedString *)title URL:(nullable NSURL *)URL;

@property (nonatomic) NSAttributedString *title;
@property (nonatomic, nullable) NSURL *URL;
@property (nonatomic, getter=isFeedbackLink) BOOL feedbackLink;

- (nullable NSURL *)feedbackURLAtCenterCoordinate:(CLLocationCoordinate2D)centerCoordinate zoomLevel:(double)zoomLevel;

@end

@interface NSMutableArray (MGLAttributionInfoAdditions)

/**
Adds the given attribution info object to the receiver as long as it isn’t
redundant to any object already in the receiver. Any existing object that is
redundant to the given object is replaced by the given object.
@param info The info object to add to the receiver.
@return True if the given info object was added to the receiver.
*/
- (void)growArrayByAddingAttributionInfo:(MGLAttributionInfo *)info;

/**
Adds each of the given attribution info objects to the receiver as long as it
isn’t redundant to any object already in the receiver. Any existing object that
is redundant to the given object is replaced by the given object.
@param infos An array of info objects to add to the receiver.
*/
- (void)growArrayByAddingAttributionInfosFromArray:(NS_ARRAY_OF(MGLAttributionInfo *) *)infos;

@end

NS_ASSUME_NONNULL_END
178 changes: 178 additions & 0 deletions platform/darwin/src/MGLAttributionInfo.mm
Original file line number Diff line number Diff line change
@@ -0,0 +1,178 @@
#import "MGLAttributionInfo.h"

#if TARGET_OS_IPHONE
#import <UIKit/UIKit.h>
#else
#import <Cocoa/Cocoa.h>
#endif

#import "MGLMapCamera.h"
#import "NSString+MGLAdditions.h"

#include <string>

@implementation MGLAttributionInfo

+ (NS_ARRAY_OF(MGLAttributionInfo *) *)attributionInfosFromHTMLString:(NSString *)htmlString fontSize:(CGFloat)fontSize linkColor:(nullable MGLColor *)linkColor {
NSDictionary *options = @{
NSDocumentTypeDocumentAttribute: NSHTMLTextDocumentType,
NSCharacterEncodingDocumentAttribute: @(NSUTF8StringEncoding),
};
// Apply a bogus, easily detectable style rule to any feedback link, since
// NSAttributedString doesn’t preserve the class attribute.
NSMutableString *css = [NSMutableString stringWithString:
@".mapbox-improve-map { -webkit-text-stroke-width: 1000px; }"];
if (fontSize) {
[css appendFormat:@"html { font-size: %.1fpx; }", fontSize];
}
if (linkColor) {
CGFloat red;
CGFloat green;
CGFloat blue;
CGFloat alpha;
#if !TARGET_OS_IPHONE
linkColor = [linkColor colorUsingColorSpaceName:NSCalibratedRGBColorSpace];
#endif
[linkColor getRed:&red green:&green blue:&blue alpha:&alpha];
[css appendFormat:
@"a:link { color: rgba(%f%%, %f%%, %f%%, %f); }",
red * 100, green * 100, blue * 100, alpha];
}
NSString *styledHTML = [NSString stringWithFormat:@"<style type='text/css'>%@</style>%@", css, htmlString];
NSData *htmlData = [styledHTML dataUsingEncoding:NSUTF8StringEncoding];

#if TARGET_OS_IPHONE
NSMutableAttributedString *attributedString = [[NSMutableAttributedString alloc] initWithData:htmlData
options:options
documentAttributes:nil
error:NULL];
#else
NSMutableAttributedString *attributedString = [[NSMutableAttributedString alloc] initWithHTML:htmlData
options:options
documentAttributes:nil];
#endif

NSMutableArray *infos = [NSMutableArray array];
[attributedString enumerateAttribute:NSLinkAttributeName
inRange:attributedString.mgl_wholeRange
options:0
usingBlock:
^(id _Nullable value, NSRange range, BOOL * _Nonnull stop) {
NSCAssert(!value || [value isKindOfClass:[NSURL class]], @"If present, URL attribute must be an NSURL.");

// Detect feedback links by the bogus style rule applied above.
NSNumber *strokeWidth = [attributedString attribute:NSStrokeWidthAttributeName
atIndex:range.location
effectiveRange:NULL];
BOOL isFeedbackLink = NO;
if ([strokeWidth floatValue] > 100) {
isFeedbackLink = YES;
[attributedString removeAttribute:NSStrokeWidthAttributeName range:range];
}

// Omit whitespace-only strings.
NSAttributedString *title = [[attributedString attributedSubstringFromRange:range]
mgl_attributedStringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
if (!title.length) {
return;
}

MGLAttributionInfo *info = [[MGLAttributionInfo alloc] initWithTitle:title URL:value];
info.feedbackLink = isFeedbackLink;
[infos addObject:info];
}];
return infos;
}

- (instancetype)initWithTitle:(NSAttributedString *)title URL:(NSURL *)URL {
if (self = [super init]) {
_title = title;
_URL = URL;
}
return self;
}

- (nullable NSURL *)feedbackURLAtCenterCoordinate:(CLLocationCoordinate2D)centerCoordinate zoomLevel:(double)zoomLevel {
if (!self.feedbackLink) {
return nil;
}

NSURLComponents *components = [NSURLComponents componentsWithURL:self.URL resolvingAgainstBaseURL:NO];
components.fragment = [NSString stringWithFormat:@"/%.5f/%.5f/%i",
centerCoordinate.longitude, centerCoordinate.latitude, (int)round(zoomLevel + 1)];
return components.URL;
}

- (BOOL)isEqual:(id)object {
return [object isKindOfClass:[self class]] && [[object title] isEqual:self.title] && [[object URL] isEqual:self.URL];
}

- (NSUInteger)hash {
return self.title.hash + self.URL.hash;
}

/**
Returns whether the given attribution info object overlaps with the receiver by
its plain text title.
@return `NSOrderedAscending` if the given object is a superset of the receiver,
`NSOrderedDescending` if it is a subset of the receiver, or `NSOrderedSame`
if there is no overlap.
*/
- (NSComparisonResult)subsetCompare:(MGLAttributionInfo *)otherInfo {
NSString *title = self.title.string;
NSString *otherTitle = otherInfo.title.string;
if ([title containsString:otherTitle]) {
return NSOrderedDescending;
}
if ([otherTitle containsString:title]) {
return NSOrderedAscending;
}
return NSOrderedSame;
}

@end

@implementation NSMutableArray (MGLAttributionInfoAdditions)

- (void)growArrayByAddingAttributionInfo:(MGLAttributionInfo *)info {
__block BOOL didInsertInfo = NO;
__block BOOL shouldAddInfo = YES;
[self enumerateObjectsUsingBlock:^(MGLAttributionInfo * _Nonnull existingInfo, NSUInteger idx, BOOL * _Nonnull stop) {
switch ([info subsetCompare:existingInfo]) {
case NSOrderedDescending:
// The existing info object is a subset of the one we’re adding.
// Replace the existing object the first time we find a subset;
// remove the existing object every time after that.
if (didInsertInfo) {
[self removeObjectAtIndex:idx];
} else {
[self replaceObjectAtIndex:idx withObject:info];
didInsertInfo = YES;
}
break;

case NSOrderedAscending:
// The info object we’re adding is a subset of the existing one.
// Don’t add the object and stop looking.
shouldAddInfo = NO;
*stop = YES;
break;

default:
break;
}
}];
if (shouldAddInfo && !didInsertInfo) {
// No overlapping infos were found, so append the info object.
[self addObject:info];
}
}

- (void)growArrayByAddingAttributionInfosFromArray:(NS_ARRAY_OF(MGLAttributionInfo *) *)infos {
for (MGLAttributionInfo *info in infos) {
[self growArrayByAddingAttributionInfo:info];
}
}

@end
Loading

0 comments on commit d9b66f9

Please sign in to comment.