2 * Copyright (c) 2021 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>
36 constexpr auto INVALID_CACHE_INDEX = int32_t{-1}; ///< Invalid Cache index
37 constexpr auto UNINITIALIZED_ID = int32_t{0}; ///< uninitialised id, use to initialize ids
39 } // Anonymous namespace
41 NPatchLoader::NPatchLoader()
42 : mCurrentNPatchDataId(0)
46 NPatchLoader::~NPatchLoader()
50 NPatchData::NPatchDataId NPatchLoader::GenerateUniqueNPatchDataId()
52 return mCurrentNPatchDataId++;
55 std::size_t NPatchLoader::Load(TextureManager& textureManager, TextureUploadObserver* textureObserver, const VisualUrl& url, const Rect<int>& border, bool& preMultiplyOnLoad, bool synchronousLoading)
57 std::size_t hash = CalculateHash(url.GetUrl());
58 OwnerContainer<NPatchData*>::SizeType index = UNINITIALIZED_ID;
59 const OwnerContainer<NPatchData*>::SizeType count = mCache.Count();
61 for(; index < count; ++index)
63 if(mCache[index]->GetHash() == hash)
65 // hash match, check url as well in case of hash collision
66 if(mCache[index]->GetUrl().GetUrl() == url.GetUrl())
69 if(mCache[index]->GetBorder() == border)
71 if(mCache[index]->GetLoadingState() == NPatchData::LoadingState::LOADING)
73 mCache[index]->AddObserver(textureObserver);
75 return mCache[index]->GetId(); // valid indices are from 1 onwards
79 if(mCache[index]->GetLoadingState() == NPatchData::LoadingState::LOAD_COMPLETE)
81 // Same url but border is different - use the existing texture
82 NPatchData* newData = new NPatchData();
83 newData->SetId(GenerateUniqueNPatchDataId());
84 newData->SetHash(hash);
86 newData->SetCroppedWidth(mCache[index]->GetCroppedWidth());
87 newData->SetCroppedHeight(mCache[index]->GetCroppedHeight());
89 newData->SetTextures(mCache[index]->GetTextures());
91 NPatchUtility::StretchRanges stretchRangesX;
92 stretchRangesX.PushBack(Uint16Pair(border.left, ((newData->GetCroppedWidth() >= static_cast<unsigned int>(border.right)) ? newData->GetCroppedHeight() - border.right : 0)));
94 NPatchUtility::StretchRanges stretchRangesY;
95 stretchRangesY.PushBack(Uint16Pair(border.top, ((newData->GetCroppedWidth() >= static_cast<unsigned int>(border.bottom)) ? newData->GetCroppedHeight() - border.bottom : 0)));
97 newData->SetStretchPixelsX(stretchRangesX);
98 newData->SetStretchPixelsY(stretchRangesY);
99 newData->SetBorder(border);
101 newData->SetPreMultiplyOnLoad(mCache[index]->IsPreMultiplied());
103 newData->SetLoadingState(NPatchData::LoadingState::LOAD_COMPLETE);
104 newData->AddObserver(textureObserver);
106 mCache.PushBack(newData);
107 return newData->GetId(); // valid ids start from 1u
114 // If this is new image loading, make new cache data
116 data = new NPatchData();
117 data->SetId(GenerateUniqueNPatchDataId());
120 data->SetBorder(border);
121 data->SetPreMultiplyOnLoad(preMultiplyOnLoad);
122 data->AddObserver(textureObserver);
123 mCache.PushBack(data);
125 auto preMultiplyOnLoading = preMultiplyOnLoad ? TextureManager::MultiplyOnLoad::MULTIPLY_ON_LOAD
126 : TextureManager::MultiplyOnLoad::LOAD_WITHOUT_MULTIPLY;
128 Devel::PixelBuffer pixelBuffer = textureManager.LoadPixelBuffer(url, Dali::ImageDimensions(), FittingMode::DEFAULT, SamplingMode::BOX_THEN_LINEAR, synchronousLoading, data, true, preMultiplyOnLoading);
132 preMultiplyOnLoad = (preMultiplyOnLoading == TextureManager::MultiplyOnLoad::MULTIPLY_ON_LOAD) ? true : false;
133 data->SetLoadedNPatchData(pixelBuffer, preMultiplyOnLoad);
135 return data->GetId();
138 int32_t NPatchLoader::GetCacheIndexFromId(const NPatchData::NPatchDataId id)
140 const unsigned int size = mCache.Count();
142 for(unsigned int i = 0; i < size; ++i)
144 if(mCache[i]->GetId() == id)
150 return INVALID_CACHE_INDEX;
153 bool NPatchLoader::GetNPatchData(const NPatchData::NPatchDataId id, const NPatchData*& data)
155 int32_t cacheIndex = GetCacheIndexFromId(id);
156 if(cacheIndex != INVALID_CACHE_INDEX)
158 data = mCache[cacheIndex];
165 void NPatchLoader::Remove(std::size_t id, TextureUploadObserver* textureObserver)
167 int32_t cacheIndex = GetCacheIndexFromId(id);
168 if(cacheIndex == INVALID_CACHE_INDEX)
174 data = mCache[cacheIndex];
176 data->RemoveObserver(textureObserver);
178 if(data->GetObserverCount() == 0)
180 mCache.Erase(mCache.Begin() + cacheIndex);
184 } // namespace Internal
186 } // namespace Toolkit