Skip to content

Commit

Permalink
Unify API to use RefPtr<> (instead of Ref<>) and String (instead of S…
Browse files Browse the repository at this point in the history
…tring16) everywhere. Fix various crashes, significantly improve performance and responsiveness while displaying pages with heavy JavaScript.
  • Loading branch information
adamjs committed Jan 6, 2022
1 parent d8690a8 commit 2613b40
Show file tree
Hide file tree
Showing 16 changed files with 207 additions and 201 deletions.
8 changes: 4 additions & 4 deletions Deps.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,10 @@ elseif (PORT MATCHES "UltralightWin")
endif ()
endif ()

set(ULTRALIGHTCORE_REV "28e3326d")
set(WEBCORE_REV "060a2f31")
set(ULTRALIGHT_REV "a40620b7")
set(APPCORE_REV "514bb70")
set(ULTRALIGHTCORE_REV "afa3fd7f")
set(WEBCORE_REV "a7aa2d1b")
set(ULTRALIGHT_REV "8d4c7064")
set(APPCORE_REV "b0e2023")

set(ULTRALIGHTCORE_DIR "${CMAKE_CURRENT_BINARY_DIR}/deps/UltralightCore/")
set(WEBCORE_DIR "${CMAKE_CURRENT_BINARY_DIR}/deps/WebCore/")
Expand Down
106 changes: 65 additions & 41 deletions samples/Sample 1 - Render to PNG/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,12 @@ const char* htmlString();
///
/// In this sample we'll load a string of HTML and render it to a PNG.
///
/// Since we're rendering offscreen and don't need to create any windows or
/// handle any user input, we won't be using App::Create() and will instead be using
/// the Ultralight API directly with our own custom main loop.
/// Since we're rendering offscreen and don't need to create any windows or handle any user input,
/// we won't be using App::Create() and will instead be using the Ultralight API directly with our
/// own custom main loop.
///
/// Our main loop waits for the page to finish loading by subscribing to the
/// LoadListener interface then writes the rendering surface to a PNG on disk.
/// Our main loop waits for the page to finish loading by subscribing to the LoadListener
/// interface then writes the rendering surface to a PNG on disk.
///
class MyApp : public LoadListener,
public Logger {
Expand All @@ -33,6 +33,9 @@ class MyApp : public LoadListener,
///
/// Setup our config.
///
/// @note:
/// We don't set any config options in this sample but you could set your own options here.
///
Config config;

///
Expand All @@ -46,31 +49,45 @@ class MyApp : public LoadListener,
Platform::instance().set_config(config);

///
/// Use AppCore's font loader singleton to load fonts from the OS.
/// Since we're not using App::Create(), we must provide our own Platform API handlers.
///
/// The Platform API handlers we can set are:
///
/// - Platform::set_logger (empty, optional)
/// - Platform::set_gpu_driver (empty, optional)
/// - Platform::set_font_loader (empty, **required**)
/// - Platform::set_file_system (empty, optional)
/// - Platform::set_clipboard (empty, optional)
/// - Platform::set_surface_factory (defaults to BitmapSurfaceFactory, **required**)
///
/// The only Platform API handler we are required to provide is a font loader.
///
/// In this sample we will use AppCore's font loader singleton via GetPlatformFontLoader()
/// which loads fonts from the OS.
///
/// You could replace this with your own to provide your own fonts.
/// You could replace this with your own loader if you wanted to bundle your own fonts.
///
Platform::instance().set_font_loader(GetPlatformFontLoader());

///
/// Use AppCore's file system singleton to load file:/// URLs from the OS.
///
/// You could replace this with your own to provide your own file loader
/// (useful if you need to bundle encrypted / compressed HTML assets).
/// You could replace this with your own to provide your own file loader (useful if you need to
/// bundle encrypted / compressed HTML assets).
///
Platform::instance().set_file_system(GetPlatformFileSystem("./assets/"));

///
/// Register our MyApp instance as a logger so we can handle the
/// library's LogMessage() event below in case we encounter an error.
/// Register our MyApp instance as a logger so we can handle the library's LogMessage() event
/// below in case we encounter an error.
///
Platform::instance().set_logger(this);

///
/// Create our Renderer (you should only create this once per application).
///
/// The Renderer singleton maintains the lifetime of the library and
/// is required before creating any Views. It should outlive any Views.
/// The Renderer singleton maintains the lifetime of the library and is required before
/// creating any Views. It should outlive any Views.
///
/// You should set up the Platform singleton before creating this.
///
Expand All @@ -83,8 +100,7 @@ class MyApp : public LoadListener,
///
/// Our view config uses 2x DPI scale and "Arial" as the default font.
///
/// We make sure GPU acceleration is disabled so we can render to an
/// offscreen pixel buffer surface.
/// We make sure GPU acceleration is disabled so we can render to an offscreen bitmap.
///
ViewConfig view_config;
view_config.initial_device_scale = 2.0;
Expand All @@ -94,19 +110,18 @@ class MyApp : public LoadListener,
view_ = renderer_->CreateView(1600, 1600, view_config, nullptr);

///
/// Register our MyApp instance as a load listener so we can handle the
/// View's OnFinishLoading event below.
/// Register our MyApp instance as a LoadListener so we can handle the View's OnFinishLoading
/// event below.
///
view_->set_load_listener(this);

///
/// Load a string of HTML into our View. (For code readability, the string
/// is defined in the htmlString() function at the bottom of this file)
/// Load a string of HTML into our View. (For code readability, the string is defined in the
/// htmlString() function at the bottom of this file)
///
/// **Note**:
/// This operation may not complete immediately-- we will call
/// Renderer::Update continuously and wait for the OnFinishLoading event
/// before rendering our View.
/// @note:
/// This operation may not complete immediately-- we will call Renderer::Update continuously
/// and wait for the OnFinishLoading event before rendering our View.
///
/// Views can also load remote URLs, try replacing the code below with:
///
Expand All @@ -122,24 +137,32 @@ class MyApp : public LoadListener,

void Run() {
std::cout << "Starting Run(), waiting for page to load..." << std::endl;

///
/// Continuously update our Renderer until are done flag is set to true.
/// Continuously update until OnFinishLoading() is called below (which sets done = true).
///
/// **Note**:
/// Calling Renderer::Update handles any pending network requests,
/// resource loads, and JavaScript timers.
/// @note:
/// Calling Renderer::Update handles any pending network requests, resource loads, and
/// JavaScript timers.
///
while (!done_) {
std::this_thread::sleep_for (std::chrono::milliseconds(10));
do {
renderer_->Update();
renderer_->Render();
}
std::this_thread::sleep_for(std::chrono::milliseconds(10));
} while (!done_);

///
/// Render our View.
///
/// @note:
/// Calling Renderer::Render will render any dirty Views to their respective Surfaces.
///
renderer_->Render();

///
/// Get our View's rendering surface and cast it to BitmapSurface.
///
/// BitmapSurface is the default Surface implementation, you can provide
/// your own via Platform::set_surface_factory.
/// BitmapSurface is the default Surface implementation, you can provide your own via
/// Platform::set_surface_factory.
///
BitmapSurface* bitmap_surface = (BitmapSurface*)view_->surface();

Expand All @@ -159,11 +182,10 @@ class MyApp : public LoadListener,
}

///
/// Inherited from LoadListener, this event is called when the View finishes
/// loading a page into the main frame.
/// Inherited from LoadListener, this is called when a View finishes loading a page into a frame.
///
virtual void OnFinishLoading(ultralight::View* caller,
uint64_t frame_id, bool is_main_frame, const String& url) override {
virtual void OnFinishLoading(ultralight::View* caller, uint64_t frame_id, bool is_main_frame,
const String& url) override {
///
/// Our page is done when the main frame finishes loading.
///
Expand All @@ -178,11 +200,10 @@ class MyApp : public LoadListener,
}

///
/// Inherited from Logger, this event is called when the library wants to
/// print a message to the log.
/// Inherited from Logger, this is called when the library wants to print a message to the log.
///
virtual void LogMessage(LogLevel log_level, const String16& message) override {
std::cout << String(message).utf8().data() << std::endl << std::endl;
virtual void LogMessage(LogLevel log_level, const String& message) override {
std::cout << message.utf8().data() << std::endl << std::endl;
}
};

Expand All @@ -193,6 +214,9 @@ int main() {
return 0;
}

///
/// Our HTML string to load into the View.
///
const char* htmlString() {
return R"(
<html>
Expand Down
44 changes: 21 additions & 23 deletions samples/Sample 2 - Basic App/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,17 +9,17 @@ const char* htmlString();
///
/// Welcome to Sample 2!
///
/// In this sample we'll introduce the AppCore API and use it to build a
/// simple application that creates a window and displays a string of HTML.
/// In this sample we'll introduce the AppCore API and use it to build a simple application that
/// creates a window and displays a string of HTML.
///
/// __What is AppCore?__
///
/// AppCore is an optional, high-performance, cross-platform application
/// framework built on top of the Ultralight renderer.
/// AppCore is an optional, high-performance, cross-platform application framework built on top of
/// the Ultralight renderer.
///
/// It can be used to create standalone, GPU-accelerated HTML applications
/// that paint directly to the native window's backbuffer using the best
/// technology available on each platform (D3D, Metal, OpenGL, etc.).
/// It can be used to create standalone, GPU-accelerated HTML applications that paint directly to
/// the native window's backbuffer using the best technology available on each platform (D3D,
/// Metal, OpenGL, etc.).
///
/// We will create the simplest possible AppCore application in this sample.
///
Expand All @@ -34,8 +34,8 @@ class MyApp : public WindowListener,
///
/// Create our main App instance.
///
/// The App class is responsible for the lifetime of the application
/// and is required to create any windows.
/// The App class is responsible for the lifetime of the application and is required to create
/// any windows.
///
app_ = App::Create();

Expand All @@ -44,11 +44,10 @@ class MyApp : public WindowListener,
///
/// This command creates a native platform window and shows it immediately.
///
/// The window's size (900 by 600) is in virtual device coordinates, the
/// actual size in pixels is automatically determined by the monitor's DPI.
/// The window's size (900 by 600) is in virtual device coordinates, the actual size in pixels
/// is automatically determined by the monitor's DPI.
///
window_ = Window::Create(app_->main_monitor(), 900, 600, false,
kWindowFlags_Titled);
window_ = Window::Create(app_->main_monitor(), 900, 600, false, kWindowFlags_Titled);

///
/// Set the title of our window.
Expand All @@ -58,29 +57,28 @@ class MyApp : public WindowListener,
///
/// Create a web-content overlay that spans the entire window.
///
/// You can create multiple overlays per window, each overlay has its own
/// View which can be used to load and display web-content.
/// You can create multiple overlays per window, each overlay has its own View which can be
/// used to load and display web-content.
///
/// AppCore automatically manages focus, keyboard/mouse input, and GPU
/// painting for each active overlay. Destroying the overlay will remove
/// it from the window.
/// AppCore automatically manages focus, keyboard/mouse input, and GPU painting for each active
/// overlay. Destroying the overlay will remove it from the window.
///
overlay_ = Overlay::Create(*window_, window_->width(), window_->height(), 0, 0);
overlay_ = Overlay::Create(window_, window_->width(), window_->height(), 0, 0);

///
/// Load a string of HTML into our overlay's View
///
overlay_->view()->LoadHTML(htmlString());

///
/// Register our MyApp instance as a WindowListener so we can handle the
/// Window's OnClose event below.
/// Register our MyApp instance as a WindowListener so we can handle the Window's OnClose event
/// below.
///
window_->set_listener(this);

///
/// Register our MyApp instance as a ViewListener so we can handle the
/// View's OnChangeCursor event below.
/// Register our MyApp instance as a ViewListener so we can handle the View's OnChangeCursor
/// event below.
///
overlay_->view()->set_view_listener(this);
}
Expand Down
38 changes: 18 additions & 20 deletions samples/Sample 3 - Resizable App/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,11 @@ const char* htmlString_RightPane();
///
/// Welcome to Sample 3!
///
/// In this sample we'll continue working with the AppCore API and show
/// how to make your app responsive to changes in window size by updating the
/// layout of multiple overlays.
/// In this sample we'll continue working with the AppCore API and show how to make your app
/// responsive to changes in window size by updating the layout of multiple overlays.
///
/// We will create a window with two overlays-- a left pane with a fixed width
/// and a right pane that takes up the remaining width.
/// We will create a window with two overlays-- a left pane with a fixed width and a right pane
/// that takes up the remaining width.
///
/// +----------------------------------------------------+
/// | | |
Expand All @@ -36,8 +35,8 @@ const char* htmlString_RightPane();
/// | | |
/// +----------------------------------------------------+
///
/// To respond to resize events, we'll attach a WindowListener to our window
/// and re-calculate layout of our overlays in the OnResize callback.
/// To respond to resize events, we'll attach a WindowListener to our window and re-calculate
/// layout of our overlays in the OnResize callback.
///

class MyApp : public WindowListener,
Expand All @@ -57,25 +56,24 @@ class MyApp : public WindowListener,
/// Create a resizable window by passing by OR'ing our window flags with
/// kWindowFlags_Resizable.
///
window_ = Window::Create(app_->main_monitor(), WINDOW_WIDTH, WINDOW_HEIGHT,
false, kWindowFlags_Titled | kWindowFlags_Resizable);
window_ = Window::Create(app_->main_monitor(), WINDOW_WIDTH, WINDOW_HEIGHT, false,
kWindowFlags_Titled | kWindowFlags_Resizable);

///
/// Set the title of our window.
///
window_->SetTitle("Ultralight Sample 3 - Resize Me!");

///
/// Create the overlays for our left and right panes-- we don't care about
/// their initial size and position because they'll be set when we call
/// OnResize() below.
/// Create the overlays for our left and right panes-- we don't care about their initial size
/// and position because they'll be set when we call OnResize() below.
///
left_pane_ = Overlay::Create(*window_.get(), 100, 100, 0, 0);
right_pane_ = Overlay::Create(*window_.get(), 100, 100, 0, 0);
left_pane_ = Overlay::Create(window_.get(), 100, 100, 0, 0);
right_pane_ = Overlay::Create(window_.get(), 100, 100, 0, 0);

///
/// Force a call to OnResize to perform initial layout and sizing of our
/// left and right overlays.
/// Force a call to OnResize to perform initial layout and sizing of our left and right
/// overlays.
///
OnResize(window_.get(), window_->width(), window_->height());

Expand All @@ -86,14 +84,14 @@ class MyApp : public WindowListener,
right_pane_->view()->LoadHTML(htmlString_RightPane());

///
/// Register our MyApp instance as a WindowListener so we can handle the
/// Window's OnResize event below.
/// Register our MyApp instance as a WindowListener so we can handle the Window's OnResize
/// event below.
///
window_->set_listener(this);

///
/// Register our MyApp instance as a ViewListener so we can handle the
/// Views' OnChangeCursor event below.
/// Register our MyApp instance as a ViewListener so we can handle the Views' OnChangeCursor
/// event below.
///
left_pane_->view()->set_view_listener(this);
right_pane_->view()->set_view_listener(this);
Expand Down
Loading

0 comments on commit 2613b40

Please sign in to comment.