2 * Copyright (c) 2015 Samsung Electronics Co., Ltd.
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
19 #include <dali/devel-api/scripting/scripting.h>
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>
41 // Tables used here for converting strings to the enumerations and vice versa
42 const StringEnum IMAGE_LOAD_POLICY_TABLE[] =
44 { "IMMEDIATE", ResourceImage::IMMEDIATE },
45 { "ON_DEMAND", ResourceImage::ON_DEMAND },
47 const unsigned int IMAGE_LOAD_POLICY_TABLE_COUNT = sizeof( IMAGE_LOAD_POLICY_TABLE ) / sizeof( IMAGE_LOAD_POLICY_TABLE[0] );
49 const StringEnum IMAGE_RELEASE_POLICY_TABLE[] =
51 { "UNUSED", Image::UNUSED },
52 { "NEVER", Image::NEVER },
54 const unsigned int IMAGE_RELEASE_POLICY_TABLE_COUNT = sizeof( IMAGE_RELEASE_POLICY_TABLE ) / sizeof( IMAGE_RELEASE_POLICY_TABLE[0] );
56 const StringEnum PIXEL_FORMAT_TABLE[] =
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 },
85 const unsigned int PIXEL_FORMAT_TABLE_COUNT = sizeof( PIXEL_FORMAT_TABLE ) / sizeof( PIXEL_FORMAT_TABLE[0] );
87 const StringEnum IMAGE_FITTING_MODE_TABLE[] =
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 },
94 const unsigned int IMAGE_FITTING_MODE_TABLE_COUNT = sizeof( IMAGE_FITTING_MODE_TABLE ) / sizeof( IMAGE_FITTING_MODE_TABLE[0] );
96 const StringEnum IMAGE_SAMPLING_MODE_TABLE[] =
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 },
106 const unsigned int IMAGE_SAMPLING_MODE_TABLE_COUNT = sizeof( IMAGE_SAMPLING_MODE_TABLE ) / sizeof( IMAGE_SAMPLING_MODE_TABLE[0] );
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* );
112 } // unnamed namespace
114 bool EnumStringToInteger( const char * const value, const StringEnum* const enumTable, unsigned int tableCount, unsigned int& integerEnum )
116 unsigned int ret = 0;
121 if( value && enumTable && tableCount )
123 const char* pValue = value;
129 const StringEnum* table = enumTable;
131 for ( unsigned int i = 0; i < tableCount; ++i )
133 if( Internal::CompareTokens( pValue, table->string, size ) )
146 // allow comma separated or'd value
147 if( *(pValue+size) == ',' )
161 DALI_LOG_ERROR( "Unknown enumeration string %s\n", value );
166 unsigned int FindEnumIndex( const char* value, const StringEnum* table, unsigned int tableCount )
168 unsigned int index = 0;
170 for ( unsigned int i = 0; i < tableCount; ++i, ++index )
172 size_t sizeIgnored = 0;
173 if( Internal::CompareTokens( value, table->string, sizeIgnored ) )
182 DALI_LOG_ERROR( "Unknown enumeration string %s\n", value );
188 Image NewImage( const Property::Value& property )
192 std::string filename;
193 ResourceImage::LoadPolicy loadPolicy = Dali::Internal::IMAGE_LOAD_POLICY_DEFAULT;
194 Image::ReleasePolicy releasePolicy = Dali::Internal::IMAGE_RELEASE_POLICY_DEFAULT;
195 Internal::ImageAttributes attributes = Internal::ImageAttributes::New();
197 const Property::Map* map = property.GetMap();
198 ImageType imageType = RESOURCE_IMAGE; // default to resource image
201 // first check the type as it determines, which other parameters are needed
202 const Property::Value* value = map->Find( "type" );
207 for( unsigned int i = 0; i < imageTypeCount; ++i )
209 if( 0 == type.compare( ImageTypeName[ i ] ) )
211 imageType = static_cast<ImageType>( i );
217 // filename is only needed for resource images
218 if( RESOURCE_IMAGE == imageType )
220 const Property::Value* value = map->Find( "filename" );
223 value->Get( filename );
225 // if empty file, no need to go further
226 if( filename.size() == 0 )
228 DALI_LOG_ERROR( "No filename\n" );
233 value = map->Find( "loadPolicy" );
237 value->Get( policy );
238 // keep default value on error
239 GetEnumeration< ResourceImage::LoadPolicy >( policy.c_str(), IMAGE_LOAD_POLICY_TABLE, IMAGE_LOAD_POLICY_TABLE_COUNT, loadPolicy );
242 value = map->Find( "releasePolicy" );
246 value->Get( policy );
247 // keep default value on error
248 GetEnumeration< Image::ReleasePolicy >( policy.c_str(), IMAGE_RELEASE_POLICY_TABLE, IMAGE_RELEASE_POLICY_TABLE_COUNT, releasePolicy );
251 // Width and height can be set individually. Dali derives the unspecified
252 // dimension from the aspect ratio of the raw image.
253 int width = 0, height = 0;
255 value = map->Find( "width" );
258 // handle floats and integer the same for json script
259 if( value->GetType() == Property::FLOAT )
261 width = static_cast<unsigned int>( value->Get<float>() );
268 value = map->Find( "height" );
271 if( value->GetType() == Property::FLOAT )
273 height = static_cast<int>( value->Get<float>() );
277 value->Get( height );
280 attributes.SetSize( width, height );
282 Pixel::Format pixelFormat = Pixel::RGBA8888;
283 value = map->Find( "pixelFormat" );
287 value->Get( format );
288 GetEnumeration< Pixel::Format >( format.c_str(), PIXEL_FORMAT_TABLE, PIXEL_FORMAT_TABLE_COUNT, pixelFormat );
291 value = map->Find( "fittingMode" );
295 value->Get( fitting );
296 FittingMode::Type mode;
297 if( GetEnumeration< FittingMode::Type >( fitting.c_str(), IMAGE_FITTING_MODE_TABLE, IMAGE_FITTING_MODE_TABLE_COUNT, mode ) )
299 attributes.SetScalingMode( mode );
303 value = map->Find( "samplingMode" );
306 std::string sampling;
307 value->Get( sampling );
308 SamplingMode::Type mode;
309 if( GetEnumeration< SamplingMode::Type >( sampling.c_str(), IMAGE_SAMPLING_MODE_TABLE, IMAGE_SAMPLING_MODE_TABLE_COUNT, mode ) )
311 attributes.SetFilterMode( mode );
315 value = map->Find( "orientation" );
318 bool b = value->Get<bool>();
319 attributes.SetOrientationCorrection( b );
324 case RESOURCE_IMAGE :
326 ret = ResourceImage::New( filename, loadPolicy, releasePolicy,
327 ImageDimensions( attributes.GetSize().x, attributes.GetSize().y ),
328 attributes.GetScalingMode(), attributes.GetFilterMode(), attributes.GetOrientationCorrection() );
333 ret = BufferImage::New( attributes.GetWidth(),
334 attributes.GetHeight(),
339 case FRAME_BUFFER_IMAGE :
341 ret = FrameBufferImage::New( attributes.GetWidth(),
342 attributes.GetHeight(),
352 } // Image NewImage( Property::Value map )
355 Actor NewActor( const Property::Map& map )
359 // First find type and create Actor
360 Property::Value* typeValue = map.Find( "type" );
363 TypeInfo type = TypeRegistry::Get().GetTypeInfo( typeValue->Get< std::string >() );
366 handle = type.CreateInstance();
372 DALI_LOG_ERROR( "Actor type not provided\n" );
376 Actor actor( Actor::DownCast( handle ) );
380 // Now set the properties, or create children
381 for ( unsigned int i = 0, mapCount = map.Count(); i < mapCount; ++i )
383 const StringValuePair& pair( map.GetPair( i ) );
384 const std::string& key( pair.first );
390 const Property::Value& value( pair.second );
392 if ( key == "actors" )
395 Property::Array actorArray = value.Get< Property::Array >();
396 for ( Property::Array::SizeType i = 0; i < actorArray.Size(); ++i)
398 actor.Add( NewActor( actorArray[i].Get< Property::Map >() ) );
403 Property::Index index( actor.GetPropertyIndex( key ) );
405 if ( index != Property::INVALID_INDEX )
407 actor.SetProperty( index, value );
416 void CreatePropertyMap( Actor actor, Property::Map& map )
422 map[ "type" ] = actor.GetTypeName();
424 // Default properties
425 Property::IndexContainer indices;
426 actor.GetPropertyIndices( indices );
427 const Property::IndexContainer::ConstIterator endIter = indices.End();
429 for ( Property::IndexContainer::Iterator iter = indices.Begin(); iter != endIter; ++iter )
431 map[ actor.GetPropertyName( *iter ) ] = actor.GetProperty( *iter );
435 unsigned int childCount( actor.GetChildCount() );
438 Property::Array childArray;
439 for ( unsigned int child = 0; child < childCount; ++child )
441 Property::Map childMap;
442 CreatePropertyMap( actor.GetChildAt( child ), childMap );
443 childArray.PushBack( childMap );
445 map[ "actors" ] = childArray;
450 void CreatePropertyMap( Image image, Property::Map& map )
456 std::string imageType( "ResourceImage" );
458 // Get Type - cannot use TypeRegistry as Image is not an Object and thus, not registered
459 BufferImage bufferImage = BufferImage::DownCast( image );
462 imageType = "BufferImage";
463 map[ "pixelFormat" ] = GetEnumerationName< Pixel::Format >( bufferImage.GetPixelFormat(), PIXEL_FORMAT_TABLE, PIXEL_FORMAT_TABLE_COUNT );
465 else if ( FrameBufferImage::DownCast( image ) )
467 imageType = "FrameBufferImage";
470 map[ "type" ] = imageType;
471 map[ "releasePolicy" ] = GetEnumerationName< Image::ReleasePolicy >( image.GetReleasePolicy(), IMAGE_RELEASE_POLICY_TABLE, IMAGE_RELEASE_POLICY_TABLE_COUNT );
473 ResourceImage resourceImage = ResourceImage::DownCast( image );
476 map[ "filename" ] = resourceImage.GetUrl();
477 map[ "loadPolicy" ] = GetEnumerationName< ResourceImage::LoadPolicy >( resourceImage.GetLoadPolicy(), IMAGE_LOAD_POLICY_TABLE, IMAGE_LOAD_POLICY_TABLE_COUNT );
480 int width( image.GetWidth() );
481 int height( image.GetHeight() );
483 if ( width && height )
485 map[ "width" ] = width;
486 map[ "height" ] = height;
491 void NewAnimation( const Property::Map& map, Dali::AnimationData& outputAnimationData )
493 // Note: Builder cannot currently pass generic Property::Maps "{" that are nested, so currently we can only have one AnimateTo per animation.
494 Dali::AnimationData::AnimationDataElement* element = new Dali::AnimationData::AnimationDataElement();
495 element->alphaFunction = AlphaFunction::LINEAR;
496 element->timePeriodDelay = 0.0f;
497 element->timePeriodDuration = 1.0f;
499 // Now set the properties, or create children
500 for( unsigned int i = 0, animationMapCount = map.Count(); i < animationMapCount; ++i )
502 const StringValuePair& pair( map.GetPair( i ) );
503 const std::string& key( pair.first );
504 const Property::Value& value( pair.second );
508 element->actor = value.Get< std::string >();
510 else if( key == "property" )
512 element->property = value.Get< std::string >();
514 else if( key == "value" )
516 element->value = value;
518 else if( key == "alphaFunction" )
520 std::string alphaFunctionValue = value.Get< std::string >();
522 if( alphaFunctionValue == "LINEAR" )
524 element->alphaFunction = AlphaFunction::LINEAR;
526 else if( alphaFunctionValue == "REVERSE" )
528 element->alphaFunction = AlphaFunction::REVERSE;
530 else if( alphaFunctionValue == "EASE_IN_SQUARE" )
532 element->alphaFunction = AlphaFunction::EASE_IN_SQUARE;
534 else if( alphaFunctionValue == "EASE_OUT_SQUARE" )
536 element->alphaFunction = AlphaFunction::EASE_OUT_SQUARE;
538 else if( alphaFunctionValue == "EASE_IN" )
540 element->alphaFunction = AlphaFunction::EASE_IN;
542 else if( alphaFunctionValue == "EASE_OUT" )
544 element->alphaFunction = AlphaFunction::EASE_OUT;
546 else if( alphaFunctionValue == "EASE_IN_OUT" )
548 element->alphaFunction = AlphaFunction::EASE_IN_OUT;
550 else if( alphaFunctionValue == "EASE_IN_SINE" )
552 element->alphaFunction = AlphaFunction::EASE_IN_SINE;
554 else if( alphaFunctionValue == "EASE_OUT_SINE" )
556 element->alphaFunction = AlphaFunction::EASE_OUT_SINE;
558 else if( alphaFunctionValue == "EASE_IN_OUT_SINE" )
560 element->alphaFunction = AlphaFunction::EASE_IN_OUT_SINE;
562 else if( alphaFunctionValue == "BOUNCE" )
564 element->alphaFunction = AlphaFunction::BOUNCE;
566 else if( alphaFunctionValue == "SIN" )
568 element->alphaFunction = AlphaFunction::SIN;
570 else if( alphaFunctionValue == "EASE_OUT_BACK" )
572 element->alphaFunction = AlphaFunction::EASE_OUT_BACK;
575 else if( key == "timePeriod" )
577 Property::Map timeMap = value.Get< Property::Map >();
578 for( unsigned int i = 0; i < timeMap.Count(); ++i )
580 const StringValuePair& pair( timeMap.GetPair( i ) );
581 if( pair.first == "delay" )
583 element->timePeriodDelay = pair.second.Get< float >();
585 else if( pair.first == "duration" )
587 element->timePeriodDuration = pair.second.Get< float >();
593 outputAnimationData.Add( element );
596 } // namespace scripting