Automatic image atlasing
[platform/core/uifw/dali-toolkit.git] / dali-toolkit / internal / controls / renderers / image-atlas-manager.cpp
1  /*
2  * Copyright (c) 2015 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/public-api/images/resource-image.h>
23
24 namespace Dali
25 {
26
27 namespace Toolkit
28 {
29
30 namespace Internal
31 {
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 }
39
40 ImageAtlasManager::ImageAtlasManager( Shader shader, const std::string& textureUniformName )
41 : mShader( shader ),
42   mTextureUniformName( textureUniformName ),
43   mBrokenImageUrl( "" )
44 {
45 }
46
47 ImageAtlasManager::~ImageAtlasManager()
48 {
49 }
50
51 Material ImageAtlasManager::Add( Vector4& textureRect,
52                                  const std::string& url,
53                                  ImageDimensions size,
54                                  FittingMode::Type fittingMode,
55                                  bool orientationCorrection )
56 {
57   ImageDimensions dimensions = size;
58   ImageDimensions zero;
59   if( size == zero )
60   {
61     dimensions = ResourceImage::GetImageSize( url );
62   }
63
64   // big image, atlasing is not applied
65   if( static_cast<uint32_t>(dimensions.GetWidth()) * static_cast<uint32_t>(dimensions.GetHeight()) > MAX_ITEM_AREA
66       || dimensions.GetWidth()>DEFAULT_ATLAS_SIZE
67       || dimensions.GetHeight()>DEFAULT_ATLAS_SIZE)
68   {
69     return Material();
70   }
71
72   unsigned int i = 0;
73   for( AtlasContainer::iterator iter = mAtlasList.begin(); iter != mAtlasList.end(); ++iter)
74   {
75     if( (*iter).Upload( textureRect, url, size, fittingMode, orientationCorrection ) )
76     {
77       return mMaterialList[i];
78     }
79     i++;
80   }
81
82   Toolkit::ImageAtlas newAtlas = Toolkit::ImageAtlas::New( DEFAULT_ATLAS_SIZE, DEFAULT_ATLAS_SIZE  );
83   if( !mBrokenImageUrl.empty() )
84   {
85     newAtlas.SetBrokenImage( mBrokenImageUrl );
86   }
87   mAtlasList.push_back( newAtlas );
88   Material newMaterial = Material::New( mShader );
89   newMaterial.AddTexture( newAtlas.GetAtlas(), mTextureUniformName );
90   mMaterialList.push_back( newMaterial );
91
92   newAtlas.Upload( textureRect, url, size, fittingMode, orientationCorrection );
93
94   return newMaterial;
95 }
96
97 void ImageAtlasManager::Remove( Material material, const Vector4& textureRect )
98 {
99   unsigned int i = 0;
100   for( MaterialContainer::iterator iter = mMaterialList.begin(); iter != mMaterialList.end(); ++iter)
101   {
102     if( (*iter) == material )
103     {
104       mAtlasList[i].Remove(textureRect);
105       return;
106     }
107     i++;
108   }
109 }
110
111 void ImageAtlasManager::SetBrokenImage( const std::string& brokenImageUrl )
112 {
113   if( !brokenImageUrl.empty() )
114   {
115     mBrokenImageUrl = brokenImageUrl;
116   }
117 }
118
119 } // namespace Internal
120
121 } // namespace Toolkit
122
123 } // namespace Dali