2 * Copyright (c) 2020 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 <dali-toolkit/internal/visuals/npatch-loader.h>
22 #include <dali-toolkit/internal/visuals/rendering-addon.h>
25 #include <dali/devel-api/common/hash.h>
26 #include <dali/integration-api/debug.h>
40 constexpr auto INVALID_CACHE_INDEX = int32_t{-1}; ///< Invalid Cache index
41 constexpr auto UNINITIALIZED_ID = int32_t{0}; ///< uninitialised id, use to initialize ids
43 } // Anonymous namespace
45 NPatchLoader::NPatchLoader()
46 : mCurrentNPatchDataId(0)
50 NPatchLoader::~NPatchLoader()
54 NPatchData::NPatchDataId NPatchLoader::GenerateUniqueNPatchDataId()
56 return mCurrentNPatchDataId++;
59 std::size_t NPatchLoader::Load( TextureManager& textureManager, TextureUploadObserver* textureObserver, const std::string& url, const Rect< int >& border, bool& preMultiplyOnLoad, bool synchronousLoading )
61 std::size_t hash = CalculateHash( url );
62 OwnerContainer< NPatchData* >::SizeType index = UNINITIALIZED_ID;
63 const OwnerContainer< NPatchData* >::SizeType count = mCache.Count();
65 for( ; index < count; ++index )
67 if( mCache[ index ]->GetHash() == hash )
69 // hash match, check url as well in case of hash collision
70 if(mCache[ index ]->GetUrl() == url)
73 if( mCache[ index ]->GetBorder() == border )
75 if( mCache[ index ]->GetLoadingState() == NPatchData::LoadingState::LOADING )
77 mCache[ index ]->AddObserver( textureObserver );
79 return mCache[ index ]->GetId(); // valid indices are from 1 onwards
83 if( mCache[ index ]->GetLoadingState() == NPatchData::LoadingState::LOAD_COMPLETE )
85 // Same url but border is different - use the existing texture
86 NPatchData* newData = new NPatchData();
87 newData->SetId(GenerateUniqueNPatchDataId());
88 newData->SetHash(hash);
90 newData->SetCroppedWidth(mCache[ index ]->GetCroppedWidth());
91 newData->SetCroppedHeight(mCache[ index ]->GetCroppedHeight());
93 newData->SetTextures(mCache[ index ]->GetTextures());
95 NPatchUtility::StretchRanges stretchRangesX;
96 stretchRangesX.PushBack( Uint16Pair( border.left, ( (newData->GetCroppedWidth() >= static_cast< unsigned int >( border.right )) ? newData->GetCroppedHeight() - border.right : 0 ) ) );
98 NPatchUtility::StretchRanges stretchRangesY;
99 stretchRangesY.PushBack( Uint16Pair( border.top, ( (newData->GetCroppedWidth() >= static_cast< unsigned int >( border.bottom )) ? newData->GetCroppedHeight() - border.bottom : 0 ) ) );
101 newData->SetStretchPixelsX(stretchRangesX);
102 newData->SetStretchPixelsY(stretchRangesY);
103 newData->SetBorder(border);
105 newData->SetPreMultiplyOnLoad(mCache[ index ]->IsPreMultiplied());
107 newData->SetLoadingState(NPatchData::LoadingState::LOAD_COMPLETE);
108 newData->AddObserver( textureObserver );
110 mCache.PushBack( newData );
112 return newData->GetId(); // valid ids start from 1u
119 // If this is new image loading, make new cache data
121 data = new NPatchData();
122 data->SetId(GenerateUniqueNPatchDataId());
125 data->SetBorder(border);
126 data->SetPreMultiplyOnLoad(preMultiplyOnLoad);
127 data->AddObserver(textureObserver);
128 mCache.PushBack(data);
130 auto preMultiplyOnLoading = preMultiplyOnLoad ? TextureManager::MultiplyOnLoad::MULTIPLY_ON_LOAD
131 : TextureManager::MultiplyOnLoad::LOAD_WITHOUT_MULTIPLY;
133 Devel::PixelBuffer pixelBuffer = textureManager.LoadPixelBuffer( url, Dali::ImageDimensions(), FittingMode::DEFAULT,
134 SamplingMode::BOX_THEN_LINEAR, synchronousLoading,
135 data, true, preMultiplyOnLoading );
139 preMultiplyOnLoad = ( preMultiplyOnLoading == TextureManager::MultiplyOnLoad::MULTIPLY_ON_LOAD ) ? true : false;
140 data->SetLoadedNPatchData( pixelBuffer, preMultiplyOnLoad );
143 return data->GetId();
146 int32_t NPatchLoader::GetCacheIndexFromId( const NPatchData::NPatchDataId id )
148 const unsigned int size = mCache.Count();
150 for( unsigned int i = 0; i < size; ++i )
152 if( mCache[i]->GetId() == id )
158 DALI_LOG_ERROR("Wrong NPatchDataId is used\n");
159 return INVALID_CACHE_INDEX;
162 bool NPatchLoader::GetNPatchData( const NPatchData::NPatchDataId id, const NPatchData*& data )
164 int32_t cacheIndex = GetCacheIndexFromId(id);
165 if( cacheIndex != INVALID_CACHE_INDEX )
167 data = mCache[cacheIndex];
174 void NPatchLoader::Remove( std::size_t id, TextureUploadObserver* textureObserver )
176 int32_t cacheIndex = GetCacheIndexFromId(id);
177 if( cacheIndex == INVALID_CACHE_INDEX )
183 data = mCache[cacheIndex];
185 data->RemoveObserver(textureObserver);
187 if(data->GetObserverCount() == 0)
189 mCache.Erase( mCache.Begin() + cacheIndex );
193 } // namespace Internal
195 } // namespace Toolkit