883592f9984b2d2ed798113f29c764727c5e1439
[platform/core/uifw/dali-core.git] / dali / devel-api / scripting / scripting.cpp
1 /*
2  * Copyright (c) 2016 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/devel-api/scripting/scripting.h>
20
21 // INTERNAL INCLUDES
22 #include <dali/public-api/actors/actor.h>
23 #include <dali/public-api/images/resource-image.h>
24 #include <dali/public-api/object/type-registry.h>
25 #include <dali/public-api/object/property-array.h>
26 #include <dali/internal/common/image-attributes.h>
27 #include <dali/internal/event/common/property-helper.h>
28 #include <dali/internal/event/images/resource-image-impl.h>
29 #include <dali/internal/event/images/frame-buffer-image-impl.h>
30 #include <dali/internal/event/images/buffer-image-impl.h>
31
32 namespace Dali
33 {
34
35 namespace Scripting
36 {
37
38 namespace
39 {
40
41 // Tables used here for converting strings to the enumerations and vice versa
42 const StringEnum IMAGE_LOAD_POLICY_TABLE[] =
43 {
44   { "IMMEDIATE", ResourceImage::IMMEDIATE },
45   { "ON_DEMAND", ResourceImage::ON_DEMAND },
46 };
47 const unsigned int IMAGE_LOAD_POLICY_TABLE_COUNT = sizeof( IMAGE_LOAD_POLICY_TABLE ) / sizeof( IMAGE_LOAD_POLICY_TABLE[0] );
48
49 const StringEnum IMAGE_RELEASE_POLICY_TABLE[] =
50 {
51   { "UNUSED", Image::UNUSED },
52   { "NEVER",  Image::NEVER  },
53 };
54 const unsigned int IMAGE_RELEASE_POLICY_TABLE_COUNT = sizeof( IMAGE_RELEASE_POLICY_TABLE ) / sizeof( IMAGE_RELEASE_POLICY_TABLE[0] );
55
56 const StringEnum PIXEL_FORMAT_TABLE[] =
57 {
58   { "A8",                                           Pixel::A8                                           },
59   { "L8",                                           Pixel::L8                                           },
60   { "LA88",                                         Pixel::LA88                                         },
61   { "RGB565",                                       Pixel::RGB565                                       },
62   { "BGR565",                                       Pixel::BGR565                                       },
63   { "RGBA4444",                                     Pixel::RGBA4444                                     },
64   { "BGRA4444",                                     Pixel::BGRA4444                                     },
65   { "RGBA5551",                                     Pixel::RGBA5551                                     },
66   { "BGRA5551",                                     Pixel::BGRA5551                                     },
67   { "RGB888",                                       Pixel::RGB888                                       },
68   { "RGB8888",                                      Pixel::RGB8888                                      },
69   { "BGR8888",                                      Pixel::BGR8888                                      },
70   { "RGBA8888",                                     Pixel::RGBA8888                                     },
71   { "BGRA8888",                                     Pixel::BGRA8888                                     },
72   { "COMPRESSED_R11_EAC",                           Pixel::COMPRESSED_R11_EAC                           },
73   { "COMPRESSED_SIGNED_R11_EAC",                    Pixel::COMPRESSED_SIGNED_R11_EAC                    },
74   { "COMPRESSED_SIGNED_RG11_EAC",                   Pixel::COMPRESSED_SIGNED_RG11_EAC                   },
75   { "COMPRESSED_RG11_EAC",                          Pixel::COMPRESSED_RG11_EAC                          },
76   { "COMPRESSED_RGB8_ETC2",                         Pixel::COMPRESSED_RGB8_ETC2                         },
77   { "COMPRESSED_SRGB8_ETC2",                        Pixel::COMPRESSED_SRGB8_ETC2                        },
78   { "COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2",     Pixel::COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2     },
79   { "COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2",    Pixel::COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2    },
80   { "COMPRESSED_RGBA8_ETC2_EAC",                    Pixel::COMPRESSED_RGBA8_ETC2_EAC                    },
81   { "COMPRESSED_SRGB8_ALPHA8_ETC2_EAC",             Pixel::COMPRESSED_SRGB8_ALPHA8_ETC2_EAC             },
82   { "COMPRESSED_RGB8_ETC1",                         Pixel::COMPRESSED_RGB8_ETC1                         },
83   { "COMPRESSED_RGB_PVRTC_4BPPV1",                  Pixel::COMPRESSED_RGB_PVRTC_4BPPV1                  },
84 };
85 const unsigned int PIXEL_FORMAT_TABLE_COUNT = sizeof( PIXEL_FORMAT_TABLE ) / sizeof( PIXEL_FORMAT_TABLE[0] );
86
87 const StringEnum IMAGE_FITTING_MODE_TABLE[] =
88 {
89   { "SHRINK_TO_FIT", FittingMode::SHRINK_TO_FIT },
90   { "SCALE_TO_FILL", FittingMode::SCALE_TO_FILL },
91   { "FIT_WIDTH",     FittingMode::FIT_WIDTH    },
92   { "FIT_HEIGHT",    FittingMode::FIT_HEIGHT   },
93 };
94 const unsigned int IMAGE_FITTING_MODE_TABLE_COUNT = sizeof( IMAGE_FITTING_MODE_TABLE ) / sizeof( IMAGE_FITTING_MODE_TABLE[0] );
95
96 const StringEnum IMAGE_SAMPLING_MODE_TABLE[] =
97 {
98   { "BOX",              SamplingMode::BOX            },
99   { "NEAREST",          SamplingMode::NEAREST        },
100   { "LINEAR",           SamplingMode::LINEAR         },
101   { "BOX_THEN_NEAREST", SamplingMode::BOX_THEN_NEAREST },
102   { "BOX_THEN_LINEAR",  SamplingMode::BOX_THEN_LINEAR  },
103   { "NO_FILTER",        SamplingMode::NO_FILTER       },
104   { "DONT_CARE",        SamplingMode::DONT_CARE       },
105 };
106 const unsigned int IMAGE_SAMPLING_MODE_TABLE_COUNT = sizeof( IMAGE_SAMPLING_MODE_TABLE ) / sizeof( IMAGE_SAMPLING_MODE_TABLE[0] );
107
108 const char* ImageTypeName[] = { "ResourceImage", "FrameBufferImage", "BufferImage" };
109 enum ImageType                { RESOURCE_IMAGE,  FRAME_BUFFER_IMAGE, BUFFER_IMAGE };
110 const unsigned int imageTypeCount = sizeof( ImageTypeName ) / sizeof( const char* );
111
112 } // unnamed namespace
113
114 bool EnumStringToInteger( const char * const value, const StringEnum* const enumTable, unsigned int tableCount, int& integerEnum )
115 {
116   int ret = 0;
117
118   bool found = false;
119   bool done = false;
120
121   if( value && enumTable && tableCount )
122   {
123     const char* pValue = value;
124
125     while(!done)
126     {
127       size_t size = 0;
128
129       const StringEnum* table = enumTable;
130
131       for ( unsigned int i = 0; i < tableCount; ++i )
132       {
133         if( Internal::CompareTokens( pValue, table->string, size ) )
134         {
135           found = true;
136           ret |= table->value;
137           break;
138         }
139         table++;
140       }
141
142       done = true;
143
144       if(found)
145       {
146         // allow comma separated or'd value
147         if( *(pValue+size) == ',' )
148         {
149           pValue += size + 1;
150           done = false;
151         }
152       }
153
154     }
155
156     integerEnum = ret;
157   }
158
159   if ( !found )
160   {
161     DALI_LOG_ERROR( "Unknown enumeration string %s\n", value );
162   }
163   return found;
164 }
165
166 unsigned int FindEnumIndex( const char* value, const StringEnum* table, unsigned int tableCount )
167 {
168   unsigned int index = 0;
169   bool found = false;
170   for ( unsigned int i = 0; i < tableCount; ++i, ++index )
171   {
172     size_t sizeIgnored = 0;
173     if( Internal::CompareTokens( value, table->string, sizeIgnored ) )
174     {
175       found = true;
176       break;
177     }
178     ++table;
179   }
180   if ( !found )
181   {
182     DALI_LOG_ERROR( "Unknown enumeration string %s\n", value );
183   }
184   return index;
185 }
186
187
188 Image NewImage( const Property::Value& property )
189 {
190   Image ret;
191
192   std::string filename;
193   Internal::ImageAttributes attributes = Internal::ImageAttributes::New();
194
195   const Property::Map* map = property.GetMap();
196   ImageType imageType = RESOURCE_IMAGE; // default to resource image
197   if( map )
198   {
199     // first check the type as it determines, which other parameters are needed
200     const Property::Value* value = map->Find( "type" );
201     if( value )
202     {
203       std::string type;
204       value->Get( type );
205       for( unsigned int i = 0; i < imageTypeCount; ++i )
206       {
207         if( 0 == type.compare( ImageTypeName[ i ] ) )
208         {
209           imageType = static_cast<ImageType>( i );
210           break;
211         }
212       }
213     }
214
215     // filename is only needed for resource images
216     if( RESOURCE_IMAGE == imageType )
217     {
218       const Property::Value* value = map->Find( "filename" );
219       if( value )
220       {
221         value->Get( filename );
222       }
223       // if empty file, no need to go further
224       if( filename.size() == 0 )
225       {
226         DALI_LOG_ERROR( "No filename\n" );
227         return Image();
228       }
229     }
230
231     // Width and height can be set individually. Dali derives the unspecified
232     // dimension from the aspect ratio of the raw image.
233     int width = 0, height = 0;
234
235     value = map->Find( "width" );
236     if( value )
237     {
238       // handle floats and integer the same for json script
239       if( value->GetType() == Property::FLOAT )
240       {
241         width = static_cast<unsigned int>( value->Get<float>() );
242       }
243       else
244       {
245         value->Get( width );
246       }
247     }
248     value = map->Find( "height" );
249     if( value )
250     {
251       if( value->GetType() == Property::FLOAT )
252       {
253         height = static_cast<int>( value->Get<float>() );
254       }
255       else
256       {
257         value->Get( height );
258       }
259     }
260     attributes.SetSize( width, height );
261
262     Pixel::Format pixelFormat = Pixel::RGBA8888;
263     value = map->Find( "pixelFormat" );
264     if( value )
265     {
266       std::string format;
267       value->Get( format );
268       GetEnumeration< Pixel::Format >( format.c_str(), PIXEL_FORMAT_TABLE, PIXEL_FORMAT_TABLE_COUNT, pixelFormat );
269     }
270
271     value = map->Find( "fittingMode" );
272     if( value )
273     {
274       std::string fitting;
275       value->Get( fitting );
276       FittingMode::Type mode;
277       if( GetEnumeration< FittingMode::Type >( fitting.c_str(), IMAGE_FITTING_MODE_TABLE, IMAGE_FITTING_MODE_TABLE_COUNT, mode ) )
278       {
279         attributes.SetScalingMode( mode );
280       }
281     }
282
283     value = map->Find( "samplingMode" );
284     if( value )
285     {
286       std::string sampling;
287       value->Get( sampling );
288       SamplingMode::Type mode;
289       if( GetEnumeration< SamplingMode::Type >( sampling.c_str(), IMAGE_SAMPLING_MODE_TABLE, IMAGE_SAMPLING_MODE_TABLE_COUNT, mode ) )
290       {
291         attributes.SetFilterMode( mode );
292       }
293     }
294
295     value = map->Find( "orientation" );
296     if( value )
297     {
298       bool b = value->Get<bool>();
299       attributes.SetOrientationCorrection( b );
300     }
301
302     switch( imageType )
303     {
304       case RESOURCE_IMAGE :
305       {
306         ret = ResourceImage::New( filename, ImageDimensions( attributes.GetSize().x, attributes.GetSize().y ),
307                                   attributes.GetScalingMode(), attributes.GetFilterMode(), attributes.GetOrientationCorrection() );
308         break;
309       }
310       case BUFFER_IMAGE :
311       {
312         ret = BufferImage::New( attributes.GetWidth(),
313                                 attributes.GetHeight(),
314                                 pixelFormat );
315         break;
316       }
317       case FRAME_BUFFER_IMAGE :
318       {
319         ret = FrameBufferImage::New( attributes.GetWidth(),
320                                      attributes.GetHeight(),
321                                      pixelFormat );
322         break;
323       }
324     }
325   }
326
327   return ret;
328
329 } // Image NewImage( Property::Value map )
330
331
332 Actor NewActor( const Property::Map& map )
333 {
334   BaseHandle handle;
335
336   // First find type and create Actor
337   Property::Value* typeValue = map.Find( "type" );
338   if ( typeValue )
339   {
340     TypeInfo type = TypeRegistry::Get().GetTypeInfo( typeValue->Get< std::string >() );
341     if ( type )
342     {
343       handle = type.CreateInstance();
344     }
345   }
346
347   if ( !handle )
348   {
349     DALI_LOG_ERROR( "Actor type not provided\n" );
350     return Actor();
351   }
352
353   Actor actor( Actor::DownCast( handle ) );
354
355   if ( actor )
356   {
357     // Now set the properties, or create children
358     for ( unsigned int i = 0, mapCount = map.Count(); i < mapCount; ++i )
359     {
360       const StringValuePair& pair( map.GetPair( i ) );
361       const std::string& key( pair.first );
362       if ( key == "type" )
363       {
364         continue;
365       }
366
367       const Property::Value& value( pair.second );
368
369       if ( key == "actors" )
370       {
371         // Create children
372         Property::Array actorArray = value.Get< Property::Array >();
373         for ( Property::Array::SizeType i = 0; i < actorArray.Size(); ++i)
374         {
375           actor.Add( NewActor( actorArray[i].Get< Property::Map >() ) );
376         }
377       }
378       else
379       {
380         Property::Index index( actor.GetPropertyIndex( key ) );
381
382         if ( index != Property::INVALID_INDEX )
383         {
384           actor.SetProperty( index, value );
385         }
386       }
387     }
388   }
389
390   return actor;
391 }
392
393 void CreatePropertyMap( Actor actor, Property::Map& map )
394 {
395   map.Clear();
396
397   if ( actor )
398   {
399     map[ "type" ] = actor.GetTypeName();
400
401     // Default properties
402     Property::IndexContainer indices;
403     actor.GetPropertyIndices( indices );
404     const Property::IndexContainer::ConstIterator endIter = indices.End();
405
406     for ( Property::IndexContainer::Iterator iter = indices.Begin(); iter != endIter; ++iter )
407     {
408       map[ actor.GetPropertyName( *iter ) ] = actor.GetProperty( *iter );
409     }
410
411     // Children
412     unsigned int childCount( actor.GetChildCount() );
413     if ( childCount )
414     {
415       Property::Array childArray;
416       for ( unsigned int child = 0; child < childCount; ++child )
417       {
418         Property::Map childMap;
419         CreatePropertyMap( actor.GetChildAt( child ), childMap );
420         childArray.PushBack( childMap );
421       }
422       map[ "actors" ] = childArray;
423     }
424   }
425 }
426
427 void CreatePropertyMap( Image image, Property::Map& map )
428 {
429   map.Clear();
430
431   if ( image )
432   {
433     std::string imageType( "ResourceImage" );
434
435     // Get Type - cannot use TypeRegistry as Image is not an Object and thus, not registered
436     BufferImage bufferImage = BufferImage::DownCast( image );
437     if ( bufferImage )
438     {
439       imageType = "BufferImage";
440       map[ "pixelFormat" ] = GetEnumerationName< Pixel::Format >( bufferImage.GetPixelFormat(), PIXEL_FORMAT_TABLE, PIXEL_FORMAT_TABLE_COUNT );
441     }
442     else if ( FrameBufferImage::DownCast( image ) )
443     {
444       imageType = "FrameBufferImage";
445     }
446
447     map[ "type" ] = imageType;
448     map[ "releasePolicy" ] = GetEnumerationName< Image::ReleasePolicy >( image.GetReleasePolicy(), IMAGE_RELEASE_POLICY_TABLE, IMAGE_RELEASE_POLICY_TABLE_COUNT );
449
450     ResourceImage resourceImage = ResourceImage::DownCast( image );
451     if( resourceImage )
452     {
453       map[ "filename" ] = resourceImage.GetUrl();
454       map[ "loadPolicy" ] = GetEnumerationName< ResourceImage::LoadPolicy >( resourceImage.GetLoadPolicy(), IMAGE_LOAD_POLICY_TABLE, IMAGE_LOAD_POLICY_TABLE_COUNT );
455     }
456
457     int width( image.GetWidth() );
458     int height( image.GetHeight() );
459
460     if ( width && height )
461     {
462       map[ "width" ] = width;
463       map[ "height" ] = height;
464     }
465   }
466 }
467
468 void NewAnimation( const Property::Map& map, Dali::AnimationData& outputAnimationData )
469 {
470   // Note: Builder cannot currently pass generic Property::Maps "{" that are nested, so currently we can only have one AnimateTo per animation.
471   Dali::AnimationData::AnimationDataElement* element = new Dali::AnimationData::AnimationDataElement();
472   element->alphaFunction = AlphaFunction::LINEAR;
473   element->timePeriodDelay = 0.0f;
474   element->timePeriodDuration = 1.0f;
475
476   // Now set the properties, or create children
477   for( unsigned int i = 0, animationMapCount = map.Count(); i < animationMapCount; ++i )
478   {
479     const StringValuePair& pair( map.GetPair( i ) );
480     const std::string& key( pair.first );
481     const Property::Value& value( pair.second );
482
483     if( key == "actor" )
484     {
485       element->actor = value.Get< std::string >();
486     }
487     else if( key == "property" )
488     {
489       element->property = value.Get< std::string >();
490     }
491     else if( key == "value" )
492     {
493       element->value = value;
494     }
495     else if( key == "alphaFunction" )
496     {
497       std::string alphaFunctionValue = value.Get< std::string >();
498
499       if( alphaFunctionValue == "LINEAR" )
500       {
501         element->alphaFunction = AlphaFunction::LINEAR;
502       }
503       else if( alphaFunctionValue == "REVERSE" )
504       {
505         element->alphaFunction = AlphaFunction::REVERSE;
506       }
507       else if( alphaFunctionValue == "EASE_IN_SQUARE" )
508       {
509         element->alphaFunction = AlphaFunction::EASE_IN_SQUARE;
510       }
511       else if( alphaFunctionValue == "EASE_OUT_SQUARE" )
512       {
513         element->alphaFunction = AlphaFunction::EASE_OUT_SQUARE;
514       }
515       else if( alphaFunctionValue == "EASE_IN" )
516       {
517         element->alphaFunction = AlphaFunction::EASE_IN;
518       }
519       else if( alphaFunctionValue == "EASE_OUT" )
520       {
521         element->alphaFunction = AlphaFunction::EASE_OUT;
522       }
523       else if( alphaFunctionValue == "EASE_IN_OUT" )
524       {
525         element->alphaFunction = AlphaFunction::EASE_IN_OUT;
526       }
527       else if( alphaFunctionValue == "EASE_IN_SINE" )
528       {
529         element->alphaFunction = AlphaFunction::EASE_IN_SINE;
530       }
531       else if( alphaFunctionValue == "EASE_OUT_SINE" )
532       {
533         element->alphaFunction = AlphaFunction::EASE_OUT_SINE;
534       }
535       else if( alphaFunctionValue == "EASE_IN_OUT_SINE" )
536       {
537         element->alphaFunction = AlphaFunction::EASE_IN_OUT_SINE;
538       }
539       else if( alphaFunctionValue == "BOUNCE" )
540       {
541         element->alphaFunction = AlphaFunction::BOUNCE;
542       }
543       else if( alphaFunctionValue == "SIN" )
544       {
545         element->alphaFunction = AlphaFunction::SIN;
546       }
547       else if( alphaFunctionValue == "EASE_OUT_BACK" )
548       {
549         element->alphaFunction = AlphaFunction::EASE_OUT_BACK;
550       }
551     }
552     else if( key == "timePeriod" )
553     {
554       Property::Map timeMap = value.Get< Property::Map >();
555       for( unsigned int i = 0; i < timeMap.Count(); ++i )
556       {
557         const StringValuePair& pair( timeMap.GetPair( i ) );
558         if( pair.first == "delay" )
559         {
560           element->timePeriodDelay = pair.second.Get< float >();
561         }
562         else if( pair.first == "duration" )
563         {
564           element->timePeriodDuration = pair.second.Get< float >();
565         }
566       }
567     }
568   }
569
570   outputAnimationData.Add( element );
571 }
572
573 } // namespace scripting
574
575 } // namespace Dali
576
577
578
579