License conversion from Flora to Apache 2.0
[platform/core/uifw/dali-toolkit.git] / optional / dali-toolkit / internal / controls / image-view / image-view-impl.cpp
1 /*
2  * Copyright (c) 2014 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 #include <dali-toolkit/internal/controls/image-view/image-view-impl.h>
19 #include <dali-toolkit/public-api/shader-effects/distance-field-effect.h>
20
21 using namespace Dali;
22
23 namespace
24 {
25 //Type registration
26 BaseHandle Create()
27 {
28   return Toolkit::ImageView::New();
29 }
30 TypeRegistration mType( typeid(Toolkit::ImageView), typeid(Toolkit::Control), Create );
31
32   /**
33    * CameraDetailConstraint, generates detail value
34    * based on camera's position and ImageView's position.
35    */
36   struct CameraDetailConstraint
37   {
38     CameraDetailConstraint(float detailFactor)
39       : mDetailFactor(detailFactor)
40     {
41
42     }
43
44     float operator()(const float&    current,
45                      const PropertyInput& propertyTargetPosition,
46                      const PropertyInput& propertySourcePosition)
47     {
48       const Vector3& targetPosition = propertyTargetPosition.GetVector3();
49       const Vector3& sourcePosition = propertySourcePosition.GetVector3();
50       const float distance = (targetPosition - sourcePosition).Length();
51       const float detail = mDetailFactor / distance;
52
53       return detail;
54     }
55
56     const float mDetailFactor;
57   };
58
59 } // unnamed namespace
60
61 namespace Dali
62 {
63
64 namespace Toolkit
65 {
66
67 namespace Internal
68 {
69
70 ///////////////////////////////////////////////////////////////////////////////////////////////////
71 // ImageView
72 ///////////////////////////////////////////////////////////////////////////////////////////////////
73
74 Dali::Toolkit::ImageView ImageView::New()
75 {
76   // Create the implementation
77   ImageViewPtr imageView(new ImageView());
78
79   // Pass ownership to CustomActor via derived handle
80   Dali::Toolkit::ImageView handle(*imageView);
81
82   // Second-phase init of the implementation
83   // This can only be done after the CustomActor connection has been made...
84   imageView->Initialize();
85
86   return handle;
87 }
88
89 ImageView::ImageView()
90 : ControlImpl(true)
91 {
92 }
93
94 void ImageView::Initialize()
95 {
96   Actor self = Self();
97   // Register property that represents the level of detail.
98   mPropertyDetail = self.RegisterProperty(Toolkit::ImageView::DETAIL_PROPERTY_NAME, 0.0f);
99
100   // Create an empty image actor, filling the entire size of this ImageView.
101   Image emptyImage;
102   mImageActor = ImageActor::New( emptyImage );
103   self.Add( mImageActor );
104   mImageActor.ApplyConstraint( Constraint::New<Vector3>( Actor::SIZE, ParentSource( Actor::SIZE ), EqualToConstraint() ) );
105   mImageActor.SetParentOrigin( ParentOrigin::CENTER );
106 }
107
108 ImageView::~ImageView()
109 {
110
111 }
112
113 void ImageView::SetImage(const std::string& filename, ImageType type, float min, float max)
114 {
115   switch(type)
116   {
117     case Toolkit::ImageView::BitmapType:
118     {
119       SetImageBitmap(filename, min, max);
120       break;
121     }
122     case Toolkit::ImageView::DistanceFieldType:
123     {
124       SetImageDistanceField(filename);
125       break;
126     }
127   }
128 }
129
130 void ImageView::SetImageBitmap(const std::string& filename, float min, float max)
131 {
132   int minLevel = ceilf(logf(min) / logf(2.0f));
133   int maxLevel = ceilf(logf(max) / logf(2.0f));
134
135   ImageAttributes attributes;
136   const Vector3 size = Self().GetCurrentSize();
137
138   if(minLevel==maxLevel)
139   { // Single image detail level, no need for any notifications.
140     const float detail = powf(2.0f, maxLevel);
141     attributes.SetSize( size.x * detail, size.y * detail );
142     Image image = Image::New( filename, attributes);
143     mImageActor.SetImage( image );
144   }
145   else
146   { // Multi image detail level...
147     for( int level = minLevel; level <= maxLevel; level++)
148     {
149       const float minDetail = powf(2.0f, level - 1);
150       const float maxDetail = powf(2.0f, level);
151       ImageRequest req(filename, size.x * maxDetail, size.y * maxDetail );
152
153       if(level==minLevel)
154       {
155         AddImage(req, LessThanCondition(maxDetail) );
156       }
157       else if(level==maxLevel)
158       {
159         AddImage(req, GreaterThanCondition(minDetail) );
160       }
161       else
162       {
163         AddImage(req, InsideCondition(minDetail, maxDetail) );
164       }
165     }
166   }
167 }
168
169 void ImageView::SetImageDistanceField(const std::string& filename)
170 {
171   ImageAttributes attributes = Dali::ImageAttributes::NewDistanceField(1.0f, 1);
172   const Vector3 size = Self().GetCurrentSize();
173
174   attributes.SetSize( size.x, size.y );
175   Image image = Image::NewDistanceField(filename, attributes);
176   mImageActor.SetImage( image );
177
178   DistanceFieldEffect effect = DistanceFieldEffect::New();
179   Self().SetShaderEffect( effect );
180 }
181
182 void ImageView::SetImage(Image image)
183 {
184   mImageActor.SetImage( image );
185 }
186
187 void ImageView::AddImage(ImageRequest& req, PropertyCondition condition)
188 {
189   Actor self = Self();
190
191   PropertyNotification notification = self.AddPropertyNotification( mPropertyDetail, condition );
192
193   notification.NotifySignal().Connect( this, &ImageView::OnDetailChange );
194
195   mNotifications[notification] = req;
196 }
197
198 void ImageView::SetDetail(float detail)
199 {
200   Self().SetProperty( mPropertyDetail, detail );
201 }
202
203 void ImageView::SetCameraActor(CameraActor camera, float detailFactor)
204 {
205   Constraint constraint = Constraint::New<float>( mPropertyDetail,
206                                                   LocalSource( Actor::WORLD_POSITION ),
207                                                   Source( camera, Actor::WORLD_POSITION ),
208                                                   CameraDetailConstraint(detailFactor));
209   Self().RemoveConstraints();
210   Self().ApplyConstraint(constraint);
211 }
212
213 void ImageView::OnDetailChange( PropertyNotification& notification )
214 {
215   ImageRequest& req = mNotifications[notification];
216   Image image = Image::New( req.mFilename, req.mAttributes );
217   mImageActor.SetImage( image );
218 }
219
220 } // namespace Internal
221
222 } // namespace Toolkit
223
224 } // namespace Dali