Core.cpp 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460
  1. #include "../../Include/RmlUi/Core/Core.h"
  2. #include "../../Include/RmlUi/Core/Context.h"
  3. #include "../../Include/RmlUi/Core/Element.h"
  4. #include "../../Include/RmlUi/Core/ElementInstancer.h"
  5. #include "../../Include/RmlUi/Core/Factory.h"
  6. #include "../../Include/RmlUi/Core/FileInterface.h"
  7. #include "../../Include/RmlUi/Core/FontEngineInterface.h"
  8. #include "../../Include/RmlUi/Core/Plugin.h"
  9. #include "../../Include/RmlUi/Core/RenderInterface.h"
  10. #include "../../Include/RmlUi/Core/RenderManager.h"
  11. #include "../../Include/RmlUi/Core/StyleSheetSpecification.h"
  12. #include "../../Include/RmlUi/Core/SystemInterface.h"
  13. #include "../../Include/RmlUi/Core/TextInputHandler.h"
  14. #include "../../Include/RmlUi/Core/Types.h"
  15. #include "BoxShadowCache.h"
  16. #include "ComputeProperty.h"
  17. #include "ControlledLifetimeResource.h"
  18. #include "ElementMeta.h"
  19. #include "EventSpecification.h"
  20. #include "FileInterfaceDefault.h"
  21. #include "Layout/LayoutPools.h"
  22. #include "PluginRegistry.h"
  23. #include "RenderManagerAccess.h"
  24. #include "StyleSheetFactory.h"
  25. #include "StyleSheetParser.h"
  26. #include "TemplateCache.h"
  27. #ifdef RMLUI_FONT_ENGINE_FREETYPE
  28. #include "FontEngineDefault/FontEngineInterfaceDefault.h"
  29. #endif
  30. #ifdef RMLUI_LOTTIE_PLUGIN
  31. #include "../Lottie/LottiePlugin.h"
  32. #endif
  33. #ifdef RMLUI_SVG_PLUGIN
  34. #include "../SVG/SVGPlugin.h"
  35. #endif
  36. #include <algorithm>
  37. namespace Rml {
  38. static RenderInterface* render_interface = nullptr;
  39. static SystemInterface* system_interface = nullptr;
  40. static FileInterface* file_interface = nullptr;
  41. static FontEngineInterface* font_interface = nullptr;
  42. static TextInputHandler* text_input_handler = nullptr;
  43. struct CoreData {
  44. // Default interfaces should be created and destroyed on Initialise and Shutdown, respectively.
  45. UniquePtr<SystemInterface> default_system_interface;
  46. UniquePtr<FileInterface> default_file_interface;
  47. UniquePtr<FontEngineInterface> default_font_interface;
  48. UniquePtr<TextInputHandler> default_text_input_handler;
  49. SmallUnorderedMap<RenderInterface*, UniquePtr<RenderManager>> render_managers;
  50. UnorderedMap<String, ContextPtr> contexts;
  51. };
  52. static ControlledLifetimeResource<CoreData> core_data;
  53. static bool initialised = false;
  54. static void InitializeMemoryPools()
  55. {
  56. Detail::InitializeElementInstancerPools();
  57. ElementMetaPool::Initialize();
  58. LayoutPools::Initialize();
  59. }
  60. static void ReleaseMemoryPools()
  61. {
  62. LayoutPools::Shutdown();
  63. ElementMetaPool::Shutdown();
  64. Detail::ShutdownElementInstancerPools();
  65. }
  66. #ifndef RMLUI_VERSION
  67. #define RMLUI_VERSION "custom"
  68. #endif
  69. bool Initialise()
  70. {
  71. RMLUI_ASSERTMSG(!initialised, "Rml::Initialise() called, but RmlUi is already initialised!");
  72. InitializeMemoryPools();
  73. InitializeComputeProperty();
  74. core_data.Initialize();
  75. // Install default interfaces as appropriate.
  76. if (!system_interface)
  77. {
  78. core_data->default_system_interface = MakeUnique<SystemInterface>();
  79. system_interface = core_data->default_system_interface.get();
  80. }
  81. if (!file_interface)
  82. {
  83. #ifndef RMLUI_NO_FILE_INTERFACE_DEFAULT
  84. core_data->default_file_interface = MakeUnique<FileInterfaceDefault>();
  85. file_interface = core_data->default_file_interface.get();
  86. #else
  87. Log::Message(Log::LT_ERROR, "No file interface set!");
  88. return false;
  89. #endif
  90. }
  91. if (!font_interface)
  92. {
  93. #ifdef RMLUI_FONT_ENGINE_FREETYPE
  94. core_data->default_font_interface = MakeUnique<FontEngineInterfaceDefault>();
  95. font_interface = core_data->default_font_interface.get();
  96. #else
  97. Log::Message(Log::LT_ERROR, "No font engine interface set!");
  98. return false;
  99. #endif
  100. }
  101. if (!text_input_handler)
  102. {
  103. core_data->default_text_input_handler = MakeUnique<TextInputHandler>();
  104. text_input_handler = core_data->default_text_input_handler.get();
  105. }
  106. EventSpecificationInterface::Initialize();
  107. Detail::InitializeObserverPtrPool();
  108. if (render_interface)
  109. core_data->render_managers[render_interface] = MakeUnique<RenderManager>(render_interface);
  110. font_interface->Initialize();
  111. StyleSheetSpecification::Initialise();
  112. StyleSheetParser::Initialise();
  113. StyleSheetFactory::Initialise();
  114. TemplateCache::Initialise();
  115. Factory::Initialise();
  116. // Initialise plugins integrated with Core.
  117. #ifdef RMLUI_LOTTIE_PLUGIN
  118. Lottie::Initialise();
  119. #endif
  120. #ifdef RMLUI_SVG_PLUGIN
  121. SVG::Initialise();
  122. #endif
  123. BoxShadowCache::Initialize();
  124. // Notify all plugins we're starting up.
  125. PluginRegistry::NotifyInitialise();
  126. initialised = true;
  127. return true;
  128. }
  129. void Shutdown()
  130. {
  131. RMLUI_ASSERTMSG(initialised, "Rml::Shutdown() called, but RmlUi is not initialised!");
  132. // Clear out all contexts, which should also clean up all attached elements.
  133. core_data->contexts.clear();
  134. // Notify all plugins we're being shutdown.
  135. PluginRegistry::NotifyShutdown();
  136. BoxShadowCache::Shutdown();
  137. Factory::Shutdown();
  138. TemplateCache::Shutdown();
  139. StyleSheetFactory::Shutdown();
  140. StyleSheetParser::Shutdown();
  141. StyleSheetSpecification::Shutdown();
  142. font_interface->Shutdown();
  143. core_data->render_managers.clear();
  144. Detail::ShutdownObserverPtrPool();
  145. initialised = false;
  146. text_input_handler = nullptr;
  147. font_interface = nullptr;
  148. render_interface = nullptr;
  149. file_interface = nullptr;
  150. system_interface = nullptr;
  151. core_data.Shutdown();
  152. EventSpecificationInterface::Shutdown();
  153. ShutdownComputeProperty();
  154. ReleaseMemoryPools();
  155. }
  156. String GetVersion()
  157. {
  158. return RMLUI_VERSION;
  159. }
  160. void SetSystemInterface(SystemInterface* _system_interface)
  161. {
  162. system_interface = _system_interface;
  163. }
  164. SystemInterface* GetSystemInterface()
  165. {
  166. return system_interface;
  167. }
  168. void SetRenderInterface(RenderInterface* _render_interface)
  169. {
  170. render_interface = _render_interface;
  171. }
  172. RenderInterface* GetRenderInterface()
  173. {
  174. return render_interface;
  175. }
  176. void SetFileInterface(FileInterface* _file_interface)
  177. {
  178. file_interface = _file_interface;
  179. }
  180. FileInterface* GetFileInterface()
  181. {
  182. return file_interface;
  183. }
  184. void SetFontEngineInterface(FontEngineInterface* _font_interface)
  185. {
  186. font_interface = _font_interface;
  187. }
  188. FontEngineInterface* GetFontEngineInterface()
  189. {
  190. return font_interface;
  191. }
  192. void SetTextInputHandler(TextInputHandler* _text_input_handler)
  193. {
  194. text_input_handler = _text_input_handler;
  195. }
  196. TextInputHandler* GetTextInputHandler()
  197. {
  198. return text_input_handler;
  199. }
  200. Context* CreateContext(const String& name, const Vector2i dimensions, RenderInterface* render_interface_for_context,
  201. TextInputHandler* text_input_handler_for_context)
  202. {
  203. if (!initialised)
  204. return nullptr;
  205. if (!render_interface_for_context)
  206. render_interface_for_context = render_interface;
  207. if (!text_input_handler_for_context)
  208. text_input_handler_for_context = text_input_handler;
  209. if (!render_interface_for_context)
  210. {
  211. Log::Message(Log::LT_WARNING, "Failed to create context '%s', no render interface specified and no default render interface exists.",
  212. name.c_str());
  213. return nullptr;
  214. }
  215. if (GetContext(name))
  216. {
  217. Log::Message(Log::LT_WARNING, "Failed to create context '%s', context already exists.", name.c_str());
  218. return nullptr;
  219. }
  220. // Each unique render interface gets its own render manager.
  221. auto& render_manager = core_data->render_managers[render_interface_for_context];
  222. if (!render_manager)
  223. render_manager = MakeUnique<RenderManager>(render_interface_for_context);
  224. ContextPtr new_context = Factory::InstanceContext(name, render_manager.get(), text_input_handler_for_context);
  225. if (!new_context)
  226. {
  227. Log::Message(Log::LT_WARNING, "Failed to instance context '%s', instancer returned nullptr.", name.c_str());
  228. return nullptr;
  229. }
  230. new_context->SetDimensions(dimensions);
  231. Context* new_context_raw = new_context.get();
  232. core_data->contexts[name] = std::move(new_context);
  233. PluginRegistry::NotifyContextCreate(new_context_raw);
  234. return new_context_raw;
  235. }
  236. bool RemoveContext(const String& name)
  237. {
  238. return core_data->contexts.erase(name) != 0;
  239. }
  240. Context* GetContext(const String& name)
  241. {
  242. auto it = core_data->contexts.find(name);
  243. if (it == core_data->contexts.end())
  244. return nullptr;
  245. return it->second.get();
  246. }
  247. Context* GetContext(int index)
  248. {
  249. if (index < 0 || index >= GetNumContexts())
  250. return nullptr;
  251. auto it = core_data->contexts.begin();
  252. std::advance(it, index);
  253. if (it == core_data->contexts.end())
  254. return nullptr;
  255. return it->second.get();
  256. }
  257. int GetNumContexts()
  258. {
  259. return (int)core_data->contexts.size();
  260. }
  261. bool LoadFontFace(const String& file_path, bool fallback_face, Style::FontWeight weight, int face_index)
  262. {
  263. return font_interface->LoadFontFace(file_path, face_index, fallback_face, weight);
  264. }
  265. bool LoadFontFace(Span<const byte> data, const String& family, Style::FontStyle style, Style::FontWeight weight, bool fallback_face, int face_index)
  266. {
  267. return font_interface->LoadFontFace(data, face_index, family, style, weight, fallback_face);
  268. }
  269. void RegisterPlugin(Plugin* plugin)
  270. {
  271. if (initialised)
  272. plugin->OnInitialise();
  273. PluginRegistry::RegisterPlugin(plugin);
  274. }
  275. void UnregisterPlugin(Plugin* plugin)
  276. {
  277. PluginRegistry::UnregisterPlugin(plugin);
  278. if (initialised)
  279. plugin->OnShutdown();
  280. }
  281. EventId RegisterEventType(const String& type, bool interruptible, bool bubbles, DefaultActionPhase default_action_phase)
  282. {
  283. return EventSpecificationInterface::InsertOrReplaceCustom(type, interruptible, bubbles, default_action_phase);
  284. }
  285. StringList GetTextureSourceList()
  286. {
  287. StringList result;
  288. if (!core_data)
  289. return result;
  290. for (const auto& render_manager : core_data->render_managers)
  291. {
  292. RenderManagerAccess::GetTextureSourceList(render_manager.second.get(), result);
  293. }
  294. return result;
  295. }
  296. void ReleaseTextures(RenderInterface* match_render_interface)
  297. {
  298. if (!core_data)
  299. return;
  300. for (auto& render_manager : core_data->render_managers)
  301. {
  302. if (!match_render_interface || render_manager.first == match_render_interface)
  303. RenderManagerAccess::ReleaseAllTextures(render_manager.second.get());
  304. }
  305. }
  306. bool ReleaseTexture(const String& source, RenderInterface* match_render_interface)
  307. {
  308. bool result = false;
  309. if (!core_data)
  310. return result;
  311. for (auto& render_manager : core_data->render_managers)
  312. {
  313. if (!match_render_interface || render_manager.first == match_render_interface)
  314. {
  315. if (RenderManagerAccess::ReleaseTexture(render_manager.second.get(), source))
  316. result = true;
  317. }
  318. }
  319. return result;
  320. }
  321. void ReleaseCompiledGeometry(RenderInterface* match_render_interface)
  322. {
  323. if (!core_data)
  324. return;
  325. for (auto& render_manager : core_data->render_managers)
  326. {
  327. if (!match_render_interface || render_manager.first == match_render_interface)
  328. RenderManagerAccess::ReleaseAllCompiledGeometry(render_manager.second.get());
  329. }
  330. }
  331. void ReleaseFontResources()
  332. {
  333. if (!font_interface)
  334. return;
  335. for (const auto& name_context : core_data->contexts)
  336. name_context.second->GetRootElement()->DirtyFontFaceRecursive();
  337. font_interface->ReleaseFontResources();
  338. for (const auto& name_context : core_data->contexts)
  339. name_context.second->Update();
  340. }
  341. void ReleaseRenderManagers()
  342. {
  343. auto& contexts = core_data->contexts;
  344. auto& render_managers = core_data->render_managers;
  345. ReleaseFontResources();
  346. for (auto it = render_managers.begin(); it != render_managers.end();)
  347. {
  348. RenderManager* render_manager = it->second.get();
  349. const auto num_contexts_using_manager = std::count_if(contexts.begin(), contexts.end(),
  350. [&](const auto& context_pair) { return &context_pair.second->GetRenderManager() == render_manager; });
  351. if (num_contexts_using_manager == 0)
  352. it = render_managers.erase(it);
  353. else
  354. ++it;
  355. }
  356. }
  357. // Functions that need to be accessible within the Core library, but not publicly.
  358. namespace CoreInternal {
  359. bool HasRenderManager(RenderInterface* match_render_interface)
  360. {
  361. return core_data && core_data->render_managers.find(match_render_interface) != core_data->render_managers.end();
  362. }
  363. } // namespace CoreInternal
  364. } // namespace Rml