2 * Copyright (c) 2014 Samsung Electronics Co., Ltd.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
19 #include "resource-loader.h"
22 #include <boost/thread.hpp>
28 #include <dali/integration-api/bitmap.h>
29 #include <dali/integration-api/debug.h>
30 #include <dali/integration-api/resource-cache.h>
31 #include <dali/public-api/common/dali-common.h>
32 #include <dali/public-api/common/set-wrapper.h>
33 #include <dali/public-api/math/vector2.h>
34 #include "resource-requester-base.h"
35 #include "resource-bitmap-requester.h"
36 #include "resource-model-requester.h"
37 #include "resource-shader-requester.h"
38 #include "resource-text-requester.h"
39 #include "debug/resource-loader-debug.h"
40 #include "loader-font.h"
41 #include "../interfaces/font-controller.h"
42 #include "../interfaces/data-cache.h"
46 * A macro to expand an argument to a compile time constant string literal.
47 * Wrapping the stringify in an outer macro, means that any macro passed as
48 * "x" will be expanded before being turned into a string.
49 * Use this for example to turn the current line number into a string:
50 * puts("The current line number is " DALI_TO_STRING(__LINE__) ".");
52 #define DALI_TO_STRING_INNER(x) #x
53 #define DALI_TO_STRING(x) DALI_TO_STRING_INNER(x)
55 using namespace Dali::Integration;
57 using boost::unique_lock;
58 using boost::scoped_ptr;
69 const char * const DALI_USER_FONT_CACHE_PATH( DALI_USER_FONT_CACHE_DIR );
70 const unsigned int MAX_NUMBER_CHARS_TO_CACHE( 60000 ); ///< support up to 60,000 glyphs
71 const unsigned int DISTANCE_FIELD_SIZE = 64; // doesn't need to be power of two (the atlas may for performance)
72 const unsigned int DISTANCE_FIELD_PADDING = 30; // Number of pixels of padding around the source FreeType bitmap
73 const unsigned int HIGH_QUALITY_PIXEL_SIZE = 200; // Pixel size sent to FreeType2 FT_Set_Char_Size() for high quality glyphs
74 const float ONE_OVER_64 = 1.0f/64.0f;
77 // For DEBUG_ENABLED profiling of distance field glyph generation
78 double GetTimeMicroseconds()
81 clock_gettime(CLOCK_MONOTONIC, &time);
82 double seconds = time.tv_sec;
83 seconds += 1e-3 * time.tv_nsec;
88 } // unnamed namespace
91 struct ResourceLoader::ResourceLoaderImpl
93 typedef std::pair<ResourceId, ResourceRequest> RequestStorePair;
94 typedef std::map<ResourceId, ResourceRequest> RequestStore;
95 typedef RequestStore::iterator RequestStoreIter;
97 typedef std::queue<LoadedResource> LoadedQueue;
98 typedef std::queue<SavedResource> SavedQueue;
99 typedef std::queue<FailedResource> FailedQueue;
101 typedef std::pair<ResourceTypeId, ResourceRequesterBase*> RequestHandlerPair;
102 typedef std::map<ResourceTypeId, ResourceRequesterBase*> RequestHandlers;
103 typedef RequestHandlers::iterator RequestHandlersIter;
105 boost::mutex mQueueMutex; ///< used to synchronize access to mLoadedQueue, mSavedQueue and mFailedQueue
106 LoadedQueue mPartiallyLoadedQueue; ///< Partially complete load requests notifications are stored here until fetched by core
107 LoadedQueue mLoadedQueue; ///< Completed load requests notifications are stored here until fetched by core
108 SavedQueue mSavedQueue; ///< Completed save request notifications are stored here until fetched by core
109 FailedQueue mFailedLoads; ///< Failed load request notifications are stored here until fetched by core
110 FailedQueue mFailedSaves; ///< Failed save request notifications are stored here until fetched by core
112 Dali::Platform::FontController* mFontController; ///< Interface for accessing font information
114 RequestHandlers mRequestHandlers;
115 RequestStore mStoredRequests; ///< Used to store load requests until loading is completed
117 ResourceLoaderImpl( ResourceLoader* loader )
119 mFontController = Dali::Platform::FontController::New();
121 mRequestHandlers.insert(std::make_pair(ResourceBitmap, new ResourceBitmapRequester(*loader)));
122 mRequestHandlers.insert(std::make_pair(ResourceShader, new ResourceShaderRequester(*loader)));
123 mRequestHandlers.insert(std::make_pair(ResourceModel, new ResourceModelRequester(*loader)));
124 mRequestHandlers.insert(std::make_pair(ResourceText, new ResourceTextRequester(*loader)));
127 ~ResourceLoaderImpl()
129 // Delete resource handlers
130 for( RequestHandlersIter it = mRequestHandlers.begin(); it != mRequestHandlers.end(); ++it )
132 ResourceRequesterBase* requestBase = it->second;
136 delete mFontController;
141 // Pause all the request handlers:
142 for( RequestHandlersIter it = mRequestHandlers.begin(), end = mRequestHandlers.end(); it != end; ++it )
144 ResourceRequesterBase * const requester = it->second;
154 // Wake up all the request handlers:
155 for( RequestHandlersIter it = mRequestHandlers.begin(), end = mRequestHandlers.end(); it != end; ++it )
157 ResourceRequesterBase * const requester = it->second;
165 ResourceRequesterBase* GetRequester(ResourceTypeId typeId)
167 ResourceRequesterBase* requestHandler = NULL;
168 RequestHandlersIter iter = mRequestHandlers.find(typeId);
169 if(iter != mRequestHandlers.end())
171 requestHandler = iter->second;
173 DALI_ASSERT_DEBUG(requestHandler && "All resource types should have a requester defined for them.");
174 return requestHandler;
177 void LoadResource(const ResourceRequest& request)
179 // Store resource request for partial loaders. Will get cleaned up after load complete has finished
180 StoreRequest(request);
182 ResourceRequesterBase* requester = GetRequester(request.GetType()->id);
185 ResourceRequest* storedRequest = GetRequest(request.GetId());
186 if( storedRequest != NULL )
188 requester->LoadResource(*storedRequest); // Pass in stored request
193 DALI_LOG_ERROR( "Unknown resource type (%u) with path \"%s\" in load request.\n", request.GetType()->id, request.GetPath().c_str() );
194 DALI_ASSERT_DEBUG( 0 == "Unknown resource type in load request at " __FILE__ ", line " DALI_TO_STRING(__LINE__) ".\n" );
198 void SaveResource(const ResourceRequest& request)
200 ResourceRequesterBase* requester = GetRequester( request.GetType()->id );
203 requester->SaveResource( request );
207 void CancelLoad(ResourceId id, ResourceTypeId typeId)
209 ResourceRequesterBase* requester = GetRequester(typeId);
212 requester->CancelLoad( id, typeId );
217 LoadStatus LoadFurtherResources( LoadedResource partialResource )
219 LoadStatus loadStatus = RESOURCE_LOADING;
220 RequestStoreIter iter = mStoredRequests.find(partialResource.id);
222 if( mStoredRequests.end() != iter ) // else cancelled. Ignore response
224 ResourceRequest& request = iter->second;
225 ResourceRequesterBase* requester = GetRequester(request.GetType()->id);
228 loadStatus = requester->LoadFurtherResources( request, partialResource );
231 DALI_LOG_INFO(gLoaderFilter, Debug::General, "ResourceLoader::LoadFurtherResources( ID:%u complete: %s)\n", request.GetId(), loadStatus==RESOURCE_LOADING?"Loading":loadStatus==RESOURCE_PARTIALLY_LOADED?"PARTIAL":"COMPLETE" );
234 if( loadStatus == RESOURCE_COMPLETELY_LOADED )
236 ClearRequest( partialResource.id );
244 // TODO - not used - remove?
248 void GetResources(ResourceCache& cache)
250 // Fill the resource cache
252 unique_lock<mutex> lock(mQueueMutex);
254 // iterate through the partially loaded resources
255 while (!mPartiallyLoadedQueue.empty())
257 LoadedResource loaded( mPartiallyLoadedQueue.front() );
258 mPartiallyLoadedQueue.pop();
259 LoadStatus loadStatus = LoadFurtherResources( loaded );
260 cache.LoadResponse( loaded.id, loaded.type, loaded.resource, loadStatus );
263 // iterate through the successfully loaded resources
264 while (!mLoadedQueue.empty())
266 LoadedResource loaded( mLoadedQueue.front() );
268 ClearRequest( loaded.id );
269 cache.LoadResponse( loaded.id, loaded.type, loaded.resource, RESOURCE_COMPLETELY_LOADED );
272 // iterate through the successfully saved resources
273 while (!mSavedQueue.empty())
275 SavedResource saved(mSavedQueue.front());
277 cache.SaveComplete(saved.id, saved.type);
280 // iterate through the resources which failed to load
281 while (!mFailedLoads.empty())
283 FailedResource failed(mFailedLoads.front());
285 ClearRequest(failed.id);
286 cache.LoadFailed(failed.id, failed.failureType);
289 // iterate through the resources which failed to save
290 while (!mFailedSaves.empty())
292 FailedResource failed(mFailedSaves.front());
294 cache.SaveFailed(failed.id, failed.failureType);
298 void AddPartiallyLoadedResource( LoadedResource& resource)
300 // Lock the LoadedQueue to store the loaded resource
301 unique_lock<mutex> lock(mQueueMutex);
303 mPartiallyLoadedQueue.push( resource );
306 void AddLoadedResource(LoadedResource& resource)
308 // Lock the LoadedQueue to store the loaded resource
309 unique_lock<mutex> lock(mQueueMutex);
311 mLoadedQueue.push( resource );
314 void AddSavedResource(SavedResource& resource)
316 // Lock the SavedQueue to store the loaded resource
317 unique_lock<mutex> lock(mQueueMutex);
319 mSavedQueue.push(resource);
322 void AddFailedLoad(FailedResource& resource)
324 // Lock the FailedQueue to store the failed resource information
325 unique_lock<mutex> lock(mQueueMutex);
327 mFailedLoads.push(resource);
330 void AddFailedSave(FailedResource& resource)
332 // Lock the FailedQueue to store the failed resource information
333 unique_lock<mutex> lock(mQueueMutex);
335 mFailedSaves.push(resource);
338 void StoreRequest( const ResourceRequest& request )
340 DALI_LOG_INFO(gLoaderFilter, Debug::Verbose, "ResourceLoader: StoreRequest(id:%u)\n", request.GetId());
341 mStoredRequests.insert( RequestStorePair( request.GetId(), request ) ); // copy request as value type
344 ResourceRequest* GetRequest( ResourceId id )
346 ResourceRequest* found(NULL);
347 DALI_LOG_INFO(gLoaderFilter, Debug::Verbose, "ResourceLoader: GetRequest(id:%u)\n", id);
348 RequestStoreIter iter = mStoredRequests.find( id );
349 if( mStoredRequests.end() != iter )
351 found = &iter->second;
356 void ClearRequest( ResourceId resourceId )
358 DALI_LOG_INFO(gLoaderFilter, Debug::Verbose, "ResourceLoader: ClearRequest(id:%u)\n", resourceId);
359 RequestStoreIter iter = mStoredRequests.find( resourceId );
360 if( mStoredRequests.end() != iter ) // Can't assert here - cancel load may cross with load failed
362 mStoredRequests.erase( iter );
367 /********************************************************************************/
368 /**************************** RESOURCE LOADER METHODS ************************/
369 /********************************************************************************/
370 ResourceLoader::ResourceLoader()
371 : mTerminateThread(0)
373 mImpl = new ResourceLoaderImpl( this );
376 ResourceLoader::~ResourceLoader()
378 // Flag that the ResourceLoader is exiting
379 (void)__sync_or_and_fetch( &mTerminateThread, -1 );
384 void ResourceLoader::Pause()
389 void ResourceLoader::Resume()
394 bool ResourceLoader::IsTerminating()
396 return __sync_fetch_and_or( &mTerminateThread, 0 );
399 void ResourceLoader::GetResources(ResourceCache& cache)
401 mImpl->GetResources( cache );
404 /********************************************************************************/
405 /************************** CALLED FROM LOADER THREADS **********************/
406 /********************************************************************************/
408 void ResourceLoader::AddPartiallyLoadedResource( LoadedResource& resource)
410 mImpl->AddPartiallyLoadedResource( resource );
413 void ResourceLoader::AddLoadedResource(LoadedResource& resource)
415 mImpl->AddLoadedResource( resource );
418 void ResourceLoader::AddSavedResource(SavedResource& resource)
420 mImpl->AddSavedResource( resource );
423 void ResourceLoader::AddFailedLoad(FailedResource& resource)
425 mImpl->AddFailedLoad( resource );
428 void ResourceLoader::AddFailedSave(FailedResource& resource)
430 mImpl->AddFailedSave( resource );
433 /********************************************************************************/
434 /********************* CALLED FROM PLATFORM ABSTRACTION **********************/
435 /********************************************************************************/
437 void ResourceLoader::LoadResource(const ResourceRequest& request)
439 mImpl->LoadResource(request);
442 void ResourceLoader::SaveResource(const ResourceRequest& request)
444 mImpl->SaveResource(request);
447 void ResourceLoader::CancelLoad(ResourceId id, ResourceTypeId typeId)
449 mImpl->CancelLoad(id, typeId);
452 bool ResourceLoader::IsLoading()
454 return mImpl->IsLoading();
457 const std::string& ResourceLoader::GetFontFamilyForChars( const Integration::TextArray& charsRequested )
459 return mImpl->mFontController->GetFontFamilyForChars( charsRequested ).first;
462 bool ResourceLoader::AllGlyphsSupported( const std::string& fontFamily, const std::string& fontStyle, const Integration::TextArray& charsRequested )
464 // At this point fontFamily and fontStyle must have been validated.
466 return mImpl->mFontController->AllGlyphsSupported( Platform::FontController::StyledFontFamily( fontFamily, fontStyle ), charsRequested );
469 bool ResourceLoader::ValidateFontFamilyName( const std::string& fontFamily,
470 const std::string& fontStyle,
471 bool& isDefaultSystemFontFamily,
472 bool& isDefaultSystemFontStyle,
473 std::string& closestFontFamilyMatch,
474 std::string& closestFontStyleMatch )
476 Platform::FontController::StyledFontFamily closestMatch;
478 bool result = mImpl->mFontController->ValidateFontFamilyName( Platform::FontController::StyledFontFamily( fontFamily, fontStyle ),
479 isDefaultSystemFontFamily,
480 isDefaultSystemFontStyle,
483 closestFontFamilyMatch = closestMatch.first;
484 closestFontStyleMatch = closestMatch.second;
489 PixelSize ResourceLoader::GetFontLineHeightFromCapsHeight( const std::string& fontFamily, const std::string& fontStyle, CapsHeight capsHeight, FT_Library freeType )
491 // At this point fontFamily and fontStyle must have been validated.
495 if (!fontFamily.empty())
497 const std::string& fontFileName = GetFontPath( fontFamily, fontStyle );
498 SlpFace* slpFace = LoadFontFace(fontFileName, PixelSize(capsHeight), freeType);
502 const float scale = static_cast<float>(capsHeight.value) / ((slpFace->face->ascender / 64.0f) * 0.95f);
504 result.value = static_cast<unsigned int>(roundf(scale * (slpFace->face->height / 64.0f)));
514 void ResourceLoader::GetFontList( Dali::Integration::PlatformAbstraction::FontListMode mode, std::vector<std::string>& fontList )
516 // VCC TODO: A GetStyles() method which returns a list of styles for a given font family is needed.
518 Platform::FontController::FontListMode listMode = Platform::FontController::LIST_SYSTEM_FONTS;
522 case Dali::Integration::PlatformAbstraction::LIST_ALL_FONTS:
524 listMode = Platform::FontController::LIST_ALL_FONTS;
527 case Dali::Integration::PlatformAbstraction::LIST_SYSTEM_FONTS:
529 listMode = Platform::FontController::LIST_SYSTEM_FONTS;
532 case Dali::Integration::PlatformAbstraction::LIST_APPLICATION_FONTS:
534 listMode = Platform::FontController::LIST_APPLICATION_FONTS;
539 DALI_ASSERT_DEBUG( false && "invalid mode" );
543 Platform::FontController::FontList styledFontList;
544 mImpl->mFontController->GetFontList( listMode, styledFontList );
546 std::set<std::string> uniqueFontNames;
547 for( Platform::FontController::FontList::const_iterator it = styledFontList.begin(), endIt = styledFontList.end(); it != endIt; ++it )
549 uniqueFontNames.insert( it->first );
552 // copy into a vector
553 std::copy( uniqueFontNames.begin(), uniqueFontNames.end(), std::back_inserter( fontList ) );
558 * Note, called from both platform abstraction & from text loader threads
560 GlyphSet* ResourceLoader::GetGlyphData (const TextResourceType& textRequest,
562 const std::string& fontFamily,
565 // At this point fontFamily and the font style stored in the textRequest must have been validated.
567 GlyphSet* glyphSet = NULL;
569 size_t fontHash = textRequest.mFontHash;
571 DALI_LOG_INFO(gLoaderFilter, Debug::Verbose, "LoadGlyphSet - requested string is %d characters long\n", textRequest.mCharacterList.size());
573 // path holds the font name
574 if( !fontFamily.empty() )
576 const std::string& fontFileName = GetFontPath( fontFamily, textRequest.mStyle );
578 const bool highQuality(textRequest.mQuality == TextResourceType::TextQualityHigh);
579 const unsigned int glyphQuality( highQuality ? GlyphMetrics::HIGH_QUALITY : GlyphMetrics::LOW_QUALITY );
581 SlpFace* slpFace = LoadFontFace( fontFileName, PixelSize( HIGH_QUALITY_PIXEL_SIZE), freeType );
584 glyphSet = new GlyphSet();
585 glyphSet->mFontHash = fontHash;
586 glyphSet->SetAtlasResourceId( textRequest.mTextureAtlasId );
588 for( TextResourceType::CharacterList::const_iterator it = textRequest.mCharacterList.begin(), endIt = textRequest.mCharacterList.end(); it != endIt; ++it )
590 uint32_t charCode( it->character );
592 if (!glyphSet->HasCharacter(charCode)) // ignore duplicate glyphs in the request
595 // DEBUG_ENABLED profiling of distance field glyph generation
599 then = GetTimeMicroseconds();
602 scoped_ptr< GlyphSet::Character > character( GetCharacter(slpFace->face, charCode,
603 DISTANCE_FIELD_SIZE, DISTANCE_FIELD_PADDING, textRequest.mMaxGlyphSize,
604 getBitmap, highQuality ) );
607 // DEBUG_ENABLED profiling of distance field glyph generation
610 double now( GetTimeMicroseconds() );
612 DALI_LOG_INFO( gLoaderFilter, Log::Verbose, "Generating (%c) in %s quality took %.3f ms\n", charCode, highQuality ? "high" : "low", 1e-3 * ( now - then ) );
617 GlyphSet::Character& glyphCharacter( *character.get() );
619 glyphCharacter.second.quality = glyphQuality;
620 glyphCharacter.second.xPosition = it->xPosition;
621 glyphCharacter.second.yPosition = it->yPosition;
622 // copy character to GlyphSet
623 glyphSet->AddCharacter( glyphCharacter );
635 GlyphSet* ResourceLoader::GetCachedGlyphData(const TextResourceType& textRequest, const std::string& fontFamily)
637 GlyphSet* glyphSet( new GlyphSet() );
638 glyphSet->mFontHash = textRequest.mFontHash;
639 glyphSet->SetAtlasResourceId(textRequest.mTextureAtlasId);
641 std::string cachePath(DALI_USER_FONT_CACHE_PATH);
642 cachePath.append(fontFamily + "-" + textRequest.mStyle);
643 std::replace(cachePath.begin(), cachePath.end(), ' ', '-');
645 DALI_LOG_INFO(gLoaderFilter, Debug::Verbose, "ResourceLoader::GetCachedGlyphData() - cachefile: %s\n", cachePath.c_str() );
647 Platform::DataCache* dataCache = Platform::DataCache::New( Platform::DataCache::READ_ONLY,
648 Platform::DataCache::RUN_LENGTH_ENCODING,
650 DISTANCE_FIELD_SIZE * DISTANCE_FIELD_SIZE,
651 MAX_NUMBER_CHARS_TO_CACHE);
653 Platform::DataCache::KeyVector keyVector;
654 Platform::DataCache::DataVector dataVector;
656 const TextResourceType::CharacterList& requestedCharacters = textRequest.mCharacterList;
657 for( std::size_t i=0, length = requestedCharacters.size(); i < length; ++i )
659 keyVector.push_back( requestedCharacters[i].character );
662 // load the glyphs from file
663 dataCache->Find( keyVector, dataVector );
665 // for each glyph found, add to the glyph set
666 for( std::size_t n = 0, arraySize = keyVector.size(); n < arraySize ; n++ )
668 Platform::DataCache::Data& data( dataVector[n]);
672 GlyphMetrics glyphMetrics;
673 glyphMetrics.code = keyVector[ n ];
674 glyphMetrics.quality = GlyphMetrics::HIGH_QUALITY;
675 glyphMetrics.xPosition = requestedCharacters[n].xPosition;
676 glyphMetrics.yPosition = requestedCharacters[n].yPosition;
678 // create a new bitmap, and copy in the data
679 BitmapPtr bitmapData ( Integration::Bitmap::New(Bitmap::BITMAP_2D_PACKED_PIXELS, ResourcePolicy::DISCARD) );
682 bitmapData->GetPackedPixelsProfile()->AssignBuffer( Pixel::A8, data.data, DISTANCE_FIELD_SIZE * DISTANCE_FIELD_SIZE, DISTANCE_FIELD_SIZE, DISTANCE_FIELD_SIZE );
686 // add to the glyphset
687 glyphSet->AddCharacter( bitmapData, glyphMetrics );
690 DALI_LOG_INFO( gLoaderFilter, Debug::Verbose, "ResourceLoader::GetCachedGlyphData() - requestedGlyphs:%u, cachedGlyphs:%u\n",
691 requestedCharacters.size(), glyphSet->GetCharacterList().size() );
698 void ResourceLoader::GetGlobalMetrics( FT_Library freeType,
699 const std::string& fontFamily,
700 const std::string& fontStyle,
701 GlobalMetrics& globalMetrics )
703 // At this point fontFamily and fontStyle must have been validated.
705 if( !fontFamily.empty() )
707 const std::string& fontFileName = GetFontPath( fontFamily, fontStyle );
709 SlpFace* slpFace = LoadFontFace( fontFileName, PixelSize( HIGH_QUALITY_PIXEL_SIZE), freeType );
712 // scale factor for unit scaled glyphs
713 const float xScale = 1.0f / (slpFace->face->size->metrics.x_scale / 65536.0f);
714 const float yScale = 1.0f / (slpFace->face->size->metrics.y_scale / 65536.0f);
716 globalMetrics.lineHeight = slpFace->face->height * ONE_OVER_64;
717 globalMetrics.ascender = slpFace->face->ascender * ONE_OVER_64;
718 globalMetrics.unitsPerEM = slpFace->face->units_per_EM * ONE_OVER_64;
720 globalMetrics.underlinePosition = -4.f;
721 globalMetrics.underlineThickness = 5.f * yScale;
722 if( 1.f > globalMetrics.underlineThickness )
724 globalMetrics.underlineThickness = 1.f;
726 globalMetrics.maxWidth = DISTANCE_FIELD_SIZE * xScale;
727 globalMetrics.maxHeight = DISTANCE_FIELD_SIZE * yScale;
728 globalMetrics.padAdjustX = DISTANCE_FIELD_PADDING * xScale;
729 globalMetrics.padAdjustY = DISTANCE_FIELD_PADDING * yScale;
736 void ResourceLoader::SetDpi(unsigned int dpiHor, unsigned int dpiVer)
741 bool ResourceLoader::LoadFile( const std::string& filename, std::vector< unsigned char >& buffer ) const
743 DALI_LOG_TRACE_METHOD(gLoaderFilter);
745 DALI_ASSERT_DEBUG( 0 != filename.length());
750 buf.open(filename.c_str(), std::ios::in | std::ios::binary);
753 std::istream stream(&buf);
755 // determine data length
756 stream.seekg(0, std::ios_base::end);
757 unsigned int length = static_cast<unsigned int>( stream.tellg() );
758 stream.seekg(0, std::ios_base::beg);
761 buffer.resize(length);
762 // read data into buffer
763 stream.read(reinterpret_cast<char*>(buffer.data()), length);
765 DALI_LOG_INFO(gLoaderFilter, Debug::Verbose, "ResourceLoader::LoadFile(%s) - loaded %d bytes\n", filename.c_str(), length);
771 DALI_LOG_INFO(gLoaderFilter, Debug::Verbose, "ResourceLoader::LoadFile(%s) - failed to load\n", filename.c_str());
778 std::string ResourceLoader::LoadFile(const std::string& filename) const
780 DALI_LOG_TRACE_METHOD(gLoaderFilter);
782 DALI_ASSERT_DEBUG( 0 != filename.length());
784 std::string contents;
787 buf.open(filename.c_str(), std::ios::in);
790 std::istream stream(&buf);
792 // determine data length
793 stream.seekg(0, std::ios_base::end);
794 unsigned int length = static_cast<unsigned int>( stream.tellg() );
795 stream.seekg(0, std::ios_base::beg);
798 contents.resize(length);
799 // read data into buffer
800 stream.read(&contents[0], length);
802 DALI_LOG_INFO(gLoaderFilter, Debug::Verbose, "ResourceLoader::LoadFile(%s) - loaded %d bytes\n", filename.c_str(), length);
806 DALI_LOG_INFO(gLoaderFilter, Debug::Verbose, "ResourceLoader::LoadFile(%s) - failed to load\n", filename.c_str());
812 bool ResourceLoader::SaveFile(const std::string& filename, std::vector< unsigned char >& buffer)
814 DALI_LOG_TRACE_METHOD(gLoaderFilter);
816 DALI_ASSERT_DEBUG( 0 != filename.length());
821 buf.open(filename.c_str(), std::ios::out | std::ios_base::trunc | std::ios::binary);
824 std::ostream stream(&buf);
826 // determine size of buffer
827 int length = static_cast<int>(buffer.size());
829 // write contents of buffer to the file
830 stream.write(reinterpret_cast<char*>(buffer.data()), length);
834 DALI_LOG_INFO(gLoaderFilter, Debug::Verbose, "ResourceLoader::SaveFile(%s) - wrote %d bytes\n", filename.c_str(), length);
839 #if defined(DEBUG_BUILD)
842 DALI_LOG_INFO(gLoaderFilter, Debug::Verbose, "ResourceLoader::SaveFile(%s) - failed to load\n", filename.c_str());
849 Integration::BitmapPtr ResourceLoader::GetGlyphImage( FT_Library freeType, const std::string& fontFamily, const std::string& fontStyle, float fontSize, uint32_t character )
851 // At this point fontFamily and fontStyle must have been validated.
853 Integration::BitmapPtr image;
855 const std::string& fontFileName = GetFontPath( fontFamily, fontStyle );
856 SlpFace* slpFace = LoadFontFace( fontFileName, PixelSize( Font::PointsToPixels( fontSize ) ), freeType );
858 if( NULL != slpFace )
860 image = GetGlyphBitmap( slpFace->face, character );
867 void ResourceLoader::SetDefaultFontFamily( const std::string& fontFamily, const std::string& fontStyle )
869 mImpl->mFontController->SetDefaultFontFamily( Platform::FontController::StyledFontFamily( fontFamily, fontStyle ) );
872 const std::string& ResourceLoader::GetFontPath(const std::string& fontFamily, const std::string& fontStyle)
874 // At this point fontFamily and fontStyle must have been validated.
875 return mImpl->mFontController->GetFontPath(std::make_pair(fontFamily,fontStyle));
878 } // namespace SlpPlatform