Merge branch 'tizen' into devel/new_mesh
[platform/core/uifw/dali-toolkit.git] / plugins / dali-script-v8 / src / dali-wrapper.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 "dali-wrapper.h"
20
21 // INTERNAL INCLUDES
22 #include <v8-utils.h>
23 #include <object/property-value-wrapper.h>
24 #include <dali/integration-api/debug.h>
25 #include <actors/actor-wrapper.h>
26 #include <stage/stage-wrapper.h>
27 #include <image/image-attributes-wrapper.h>
28 #include <image/image-wrapper.h>
29 #include <text/font-wrapper.h>
30 #include <animation/path-wrapper.h>
31 #include <animation/path-constraint-wrapper.h>
32 #include <animation/animation-wrapper.h>
33 #include <events/pan-gesture-detector-wrapper.h>
34 #include <shader-effects/shader-effect-wrapper.h>
35 #include <shared/object-template-helper.h>
36 #include <constants/constants-wrapper.h>
37 #include <toolkit/builder/builder-wrapper.h>
38 #include <toolkit/focus-manager/keyboard-focus-manager-wrapper.h>
39
40
41 namespace Dali
42 {
43
44 namespace V8Plugin
45 {
46
47 namespace
48 {
49 /**
50  * This string defines how the global DALi object/namespace is used from JavaScript
51  * E.g. new dali.Image or dali.stage.add( )
52  */
53 const char* const DALI_API_NAME = "dali";
54
55 /**
56  * lookup table for setting up function calls for creating Dali objects
57  * e.g.  new dali.TextActor()
58  */
59 const ApiFunction ConstructorFunctionTable[]=
60 {
61     { "Rotation",           PropertyValueWrapper::NewRotation},
62     { "Matrix",             PropertyValueWrapper::NewMatrix},
63     { "Font",               FontWrapper::NewFont },
64     { "Path",               PathWrapper::NewPath },
65     { "PathConstraint",     PathConstraintWrapper::NewPathConstraint },
66     { "Actor",              ActorWrapper::NewActor },
67     { "TextActor",          ActorWrapper::NewActor },
68     { "ImageActor",         ActorWrapper::NewActor },
69     { "MeshActor",          ActorWrapper::NewActor },
70     { "CameraActor",        ActorWrapper::NewActor },
71     { "Layer",              ActorWrapper::NewActor },
72     { "TextView",           ActorWrapper::NewActor },
73     { "ResourceImage",      ImageWrapper::NewImage },
74     { "BufferImage",        ImageWrapper::NewImage },
75     { "NinePatchImage",     ImageWrapper::NewImage },
76     { "FrameBufferImage",   ImageWrapper::NewImage },
77     { "ImageAttributes",    ImageAttributesWrapper::NewImageAttributes },
78     { "Animation",          AnimationWrapper::NewAnimation},
79     { "ShaderEffect",       ShaderEffectWrapper::NewShaderEffect},
80     { "Builder",            BuilderWrapper::NewBuilder},
81     { "PanGestureDetector", PanGestureDetectorWrapper::NewPanGestureDetector},
82
83 };
84
85 const unsigned int PropertyFunctionTableCount = sizeof(ConstructorFunctionTable)/sizeof(ConstructorFunctionTable[0]);
86
87 void FatalErrorCallback(const char* location, const char* message)
88 {
89   DALI_LOG_ERROR("%s, %s \n",location,message);
90   DALI_ASSERT_ALWAYS( 0 && "V8 fatal error");
91 }
92
93 #if defined(DEBUG_ENABLED)
94 // default to verbose logging
95 Integration::Log::Filter* gLogExecuteFilter( Integration::Log::Filter::New(Debug::Verbose, false, "EXECUTE_JAVASCRIPT") );
96 #endif
97 } // un-named name space
98
99
100
101 bool DaliWrapper::mInstanceCreated = false;
102 DaliWrapper* DaliWrapper::mWrapper = NULL;
103
104 DaliWrapper::DaliWrapper()
105 :mIsolate( NULL )
106 {
107 }
108
109 DaliWrapper::~DaliWrapper()
110 {
111   mInstanceCreated = false;
112 }
113
114 DaliWrapper& DaliWrapper::Get()
115 {
116   if(!mInstanceCreated)
117   {
118     mWrapper = new DaliWrapper();
119     mInstanceCreated = true;
120
121     if(mWrapper)
122     {
123       mWrapper->Initialize();
124     }
125   }
126
127   return *mWrapper;
128 }
129
130 void DaliWrapper::SetFlagsFromString(const std::string &flags)
131 {
132   v8::V8::SetFlagsFromString(flags.c_str(), flags.size());
133 }
134
135 void DaliWrapper::Shutdown()
136 {
137   DALI_LOG_WARNING("Destroying V8 DALi context\n");
138
139   if( !mContext.IsEmpty())
140   {
141     v8::HandleScope handleScope( mIsolate );
142     v8::Local<v8::Context> context = v8::Local<v8::Context>::New(mIsolate, mContext);
143     context->Exit();   // exit the context
144     mContext.Reset();  // destroys the context
145   }
146 }
147
148 void DaliWrapper::ExecuteBuffer(const std::string &sourceCode, const std::string &sourceFileName)
149 {
150   mModuleLoader.ExecuteScript( mIsolate,  sourceCode, sourceFileName );
151 }
152
153 void DaliWrapper::ExecuteFile( const std::string& sourceFileName )
154 {
155   DALI_LOG_INFO( gLogExecuteFilter, Debug::Verbose, "Executing source file %s \n",sourceFileName.c_str() );
156
157   mModuleLoader.ExecuteScriptFromFile( mIsolate,  sourceFileName );
158 }
159
160 GarbageCollectorInterface& DaliWrapper::GetDaliGarbageCollector()
161 {
162   return mGarbageCollector;
163 }
164
165 void DaliWrapper::CreateContext( )
166 {
167   v8::HandleScope handleScope( mIsolate );
168
169   // Create a  global JavaScript object so we can set built-in global functions, like Log.
170   v8::Handle<v8::ObjectTemplate> global = v8::ObjectTemplate::New( mIsolate );
171
172   // Add global objects ( functions/ values ) e.g. log function and V8_VERSION
173   global->Set( v8::String::NewFromUtf8( mIsolate,  "log"),        v8::FunctionTemplate::New( mIsolate, V8Utils::Log) );
174   global->Set( v8::String::NewFromUtf8( mIsolate,  "logError"),   v8::FunctionTemplate::New( mIsolate, V8Utils::LogError) );
175   global->Set( v8::String::NewFromUtf8( mIsolate,  "require"),    v8::FunctionTemplate::New( mIsolate, DaliWrapper::Require));
176   global->Set( v8::String::NewFromUtf8( mIsolate,  "V8_VERSION") ,v8::String::NewFromUtf8( mIsolate, v8::V8::GetVersion() ));
177
178    // add the dali object to it, assume it won't be garbage collected until global is deleted
179   global->Set(v8::String::NewFromUtf8( mIsolate, DALI_API_NAME) ,  NewDaliObjectTemplate( mIsolate ));
180
181
182   // create a new context.
183   // Isolate = isolated copy of the V8 including a heap manager, a garbage collector
184   // Only 1 thread can access a single Isolate at a given time. However, multiple Isolates can be run in parallel.
185   // Context = multiple contexts can exist in a given Isolate, and share data between contexts
186   v8::Handle<v8::Context> context  = v8::Context::New( mIsolate, NULL, global);
187
188   mGlobalObjectTemplate.Reset( mIsolate,  global);
189
190   mContext.Reset( mIsolate, context);
191 }
192
193 void DaliWrapper::Initialize()
194 {
195   if( !mIsolate )
196   {
197     v8::V8::InitializeICU();
198
199     v8::V8::Initialize();
200
201     // default isolate removed from V8 version 3.27.1 and beyond.
202     mIsolate = v8::Isolate::New();
203     mIsolate->Enter();
204
205     v8::V8::SetFatalErrorHandler( FatalErrorCallback );
206
207   }
208   // if context is null, create it and add dali object to the global object.
209   if( mContext.IsEmpty())
210   {
211      v8::HandleScope handleScope( mIsolate );
212      CreateContext();
213      v8::Local<v8::Context> context = v8::Local<v8::Context>::New(mIsolate, mContext);
214
215      context->Enter();
216
217      // Add the dali global object. Used for creating objects, and accessing constant values
218      // e.g. var x =  new dali.ImageActor(), or var col = dali.COLOR_RED;
219
220      v8::Local<v8::Object> daliObject = v8::Local<v8::Object>::Cast( context->Global()->Get( v8::String::NewFromUtf8( mIsolate, DALI_API_NAME)));
221
222      v8::Local<v8::Object> stageObject = StageWrapper::WrapStage( mIsolate, Stage::GetCurrent() );
223      daliObject->Set( v8::String::NewFromUtf8( mIsolate, "stage") , stageObject );
224
225      // fontObject provides static font functionality like GetFontList...
226      v8::Local<v8::Object> fontObject = FontWrapper::GetStaticFontObject( mIsolate );
227      daliObject->Set( v8::String::NewFromUtf8( mIsolate, "font") , fontObject );
228
229      // keyboard focus manager is a singleton
230      v8::Local<v8::Object> keyboardObject = KeyboardFocusManagerWrapper::WrapKeyboardFocusManager( mIsolate,Toolkit::KeyboardFocusManager::Get() );
231      daliObject->Set( v8::String::NewFromUtf8( mIsolate, "keyboardFocusManager") , keyboardObject );
232
233      ConstantsWrapper::AddDaliConstants( mIsolate, daliObject);
234
235   }
236   DALI_LOG_INFO( gLogExecuteFilter, Debug::Verbose, "V8 Library %s loaded \n", v8::V8::GetVersion() );
237 }
238
239 v8::Handle<v8::ObjectTemplate> DaliWrapper::NewDaliObjectTemplate( v8::Isolate* isolate )
240 {
241   v8::EscapableHandleScope handleScope( isolate );
242
243   // create the template
244   v8::Local< v8::ObjectTemplate > objTemplate = v8::ObjectTemplate::New( isolate );
245
246   // Add some value properties ( a property can be a primitive value, an object or a function).
247   objTemplate->Set( v8::String::NewFromUtf8( isolate, "BUILD"),
248                     v8::String::NewFromUtf8( isolate, "Dali binary built on:" __DATE__ ", at " __TIME__));
249
250
251   // add the data data directory,
252   objTemplate->Set( v8::String::NewFromUtf8( isolate, "DALI_DATA_DIRECTORY"),
253                       v8::String::NewFromUtf8( isolate, DALI_DATA_READ_ONLY_DIR));
254
255   // add our constructor functions
256   ObjectTemplateHelper::InstallFunctions( isolate,
257                                           objTemplate,
258                                           ConstructorFunctionTable,
259                                           PropertyFunctionTableCount,
260                                           ObjectTemplateHelper::CONSTRUCTOR_FUNCTIONS);
261
262   return handleScope.Escape( objTemplate );
263 }
264
265 void DaliWrapper::Require(const v8::FunctionCallbackInfo< v8::Value >& args)
266 {
267   DaliWrapper& wrapper( DaliWrapper::Get() );
268   wrapper.mModuleLoader.Require( args, wrapper.mGlobalObjectTemplate );
269 }
270
271
272
273
274 } // namespace V8Plugin
275
276 } // namespace Dali