diff options
Diffstat (limited to 'platform')
27 files changed, 181 insertions, 85 deletions
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/exceptions/UnknownContentEncodingException.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/exceptions/UnknownContentEncodingException.java new file mode 100644 index 0000000000..4debc33ee4 --- /dev/null +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/exceptions/UnknownContentEncodingException.java @@ -0,0 +1,12 @@ +package com.mapbox.mapboxsdk.exceptions; + +/** + * An UnknownContentEncodingException is thrown by HTTPRequest + * when there aren't enough LatLng to create a bounds. + */ +public class UnknownContentEncodingException extends RuntimeException { + + public UnknownContentEncodingException(String encoding) { + super("Unknown content encoding '" + encoding + "'"); + } +} diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/http/HTTPRequest.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/http/HTTPRequest.java index caee493e6f..942b88f1fb 100644 --- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/http/HTTPRequest.java +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/http/HTTPRequest.java @@ -9,6 +9,7 @@ import android.text.TextUtils; import com.mapbox.mapboxsdk.BuildConfig; import com.mapbox.mapboxsdk.Mapbox; import com.mapbox.mapboxsdk.constants.MapboxConstants; +import com.mapbox.mapboxsdk.exceptions.UnknownContentEncodingException; import java.io.IOException; import java.io.InterruptedIOException; @@ -66,7 +67,7 @@ class HTTPRequest implements Callback { private native void nativeOnFailure(int type, String message); private native void nativeOnResponse(int code, String etag, String modified, String cacheControl, String expires, - String retryAfter, String xRateLimitReset, byte[] body); + String retryAfter, String xRateLimitReset, byte[] body, boolean gzip); private HTTPRequest(long nativePtr, String resourceUrl, String etag, String modified) { mNativePtr = nativePtr; @@ -93,6 +94,7 @@ class HTTPRequest implements Callback { Request.Builder builder = new Request.Builder() .url(resourceUrl) .tag(resourceUrl.toLowerCase(MapboxConstants.MAPBOX_LOCALE)) + .addHeader("Accept-Encoding", "gzip, deflate") .addHeader("User-Agent", getUserAgent()); if (etag.length() > 0) { builder = builder.addHeader("If-None-Match", etag); @@ -149,6 +151,18 @@ class HTTPRequest implements Callback { mLock.lock(); if (mNativePtr != 0) { + String encoding = response.header("Content-Encoding"); + boolean compressed = false; + if (encoding != null) { + if (encoding.equals("gzip") || encoding.equals("deflate")) { + compressed = true; + } else if (!encoding.equals("identity")) { + mLock.unlock(); + handleFailure(call, new UnknownContentEncodingException(encoding)); + return; + } + } + nativeOnResponse(response.code(), response.header("ETag"), response.header("Last-Modified"), @@ -156,7 +170,8 @@ class HTTPRequest implements Callback { response.header("Expires"), response.header("Retry-After"), response.header("x-rate-limit-reset"), - body); + body, + compressed); } mLock.unlock(); } diff --git a/platform/android/src/asset_manager_file_source.cpp b/platform/android/src/asset_manager_file_source.cpp index aa65e3ff48..404177ba95 100644 --- a/platform/android/src/asset_manager_file_source.cpp +++ b/platform/android/src/asset_manager_file_source.cpp @@ -23,8 +23,9 @@ public: Response response; if (AAsset* asset = AAssetManager_open(assetManager, path.c_str(), AASSET_MODE_BUFFER)) { - response.data = std::make_shared<std::string>( - reinterpret_cast<const char*>(AAsset_getBuffer(asset)), AAsset_getLength64(asset)); + response.data = { { reinterpret_cast<const char*>(AAsset_getBuffer(asset)), + static_cast<size_t>(AAsset_getLength64(asset)) }, + false }; AAsset_close(asset); } else { response.error = std::make_unique<Response::Error>(Response::Error::Reason::NotFound, diff --git a/platform/android/src/http_file_source.cpp b/platform/android/src/http_file_source.cpp index 8eb9416e9d..7602c1914e 100644 --- a/platform/android/src/http_file_source.cpp +++ b/platform/android/src/http_file_source.cpp @@ -30,7 +30,8 @@ public: jni::String etag, jni::String modified, jni::String cacheControl, jni::String expires, jni::String retryAfter, jni::String xRateLimitReset, - jni::Array<jni::jbyte> body); + jni::Array<jni::jbyte> body, + jni::jboolean compressed); static jni::Class<HTTPRequest> javaClass; jni::UniqueObject<HTTPRequest> javaRequest; @@ -104,7 +105,8 @@ void HTTPRequest::onResponse(jni::JNIEnv& env, int code, jni::String etag, jni::String modified, jni::String cacheControl, jni::String expires, jni::String jRetryAfter, jni::String jXRateLimitReset, - jni::Array<jni::jbyte> body) { + jni::Array<jni::jbyte> body, + jni::jboolean compressed) { using Error = Response::Error; @@ -128,11 +130,11 @@ void HTTPRequest::onResponse(jni::JNIEnv& env, int code, if (code == 200) { if (body) { - auto data = std::make_shared<std::string>(body.Length(env), char()); - jni::GetArrayRegion(env, *body, 0, data->size(), reinterpret_cast<jbyte*>(&(*data)[0])); - response.data = data; + std::string data(static_cast<size_t>(body.Length(env)), char()); + jni::GetArrayRegion(env, *body, 0, data.size(), reinterpret_cast<jbyte*>(&data[0])); + response.data = Blob{ std::move(data), static_cast<bool>(compressed) }; } else { - response.data = std::make_shared<std::string>(); + response.data = {}; } } else if (code == 204 || (code == 404 && resource.kind == Resource::Kind::Tile)) { response.noContent = true; diff --git a/platform/android/src/image.cpp b/platform/android/src/image.cpp index 2a33944b18..dd98a3a6c8 100644 --- a/platform/android/src/image.cpp +++ b/platform/android/src/image.cpp @@ -8,14 +8,16 @@ namespace mbgl { -PremultipliedImage decodeImage(const std::string& string) { +PremultipliedImage decodeImage(Blob blob) { auto env{ android::AttachEnv() }; - auto array = jni::Array<jni::jbyte>::New(*env, string.size()); - jni::SetArrayRegion(*env, *array, 0, string.size(), - reinterpret_cast<const signed char*>(string.data())); + const auto string = blob.uncompressedData(); - auto bitmap = android::BitmapFactory::DecodeByteArray(*env, array, 0, string.size()); + auto array = jni::Array<jni::jbyte>::New(*env, string->size()); + jni::SetArrayRegion(*env, *array, 0, string->size(), + reinterpret_cast<const signed char*>(string->data())); + + auto bitmap = android::BitmapFactory::DecodeByteArray(*env, array, 0, string->size()); return android::Bitmap::GetImage(*env, bitmap); } diff --git a/platform/android/src/native_map_view.cpp b/platform/android/src/native_map_view.cpp index 67fc132204..c52aad6405 100755 --- a/platform/android/src/native_map_view.cpp +++ b/platform/android/src/native_map_view.cpp @@ -188,11 +188,11 @@ void NativeMapView::setStyleUrl(jni::JNIEnv& env, jni::String url) { } jni::String NativeMapView::getStyleJson(jni::JNIEnv& env) { - return jni::Make<jni::String>(env, map->getStyle().getJSON()); + return jni::Make<jni::String>(env, *map->getStyle().getJSON().uncompressedData()); } void NativeMapView::setStyleJson(jni::JNIEnv& env, jni::String json) { - map->getStyle().loadJSON(jni::Make<std::string>(env, json)); + map->getStyle().loadJSON(Blob{ jni::Make<std::string>(env, json), false }); } void NativeMapView::setLatLngBounds(jni::JNIEnv& env, jni::Object<mbgl::android::LatLngBounds> jBounds) { diff --git a/platform/darwin/src/http_file_source.mm b/platform/darwin/src/http_file_source.mm index 4a16ad82fb..6840740c44 100644 --- a/platform/darwin/src/http_file_source.mm +++ b/platform/darwin/src/http_file_source.mm @@ -232,8 +232,7 @@ std::unique_ptr<AsyncRequest> HTTPFileSource::request(const Resource& resource, if (error) { if (data) { - response.data = - std::make_shared<std::string>((const char*)[data bytes], [data length]); + response.data = Blob{ { (const char*)[data bytes], [data length] }, false }; } switch ([error code]) { @@ -287,7 +286,7 @@ std::unique_ptr<AsyncRequest> HTTPFileSource::request(const Resource& resource, } if (responseCode == 200) { - response.data = std::make_shared<std::string>((const char *)[data bytes], [data length]); + response.data = { { (const char *)[data bytes], [data length] }, false }; } else if (responseCode == 204 || (responseCode == 404 && resource.kind == Resource::Kind::Tile)) { response.noContent = true; } else if (responseCode == 304) { diff --git a/platform/darwin/src/image.mm b/platform/darwin/src/image.mm index 3a5adcca0a..f08fb9a25f 100644 --- a/platform/darwin/src/image.mm +++ b/platform/darwin/src/image.mm @@ -71,9 +71,10 @@ mbgl::PremultipliedImage MGLPremultipliedImageFromCGImage(CGImageRef src) { namespace mbgl { -PremultipliedImage decodeImage(const std::string& source) { +PremultipliedImage decodeImage(Blob blob) { + const auto source = blob.uncompressedData(); CFDataHandle data(CFDataCreateWithBytesNoCopy( - kCFAllocatorDefault, reinterpret_cast<const unsigned char*>(source.data()), source.size(), + kCFAllocatorDefault, reinterpret_cast<const unsigned char*>(source->data()), source->size(), kCFAllocatorNull)); if (!data) { throw std::runtime_error("CFDataCreateWithBytesNoCopy failed"); diff --git a/platform/darwin/test/MGLOfflineStorageTests.mm b/platform/darwin/test/MGLOfflineStorageTests.mm index 28c6633028..f0d54f81b4 100644 --- a/platform/darwin/test/MGLOfflineStorageTests.mm +++ b/platform/darwin/test/MGLOfflineStorageTests.mm @@ -182,8 +182,8 @@ req = fs->request(resource, [&](mbgl::Response res) { req.reset(); XCTAssertFalse(res.error.get(), @"Request should not return an error"); - XCTAssertTrue(res.data.get(), @"Request should return data"); - XCTAssertEqual("{\"api\":\"mapbox\"}", *res.data, @"Request did not return expected data"); + XCTAssertTrue(res.data, @"Request should return data"); + XCTAssertEqual("{\"api\":\"mapbox\"}", *res.data.uncompressedData(), @"Request did not return expected data"); CFRunLoopStop(CFRunLoopGetCurrent()); }); diff --git a/platform/default/asset_file_source.cpp b/platform/default/asset_file_source.cpp index 3063bf88a0..0b57a6dcef 100644 --- a/platform/default/asset_file_source.cpp +++ b/platform/default/asset_file_source.cpp @@ -44,12 +44,10 @@ public: } else if (result == -1 && errno == ENOENT) { response.error = std::make_unique<Response::Error>(Response::Error::Reason::NotFound); } else { - try { - response.data = std::make_shared<std::string>(util::read_file(path)); - } catch (...) { + response.data = util::readFile(path); + if (!response.data) { response.error = std::make_unique<Response::Error>( - Response::Error::Reason::Other, - util::toString(std::current_exception())); + Response::Error::Reason::Other, "Cannot read file " + path); } } diff --git a/platform/default/default_file_source.cpp b/platform/default/default_file_source.cpp index cb602995a4..5dcd28facd 100644 --- a/platform/default/default_file_source.cpp +++ b/platform/default/default_file_source.cpp @@ -151,8 +151,23 @@ public: // Get from the online file source if (resource.hasLoadingMethod(Resource::LoadingMethod::Network)) { + // Always solicit a compressed response so that we can insert it into the database + // while still compressed to save on CPU time. + const auto compression = resource.compression; + resource.compression = Resource::Compression::PreferCompressed; tasks[req] = onlineFileSource.request(resource, [=] (Response onlineResponse) mutable { this->offlineDatabase->put(resource, onlineResponse); + // If the original request expects an uncompressed response, uncompress before + // handing it back. + if (onlineResponse.data && onlineResponse.data.isCompressed() && + compression == Resource::Compression::Uncompressed) { + try { + onlineResponse.data.uncompress(); + } catch (std::exception& ex) { + onlineResponse.error = std::make_unique<Response::Error>( + Response::Error::Reason::Other, ex.what()); + } + } callback(onlineResponse); }); } diff --git a/platform/default/http_file_source.cpp b/platform/default/http_file_source.cpp index a9c442c2de..1a0ae577b8 100644 --- a/platform/default/http_file_source.cpp +++ b/platform/default/http_file_source.cpp @@ -371,9 +371,9 @@ void HTTPRequest::handleResult(CURLcode code) { if (responseCode == 200) { if (data) { - response->data = std::move(data); + response->data = Blob{ std::move(data), false }; } else { - response->data = std::make_shared<std::string>(); + response->data = Blob{ "", false }; } } else if (responseCode == 204 || (responseCode == 404 && resource.kind == Resource::Kind::Tile)) { response->noContent = true; diff --git a/platform/default/image.cpp b/platform/default/image.cpp index 447c6bcd66..4fde1898c6 100644 --- a/platform/default/image.cpp +++ b/platform/default/image.cpp @@ -11,9 +11,10 @@ PremultipliedImage decodeWebP(const uint8_t*, size_t); PremultipliedImage decodePNG(const uint8_t*, size_t); PremultipliedImage decodeJPEG(const uint8_t*, size_t); -PremultipliedImage decodeImage(const std::string& string) { - const auto* data = reinterpret_cast<const uint8_t*>(string.data()); - const size_t size = string.size(); +PremultipliedImage decodeImage(Blob blob) { + const auto uncompressed = blob.uncompressedData(); + const auto* data = reinterpret_cast<const uint8_t*>(uncompressed->data()); + const size_t size = uncompressed->size(); #if !defined(__ANDROID__) && !defined(__APPLE__) if (size >= 12) { diff --git a/platform/default/local_file_source.cpp b/platform/default/local_file_source.cpp index 0635e86d80..9a8f5ae51b 100644 --- a/platform/default/local_file_source.cpp +++ b/platform/default/local_file_source.cpp @@ -46,12 +46,10 @@ public: } else if (result == -1 && errno == ENOENT) { response.error = std::make_unique<Response::Error>(Response::Error::Reason::NotFound); } else { - try { - response.data = std::make_shared<std::string>(util::read_file(path)); - } catch (...) { + response.data = util::readFile(path); + if (!response.data) { response.error = std::make_unique<Response::Error>( - Response::Error::Reason::Other, - util::toString(std::current_exception())); + Response::Error::Reason::Other, "Cannot read file " + path); } } diff --git a/platform/default/mbgl/storage/offline_database.cpp b/platform/default/mbgl/storage/offline_database.cpp index 65c2097182..d7022f1c80 100644 --- a/platform/default/mbgl/storage/offline_database.cpp +++ b/platform/default/mbgl/storage/offline_database.cpp @@ -1,10 +1,10 @@ #include <mbgl/storage/offline_database.hpp> #include <mbgl/storage/response.hpp> -#include <mbgl/util/compression.hpp> #include <mbgl/util/io.hpp> #include <mbgl/util/string.hpp> #include <mbgl/util/chrono.hpp> #include <mbgl/util/logging.hpp> +#include <mbgl/util/compression.hpp> #include "sqlite3.hpp" @@ -153,7 +153,7 @@ optional<Response> OfflineDatabase::get(const Resource& resource) { optional<std::pair<Response, uint64_t>> OfflineDatabase::getInternal(const Resource& resource) { if (resource.kind == Resource::Kind::Tile) { assert(resource.tileData); - return getTile(*resource.tileData); + return getTile(resource); } else { return getResource(resource); } @@ -177,14 +177,31 @@ std::pair<bool, uint64_t> OfflineDatabase::putInternal(const Resource& resource, return { false, 0 }; } - std::string compressedData; + std::shared_ptr<const std::string> data; bool compressed = false; uint64_t size = 0; if (response.data) { - compressedData = util::compress(*response.data); - compressed = compressedData.size() < response.data->size(); - size = compressed ? compressedData.size() : response.data->size(); + if (response.data.isCompressed()) { + // The response is already compressed; don't try to compare it against the uncompressed size. + compressed = true; + data = response.data.compressedData(); + } else { + data = response.data.uncompressedData(); + + // Only try to compress the data when we have a good chance that the data can actually + // be considerably compressed. + if (util::isCompressible(*data)) { + const auto compressedData = response.data.compressedData(); + if (compressedData->size() < data->size()) { + compressed = true; + data = compressedData; + } + } + } + size = data->size(); + } else { + data = std::make_shared<const std::string>(); } if (evict_ && !evict(size)) { @@ -196,13 +213,9 @@ std::pair<bool, uint64_t> OfflineDatabase::putInternal(const Resource& resource, if (resource.kind == Resource::Kind::Tile) { assert(resource.tileData); - inserted = putTile(*resource.tileData, response, - compressed ? compressedData : response.data ? *response.data : "", - compressed); + inserted = putTile(*resource.tileData, response, *data, compressed); } else { - inserted = putResource(resource, response, - compressed ? compressedData : response.data ? *response.data : "", - compressed); + inserted = putResource(resource, response, *data, compressed); } return { inserted, size }; @@ -243,12 +256,20 @@ optional<std::pair<Response, uint64_t>> OfflineDatabase::getResource(const Resou optional<std::string> data = stmt->get<optional<std::string>>(4); if (!data) { response.noContent = true; - } else if (stmt->get<bool>(5)) { - response.data = std::make_shared<std::string>(util::decompress(*data)); - size = data->length(); } else { - response.data = std::make_shared<std::string>(*data); + response.data = { std::move(*data), stmt->get<bool>(5) }; size = data->length(); + + // Make sure the data is decompressed when the user explicitly requested uncompressed data. + if (response.data.isCompressed() && + resource.compression == Resource::Compression::Uncompressed) { + try { + response.data.uncompress(); + } catch (std::exception& ex) { + response.error = + std::make_unique<Response::Error>(Response::Error::Reason::Other, ex.what()); + } + } } return std::make_pair(response, size); @@ -359,7 +380,9 @@ bool OfflineDatabase::putResource(const Resource& resource, return true; } -optional<std::pair<Response, uint64_t>> OfflineDatabase::getTile(const Resource::TileData& tile) { +optional<std::pair<Response, uint64_t>> OfflineDatabase::getTile(const Resource& resource) { + const auto& tile = *resource.tileData; + // clang-format off Statement accessedStmt = getStatement( "UPDATE tiles " @@ -412,12 +435,20 @@ optional<std::pair<Response, uint64_t>> OfflineDatabase::getTile(const Resource: optional<std::string> data = stmt->get<optional<std::string>>(4); if (!data) { response.noContent = true; - } else if (stmt->get<bool>(5)) { - response.data = std::make_shared<std::string>(util::decompress(*data)); - size = data->length(); } else { - response.data = std::make_shared<std::string>(*data); + response.data = { std::move(*data), stmt->get<bool>(5) }; size = data->length(); + + // Make sure the data is decompressed when the user explicitly requested uncompressed data. + if (response.data.isCompressed() && + resource.compression == Resource::Compression::Uncompressed) { + try { + response.data.uncompress(); + } catch (std::exception& ex) { + response.error = + std::make_unique<Response::Error>(Response::Error::Reason::Other, ex.what()); + } + } } return std::make_pair(response, size); diff --git a/platform/default/mbgl/storage/offline_database.hpp b/platform/default/mbgl/storage/offline_database.hpp index 91b544a9e0..fba1a3c230 100644 --- a/platform/default/mbgl/storage/offline_database.hpp +++ b/platform/default/mbgl/storage/offline_database.hpp @@ -81,7 +81,7 @@ private: Statement getStatement(const char *); - optional<std::pair<Response, uint64_t>> getTile(const Resource::TileData&); + optional<std::pair<Response, uint64_t>> getTile(const Resource&); optional<int64_t> hasTile(const Resource::TileData&); bool putTile(const Resource::TileData&, const Response&, const std::string&, bool compressed); diff --git a/platform/default/mbgl/storage/offline_download.cpp b/platform/default/mbgl/storage/offline_download.cpp index ba504c1f9b..d8fe8c646b 100644 --- a/platform/default/mbgl/storage/offline_download.cpp +++ b/platform/default/mbgl/storage/offline_download.cpp @@ -71,7 +71,7 @@ OfflineRegionStatus OfflineDownload::getStatus() const { } style::Parser parser; - parser.parse(*styleResponse->data); + parser.parse(*styleResponse->data.uncompressedData()); result.requiredResourceCountIsPrecise = true; @@ -88,7 +88,8 @@ OfflineRegionStatus OfflineDownload::getStatus() const { optional<Response> sourceResponse = offlineDatabase.get(Resource::source(url)); if (sourceResponse) { style::conversion::Error error; - optional<Tileset> tileset = style::conversion::convertJSON<Tileset>(*sourceResponse->data, error); + optional<Tileset> tileset = style::conversion::convertJSON<Tileset>( + *sourceResponse->data.uncompressedData(), error); if (tileset) { result.requiredResourceCount += definition.tileCount(type, tileSize, (*tileset).zoomRange); @@ -160,7 +161,7 @@ void OfflineDownload::activateDownload() { status.requiredResourceCountIsPrecise = true; style::Parser parser; - parser.parse(*styleResponse.data); + parser.parse(*styleResponse.data.uncompressedData()); for (const auto& source : parser.sources) { SourceType type = source->getType(); @@ -176,7 +177,8 @@ void OfflineDownload::activateDownload() { ensureResource(Resource::source(url), [=](Response sourceResponse) { style::conversion::Error error; - optional<Tileset> tileset = style::conversion::convertJSON<Tileset>(*sourceResponse.data, error); + optional<Tileset> tileset = style::conversion::convertJSON<Tileset>( + *sourceResponse.data.uncompressedData(), error); if (tileset) { util::mapbox::canonicalizeTileset(*tileset, url, type, tileSize); queueTiles(type, tileSize, *tileset); @@ -236,14 +238,18 @@ void OfflineDownload::activateDownload() { if (!parser.glyphURL.empty()) { for (const auto& fontStack : parser.fontStacks()) { for (char16_t i = 0; i < GLYPH_RANGES_PER_FONT_STACK; i++) { - queueResource(Resource::glyphs(parser.glyphURL, fontStack, getGlyphRange(i * GLYPHS_PER_GLYPH_RANGE))); + auto resource = Resource::glyphs(parser.glyphURL, fontStack, getGlyphRange(i * GLYPHS_PER_GLYPH_RANGE)); + resource.compression = Resource::Compression::PreferCompressed; + queueResource(resource); } } } if (!parser.spriteURL.empty()) { queueResource(Resource::spriteImage(parser.spriteURL, definition.pixelRatio)); - queueResource(Resource::spriteJSON(parser.spriteURL, definition.pixelRatio)); + auto spriteJSON = Resource::spriteJSON(parser.spriteURL, definition.pixelRatio); + spriteJSON.compression = Resource::Compression::PreferCompressed; + queueResource(spriteJSON); } continueDownload(); diff --git a/platform/default/online_file_source.cpp b/platform/default/online_file_source.cpp index d685109b95..fe77df8c02 100644 --- a/platform/default/online_file_source.cpp +++ b/platform/default/online_file_source.cpp @@ -374,6 +374,16 @@ void OnlineFileRequest::completed(Response response) { failedRequestReason = Response::Error::Reason::Success; } + // Make sure the data is decompressed when the user explicitly requested uncompressed data. + if (response.data && response.data.isCompressed() && + resource.compression == Resource::Compression::Uncompressed) { + try { + response.data.uncompress(); + } catch (std::exception& ex) { + response.error = std::make_unique<Response::Error>(Response::Error::Reason::Other, ex.what()); + } + } + schedule(response.expires); // Calling the callback may result in `this` being deleted. It needs to be done last, diff --git a/platform/default/png_writer.cpp b/platform/default/png_writer.cpp index 9ef9052158..d3297b8ebf 100644 --- a/platform/default/png_writer.cpp +++ b/platform/default/png_writer.cpp @@ -38,7 +38,7 @@ void addChunk(std::string& png, const char* type, const char* data = "", const u namespace mbgl { // Encode PNGs without libpng. -std::string encodePNG(const PremultipliedImage& pre) { +Blob encodePNG(const PremultipliedImage& pre) { // Make copy of the image so that we can unpremultiply it. const auto src = util::unpremultiply(pre.clone()); @@ -74,7 +74,7 @@ std::string encodePNG(const PremultipliedImage& pre) { addChunk(png, "IHDR", ihdr, 13); addChunk(png, "IDAT", idat.data(), static_cast<uint32_t>(idat.size())); addChunk(png, "IEND"); - return png; + return { std::move(png), false }; } } // namespace mbgl diff --git a/platform/ios/ios.xcodeproj/project.pbxproj b/platform/ios/ios.xcodeproj/project.pbxproj index 07fae5945c..c29c2ec89f 100644 --- a/platform/ios/ios.xcodeproj/project.pbxproj +++ b/platform/ios/ios.xcodeproj/project.pbxproj @@ -211,6 +211,7 @@ 40F887701D7A1E58008ECB67 /* MGLShapeSource_Private.h in Headers */ = {isa = PBXBuildFile; fileRef = 40F8876F1D7A1DB8008ECB67 /* MGLShapeSource_Private.h */; }; 40F887711D7A1E59008ECB67 /* MGLShapeSource_Private.h in Headers */ = {isa = PBXBuildFile; fileRef = 40F8876F1D7A1DB8008ECB67 /* MGLShapeSource_Private.h */; }; 40FDA76B1CCAAA6800442548 /* MBXAnnotationView.m in Sources */ = {isa = PBXBuildFile; fileRef = 40FDA76A1CCAAA6800442548 /* MBXAnnotationView.m */; }; + 55434256203C7530002624EB /* libz.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = 55434255203C7530002624EB /* libz.tbd */; }; 5549A0381EF1D86B00073113 /* libmbgl-core.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 5549A0371EF1D86B00073113 /* libmbgl-core.a */; }; 5549A0391EF2877100073113 /* OpenGLES.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 554180411D2E97DE00012372 /* OpenGLES.framework */; }; 5549A03A1EF2877500073113 /* OpenGLES.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 554180411D2E97DE00012372 /* OpenGLES.framework */; }; @@ -794,6 +795,7 @@ 40FDA7691CCAAA6800442548 /* MBXAnnotationView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MBXAnnotationView.h; sourceTree = "<group>"; }; 40FDA76A1CCAAA6800442548 /* MBXAnnotationView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MBXAnnotationView.m; sourceTree = "<group>"; }; 554180411D2E97DE00012372 /* OpenGLES.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = OpenGLES.framework; path = System/Library/Frameworks/OpenGLES.framework; sourceTree = SDKROOT; }; + 55434255203C7530002624EB /* libz.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = libz.tbd; path = usr/lib/libz.tbd; sourceTree = SDKROOT; }; 5549A0371EF1D86B00073113 /* libmbgl-core.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = "libmbgl-core.a"; path = "../../build/ios/Debug-iphonesimulator/libmbgl-core.a"; sourceTree = "<group>"; }; 556660C91E1BF3A900E2C41B /* MGLFoundation.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MGLFoundation.h; sourceTree = "<group>"; }; 556660D71E1D085500E2C41B /* MGLVersionNumber.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = MGLVersionNumber.m; path = ../../darwin/test/MGLVersionNumber.m; sourceTree = "<group>"; }; @@ -1145,6 +1147,7 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( + 55434256203C7530002624EB /* libz.tbd in Frameworks */, 5549A0381EF1D86B00073113 /* libmbgl-core.a in Frameworks */, DA2E88561CC036F400F24E7B /* Mapbox.framework in Frameworks */, ); @@ -1477,6 +1480,7 @@ DA1DC9921CB6DF24006E619F /* Frameworks */ = { isa = PBXGroup; children = ( + 55434255203C7530002624EB /* libz.tbd */, 55D120AD1F791018004B6D81 /* libmbgl-loop-darwin.a */, 55D120AB1F791015004B6D81 /* libmbgl-filesource.a */, 55D120A91F79100C004B6D81 /* libmbgl-filesource.a */, diff --git a/platform/macos/macos.xcodeproj/project.pbxproj b/platform/macos/macos.xcodeproj/project.pbxproj index 4327670911..58f29ed2a3 100644 --- a/platform/macos/macos.xcodeproj/project.pbxproj +++ b/platform/macos/macos.xcodeproj/project.pbxproj @@ -80,6 +80,7 @@ 52B5D17F1E5E26DF00BBCB48 /* libmbgl-loop-darwin.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 5548BE7B1D0ACBBD005DDE81 /* libmbgl-loop-darwin.a */; }; 52B5D1801E5E26DF00BBCB48 /* libmbgl-loop-darwin.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 5548BE7B1D0ACBBD005DDE81 /* libmbgl-loop-darwin.a */; }; 5548BE781D09E718005DDE81 /* libmbgl-core.a in Frameworks */ = {isa = PBXBuildFile; fileRef = DAE6C3451CC31D1200DB3429 /* libmbgl-core.a */; }; + 555CF3EC203DA46F004C828F /* libz.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = 55D9B4B01D005D3900C1CCE2 /* libz.tbd */; }; 556660C61E1BEA0100E2C41B /* MGLFoundation.h in Headers */ = {isa = PBXBuildFile; fileRef = 556660C51E1BEA0100E2C41B /* MGLFoundation.h */; settings = {ATTRIBUTES = (Public, ); }; }; 556660D61E1D07E400E2C41B /* MGLVersionNumber.m in Sources */ = {isa = PBXBuildFile; fileRef = 556660D51E1D07E400E2C41B /* MGLVersionNumber.m */; }; 558DE7A61E56161C00C7916D /* MGLFoundation_Private.h in Headers */ = {isa = PBXBuildFile; fileRef = 558DE7A41E56161C00C7916D /* MGLFoundation_Private.h */; }; @@ -659,6 +660,7 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( + 555CF3EC203DA46F004C828F /* libz.tbd in Frameworks */, DAE0DD7A1D5F015A005A6BB1 /* libmbgl-core.a in Frameworks */, 55D120A51F790A0C004B6D81 /* libmbgl-filesource.a in Frameworks */, DAE6C3321CC30DB200DB3429 /* Mapbox.framework in Frameworks */, diff --git a/platform/node/src/node_map.cpp b/platform/node/src/node_map.cpp index ac14df0228..a4f6f6a9de 100644 --- a/platform/node/src/node_map.cpp +++ b/platform/node/src/node_map.cpp @@ -214,8 +214,8 @@ void NodeMap::Load(const Nan::FunctionCallbackInfo<v8::Value>& info) { } try { - nodeMap->map->getStyle().loadJSON(style); - } catch (const std::exception &ex) { + nodeMap->map->getStyle().loadJSON(mbgl::Blob{ std::move(style), false }); + } catch (const std::exception& ex) { return Nan::ThrowError(ex.what()); } diff --git a/platform/node/src/node_request.cpp b/platform/node/src/node_request.cpp index de16710f78..7b2b57fd1f 100644 --- a/platform/node/src/node_request.cpp +++ b/platform/node/src/node_request.cpp @@ -99,10 +99,8 @@ void NodeRequest::HandleCallback(const Nan::FunctionCallbackInfo<v8::Value>& inf if (Nan::Has(res, Nan::New("data").ToLocalChecked()).FromJust()) { auto data = Nan::Get(res, Nan::New("data").ToLocalChecked()).ToLocalChecked(); if (node::Buffer::HasInstance(data)) { - response.data = std::make_shared<std::string>( - node::Buffer::Data(data), - node::Buffer::Length(data) - ); + response.data = { std::string{ node::Buffer::Data(data), node::Buffer::Length(data), }, + false }; } else { return Nan::ThrowTypeError("Response data must be a Buffer"); } diff --git a/platform/qt/src/http_request.cpp b/platform/qt/src/http_request.cpp index ea3f388bd5..4e2143ba8e 100644 --- a/platform/qt/src/http_request.cpp +++ b/platform/qt/src/http_request.cpp @@ -99,9 +99,9 @@ void HTTPRequest::handleNetworkReply(QNetworkReply *reply, const QByteArray& dat switch(responseCode) { case 200: { if (data.isEmpty()) { - response.data = std::make_shared<std::string>(); + response.data = Blob{ "", false }; } else { - response.data = std::make_shared<std::string>(data.constData(), data.size()); + response.data = Blob{ std::string{ data.constData(), static_cast<size_t>(data.size()) }, false }; } break; } diff --git a/platform/qt/src/qmapboxgl.cpp b/platform/qt/src/qmapboxgl.cpp index 414b65255c..e054d88489 100644 --- a/platform/qt/src/qmapboxgl.cpp +++ b/platform/qt/src/qmapboxgl.cpp @@ -585,12 +585,12 @@ void QMapboxGL::cycleDebugOptions() */ QString QMapboxGL::styleJson() const { - return QString::fromStdString(d_ptr->mapObj->getStyle().getJSON()); + return QString::fromStdString(*d_ptr->mapObj->getStyle().getJSON().uncompressedData()); } void QMapboxGL::setStyleJson(const QString &style) { - d_ptr->mapObj->getStyle().loadJSON(style.toStdString()); + d_ptr->mapObj->getStyle().loadJSON(mbgl::Blob{ style.toStdString(), false }); } /*! diff --git a/platform/qt/src/qt_image.cpp b/platform/qt/src/qt_image.cpp index a5c92514c1..ff45b02ef1 100644 --- a/platform/qt/src/qt_image.cpp +++ b/platform/qt/src/qt_image.cpp @@ -6,7 +6,7 @@ namespace mbgl { -std::string encodePNG(const PremultipliedImage& pre) { +Blob encodePNG(const PremultipliedImage& pre) { QImage image(pre.data.get(), pre.size.width, pre.size.height, QImage::Format_ARGB32_Premultiplied); @@ -16,7 +16,7 @@ std::string encodePNG(const PremultipliedImage& pre) { buffer.open(QIODevice::WriteOnly); image.rgbSwapped().save(&buffer, "PNG"); - return std::string(array.constData(), array.size()); + return { std::string(array.constData(), array.size()), false }; } #if !defined(QT_IMAGE_DECODERS) @@ -24,9 +24,10 @@ PremultipliedImage decodeJPEG(const uint8_t*, size_t); PremultipliedImage decodeWebP(const uint8_t*, size_t); #endif -PremultipliedImage decodeImage(const std::string& string) { - const uint8_t* data = reinterpret_cast<const uint8_t*>(string.data()); - const size_t size = string.size(); +PremultipliedImage decodeImage(Blob blob) { + const auto uncompressed = blob.uncompressedData(); + const uint8_t* data = reinterpret_cast<const uint8_t*>(uncompressed->data()); + const size_t size = uncompressed->size(); #if !defined(QT_IMAGE_DECODERS) if (size >= 12) { diff --git a/platform/qt/test/qmapboxgl.test.cpp b/platform/qt/test/qmapboxgl.test.cpp index 2a56b346a3..607cdd6ba9 100644 --- a/platform/qt/test/qmapboxgl.test.cpp +++ b/platform/qt/test/qmapboxgl.test.cpp @@ -47,7 +47,7 @@ void QMapboxGLTest::onNeedsRendering() { TEST_F(QMapboxGLTest, TEST_DISABLED_ON_CI(styleJson)) { QString json = QString::fromStdString( - mbgl::util::read_file("test/fixtures/resources/style_vector.json")); + *mbgl::util::readFile("test/fixtures/resources/style_vector.json").uncompressedData()); map.setStyleJson(json); ASSERT_EQ(map.styleJson(), json); |