577a433b4442b0f3c17461bbb0dcc196fae533b6
[platform/core/uifw/dali-toolkit.git] / dali-toolkit / internal / visuals / image-atlas-manager.cpp
1 /*
2  * Copyright (c) 2021 Samsung Electronics Co., Ltd.
3  *
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
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
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.
15  *
16  */
17
18 // CLASS HEADER
19 #include "image-atlas-manager.h"
20
21 // EXTERNAL HEADER
22 #include <dali/devel-api/adaptor-framework/image-loading.h>
23
24 // INTERNAL HEADERS
25 #include <dali-toolkit/internal/image-loader/image-atlas-impl.h>
26
27 namespace Dali
28 {
29 namespace Toolkit
30 {
31 namespace Internal
32 {
33 namespace
34 {
35 const uint32_t DEFAULT_ATLAS_SIZE(1024u); // this size can fit 8 by 8 images of average size 128*128
36 const uint32_t MAX_ITEM_SIZE(512u);
37 const uint32_t MAX_ITEM_AREA(MAX_ITEM_SIZE* MAX_ITEM_SIZE);
38 } // namespace
39
40 ImageAtlasManager::ImageAtlasManager()
41 : mBrokenImageUrl("")
42 {
43 }
44
45 ImageAtlasManager::~ImageAtlasManager()
46 {
47 }
48
49 bool ImageAtlasManager::CheckAtlasAvailable(const VisualUrl& url, const ImageDimensions& size) const
50 {
51   ImageDimensions dimensions = size;
52   ImageDimensions zero;
53   if(size == zero)
54   {
55     dimensions = Dali::GetClosestImageSize(url.GetUrl());
56   }
57
58   // big image, atlasing is not applied
59   if(static_cast<uint32_t>(dimensions.GetWidth()) * static_cast<uint32_t>(dimensions.GetHeight()) > MAX_ITEM_AREA || dimensions.GetWidth() > DEFAULT_ATLAS_SIZE || dimensions.GetHeight() > DEFAULT_ATLAS_SIZE)
60   {
61     return false;
62   }
63   return true;
64 }
65
66 TextureSet ImageAtlasManager::Add(Vector4&             textureRect,
67                                   const VisualUrl&     url,
68                                   ImageDimensions&     size,
69                                   FittingMode::Type    fittingMode,
70                                   bool                 orientationCorrection,
71                                   AtlasUploadObserver* atlasUploadObserver)
72 {
73   ImageDimensions dimensions = size;
74   ImageDimensions zero;
75   if(size == zero)
76   {
77     dimensions = Dali::GetClosestImageSize(url.GetUrl());
78   }
79
80   // big image, atlasing is not applied
81   if(static_cast<uint32_t>(dimensions.GetWidth()) * static_cast<uint32_t>(dimensions.GetHeight()) > MAX_ITEM_AREA || dimensions.GetWidth() > DEFAULT_ATLAS_SIZE || dimensions.GetHeight() > DEFAULT_ATLAS_SIZE)
82   {
83     return TextureSet();
84   }
85   size = dimensions;
86
87   unsigned int i = 0;
88   for(AtlasContainer::iterator iter = mAtlasList.begin(); iter != mAtlasList.end(); ++iter)
89   {
90     if(GetImplementation(*iter).Upload(textureRect, url, size, fittingMode, orientationCorrection, atlasUploadObserver))
91     {
92       return mTextureSetList[i];
93     }
94     i++;
95   }
96
97   CreateNewAtlas();
98   GetImplementation(mAtlasList.back()).Upload(textureRect, url, size, fittingMode, orientationCorrection, atlasUploadObserver);
99   return mTextureSetList.back();
100 }
101
102 TextureSet ImageAtlasManager::Add(Vector4&  textureRect,
103                                   PixelData pixelData)
104 {
105   // big buffer, atlasing is not applied
106   if(static_cast<uint32_t>(pixelData.GetWidth()) * static_cast<uint32_t>(pixelData.GetHeight()) > MAX_ITEM_AREA || pixelData.GetWidth() > DEFAULT_ATLAS_SIZE || pixelData.GetHeight() > DEFAULT_ATLAS_SIZE)
107   {
108     return TextureSet();
109   }
110
111   unsigned int i = 0;
112   for(AtlasContainer::iterator iter = mAtlasList.begin(); iter != mAtlasList.end(); ++iter)
113   {
114     if((*iter).Upload(textureRect, pixelData))
115     {
116       return mTextureSetList[i];
117     }
118     i++;
119   }
120
121   CreateNewAtlas();
122   mAtlasList.back().Upload(textureRect, pixelData);
123   return mTextureSetList.back();
124 }
125
126 void ImageAtlasManager::Remove(TextureSet textureSet, const Vector4& textureRect)
127 {
128   unsigned int i = 0;
129   for(TextureSetContainer::iterator iter = mTextureSetList.begin(); iter != mTextureSetList.end(); ++iter)
130   {
131     if((*iter) == textureSet)
132     {
133       mAtlasList[i].Remove(textureRect);
134       return;
135     }
136     i++;
137   }
138 }
139
140 void ImageAtlasManager::SetBrokenImage(const std::string& brokenImageUrl)
141 {
142   if(!brokenImageUrl.empty())
143   {
144     mBrokenImageUrl = brokenImageUrl;
145   }
146 }
147
148 void ImageAtlasManager::CreateNewAtlas()
149 {
150   Toolkit::ImageAtlas newAtlas = Toolkit::ImageAtlas::New(DEFAULT_ATLAS_SIZE, DEFAULT_ATLAS_SIZE);
151   if(!mBrokenImageUrl.empty())
152   {
153     newAtlas.SetBrokenImage(mBrokenImageUrl);
154   }
155   mAtlasList.push_back(newAtlas);
156   TextureSet textureSet = TextureSet::New();
157   textureSet.SetTexture(0u, newAtlas.GetAtlas());
158   mTextureSetList.push_back(textureSet);
159 }
160
161 } // namespace Internal
162
163 } // namespace Toolkit
164
165 } // namespace Dali