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