From 414ccaaf93fff1096086cd5c11acccc5cf5da7c3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Konstantin=20Ka=CC=88fer?= Date: Wed, 29 Oct 2014 16:00:09 -0400 Subject: use unique_ptr for automatic deallocation --- include/mbgl/util/image.hpp | 8 +++----- src/util/image.cpp | 20 ++++++++++---------- 2 files changed, 13 insertions(+), 15 deletions(-) diff --git a/include/mbgl/util/image.hpp b/include/mbgl/util/image.hpp index dc8f6a8150..0bc5af21d2 100644 --- a/include/mbgl/util/image.hpp +++ b/include/mbgl/util/image.hpp @@ -2,8 +2,7 @@ #define MBGL_UTIL_IMAGE #include -#include -#include +#include namespace mbgl { namespace util { @@ -14,9 +13,8 @@ std::string compress_png(int width, int height, void *rgba, bool flip = false); class Image { public: Image(const std::string &img, bool flip = false); - ~Image(); - inline const char *getData() const { return img; } + inline const char *getData() const { return img.get(); } inline uint32_t getWidth() const { return width; } inline uint32_t getHeight() const { return height; } @@ -25,7 +23,7 @@ private: uint32_t width = 0, height = 0; // the raw image data - char *img = nullptr; + std::unique_ptr img; }; diff --git a/src/util/image.cpp b/src/util/image.cpp index ffa65bf0ba..bd5d7b8913 100644 --- a/src/util/image.cpp +++ b/src/util/image.cpp @@ -1,12 +1,17 @@ #include +#include #include #include #include +#include -std::string mbgl::util::compress_png(int width, int height, void *rgba, bool flip) { +namespace mbgl { +namespace util { + +std::string compress_png(int width, int height, void *rgba, bool flip) { png_voidp error_ptr = 0; png_structp png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, error_ptr, NULL, NULL); if (!png_ptr) { @@ -54,9 +59,6 @@ std::string mbgl::util::compress_png(int width, int height, void *rgba, bool fli } -using namespace mbgl::util; - - struct Buffer { Buffer(const std::string& data_) : data(data_.data()), length(data_.size()) {} @@ -139,9 +141,9 @@ Image::Image(const std::string &data, bool flip) { png_size_t rowbytes = png_get_rowbytes(png, info); assert(width * 4 == rowbytes); - img = static_cast(::operator new(width * height * 4)); + img = ::std::unique_ptr(new char[width * height * 4]()); - char *surface = img; + char *surface = img.get(); assert(surface); struct ptrs { @@ -163,14 +165,12 @@ Image::Image(const std::string &data, bool flip) { fprintf(stderr, "loading PNG failed: %s\n", e.what()); png_destroy_read_struct(&png, &info, nullptr); if (img) { - ::operator delete(img); - img = nullptr; + img.reset(); } width = 0; height = 0; } } -Image::~Image() { - ::operator delete(img),img = nullptr; +} } -- cgit v1.2.1 From 7a13db9a863c9be58709e941f44eb2c370276e2a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Konstantin=20Ka=CC=88fer?= Date: Wed, 29 Oct 2014 16:09:42 -0400 Subject: do not crash for missing images --- include/mbgl/util/image.hpp | 2 +- src/geometry/sprite_atlas.cpp | 1 + src/map/sprite.cpp | 3 +++ 3 files changed, 5 insertions(+), 1 deletion(-) diff --git a/include/mbgl/util/image.hpp b/include/mbgl/util/image.hpp index 0bc5af21d2..cb7db6d6fc 100644 --- a/include/mbgl/util/image.hpp +++ b/include/mbgl/util/image.hpp @@ -17,6 +17,7 @@ public: inline const char *getData() const { return img.get(); } inline uint32_t getWidth() const { return width; } inline uint32_t getHeight() const { return height; } + inline operator bool() const { return img && width && height; } private: // loaded image dimensions @@ -24,7 +25,6 @@ private: // the raw image data std::unique_ptr img; - }; diff --git a/src/geometry/sprite_atlas.cpp b/src/geometry/sprite_atlas.cpp index 5271122919..e5bad1eada 100644 --- a/src/geometry/sprite_atlas.cpp +++ b/src/geometry/sprite_atlas.cpp @@ -158,6 +158,7 @@ void SpriteAtlas::allocate() { void SpriteAtlas::copy(const Rect& dst, const SpritePosition& src) { if (!sprite->raster) return; const uint32_t *src_img = reinterpret_cast(sprite->raster->getData()); + if (!src_img) return; allocate(); uint32_t *dst_img = reinterpret_cast(data); diff --git a/src/map/sprite.cpp b/src/map/sprite.cpp index 876586e4b0..ad1a8e770b 100644 --- a/src/map/sprite.cpp +++ b/src/map/sprite.cpp @@ -102,6 +102,9 @@ bool Sprite::isLoaded() const { void Sprite::parseImage() { raster = std::make_unique(image); + if (!*raster) { + raster.reset(); + } image.clear(); loadedImage = true; } -- cgit v1.2.1 From e3bc69b7e77aa6771c8db3695f12548447e1de51 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Konstantin=20Ka=CC=88fer?= Date: Wed, 29 Oct 2014 19:58:34 -0400 Subject: use CoreImage for decoding/encoding images on osx/ios --- configure | 15 +- gyp/mbgl-core.gypi | 1 - gyp/mbgl-ios.gypi | 9 +- gyp/mbgl-linux.gypi | 3 + gyp/mbgl-osx.gypi | 9 +- include/mbgl/platform/default/headless_view.hpp | 2 +- include/mbgl/util/image.hpp | 4 +- platform/darwin/image.mm | 125 +++++++++++++++++ platform/default/headless_view.cpp | 4 +- platform/default/image.cpp | 177 ++++++++++++++++++++++++ src/geometry/sprite_atlas.cpp | 13 +- src/util/image.cpp | 176 ----------------------- test/headless.cpp | 14 +- 13 files changed, 352 insertions(+), 200 deletions(-) create mode 100644 platform/darwin/image.mm create mode 100644 platform/default/image.cpp delete mode 100644 src/util/image.cpp diff --git a/configure b/configure index afb94d4795..daf09eaeee 100755 --- a/configure +++ b/configure @@ -6,6 +6,10 @@ shopt -s expand_aliases CONFIG_FILE=${1:-config.gypi} +if [ `uname -s` = 'Darwin' ]; then + MASON_PLATFORM=${MASON_PLATFORM:-osx} +fi + function finish { >&2 echo -en "\033[0m"; } @@ -34,11 +38,16 @@ if [[ ! -d ~/.mason ]]; then fi alias mason='~/.mason/mason' - -case $MASON_PLATFORM in +case ${MASON_PLATFORM} in 'ios') SQLITE_VERSION=system - LIBPNG_VERSION=1.6.13 + LIBUV_VERSION=0.10.28 + ZLIB_VERSION=system + BOOST_VERSION=system + ;; + 'osx') + GLFW_VERSION=a21f2377 + SQLITE_VERSION=system LIBUV_VERSION=0.10.28 ZLIB_VERSION=system BOOST_VERSION=system diff --git a/gyp/mbgl-core.gypi b/gyp/mbgl-core.gypi index e49697388c..46ff762742 100644 --- a/gyp/mbgl-core.gypi +++ b/gyp/mbgl-core.gypi @@ -10,7 +10,6 @@ ], 'variables': { 'cflags_cc': [ - '<@(png_cflags)', '<@(uv_cflags)', '<@(sqlite3_cflags)', '<@(zlib_cflags)', diff --git a/gyp/mbgl-ios.gypi b/gyp/mbgl-ios.gypi index 755b3cc483..5566ca3a32 100644 --- a/gyp/mbgl-ios.gypi +++ b/gyp/mbgl-ios.gypi @@ -34,6 +34,7 @@ '../platform/darwin/log_nslog.mm', '../platform/darwin/string_nsstring.mm', '../platform/darwin/http_request_baton_cocoa.mm', + '../platform/darwin/image.mm', ], 'include_dirs': [ '../include', @@ -44,7 +45,13 @@ 'direct_dependent_settings': { 'include_dirs': [ '../include', - ] + ], + 'xcode_settings': { + 'OTHER_LDFLAGS': [ + '-framework ImageIO', + '-framework MobileCoreServices', + ], + }, }, }, ], diff --git a/gyp/mbgl-linux.gypi b/gyp/mbgl-linux.gypi index 337e98039e..2b166ea434 100644 --- a/gyp/mbgl-linux.gypi +++ b/gyp/mbgl-linux.gypi @@ -7,6 +7,7 @@ 'hard_dependency': 1, 'variables': { 'cflags_cc': [ + '<@(png_cflags)', '<@(uv_cflags)', '<@(curl_cflags)', ], @@ -14,6 +15,7 @@ '<@(uv_cflags)', ], 'ldflags': [ + '<@(png_ldflags)', '<@(uv_ldflags)', '<@(curl_ldflags)', ], @@ -23,6 +25,7 @@ '../platform/default/log_stderr.cpp', '../platform/default/string_stdlib.cpp', '../platform/default/http_request_baton_curl.cpp', + '../platform/default/image.cpp', ], 'include_dirs': [ '../include', diff --git a/gyp/mbgl-osx.gypi b/gyp/mbgl-osx.gypi index bee0325498..76c22f5ad6 100644 --- a/gyp/mbgl-osx.gypi +++ b/gyp/mbgl-osx.gypi @@ -10,6 +10,7 @@ '../platform/darwin/log_nslog.mm', '../platform/darwin/string_nsstring.mm', '../platform/darwin/http_request_baton_cocoa.mm', + '../platform/darwin/image.mm', ], 'include_dirs': [ '../include', @@ -20,7 +21,13 @@ 'direct_dependent_settings': { 'include_dirs': [ '../include', - ] + ], + 'xcode_settings': { + 'OTHER_LDFLAGS': [ + '-framework ImageIO', + '-framework CoreServices', + ], + }, }, }, ], diff --git a/include/mbgl/platform/default/headless_view.hpp b/include/mbgl/platform/default/headless_view.hpp index c0baddb884..f140338349 100644 --- a/include/mbgl/platform/default/headless_view.hpp +++ b/include/mbgl/platform/default/headless_view.hpp @@ -27,7 +27,7 @@ public: void createContext(); void resize(uint16_t width, uint16_t height, float pixelRatio); - const std::unique_ptr readPixels(); + std::unique_ptr readPixels(); void notify(); void notify_map_change(MapChange change, timestamp delay = 0); diff --git a/include/mbgl/util/image.hpp b/include/mbgl/util/image.hpp index cb7db6d6fc..b2f70e1442 100644 --- a/include/mbgl/util/image.hpp +++ b/include/mbgl/util/image.hpp @@ -7,12 +7,12 @@ namespace mbgl { namespace util { -std::string compress_png(int width, int height, void *rgba, bool flip = false); +std::string compress_png(int width, int height, void *rgba); class Image { public: - Image(const std::string &img, bool flip = false); + Image(const std::string &img); inline const char *getData() const { return img.get(); } inline uint32_t getWidth() const { return width; } diff --git a/platform/darwin/image.mm b/platform/darwin/image.mm new file mode 100644 index 0000000000..50c871533d --- /dev/null +++ b/platform/darwin/image.mm @@ -0,0 +1,125 @@ +#include + +#import + +#if TARGET_OS_IPHONE +#import +#else +#import +#endif + +namespace mbgl { +namespace util { + +std::string compress_png(int width, int height, void *rgba) { + CGDataProviderRef provider = CGDataProviderCreateWithData(NULL, rgba, width * height * 4, NULL); + if (!provider) { + return ""; + } + + CGColorSpaceRef color_space = CGColorSpaceCreateDeviceRGB(); + if (!color_space) { + CGDataProviderRelease(provider); + return ""; + } + + CGImageRef image = CGImageCreate(width, height, 8, 32, 4 * width, color_space, + kCGBitmapByteOrderDefault | kCGImageAlphaLast, provider, NULL, false, + kCGRenderingIntentDefault); + if (!image) { + CGColorSpaceRelease(color_space); + CGDataProviderRelease(provider); + return ""; + } + + CFMutableDataRef data = CFDataCreateMutable(kCFAllocatorDefault, 0); + if (!data) { + CGImageRelease(image); + CGColorSpaceRelease(color_space); + CGDataProviderRelease(provider); + return ""; + } + + CGImageDestinationRef image_destination = CGImageDestinationCreateWithData(data, kUTTypePNG, 1, NULL); + if (!image_destination) { + CFRelease(data); + CGImageRelease(image); + CGColorSpaceRelease(color_space); + CGDataProviderRelease(provider); + return ""; + } + + CGImageDestinationAddImage(image_destination, image, NULL); + CGImageDestinationFinalize(image_destination); + + const std::string result { + reinterpret_cast(CFDataGetBytePtr(data)), + static_cast(CFDataGetLength(data)) + }; + + CFRelease(image_destination); + CFRelease(data); + CGImageRelease(image); + CGColorSpaceRelease(color_space); + CGDataProviderRelease(provider); + + return result; +} + +Image::Image(const std::string &source_data) { + CFDataRef data = CFDataCreateWithBytesNoCopy(kCFAllocatorDefault, reinterpret_cast(source_data.data()), source_data.size(), kCFAllocatorNull); + if (!data) { + return; + } + + CGImageSourceRef image_source = CGImageSourceCreateWithData(data, NULL); + if (!image_source) { + CFRelease(data); + return; + } + + CGImageRef image = CGImageSourceCreateImageAtIndex(image_source, 0, NULL); + if (!image) { + CFRelease(image_source); + CFRelease(data); + return; + } + + CGColorSpaceRef color_space = CGColorSpaceCreateDeviceRGB(); + if (!color_space) { + CGImageRelease(image); + CFRelease(image_source); + CFRelease(data); + return; + } + + width = CGImageGetWidth(image); + height = CGImageGetHeight(image); + CGRect rect = {{ 0, 0 }, { static_cast(width), static_cast(height) }}; + + img = ::std::unique_ptr(new char[width * height * 4]()); + CGContextRef context = CGBitmapContextCreate(img.get(), width, height, 8, width * 4, + color_space, kCGImageAlphaPremultipliedLast); + if (!context) { + CGColorSpaceRelease(color_space); + CGImageRelease(image); + CFRelease(image_source); + CFRelease(data); + width = 0; + height = 0; + img.release(); + return; + } + + CGContextSetBlendMode(context, kCGBlendModeCopy); + CGContextDrawImage(context, rect, image); + + CGContextRelease(context); + CGColorSpaceRelease(color_space); + CGImageRelease(image); + CFRelease(image_source); + CFRelease(data); +} + +} +} \ No newline at end of file diff --git a/platform/default/headless_view.cpp b/platform/default/headless_view.cpp index ec5c4aabec..71096beba0 100644 --- a/platform/default/headless_view.cpp +++ b/platform/default/headless_view.cpp @@ -181,11 +181,11 @@ void HeadlessView::resize(uint16_t width, uint16_t height, float pixelRatio) { make_inactive(); } -const std::unique_ptr HeadlessView::readPixels() { +std::unique_ptr HeadlessView::readPixels() { const unsigned int w = width_ * pixelRatio_; const unsigned int h = height_ * pixelRatio_; - std::unique_ptr pixels(new uint32_t[w * h]); + auto pixels = std::unique_ptr(new uint32_t[w * h]); make_active(); glReadPixels(0, 0, width_, height_, GL_RGBA, GL_UNSIGNED_BYTE, pixels.get()); diff --git a/platform/default/image.cpp b/platform/default/image.cpp new file mode 100644 index 0000000000..5b1afec7aa --- /dev/null +++ b/platform/default/image.cpp @@ -0,0 +1,177 @@ +#include + +#include + +#include +#include +#include + + +namespace mbgl { +namespace util { + +std::string compress_png(int width, int height, void *rgba) { + png_voidp error_ptr = 0; + png_structp png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, error_ptr, NULL, NULL); + if (!png_ptr) { + fprintf(stderr, "Couldn't create png_ptr\n"); + return ""; + } + + png_infop info_ptr = png_create_info_struct(png_ptr); + if (!png_ptr) { + png_destroy_write_struct(&png_ptr, (png_infopp)0); + fprintf(stderr, "Couldn't create info_ptr\n"); + return ""; + } + + png_set_IHDR(png_ptr, info_ptr, width, height, 8, PNG_COLOR_TYPE_RGB_ALPHA, PNG_INTERLACE_NONE, + PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT); + + jmp_buf *jmp_context = (jmp_buf *)png_get_error_ptr(png_ptr); + if (jmp_context) { + png_destroy_write_struct(&png_ptr, &info_ptr); + return ""; + } + + std::string result; + png_set_write_fn(png_ptr, &result, [](png_structp png_ptr_, png_bytep data, png_size_t length) { + std::string *out = static_cast(png_get_io_ptr(png_ptr_)); + out->append(reinterpret_cast(data), length); + }, NULL); + + struct ptrs { + ptrs(size_t count) : rows(new png_bytep[count]) {} + ~ptrs() { delete[] rows; } + png_bytep *rows = nullptr; + } pointers(height); + + for (int i = 0; i < height; i++) { + pointers.rows[i] = (png_bytep)((png_bytep)rgba + width * 4 * i); + } + + png_set_rows(png_ptr, info_ptr, pointers.rows); + png_write_png(png_ptr, info_ptr, PNG_TRANSFORM_IDENTITY, NULL); + png_destroy_write_struct(&png_ptr, &info_ptr); + + return result; +} + + +struct Buffer { + Buffer(const std::string& data_) + : data(data_.data()), length(data_.size()) {} + const char *const data = 0; + const size_t length = 0; + size_t pos = 0; +}; + +void readCallback(png_structp png, png_bytep data, png_size_t length) { + Buffer *reader = static_cast(png_get_io_ptr(png)); + + // Read `length` bytes into `data`. + if (reader->pos + length > reader->length) { + png_error(png, "Read Error"); + } else { + memcpy(data, reader->data + reader->pos, length); + reader->pos += length; + } +} + +void errorHandler(png_structp, png_const_charp error_msg) { + throw std::runtime_error(error_msg); +} + +void warningHandler(png_structp, png_const_charp error_msg) { + fprintf(stderr, "PNG: %s\n", error_msg); +} + +Image::Image(const std::string &data) { + Buffer buffer(data); + + if (buffer.length < 8 || !png_check_sig((const png_bytep)buffer.data, 8)) { + fprintf(stderr, "image is not a valid PNG image\n"); + return; + } + + png_structp png = png_create_read_struct(PNG_LIBPNG_VER_STRING, nullptr, errorHandler, warningHandler); + assert(png); + + png_infop info = png_create_info_struct(png); + assert(info); + + int depth, color, interlace; + + try { + png_set_read_fn(png, (png_voidp)&buffer, readCallback); + png_read_info(png, info); + png_get_IHDR(png, info, (png_uint_32*)&width, (png_uint_32*)&height, &depth, &color, &interlace, nullptr, nullptr); + bool alpha = (color & PNG_COLOR_MASK_ALPHA) || png_get_valid(png, info, PNG_INFO_tRNS); + + // From http://trac.mapnik.org/browser/trunk/src/png_reader.cpp + if (color == PNG_COLOR_TYPE_PALETTE) + png_set_expand(png); + if (color == PNG_COLOR_TYPE_GRAY) + png_set_expand(png); + if (png_get_valid(png, info, PNG_INFO_tRNS)) + png_set_expand(png); + if (depth == 16) + png_set_strip_16(png); + if (depth < 8) + png_set_packing(png); + if (color == PNG_COLOR_TYPE_GRAY || + color == PNG_COLOR_TYPE_GRAY_ALPHA) + png_set_gray_to_rgb(png); + + if (interlace == PNG_INTERLACE_ADAM7) + png_set_interlace_handling(png); + + // Always add an alpha channel. + if (!alpha) { + png_set_add_alpha(png, 0xFF, PNG_FILLER_AFTER); + } + + double gamma; + if (png_get_gAMA(png, info, &gamma)) + png_set_gamma(png, 2.2, gamma); + + png_set_alpha_mode(png, PNG_ALPHA_PREMULTIPLIED, 2.2); + + png_read_update_info(png, info); + + png_size_t rowbytes = png_get_rowbytes(png, info); + assert(width * 4 == rowbytes); + + img = ::std::unique_ptr(new char[width * height * 4]()); + + char *surface = img.get(); + assert(surface); + + struct ptrs { + ptrs(size_t count) : rows(new png_bytep[count]) {} + ~ptrs() { delete[] rows; } + png_bytep *rows = nullptr; + } pointers(height); + for (unsigned i = 0; i < height; ++i) { + pointers.rows[i] = (png_bytep)(surface + (i * rowbytes)); + } + + // Read image data + png_read_image(png, pointers.rows); + + png_read_end(png, nullptr); + + png_destroy_read_struct(&png, &info, nullptr); + } catch (std::exception& e) { + fprintf(stderr, "loading PNG failed: %s\n", e.what()); + png_destroy_read_struct(&png, &info, nullptr); + if (img) { + img.reset(); + } + width = 0; + height = 0; + } +} + +} +} diff --git a/src/geometry/sprite_atlas.cpp b/src/geometry/sprite_atlas.cpp index e5bad1eada..d7ef1e789b 100644 --- a/src/geometry/sprite_atlas.cpp +++ b/src/geometry/sprite_atlas.cpp @@ -72,18 +72,7 @@ void copy_bitmap(const uint32_t *src, const int src_stride, const int src_x, con dst += dst_y * dst_stride + dst_x; for (int y = 0; y < height; y++, src += src_stride, dst += dst_stride) { for (int x = 0; x < width; x++) { - const uint8_t *s = reinterpret_cast(src + x); - uint8_t *d = reinterpret_cast(dst + x); - - // Premultiply the bitmap. - // Note: We don't need to clamp the component values to 0..255, since - // the source value is already 0..255 and the operation means they will - // stay within the range of 0..255 and won't overflow. - const uint8_t a = s[3]; - d[0] = s[0] * a / 255; - d[1] = s[1] * a / 255; - d[2] = s[2] * a / 255; - d[3] = a; + dst[x] = src[x]; } } } diff --git a/src/util/image.cpp b/src/util/image.cpp deleted file mode 100644 index bd5d7b8913..0000000000 --- a/src/util/image.cpp +++ /dev/null @@ -1,176 +0,0 @@ -#include -#include - -#include - -#include -#include -#include - - -namespace mbgl { -namespace util { - -std::string compress_png(int width, int height, void *rgba, bool flip) { - png_voidp error_ptr = 0; - png_structp png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, error_ptr, NULL, NULL); - if (!png_ptr) { - fprintf(stderr, "Couldn't create png_ptr\n"); - return ""; - } - - png_infop info_ptr = png_create_info_struct(png_ptr); - if (!png_ptr) { - png_destroy_write_struct(&png_ptr, (png_infopp)0); - fprintf(stderr, "Couldn't create info_ptr\n"); - return ""; - } - - png_set_IHDR(png_ptr, info_ptr, width, height, 8, PNG_COLOR_TYPE_RGB_ALPHA, PNG_INTERLACE_NONE, - PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT); - - jmp_buf *jmp_context = (jmp_buf *)png_get_error_ptr(png_ptr); - if (jmp_context) { - png_destroy_write_struct(&png_ptr, &info_ptr); - return ""; - } - - std::string result; - png_set_write_fn(png_ptr, &result, [](png_structp png_ptr_, png_bytep data, png_size_t length) { - std::string *out = static_cast(png_get_io_ptr(png_ptr_)); - out->append(reinterpret_cast(data), length); - }, NULL); - - struct ptrs { - ptrs(size_t count) : rows(new png_bytep[count]) {} - ~ptrs() { delete[] rows; } - png_bytep *rows = nullptr; - } pointers(height); - - for (int i = 0; i < height; i++) { - pointers.rows[flip ? height - 1 - i : i] = (png_bytep)((png_bytep)rgba + width * 4 * i); - } - - png_set_rows(png_ptr, info_ptr, pointers.rows); - png_write_png(png_ptr, info_ptr, PNG_TRANSFORM_IDENTITY, NULL); - png_destroy_write_struct(&png_ptr, &info_ptr); - - return result; -} - - -struct Buffer { - Buffer(const std::string& data_) - : data(data_.data()), length(data_.size()) {} - const char *const data = 0; - const size_t length = 0; - size_t pos = 0; -}; - -void readCallback(png_structp png, png_bytep data, png_size_t length) { - Buffer *reader = static_cast(png_get_io_ptr(png)); - - // Read `length` bytes into `data`. - if (reader->pos + length > reader->length) { - png_error(png, "Read Error"); - } else { - memcpy(data, reader->data + reader->pos, length); - reader->pos += length; - } -} - -void errorHandler(png_structp, png_const_charp error_msg) { - throw std::runtime_error(error_msg); -} - -void warningHandler(png_structp, png_const_charp error_msg) { - fprintf(stderr, "PNG: %s\n", error_msg); -} - -Image::Image(const std::string &data, bool flip) { - Buffer buffer(data); - - if (buffer.length < 8 || !png_check_sig((const png_bytep)buffer.data, 8)) { - fprintf(stderr, "image is not a valid PNG image\n"); - return; - } - - png_structp png = png_create_read_struct(PNG_LIBPNG_VER_STRING, nullptr, errorHandler, warningHandler); - assert(png); - - png_infop info = png_create_info_struct(png); - assert(info); - - int depth, color, interlace; - - try { - png_set_read_fn(png, (png_voidp)&buffer, readCallback); - png_read_info(png, info); - png_get_IHDR(png, info, (png_uint_32*)&width, (png_uint_32*)&height, &depth, &color, &interlace, nullptr, nullptr); - bool alpha = (color & PNG_COLOR_MASK_ALPHA) || png_get_valid(png, info, PNG_INFO_tRNS); - - // From http://trac.mapnik.org/browser/trunk/src/png_reader.cpp - if (color == PNG_COLOR_TYPE_PALETTE) - png_set_expand(png); - if (color == PNG_COLOR_TYPE_GRAY) - png_set_expand(png); - if (png_get_valid(png, info, PNG_INFO_tRNS)) - png_set_expand(png); - if (depth == 16) - png_set_strip_16(png); - if (depth < 8) - png_set_packing(png); - if (color == PNG_COLOR_TYPE_GRAY || - color == PNG_COLOR_TYPE_GRAY_ALPHA) - png_set_gray_to_rgb(png); - - if (interlace == PNG_INTERLACE_ADAM7) - png_set_interlace_handling(png); - - // Always add an alpha channel. - if (!alpha) { - png_set_add_alpha(png, 0xFF, PNG_FILLER_AFTER); - } - - double gamma; - if (png_get_gAMA(png, info, &gamma)) - png_set_gamma(png, 2.2, gamma); - - png_read_update_info(png, info); - - png_size_t rowbytes = png_get_rowbytes(png, info); - assert(width * 4 == rowbytes); - - img = ::std::unique_ptr(new char[width * height * 4]()); - - char *surface = img.get(); - assert(surface); - - struct ptrs { - ptrs(size_t count) : rows(new png_bytep[count]) {} - ~ptrs() { delete[] rows; } - png_bytep *rows = nullptr; - } pointers(height); - for (unsigned i = 0; i < height; ++i) { - pointers.rows[flip ? height - 1 - i : i] = (png_bytep)(surface + (i * rowbytes)); - } - - // Read image data - png_read_image(png, pointers.rows); - - png_read_end(png, nullptr); - - png_destroy_read_struct(&png, &info, nullptr); - } catch (std::exception& e) { - fprintf(stderr, "loading PNG failed: %s\n", e.what()); - png_destroy_read_struct(&png, &info, nullptr); - if (img) { - img.reset(); - } - width = 0; - height = 0; - } -} - -} -} diff --git a/test/headless.cpp b/test/headless.cpp index e1bdbdc061..3837beb9a0 100644 --- a/test/headless.cpp +++ b/test/headless.cpp @@ -92,13 +92,25 @@ TEST_P(HeadlessTest, render) { map.setLonLatZoom(longitude, latitude, zoom); map.setBearing(bearing); + // Run the loop. It will terminate when we don't have any further listeners. map.run(); const unsigned int w = width * pixelRatio; const unsigned int h = height * pixelRatio; - const std::string image = util::compress_png(w, h, view.readPixels().get(), true); + auto pixels = view.readPixels(); + + const int stride = w * 4; + auto tmp = std::unique_ptr(new char[stride]()); + char *rgba = reinterpret_cast(pixels.get()); + for (int i = 0, j = height - 2; i < j; i++, j--) { + memcpy(tmp.get(), rgba + i * stride, stride); + memcpy(rgba + i * stride, rgba + j * stride, stride); + memcpy(rgba + j * stride, tmp.get(), stride); + } + + const std::string image = util::compress_png(w, h, pixels.get()); util::write_file(actual_image, image); } } -- cgit v1.2.1 From 242993b43a27e6f013e622bb4f268c4fdf436ac7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Konstantin=20Ka=CC=88fer?= Date: Thu, 30 Oct 2014 15:06:10 -0400 Subject: fix gyp project --- configure | 7 ------- gyp/install.gypi | 2 -- ios/mapbox-gl-cocoa | 2 +- linux/mapboxgl-app.gyp | 25 ++++++++++++++++++------- macosx/mapboxgl-app.gyp | 3 +-- 5 files changed, 20 insertions(+), 19 deletions(-) diff --git a/configure b/configure index daf09eaeee..2bcfbdf62e 100755 --- a/configure +++ b/configure @@ -45,13 +45,6 @@ case ${MASON_PLATFORM} in ZLIB_VERSION=system BOOST_VERSION=system ;; - 'osx') - GLFW_VERSION=a21f2377 - SQLITE_VERSION=system - LIBUV_VERSION=0.10.28 - ZLIB_VERSION=system - BOOST_VERSION=system - ;; *) GLFW_VERSION=a21f2377 SQLITE_VERSION=system diff --git a/gyp/install.gypi b/gyp/install.gypi index fc0411587b..df65d0457e 100644 --- a/gyp/install.gypi +++ b/gyp/install.gypi @@ -22,8 +22,6 @@ 'conditions': [ ['OS == "linux"', { 'other_ldflags': [ - '-L<(boost_root)/lib', - '-lboost_regex', '<@(glfw3_static_libs)', '<@(glfw3_ldflags)', ] diff --git a/ios/mapbox-gl-cocoa b/ios/mapbox-gl-cocoa index f395112c34..f853a95405 160000 --- a/ios/mapbox-gl-cocoa +++ b/ios/mapbox-gl-cocoa @@ -1 +1 @@ -Subproject commit f395112c34ecc754812d4325102ee273fa8ced01 +Subproject commit f853a95405ab477853fd57c6aecd10bb21399f2e diff --git a/linux/mapboxgl-app.gyp b/linux/mapboxgl-app.gyp index 913a1fac45..03a0c0aed7 100644 --- a/linux/mapboxgl-app.gyp +++ b/linux/mapboxgl-app.gyp @@ -22,13 +22,24 @@ '<@(glfw3_cflags)', '-I<(boost_root)/include', ], - 'libraries': [ - '<@(png_ldflags)', - '<@(sqlite3_ldflags)', - '<@(glfw3_static_libs)', - '<@(glfw3_ldflags)', - '<@(curl_ldflags)', - '<@(zlib_ldflags)', + 'variables': { + 'ldflags': [ + '<@(png_ldflags)', + '<@(sqlite3_ldflags)', + '<@(glfw3_static_libs)', + '<@(glfw3_ldflags)', + '<@(curl_ldflags)', + '<@(zlib_ldflags)', + ], + }, + 'conditions': [ + ['OS == "mac"', { + 'xcode_settings': { + 'OTHER_LDFLAGS': [ '<@(ldflags)' ], + } + }, { + 'ldflags': [ '<@(ldflags)' ], + }] ], 'dependencies': [ '../mapboxgl.gyp:mbgl-standalone', diff --git a/macosx/mapboxgl-app.gyp b/macosx/mapboxgl-app.gyp index 0e6fe38042..e948d054c2 100644 --- a/macosx/mapboxgl-app.gyp +++ b/macosx/mapboxgl-app.gyp @@ -40,8 +40,7 @@ '<@(sqlite3_ldflags)', '<@(glfw3_static_libs)', '<@(glfw3_ldflags)', - '<@(curl_ldflags)', - '<@(png_ldflags)' + '<@(zlib_ldflags)', ] }, 'conditions': [ -- cgit v1.2.1 From b6dea0d8de4ec823513b7f49d2b74fc97a661c28 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Konstantin=20Ka=CC=88fer?= Date: Thu, 30 Oct 2014 15:06:18 -0400 Subject: also allow underscores in token names --- include/mbgl/util/token.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/mbgl/util/token.hpp b/include/mbgl/util/token.hpp index 0f045f434a..64192a99f9 100644 --- a/include/mbgl/util/token.hpp +++ b/include/mbgl/util/token.hpp @@ -22,7 +22,7 @@ std::string replaceTokens(const std::string &source, const Lookup &lookup) { result.append(pos, brace); pos = brace; if (pos != end) { - for (brace++; brace != end && std::isalnum(*brace); brace++); + for (brace++; brace != end && (std::isalnum(*brace) || *brace == '_'); brace++); if (brace != end && *brace == '}') { result.append(lookup({ pos + 1, brace })); pos = brace + 1; -- cgit v1.2.1 From 3d6a87ab1b43e4f4712e5456ccf91bdcbc15bb7e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Konstantin=20Ka=CC=88fer?= Date: Thu, 30 Oct 2014 15:10:24 -0400 Subject: bump cocoa --- ios/mapbox-gl-cocoa | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ios/mapbox-gl-cocoa b/ios/mapbox-gl-cocoa index f853a95405..5c4d7231a4 160000 --- a/ios/mapbox-gl-cocoa +++ b/ios/mapbox-gl-cocoa @@ -1 +1 @@ -Subproject commit f853a95405ab477853fd57c6aecd10bb21399f2e +Subproject commit 5c4d7231a47757fdcbe7ba387525cc07cb47c54f -- cgit v1.2.1 From 592ed57d09f8f0913dae195e6e867884d11a2327 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Konstantin=20Ka=CC=88fer?= Date: Thu, 30 Oct 2014 12:40:16 -0700 Subject: use more modern libpng version instead of the system-provided one and fix compile errors --- configure | 2 +- deps/gtest/gtest.gyp | 4 ++++ gyp/mbgl-linux.gypi | 6 +++++- linux/mapboxgl-app.gyp | 2 +- platform/default/image.cpp | 3 ++- test/test.gyp | 2 +- 6 files changed, 14 insertions(+), 5 deletions(-) diff --git a/configure b/configure index 2bcfbdf62e..cc96f038b0 100755 --- a/configure +++ b/configure @@ -48,7 +48,7 @@ case ${MASON_PLATFORM} in *) GLFW_VERSION=a21f2377 SQLITE_VERSION=system - LIBPNG_VERSION=system + LIBPNG_VERSION=1.6.13 LIBCURL_VERSION=system LIBUV_VERSION=0.10.28 ZLIB_VERSION=system diff --git a/deps/gtest/gtest.gyp b/deps/gtest/gtest.gyp index c62b6be3f8..56d01bf988 100644 --- a/deps/gtest/gtest.gyp +++ b/deps/gtest/gtest.gyp @@ -12,6 +12,10 @@ 'sources': [ 'gtest-all.cc' ], + 'link_settings': { + 'xcode_settings': { 'OTHER_LDFLAGS': [ '-pthread' ] }, + 'ldflags': [ '-pthread' ], + }, 'direct_dependent_settings': { 'include_dirs': [ '.', diff --git a/gyp/mbgl-linux.gypi b/gyp/mbgl-linux.gypi index 2b166ea434..ca3e2afc54 100644 --- a/gyp/mbgl-linux.gypi +++ b/gyp/mbgl-linux.gypi @@ -30,6 +30,11 @@ 'include_dirs': [ '../include', ], + 'link_settings': { + 'libraries': [ + '<@(png_static_libs)', + ], + }, 'conditions': [ ['OS == "mac"', { 'xcode_settings': { @@ -37,7 +42,6 @@ 'OTHER_CFLAGS': [ '<@(cflags)' ], } }, { - 'ldflags': [ '<@(ldflags)' ], 'cflags_cc': [ '<@(cflags_cc)' ], 'cflags': [ '<@(cflags)' ], }] diff --git a/linux/mapboxgl-app.gyp b/linux/mapboxgl-app.gyp index 03a0c0aed7..57bd1171b2 100644 --- a/linux/mapboxgl-app.gyp +++ b/linux/mapboxgl-app.gyp @@ -38,7 +38,7 @@ 'OTHER_LDFLAGS': [ '<@(ldflags)' ], } }, { - 'ldflags': [ '<@(ldflags)' ], + 'libraries': [ '<@(ldflags)' ], }] ], 'dependencies': [ diff --git a/platform/default/image.cpp b/platform/default/image.cpp index 5b1afec7aa..68d1786913 100644 --- a/platform/default/image.cpp +++ b/platform/default/image.cpp @@ -5,6 +5,7 @@ #include #include #include +#include namespace mbgl { @@ -73,7 +74,7 @@ void readCallback(png_structp png, png_bytep data, png_size_t length) { if (reader->pos + length > reader->length) { png_error(png, "Read Error"); } else { - memcpy(data, reader->data + reader->pos, length); + std::memcpy(data, reader->data + reader->pos, length); reader->pos += length; } } diff --git a/test/test.gyp b/test/test.gyp index 74f4139a96..9e56f4f2c0 100644 --- a/test/test.gyp +++ b/test/test.gyp @@ -8,7 +8,7 @@ '<@(uv_ldflags)', '<@(sqlite3_ldflags)', '<@(curl_ldflags)', - '<@(png_ldflags)' + '<@(png_ldflags)', ], }, 'targets': [ -- cgit v1.2.1 From 2ebe167add05047f4cb611503064549c0b217d18 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Konstantin=20Ka=CC=88fer?= Date: Thu, 30 Oct 2014 15:56:08 -0400 Subject: use -lpthread instead of -pthread --- deps/gtest/gtest.gyp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/deps/gtest/gtest.gyp b/deps/gtest/gtest.gyp index 56d01bf988..3728dfc914 100644 --- a/deps/gtest/gtest.gyp +++ b/deps/gtest/gtest.gyp @@ -13,8 +13,8 @@ 'gtest-all.cc' ], 'link_settings': { - 'xcode_settings': { 'OTHER_LDFLAGS': [ '-pthread' ] }, - 'ldflags': [ '-pthread' ], + 'xcode_settings': { 'OTHER_LDFLAGS': [ '-lpthread' ] }, + 'ldflags': [ '-lpthread' ], }, 'direct_dependent_settings': { 'include_dirs': [ -- cgit v1.2.1 From 8dda6482fa429e01da087a690ca7d9cde3a7abc0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Konstantin=20Ka=CC=88fer?= Date: Thu, 30 Oct 2014 15:56:17 -0400 Subject: fix image y reversal --- test/headless.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/headless.cpp b/test/headless.cpp index 3837beb9a0..0f4e100271 100644 --- a/test/headless.cpp +++ b/test/headless.cpp @@ -104,7 +104,7 @@ TEST_P(HeadlessTest, render) { const int stride = w * 4; auto tmp = std::unique_ptr(new char[stride]()); char *rgba = reinterpret_cast(pixels.get()); - for (int i = 0, j = height - 2; i < j; i++, j--) { + for (int i = 0, j = height - 1; i < j; i++, j--) { memcpy(tmp.get(), rgba + i * stride, stride); memcpy(rgba + i * stride, rgba + j * stride, stride); memcpy(rgba + j * stride, tmp.get(), stride); -- cgit v1.2.1 From d0f71242da3e5a84e3c0ba54d63a889da7a11f2e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Konstantin=20Ka=CC=88fer?= Date: Fri, 31 Oct 2014 16:51:36 -0400 Subject: bump cocoa bindings --- ios/mapbox-gl-cocoa | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ios/mapbox-gl-cocoa b/ios/mapbox-gl-cocoa index 5c4d7231a4..63d166d3dd 160000 --- a/ios/mapbox-gl-cocoa +++ b/ios/mapbox-gl-cocoa @@ -1 +1 @@ -Subproject commit 5c4d7231a47757fdcbe7ba387525cc07cb47c54f +Subproject commit 63d166d3dd33a460a5158159ea9656ea651aa179 -- cgit v1.2.1