diff --git a/android/tangram/src/main/cpp/platform_android.cpp b/android/tangram/src/main/cpp/platform_android.cpp index a58d61ae27..4c0e34fc5e 100644 --- a/android/tangram/src/main/cpp/platform_android.cpp +++ b/android/tangram/src/main/cpp/platform_android.cpp @@ -198,12 +198,14 @@ std::vector systemFontFallbacksHandle() { return handles; } -unsigned char* systemFont(const std::string& _name, const std::string& _weight, const std::string& _face, size_t* _size) { +std::vector systemFont(const std::string& _name, const std::string& _weight, const std::string& _face) { std::string path = fontPath(_name, _weight, _face); - if (path.empty()) { return nullptr; } + if (path.empty()) { return {}; } - return bytesFromFile(path.c_str(), *_size); + auto data = bytesFromFile(path.c_str()); + + return data; } void setContinuousRendering(bool _isContinuous) { @@ -277,15 +279,12 @@ std::string stringFromFile(const char* _path) { return data; } -unsigned char* bytesFromFile(const char* _path, size_t& _size) { - - _size = 0; - unsigned char* data = nullptr; +std::vector bytesFromFile(const char* _path) { + std::vector data; auto allocator = [&](size_t size) { - _size = size; - data = (unsigned char*) malloc(sizeof(char) * size); - return reinterpret_cast(data); + data.resize(size); + return data.data(); }; if (strncmp(_path, aaPrefix, aaPrefixLen) == 0) { @@ -293,6 +292,7 @@ unsigned char* bytesFromFile(const char* _path, size_t& _size) { } else { bytesFromFileSystem(_path, allocator); } + return data; } diff --git a/core/src/data/rasterSource.cpp b/core/src/data/rasterSource.cpp index 67e9c342cf..ff39eb45e9 100644 --- a/core/src/data/rasterSource.cpp +++ b/core/src/data/rasterSource.cpp @@ -74,18 +74,16 @@ RasterSource::RasterSource(const std::string& _name, const std::string& _urlTemp TextureOptions _options, bool _genMipmap) : DataSource(_name, _urlTemplate, _minDisplayZoom, _maxDisplayZoom, _maxZoom), m_texOptions(_options), m_genMipmap(_genMipmap) { - m_emptyTexture = std::make_shared(nullptr, 0, m_texOptions, m_genMipmap); + std::vector data = {}; + m_emptyTexture = std::make_shared(data, m_texOptions, m_genMipmap); } std::shared_ptr RasterSource::createTexture(const std::vector& _rawTileData) { - auto udata = reinterpret_cast(_rawTileData.data()); - size_t dataSize = _rawTileData.size(); - - if (dataSize == 0) { + if (_rawTileData.size() == 0) { return m_emptyTexture; } - auto texture = std::make_shared(udata, dataSize, m_texOptions, m_genMipmap); + auto texture = std::make_shared(_rawTileData, m_texOptions, m_genMipmap); return texture; } diff --git a/core/src/gl/renderState.cpp b/core/src/gl/renderState.cpp index e8aa0db52f..b53bd46848 100644 --- a/core/src/gl/renderState.cpp +++ b/core/src/gl/renderState.cpp @@ -367,7 +367,9 @@ void RenderState::deleteDefaultPointTexture() { void RenderState::generateDefaultPointTexture() { TextureOptions options = { GL_RGBA, GL_RGBA, { GL_LINEAR, GL_LINEAR }, { GL_CLAMP_TO_EDGE, GL_CLAMP_TO_EDGE } }; - m_defaultPointTexture = new Texture(default_point_texture_data, default_point_texture_size, options, true); + std::vector defaultPoint; + defaultPoint.insert(defaultPoint.begin(), default_point_texture_data, default_point_texture_data + default_point_texture_size); + m_defaultPointTexture = new Texture(defaultPoint, options, true); } bool RenderState::framebuffer(GLuint handle) { diff --git a/core/src/gl/texture.cpp b/core/src/gl/texture.cpp index f7bbd56c9d..b9ca39935d 100644 --- a/core/src/gl/texture.cpp +++ b/core/src/gl/texture.cpp @@ -31,10 +31,10 @@ Texture::Texture(unsigned int _width, unsigned int _height, TextureOptions _opti resize(_width, _height); } -Texture::Texture(const unsigned char* data, size_t dataSize, TextureOptions options, bool generateMipmaps) +Texture::Texture(const std::vector& _data, TextureOptions options, bool generateMipmaps) : Texture(0u, 0u, options, generateMipmaps) { - loadImageFromMemory(data, dataSize); + loadImageFromMemory(_data); } Texture::~Texture() { @@ -54,12 +54,12 @@ Texture::~Texture() { }); } -bool Texture::loadImageFromMemory(const unsigned char* blob, unsigned int size) { +bool Texture::loadImageFromMemory(const std::vector& _data) { unsigned char* pixels = nullptr; int width, height, comp; - if (blob != nullptr && size != 0) { - pixels = stbi_load_from_memory(blob, size, &width, &height, &comp, STBI_rgb_alpha); + if (_data.size() != 0) { + pixels = stbi_load_from_memory(reinterpret_cast(_data.data()), _data.size(), &width, &height, &comp, STBI_rgb_alpha); } if (pixels) { diff --git a/core/src/gl/texture.h b/core/src/gl/texture.h index 1db2d97ff3..4360529fc0 100644 --- a/core/src/gl/texture.h +++ b/core/src/gl/texture.h @@ -41,7 +41,7 @@ class Texture { TextureOptions _options = DEFAULT_TEXTURE_OPTION, bool _generateMipmaps = false); - Texture(const unsigned char* data, size_t dataSize, + Texture(const std::vector& _data, TextureOptions _options = DEFAULT_TEXTURE_OPTION, bool _generateMipmaps = false); @@ -87,7 +87,7 @@ class Texture { static bool isRepeatWrapping(TextureWrapping _wrapping); - bool loadImageFromMemory(const unsigned char* blob, unsigned int size); + bool loadImageFromMemory(const std::vector& _data); static void flipImageData(unsigned char *result, int w, int h, int depth); static void flipImageData(GLuint *result, int w, int h); diff --git a/core/src/gl/textureCube.cpp b/core/src/gl/textureCube.cpp index 06ca397d6a..b785dbbff4 100644 --- a/core/src/gl/textureCube.cpp +++ b/core/src/gl/textureCube.cpp @@ -11,27 +11,23 @@ namespace Tangram { TextureCube::TextureCube(std::string _file, TextureOptions _options) - : Texture(0u, 0u, _options) { + : Texture(0, 0, _options) { m_target = GL_TEXTURE_CUBE_MAP; load(_file); } void TextureCube::load(const std::string& _file) { - size_t size; - unsigned char* data = bytesFromFile(_file.c_str(), size); + auto data = bytesFromFile(_file.c_str()); unsigned char* pixels; int width, height, comp; - if (data == nullptr || size == 0) { + if (data.size() == 0) { LOGE("Texture not found! '%s'", _file.c_str()); - free(data); return; } - pixels = stbi_load_from_memory(data, size, &width, &height, &comp, STBI_rgb_alpha); - - size = width * height; + pixels = stbi_load_from_memory(reinterpret_cast(data.data()), data.size(), &width, &height, &comp, STBI_rgb_alpha); m_width = width / 4; m_height = height / 3; @@ -63,7 +59,6 @@ void TextureCube::load(const std::string& _file) { } } - free(data); stbi_image_free(pixels); } diff --git a/core/src/labels/label.h b/core/src/labels/label.h index 372afb0ce7..987bc97151 100644 --- a/core/src/labels/label.h +++ b/core/src/labels/label.h @@ -196,8 +196,6 @@ class Label { int m_anchorIndex; - uint32_t m_selectionColor; - protected: bool m_occludedLastFrame; diff --git a/core/src/platform.h b/core/src/platform.h index 904c975c43..06e464106d 100644 --- a/core/src/platform.h +++ b/core/src/platform.h @@ -41,7 +41,7 @@ std::string stringFromFile(const char* _path); * containing the contents of the file. The size of the memory in bytes is written to _size. * If the file cannot be read, nothing is allocated and nullptr is returned. */ -unsigned char* bytesFromFile(const char* _path, size_t& _size); +std::vector bytesFromFile(const char* _path); /* Function type for receiving data from a successful network request */ using UrlCallback = std::function&&)>; diff --git a/core/src/scene/sceneLoader.cpp b/core/src/scene/sceneLoader.cpp index 21f5bec99f..e14f8b6095 100644 --- a/core/src/scene/sceneLoader.cpp +++ b/core/src/scene/sceneLoader.cpp @@ -552,12 +552,10 @@ std::shared_ptr SceneLoader::fetchTexture(const std::string& name, cons if (std::regex_search(url, match, r)) { scene->pendingTextures++; startUrlRequest(url, [=](std::vector&& rawData) { - auto ptr = (unsigned char*)(rawData.data()); - size_t dataSize = rawData.size(); std::lock_guard lock(m_textureMutex); auto texture = scene->getTexture(name); if (texture) { - if (!texture->loadImageFromMemory(ptr, dataSize)) { + if (!texture->loadImageFromMemory(rawData)) { LOGE("Invalid texture data '%s'", url.c_str()); } @@ -568,7 +566,8 @@ std::shared_ptr SceneLoader::fetchTexture(const std::string& name, cons } } }); - texture = std::make_shared(nullptr, 0, options, generateMipmaps); + std::vector textureData = {}; + texture = std::make_shared(textureData, options, generateMipmaps); } else { if (url.substr(0, 22) == "data:image/png;base64,") { @@ -589,24 +588,25 @@ std::shared_ptr SceneLoader::fetchTexture(const std::string& name, cons } texture = std::make_shared(0, 0, options, generateMipmaps); - if (!texture->loadImageFromMemory(blob.data(), blob.size())) { + std::vector textureData; + auto cdata = reinterpret_cast(blob.data()); + textureData.insert(textureData.begin(), cdata, cdata + blob.size()); + if (!texture->loadImageFromMemory(textureData)) { LOGE("Invalid Base64 texture"); } } else { - size_t size = 0; - unsigned char* blob = bytesFromFile(url.c_str(), size); + auto data = bytesFromFile(url.c_str()); - if (!blob) { + if (data.size() == 0) { LOGE("Can't load texture resource at url '%s'", url.c_str()); return nullptr; } - texture = std::make_shared(0, 0, options, generateMipmaps); - if (!texture->loadImageFromMemory(blob, size)) { + texture = std::make_shared(0, 0, options, generateMipmaps); + if (!texture->loadImageFromMemory(data)) { LOGE("Invalid texture data '%s'", url.c_str()); } - free(blob); } } @@ -725,15 +725,13 @@ void loadFontDescription(const Node& node, const std::string& family, const std: scene->pendingFonts--; }); } else { - // Load from local storage - size_t dataSize = 0; - - if (unsigned char* data = bytesFromFile(_ft.uri.c_str(), dataSize)) { + auto data = bytesFromFile(_ft.uri.c_str()); - LOGN("Add local font %s (%s)", _ft.uri.c_str(), _ft.bundleAlias.c_str()); - scene->fontContext()->addFont(_ft, alfons::InputSource(reinterpret_cast(data), dataSize)); - } else { + if (data.size() == 0) { LOGW("Local font at path %s can't be found (%s)", _ft.uri.c_str(), _ft.bundleAlias.c_str()); + } else { + LOGN("Adding local font %s (%s)", _ft.uri.c_str(), _ft.bundleAlias.c_str()); + scene->fontContext()->addFont(_ft, alfons::InputSource(data)); } } } diff --git a/core/src/text/fontContext.cpp b/core/src/text/fontContext.cpp index 7cb7ca9ce2..5a99a737eb 100644 --- a/core/src/text/fontContext.cpp +++ b/core/src/text/fontContext.cpp @@ -284,38 +284,28 @@ std::shared_ptr FontContext::getFont(const std::string& _family, c auto font = m_alfons.getFont(FontDescription::Alias(_family, _style, _weight), fontSize); if (font->hasFaces()) { return font; } - unsigned char* data = nullptr; - size_t dataSize = 0; - // 1. Bundle // Assuming bundled ttf file follows this convention std::string bundleFontPath = m_sceneResourceRoot + "fonts/" + FontDescription::BundleAlias(_family, _style, _weight); - data = bytesFromFile(bundleFontPath.c_str(), dataSize); - std::vector systemFontData; + std::vector fontData = bytesFromFile(bundleFontPath.c_str()); // 2. System font - if (!data) { - systemFontData = systemFont(_family, _weight, _style); - } else { - systemFontData.insert(systemFontData.begin(), reinterpret_cast(data), - reinterpret_cast(data + dataSize)); - free(data); + if (fontData.size() == 0) { + fontData = systemFont(_family, _weight, _style); } - if (systemFontData.size() > 0) { - font->addFace(m_alfons.addFontFace(alfons::InputSource(systemFontData), fontSize)); + if (fontData.size() == 0) { + LOGN("Could not load font file %s", FontDescription::BundleAlias(_family, _style, _weight).c_str()); - // add fallbacks from default font + // 3. Add fallbacks from default font if (m_font[sizeIndex]) { font->addFaces(*m_font[sizeIndex]); } - } else { - LOGN("Could not load font file %s", FontDescription::BundleAlias(_family, _style, _weight).c_str()); + font->addFace(m_alfons.addFontFace(alfons::InputSource(fontData), fontSize)); - // add fallbacks from default font if (m_font[sizeIndex]) { font->addFaces(*m_font[sizeIndex]); } diff --git a/ios/src/platform_ios.mm b/ios/src/platform_ios.mm index 1843e19e71..9dcf63020a 100644 --- a/ios/src/platform_ios.mm +++ b/ios/src/platform_ios.mm @@ -82,45 +82,65 @@ bool isContinuousRendering() { } } + LOGW("Failed to resolve path: %s", _path); + return nil; } -std::string stringFromFile(const char* _path) { +bool bytesFromFileSystem(const char* _path, std::function _allocator) { + std::ifstream resource(_path, std::ifstream::ate | std::ifstream::binary); + + if(!resource.is_open()) { + logMsg("Failed to read file at path: %s\n", _path); + return false; + } + + size_t size = resource.tellg(); + char* cdata = _allocator(size); + resource.seekg(std::ifstream::beg); + resource.read(cdata, size); + resource.close(); + + return true; +} + +std::string stringFromFile(const char* _path) { NSString* path = resolvePath(_path); if (!path) { return ""; } - NSString* str = [NSString stringWithContentsOfFile:path - usedEncoding:NULL - error:NULL]; + std::string data; - if (str == nil) { - LOGW("Failed to read file at path: %s\n", [path UTF8String]); - return std::string(); - } + auto allocator = [&](size_t size) { + data.resize(size); + return &data[0]; + }; - return std::string([str UTF8String]); -} + bytesFromFileSystem([path UTF8String], allocator); -unsigned char* bytesFromFile(const char* _path, size_t& _size) { + return data; +} +std::vector bytesFromFile(const char* _path) { NSString* path = resolvePath(_path); - NSMutableData* data = [NSMutableData dataWithContentsOfFile:path]; - if (data == nil) { - LOGW("Failed to read file at path: %s\n", [path UTF8String]); - _size = 0; - return nullptr; + if (path) { + return {}; } - _size = data.length; - unsigned char* ptr = (unsigned char*)malloc(_size); - [data getBytes:ptr length:_size]; + std::vector data; + + auto allocator = [&](size_t size) { + data.resize(size); + return data.data(); + }; - return ptr; + bytesFromFileSystem([path UTF8String], allocator); + + return data; } std::vector loadUIFont(UIFont* _font) { diff --git a/osx/src/platform_osx.mm b/osx/src/platform_osx.mm index cde8719a70..9813bf2174 100644 --- a/osx/src/platform_osx.mm +++ b/osx/src/platform_osx.mm @@ -64,40 +64,73 @@ bool isContinuousRendering() { NSURL* resolvedUrl = [NSURL URLWithString:pathString relativeToURL:resourceFolderUrl]; - return [resolvedUrl path]; + NSFileManager* fileManager = [NSFileManager defaultManager]; + + NSString* pathInAppBundle = [resolvedUrl path]; + + if ([fileManager fileExistsAtPath:pathInAppBundle]) { + return pathInAppBundle; + } + + LOGW("Failed to resolve path: %s", _path); + + return nil; } -std::string stringFromFile(const char* _path) { +bool bytesFromFileSystem(const char* _path, std::function _allocator) { + std::ifstream resource(_path, std::ifstream::ate | std::ifstream::binary); + + if(!resource.is_open()) { + logMsg("Failed to read file at path: %s\n", _path); + return false; + } + + size_t size = resource.tellg(); + char* cdata = _allocator(size); + + resource.seekg(std::ifstream::beg); + resource.read(cdata, size); + resource.close(); + + return true; +} +std::string stringFromFile(const char* _path) { NSString* path = resolvePath(_path); - NSString* str = [NSString stringWithContentsOfFile:path - usedEncoding:NULL - error:NULL]; - if (str == nil) { - LOGW("Failed to read file at path: %s", [path UTF8String]); - return std::string(); + if (!path) { + return ""; } - return std::string([str UTF8String]); -} + std::string data; + + auto allocator = [&](size_t size) { + data.resize(size); + return &data[0]; + }; -unsigned char* bytesFromFile(const char* _path, size_t& _size) { + bytesFromFileSystem([path UTF8String], allocator); + return data; +} + +std::vector bytesFromFile(const char* _path) { NSString* path = resolvePath(_path); - NSMutableData* data = [NSMutableData dataWithContentsOfFile:path]; - if (data == nil) { - LOGW("Failed to read file at path: %s", [path UTF8String]); - _size = 0; - return nullptr; + if (path) { + return {}; } - _size = data.length; - unsigned char* ptr = (unsigned char*)malloc(_size); - [data getBytes:ptr length:_size]; + std::vector data; + + auto allocator = [&](size_t size) { + data.resize(size); + return data.data(); + }; + + bytesFromFileSystem([path UTF8String], allocator); - return ptr; + return data; } std::vector systemFontFallbacksHandle() {