From 6d49a90b48c8ad4bcf21a51244069239194bfe77 Mon Sep 17 00:00:00 2001 From: Karim Naaji Date: Wed, 21 Dec 2016 18:12:11 -0500 Subject: [PATCH 1/5] Reduce memory copies for font data --- core/src/platform.h | 2 +- core/src/text/fontContext.cpp | 12 ++++++++---- ios/src/TGFontConverter.h | 4 +++- ios/src/TGFontConverter.mm | 19 +++++++++---------- ios/src/platform_ios.mm | 30 +++++++++++------------------- osx/src/platform_osx.mm | 4 ++-- 6 files changed, 34 insertions(+), 37 deletions(-) diff --git a/core/src/platform.h b/core/src/platform.h index 4754f8ca9c..904c975c43 100644 --- a/core/src/platform.h +++ b/core/src/platform.h @@ -63,7 +63,7 @@ void cancelUrlRequest(const std::string& _url); */ void setCurrentThreadPriority(int priority); -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); struct FontSourceHandle { FontSourceHandle(std::string _path) : path(_path) {} diff --git a/core/src/text/fontContext.cpp b/core/src/text/fontContext.cpp index d8608cba42..7cb7ca9ce2 100644 --- a/core/src/text/fontContext.cpp +++ b/core/src/text/fontContext.cpp @@ -293,15 +293,19 @@ std::shared_ptr FontContext::getFont(const std::string& _family, c FontDescription::BundleAlias(_family, _style, _weight); data = bytesFromFile(bundleFontPath.c_str(), dataSize); + std::vector systemFontData; // 2. System font if (!data) { - data = systemFont(_family, _weight, _style, &dataSize); + systemFontData = systemFont(_family, _weight, _style); + } else { + systemFontData.insert(systemFontData.begin(), reinterpret_cast(data), + reinterpret_cast(data + dataSize)); + free(data); } - if (data) { - font->addFace(m_alfons.addFontFace(alfons::InputSource(reinterpret_cast(data), dataSize), fontSize)); - free(data); + if (systemFontData.size() > 0) { + font->addFace(m_alfons.addFontFace(alfons::InputSource(systemFontData), fontSize)); // add fallbacks from default font if (m_font[sizeIndex]) { diff --git a/ios/src/TGFontConverter.h b/ios/src/TGFontConverter.h index a431c52af2..28a87311d0 100644 --- a/ios/src/TGFontConverter.h +++ b/ios/src/TGFontConverter.h @@ -9,9 +9,11 @@ #import #import +#import + @interface TGFontConverter : NSObject -+ (unsigned char *)fontDataForCGFont:(CGFontRef)cgFont size:(size_t *)size; ++ (std::vector)fontDataForCGFont:(CGFontRef)cgFont; @end diff --git a/ios/src/TGFontConverter.mm b/ios/src/TGFontConverter.mm index bc0efec45e..6e342aadea 100644 --- a/ios/src/TGFontConverter.mm +++ b/ios/src/TGFontConverter.mm @@ -8,7 +8,7 @@ #import "TGFontConverter.h" -#include +#import struct FontHeader { int32_t version; @@ -52,10 +52,10 @@ @implementation TGFontConverter // https://skia.googlesource.com/skia/+/master/src/ports/SkFontHost_mac.cpp // https://gist.github.com/Jyczeal/1892760 -+ (unsigned char *)fontDataForCGFont:(CGFontRef)cgFont size:(size_t *)size ++ (std::vector)fontDataForCGFont:(CGFontRef)cgFont { if (!cgFont) { - return nil; + return {}; } CFRetain(cgFont); @@ -63,8 +63,8 @@ + (unsigned char *)fontDataForCGFont:(CGFontRef)cgFont size:(size_t *)size CFArrayRef tags = CGFontCopyTableTags(cgFont); int tableCount = CFArrayGetCount(tags); - size_t* tableSizes = (size_t*)malloc(sizeof(size_t) * tableCount); - memset(tableSizes, 0, sizeof(size_t) * tableCount); + std::vector tableSizes; + tableSizes.resize(tableCount); BOOL containsCFFTable = NO; @@ -88,9 +88,10 @@ + (unsigned char *)fontDataForCGFont:(CGFontRef)cgFont size:(size_t *)size tableSizes[index] = tableSize; } - unsigned char* stream = (unsigned char*)malloc(totalSize); + std::vector data; + data.resize(totalSize); + unsigned char* stream = reinterpret_cast(data.data()); - memset(stream, 0, totalSize); char* dataStart = (char*)stream; char* dataPtr = dataStart; @@ -150,10 +151,8 @@ + (unsigned char *)fontDataForCGFont:(CGFontRef)cgFont size:(size_t *)size } CFRelease(cgFont); - free(tableSizes); - *size = totalSize; - return stream; + return data; } @end diff --git a/ios/src/platform_ios.mm b/ios/src/platform_ios.mm index 3ea76bd008..1843e19e71 100644 --- a/ios/src/platform_ios.mm +++ b/ios/src/platform_ios.mm @@ -123,24 +123,24 @@ bool isContinuousRendering() { return ptr; } -unsigned char* loadUIFont(UIFont* _font, size_t* _size) { +std::vector loadUIFont(UIFont* _font) { + + if (!_font) { + return {}; + } CGFontRef fontRef = CGFontCreateWithFontName((CFStringRef)_font.fontName); if (!fontRef) { - *_size = 0; - return nullptr; + return {}; } - unsigned char* data = [TGFontConverter fontDataForCGFont:fontRef size:_size]; + std::vector data = [TGFontConverter fontDataForCGFont:fontRef]; CGFontRelease(fontRef); - if (!data) { + if (data.empty()) { LOG("CoreGraphics font failed to decode"); - - *_size = 0; - return nullptr; } return data; @@ -154,15 +154,7 @@ bool isContinuousRendering() { for (id fallback in fallbacks) { handles.emplace_back([fallback]() { - - std::vector data; - - UIFont* font = [UIFont fontWithName:fallback size:1.0]; - size_t dataSize = 0; - auto cdata = loadUIFont(font, &dataSize); - if (cdata) { - data.insert(data.begin(), cdata, cdata + dataSize); - } + auto data = loadUIFont([UIFont fontWithName:fallback size:1.0]); return data; }); } @@ -170,7 +162,7 @@ bool isContinuousRendering() { 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) { static std::map weightTraits = { {100, UIFontWeightUltraLight}, @@ -229,7 +221,7 @@ bool isContinuousRendering() { } } - return loadUIFont(font, _size); + return loadUIFont(font); } bool startUrlRequest(const std::string& _url, UrlCallback _callback) { diff --git a/osx/src/platform_osx.mm b/osx/src/platform_osx.mm index f6d3257ee6..cde8719a70 100644 --- a/osx/src/platform_osx.mm +++ b/osx/src/platform_osx.mm @@ -112,8 +112,8 @@ bool isContinuousRendering() { return handles; } -unsigned char* systemFont(const std::string& _name, const std::string& _weight, const std::string& _face, size_t* _size) { - return nullptr; +std::vector systemFont(const std::string& _name, const std::string& _weight, const std::string& _face) { + return {}; } void NSurlInit() { From 3be00cc357215f3ac0313e167acd15637641a2f3 Mon Sep 17 00:00:00 2001 From: Karim Naaji Date: Wed, 21 Dec 2016 18:25:52 -0500 Subject: [PATCH 2/5] Don't copy TTF tables twice --- ios/src/TGFontConverter.mm | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/ios/src/TGFontConverter.mm b/ios/src/TGFontConverter.mm index 6e342aadea..3cd1fc4cd0 100644 --- a/ios/src/TGFontConverter.mm +++ b/ios/src/TGFontConverter.mm @@ -65,6 +65,8 @@ @implementation TGFontConverter std::vector tableSizes; tableSizes.resize(tableCount); + std::vector dataRefs; + dataRefs.resize(tableCount); BOOL containsCFFTable = NO; @@ -78,11 +80,12 @@ @implementation TGFontConverter containsCFFTable = YES; } - CFDataRef tableDataRef = CGFontCopyTableForTag(cgFont, aTag); - if (tableDataRef != NULL) { - tableSize = CFDataGetLength(tableDataRef); - CFRelease(tableDataRef); + dataRefs[index] = CGFontCopyTableForTag(cgFont, aTag); + + if (dataRefs[index] != NULL) { + tableSize = CFDataGetLength(dataRefs[index]); } + totalSize += (tableSize + 3) & ~3; tableSizes[index] = tableSize; @@ -134,7 +137,10 @@ @implementation TGFontConverter for (int index = 0; index < tableCount; ++index) { intptr_t aTag = (intptr_t)CFArrayGetValueAtIndex(tags, index); - CFDataRef tableDataRef = CGFontCopyTableForTag(cgFont, aTag); + CFDataRef tableDataRef = dataRefs[index]; + + if (tableDataRef == NULL) { continue; } + size_t tableSize = CFDataGetLength(tableDataRef); memcpy(dataPtr, CFDataGetBytePtr(tableDataRef), tableSize); From 5429a2963624ee074cd9aa0054893b2f36f34e24 Mon Sep 17 00:00:00 2001 From: Karim Naaji Date: Thu, 5 Jan 2017 17:02:40 -0500 Subject: [PATCH 3/5] Refactor bytesFromFile to return a vector --- .../tangram/src/main/cpp/platform_android.cpp | 20 ++--- core/src/data/rasterSource.cpp | 10 +-- core/src/gl/renderState.cpp | 4 +- core/src/gl/texture.cpp | 10 +-- core/src/gl/texture.h | 4 +- core/src/gl/textureCube.cpp | 13 +--- core/src/platform.h | 2 +- core/src/scene/sceneLoader.cpp | 34 ++++----- core/src/text/fontContext.cpp | 24 ++---- ios/src/platform_ios.mm | 60 ++++++++++----- osx/src/platform_osx.mm | 73 ++++++++++++++----- 11 files changed, 145 insertions(+), 109 deletions(-) diff --git a/android/tangram/src/main/cpp/platform_android.cpp b/android/tangram/src/main/cpp/platform_android.cpp index 313acf3f4b..d4a0f39694 100644 --- a/android/tangram/src/main/cpp/platform_android.cpp +++ b/android/tangram/src/main/cpp/platform_android.cpp @@ -214,12 +214,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) { @@ -293,15 +295,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) { @@ -309,6 +308,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/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() { From a16a2fce17d3f37864312bcded213af12c3959b3 Mon Sep 17 00:00:00 2001 From: Karim Naaji Date: Fri, 6 Jan 2017 10:40:19 -0500 Subject: [PATCH 4/5] Update linux platforms with new interface --- linux/src/platform_linux.cpp | 22 +++++++++++----------- rpi/src/platform_rpi.cpp | 22 +++++++++++----------- tests/src/platform_mock.cpp | 25 +++++++++++++------------ tests/unit/lineWrapTests.cpp | 6 ++---- tizen/src/platform_tizen.cpp | 26 ++++++++++++-------------- 5 files changed, 49 insertions(+), 52 deletions(-) diff --git a/linux/src/platform_linux.cpp b/linux/src/platform_linux.cpp index a6b95e2eae..a78e4db77e 100644 --- a/linux/src/platform_linux.cpp +++ b/linux/src/platform_linux.cpp @@ -94,26 +94,26 @@ std::string stringFromFile(const char* _path) { return out; } -unsigned char* bytesFromFile(const char* _path, size_t& _size) { +std::vector bytesFromFile(const char* _path) { + if (!_path || strlen(_path) == 0) { return {}; } std::ifstream resource(_path, std::ifstream::ate | std::ifstream::binary); if(!resource.is_open()) { - logMsg("Failed to read file at path: %s\n", _path); - _size = 0; - return nullptr; + LOG("Failed to read file at path: %s", _path); + return {}; } - _size = resource.tellg(); + std::vector data; + size_t size = resource.tellg(); + data.resize(size); resource.seekg(std::ifstream::beg); - char* cdata = (char*) malloc(sizeof(char) * (_size)); - - resource.read(cdata, _size); + resource.read(data.data(), size); resource.close(); - return reinterpret_cast(cdata); + return data; } std::vector systemFontFallbacksHandle() { @@ -130,8 +130,8 @@ std::vector systemFontFallbacksHandle() { // System fonts are not available on linux yet, we will possibly use FontConfig in the future, for // references see the tizen platform implementation of system fonts -unsigned char* systemFont(const std::string& _name, const std::string& _weight, const std::string& _face, size_t* _size) { - return nullptr; +std::vector systemFont(const std::string& _name, const std::string& _weight, const std::string& _face) { + return {}; } bool startUrlRequest(const std::string& _url, UrlCallback _callback) { diff --git a/rpi/src/platform_rpi.cpp b/rpi/src/platform_rpi.cpp index ba25c61deb..93934628e0 100644 --- a/rpi/src/platform_rpi.cpp +++ b/rpi/src/platform_rpi.cpp @@ -82,26 +82,26 @@ std::string stringFromFile(const char* _path) { return out; } -unsigned char* bytesFromFile(const char* _path, size_t& _size) { +std::vector bytesFromFile(const char* _path) { + if (!_path || strlen(_path) == 0) { return {}; } std::ifstream resource(_path, std::ifstream::ate | std::ifstream::binary); if(!resource.is_open()) { - logMsg("Failed to read file at path: %s\n", _path); - _size = 0; - return nullptr; + LOG("failed to read file at path: %s", _path); + return {}; } - _size = resource.tellg(); + std::vector data; + size_t size = resource.tellg(); + data.resize(size); resource.seekg(std::ifstream::beg); - char* cdata = (char*) malloc(sizeof(char) * _size); - - resource.read(cdata, _size); + resource.read(data.data(), size); resource.close(); - return reinterpret_cast(cdata); + return data; } FontSourceHandle getFontHandle(const char* _path) { @@ -130,8 +130,8 @@ std::vector systemFontFallbacksHandle() { // System fonts are not available on Raspberry Pi yet, we will possibly use FontConfig in the future, // for references see the tizen platform implementation of system fonts -unsigned char* systemFont(const std::string& _name, const std::string& _weight, const std::string& _face, size_t* _size) { - return nullptr; +std::vector systemFont(const std::string& _name, const std::string& _weight, const std::string& _face) { + return {}; } bool startUrlRequest(const std::string& _url, UrlCallback _callback) { diff --git a/tests/src/platform_mock.cpp b/tests/src/platform_mock.cpp index 09cae8cc7a..46657ee648 100644 --- a/tests/src/platform_mock.cpp +++ b/tests/src/platform_mock.cpp @@ -15,6 +15,8 @@ #define FONT_JA "fonts/DroidSansJapanese.ttf" #define FALLBACK "fonts/DroidSansFallback.ttf" +#include "log.h" + static bool s_isContinuousRendering = false; void logMsg(const char* fmt, ...) { @@ -56,31 +58,30 @@ std::string stringFromFile(const char* _path) { return out; } -unsigned char* bytesFromFile(const char* _path, size_t& _size) { +std::vector bytesFromFile(const char* _path) { + if (!_path || strlen(_path) == 0) { return {}; } std::ifstream resource(_path, std::ifstream::ate | std::ifstream::binary); if(!resource.is_open()) { - logMsg("Failed to read file at path: %s\n", _path); - _size = 0; - return nullptr; + LOG("Failed to read file at path: %s", _path); + return {}; } - _size = resource.tellg(); + std::vector data; + size_t size = resource.tellg(); + data.resize(size); resource.seekg(std::ifstream::beg); - char* cdata = (char*) malloc(sizeof(char) * _size); - - resource.read(cdata, _size); + resource.read(data.data(), size); resource.close(); - return reinterpret_cast(cdata); + return data; } - -unsigned char* systemFont(const std::string& _name, const std::string& _weight, const std::string& _face, size_t* _size) { - return nullptr; +std::vector systemFont(const std::string& _name, const std::string& _weight, const std::string& _face) { + return {}; } std::vector systemFontFallbacksHandle() { diff --git a/tests/unit/lineWrapTests.cpp b/tests/unit/lineWrapTests.cpp index a91ca7ba44..27b41ca3c7 100644 --- a/tests/unit/lineWrapTests.cpp +++ b/tests/unit/lineWrapTests.cpp @@ -35,10 +35,8 @@ std::shared_ptr font; void initFont(std::string _font = TEST_FONT) { font = fontManager.addFont("default", TEST_FONT_SIZE, alfons::InputSource(_font)); - size_t dataSize = 0; - char* data = reinterpret_cast(bytesFromFile(_font.c_str(), dataSize)); - auto face = fontManager.addFontFace(alfons::InputSource(data, dataSize), TEST_FONT_SIZE); - free(data); + auto data = bytesFromFile(_font.c_str()); + auto face = fontManager.addFontFace(alfons::InputSource(data), TEST_FONT_SIZE); font->addFace(face); } diff --git a/tizen/src/platform_tizen.cpp b/tizen/src/platform_tizen.cpp index 83fffd071f..bb3adf7bd4 100644 --- a/tizen/src/platform_tizen.cpp +++ b/tizen/src/platform_tizen.cpp @@ -207,36 +207,34 @@ std::string fontPath(const std::string& _name, const std::string& _weight, return fontFile; } -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, size_t* _size) { std::string path = fontPath(_name, _weight, _face); - if (path.empty()) { return nullptr; } + if (path.empty()) { return {}; } - return bytesFromFile(path.c_str(), *_size); + return bytesFromFile(path.c_str()); } -unsigned char* bytesFromFile(const char* _path, size_t& _size) { - - if (!_path || strlen(_path) == 0) { return nullptr; } +std::vector bytesFromFile(const char* _path) { + if (!_path || strlen(_path) == 0) { return {}; } std::ifstream resource(_path, std::ifstream::ate | std::ifstream::binary); if(!resource.is_open()) { - logMsg("Failed to read file at path: %s\n", _path); - _size = 0; - return nullptr; + LOG("Failed to read file at path: %s", _path); + return {}; } - _size = resource.tellg(); + std::vector data; + size_t size = resource.tellg(); + data.resize(size); resource.seekg(std::ifstream::beg); - char* cdata = (char*) malloc(sizeof(char) * (_size)); - - resource.read(cdata, _size); + resource.read(data.data(), size); resource.close(); - return reinterpret_cast(cdata); + return data; } std::string stringFromFile(const char* _path) { From 269b567b1372546b502953250bf543e949c7a61c Mon Sep 17 00:00:00 2001 From: Hannes Janetzek Date: Tue, 10 Jan 2017 13:29:25 +0100 Subject: [PATCH 5/5] update alfons - use InputSource move constructor --- core/src/scene/sceneLoader.cpp | 2 +- core/src/text/fontContext.cpp | 2 +- external/alfons | 2 +- tests/unit/lineWrapTests.cpp | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/core/src/scene/sceneLoader.cpp b/core/src/scene/sceneLoader.cpp index e14f8b6095..e45a494e1f 100644 --- a/core/src/scene/sceneLoader.cpp +++ b/core/src/scene/sceneLoader.cpp @@ -731,7 +731,7 @@ void loadFontDescription(const Node& node, const std::string& family, const std: 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)); + scene->fontContext()->addFont(_ft, alfons::InputSource(std::move(data))); } } } diff --git a/core/src/text/fontContext.cpp b/core/src/text/fontContext.cpp index 5a99a737eb..e7ff00ed28 100644 --- a/core/src/text/fontContext.cpp +++ b/core/src/text/fontContext.cpp @@ -304,7 +304,7 @@ std::shared_ptr FontContext::getFont(const std::string& _family, c font->addFaces(*m_font[sizeIndex]); } } else { - font->addFace(m_alfons.addFontFace(alfons::InputSource(fontData), fontSize)); + font->addFace(m_alfons.addFontFace(alfons::InputSource(std::move(fontData)), fontSize)); if (m_font[sizeIndex]) { font->addFaces(*m_font[sizeIndex]); diff --git a/external/alfons b/external/alfons index 5a1334d5de..56b3a901c8 160000 --- a/external/alfons +++ b/external/alfons @@ -1 +1 @@ -Subproject commit 5a1334d5dec00bdca9425008903787877d11374d +Subproject commit 56b3a901c8fbdcbfa4935593e230db70d2785892 diff --git a/tests/unit/lineWrapTests.cpp b/tests/unit/lineWrapTests.cpp index 27b41ca3c7..d91f0ba5db 100644 --- a/tests/unit/lineWrapTests.cpp +++ b/tests/unit/lineWrapTests.cpp @@ -36,7 +36,7 @@ void initFont(std::string _font = TEST_FONT) { font = fontManager.addFont("default", TEST_FONT_SIZE, alfons::InputSource(_font)); auto data = bytesFromFile(_font.c_str()); - auto face = fontManager.addFontFace(alfons::InputSource(data), TEST_FONT_SIZE); + auto face = fontManager.addFontFace(alfons::InputSource(std::move(data)), TEST_FONT_SIZE); font->addFace(face); }