Skip to content

Commit

Permalink
Various changes for 1.3.0 release:
Browse files Browse the repository at this point in the history
- Fix issue drawing gradients with CPU renderer.

- Update samples and README.

- Make logging more verbose when creating Renderer and Views.

- Add context-menu support to Inspector (thanks p0358!)

- Add support for running off the main thread on macOS (thanks osener!)

- Fix compilation bug when CMAKE_CXX_FLAGS is empty (thanks 19h!)
  • Loading branch information
adamjs committed Jul 19, 2023
1 parent 125b333 commit c909371
Show file tree
Hide file tree
Showing 26 changed files with 1,100 additions and 949 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 "c870cd37")
set(WEBCORE_REV "c337f416")
set(ULTRALIGHT_REV "d7570f7e")
set(APPCORE_REV "b99e29f")
set(ULTRALIGHTCORE_REV "41a04e01")
set(WEBCORE_REV "e9fa2251")
set(ULTRALIGHT_REV "561bd7be")
set(APPCORE_REV "e8b473d")

set(ULTRALIGHTCORE_DIR "${CMAKE_CURRENT_BINARY_DIR}/deps/UltralightCore/")
set(WEBCORE_DIR "${CMAKE_CURRENT_BINARY_DIR}/deps/WebCore/")
Expand Down
96 changes: 43 additions & 53 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<img src="media/logo.png" width="700">
<img src="media/logo.png" width="200">
<a href='https://ci.ultralig.ht/job/Ultralight/job/master/'><img src='https://ci.ultralig.ht/buildStatus/icon?job=Ultralight%2Fmaster'></a>

[Website](https://ultralig.ht) | [Join our Discord!](https://chat.ultralig.ht) | [Browse C/C++ API](https://github.com/ultralight-ux/Ultralight-API/) | [ Documentation](https://docs.ultralig.ht) | [Follow on Twitter](https://twitter.com/ultralight_ux)
[Website](https://ultralig.ht) | [Join our Discord!](https://chat.ultralig.ht) | [C++ API](https://ultralig.ht/api/cpp/1_3_0/) | [C API](https://ultralig.ht/api/c/1_3_0/) | [Support Docs](https://docs.ultralig.ht) | [Twitter](https://twitter.com/ultralight_ux)

## Discord Chat

Expand All @@ -11,67 +11,56 @@ Got a question about Ultralight? Come chat with us on Discord!

# About

Ultralight is an ultra-fast, ultra-light, standards-compliant HTML renderer for applications and games. It supports most modern HTML5, CSS, and JavaScript features while still remaining light in binary size and memory usage.
Ultralight is the ultimate solution for developers seeking to seamlessly integrate web-content into games and desktop apps. Our cutting-edge engine supports the latest HTML/CSS/JS features while remaining exceptionally lightweight in binary size and memory usage.

Currently available for Windows, macOS, and Linux (64-bit only, ARM64 coming).
## Key Features

Official API is available for C and C++, with community bindings for C#, Rust, Java, and Go [available here](https://docs.ultralig.ht/docs/language-bindings).
<dl>
<dt>1. Lightweight and Powerful:</dt>
<dd>
Thanks to its dual, high-performance CPU and GPU renderers, Ultralight offers the perfect balance between performance and resource consumption, making it the go-to choice for developers who demand speed in constrained environments.
</dd>

Get started now by [reading the docs](https://docs.ultralig.ht).
<dt>2. Cross-Platform Compatibility:</dt>
<dd>
With support for Windows, macOS, Linux, Xbox, PS4, and PS5 (and ARM64 coming in 1.4), Ultralight ensures your content displays smoothly and consistently on a wide range of platforms and hardware targets.
</dd>

## Next-Generation HTML Renderer
<dt>3. Modern HTML/JS/CSS Support:</dt>
<dd>
Based on WebKit, Ultralight enjoys many of the same cutting-edge web features as Apple's Safari browser, simplifying testing and reducing production costs.
</dd>

You can think of Ultralight like a smaller, lighter, cross-platform WebKit that's more customizable and designed to display HTML in an existing app rather than function as a standalone browser.
<dt>4. Deep C/C++ and JavaScript Integration:</dt>
<dd>
Unlock the true potential of your applications. Ultralight facilitates seamless C/C++ and JavaScript integration through direct access to the JavaScriptCore API. Expose native state to web pages, extend JavaScript classes, define C/C++ callbacks, and more.
</dd>

The API allows you to integrate your native code deeply with JavaScript (we offer bare-metal access to the JavaScriptCore VM API) and allows you to customize file system loaders, font loading, clipboard integration, and even drawing itself (via GPU display lists or the Surface API).
<dt>5. Low-Level Customization:</dt>
<dd>
Tailor your integration to perfection. Ultralight allows you to override platform-specific functionality, granting you control over file-system access, clipboard management, font loading, and more to suit the unique needs of your application.
</dd>
</dl>

## For Game Developers

## For Games
Developed in collaboration with top AAA game studios, Ultralight is engineered to elevate web-content integration across a diverse set of game engine environments.

Render HTML to an in-game texture using our CPU renderer or take performance to the next level using our GPU renderer.

Take advantage of our low-level platform API— load HTML assets directly from your game's existing asset pipeline using the FileSystem interface.
Choose between our CPU renderer for fast, reliable rendering across various architectures or our customizable GPU renderer to unlock unparalleled animation performance.

__→ Learn more by visiting our [Game Integration Guide](https://docs.ultralig.ht/docs/integrating-with-games).__

## For Desktop Apps

Get the best of both worlds by building your native C/C++ desktop app's front-end with modern HTML/CSS/JS.
## For Desktop-App Developers

Take advantage of our AppCore framework to launch cross-platform windows and render to OS-native GPU surfaces (D3D11, D3D12, Metal, OpenGL, and more).
Build your native app's front-end with modern HTML/CSS/JS while harnessing the power and performance of C/C++.

_AppCore is currently under active development and only supports single-window apps at this writing. A number of planned features (app icons, automatic packager, borderless windows with custom draggable titlebars, etc) are missing but on the way._
Embed the renderer directly within your existing run loop or leverage our AppCore framework to do all the heavy lifting for you, offering convenient native window management and accelerated rendering.

__→ Learn more by visiting our [Desktop App Guide](https://docs.ultralig.ht/docs/writing-your-first-app).__

### Base Memory Usage

| | Ultralight | Electron |
|-------------|-------------|-----------|
| __Windows__ | 9 MB | 72 MB |
| __macOS__ | 17 MB | 97 MB |
| __Linux__ | 15 MB | 136 MB |

### Base Distributable Size

| | Ultralight | Electron |
|-------------|-------------|-----------|
| __Windows__ | 40 MB | 147 MB |
| __macOS__ | 55 MB | 163 MB |
| __Linux__ | 55 MB | 179 MB |

### Comparison with Chromium

| | Ultralight | Chromium |
|-----------------------|--------------------------|-----------------------------|
| __Renderer__ | Proprietary (GPU or CPU) | Skia (CPU) / GPU Compositor |
| __Layout Engine__ | WebCore (WebKit fork) | Blink |
| __JavaScript VM__ | JavaScriptCore | V8 |
| __IPC__ | None (Single Process) | Yes (Multi Process) |

# Architecture

Ultralight is a new port of WebKit combined with a new lightweight renderer intended specifically for embedding in apps and games.
Ultralight is a platform-agnostic port of WebKit for games and desktop apps.

Portions of the library are open-source, here's how the library is laid out:

Expand All @@ -80,25 +69,25 @@ Portions of the library are open-source, here's how the library is laid out:
| __UltralightCore__ | Low-level graphics renderer | Proprietary | (Available with license) |
| __WebCore__ | HTML layout engine (WebKit fork) | LGPL/BSD | [ultralight-ux/WebCore](https://github.com/ultralight-ux/WebCore) |
| __Ultralight__ | View, compositor, and event logic | Proprietary | (Avaiable with license) |
| __AppCore__ | Optional, desktop app runtime | LGPL | [ultralight-ux/AppCore](https://github.com/ultralight-ux/AppCore) |
| __AppCore__ | Optional desktop app runtime | LGPL | [ultralight-ux/AppCore](https://github.com/ultralight-ux/AppCore) |

## Dual High-Performance Renderers

We support two different renderers for integration into a variety of target environments.

### GPU Renderer
### CPU Renderer

Our optional, high-performance GPU renderer can render HTML directly on the GPU. All painting is performed via virtual display lists and translated to your target graphics platform at runtime. For more info, see [Using a Custom GPUDriver](https://docs.ultralig.ht/docs/using-a-custom-gpudriver).
For easy integration into games and other complex environments, Ultralight can render to an offscreen pixel buffer via a multi-threaded CPU rendering pipeline. For more info, see the [Game Integration Guide](https://docs.ultralig.ht/docs/integrating-with-games).

The GPU renderer is enabled by default when using Ultralight via the AppCore runtime.
The library can also render to a user-supplied block of memory via the Surface API (see [Using a Custom Surface](https://docs.ultralig.ht/docs/using-a-custom-surface)).

### CPU Renderer
Paths, gradients, images, and patterns in this pipeline are rasterized and composited in parallel using [Skia](https://skia.org/).

For easier integration into games and other complex environments, Ultralight can render to an offscreen pixel buffer using an SIMD-accelerated CPU rendering pipeline. Fore more info, see the [Game Integration Guide](https://docs.ultralig.ht/docs/integrating-with-games).
### GPU Renderer

The library can also render to a user-supplied pixel buffer via the Surface API (see [Using a Custom Surface](https://docs.ultralig.ht/docs/using-a-custom-surface)).
Our optional, high-performance GPU renderer can render HTML directly on the GPU. All painting is performed via virtual display lists and translated to your target graphics platform at runtime. For more info, see [Using a Custom GPUDriver](https://docs.ultralig.ht/docs/using-a-custom-gpudriver).

Paths, gradients, and patterns in this mode are rasterized using [Blend2D's high-performance JIT compiler](https://blend2d.com).
The GPU renderer is enabled by default when using Ultralight via the AppCore runtime.

# Licensing

Expand Down Expand Up @@ -134,5 +123,6 @@ Pre-built binares are uploaded to the following S3 buckets every commit:
| -------------------------- | --------------------------------------------------- |
| __Join our Discord!__ | <https://chat.ultralig.ht> |
| __Docs / Getting Started__ | <https://docs.ultralig.ht> |
| __Browse C/C++ API__ | <https://github.com/ultralight-ux/Ultralight-API/> |
| __Browse C++ API__ | <https://ultralig.ht/api/cpp/1_3_0/> |
| __Browse C API__ | <https://ultralig.ht/api/c/1_3_0/> |
| __Follow Us on Twitter__ | <https://twitter.com/ultralight_ux> |
Binary file modified media/logo.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
3 changes: 2 additions & 1 deletion packager/CreateSDK.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -60,8 +60,9 @@ execute_process(
)

# Get formatted log
separate_arguments(GIT_LOG_CMD UNIX_COMMAND "git log --date=short --format=\"%ad | %s [%h]%n%n%w(100,13,13)%b\"")
execute_process(
COMMAND git log --pretty=oneline --abbrev-commit
COMMAND ${GIT_LOG_CMD}
WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}
OUTPUT_VARIABLE GIT_LOG
OUTPUT_STRIP_TRAILING_WHITESPACE
Expand Down
189 changes: 189 additions & 0 deletions samples/Sample 1 - Render to PNG/C-API/main.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,189 @@
#include <Ultralight/CAPI.h>
#include <AppCore/CAPI.h>
#include <stdio.h>

#ifdef _WIN32
#include <windows.h>
#define sleep_ms(x) Sleep(x)
#else
#include <unistd.h>
#define sleep_ms(x) usleep((x)*1000)
#endif

///
/// Welcome to Sample 1 (for the C API)!
///
/// In this sample we'll load a local HTML file and render it to a PNG.
///
/// Quick overview of the steps we'll cover:
///
/// 1. Define our Platform handlers.
/// 2. Create the Renderer.
/// 3. Create our View.
/// 4. Load a local file into the View.
/// 5. Wait for it to load using our own main loop.
/// 6. Render the View.
/// 7. Get the rendered Bitmap and save it to a PNG.
///

bool done = false;

// Forward declaration of our load callback
void OnFinishLoading(void* user_data, ULView caller, unsigned long long frame_id,
bool is_main_frame, ULString url);

int main() {
///
/// Setup our config.
///
/// @note:
/// We don't set any config options in this sample but you could set your own options here.
///
ULConfig config = ulCreateConfig();

///
/// We must provide our own Platform API handlers since we're not using ulCreateApp().
///
/// The Platform API handlers we can set are:
///
/// | | ulCreateRenderer() | ulCreateApp() |
/// |-------------------|--------------------|---------------|
/// | FileSystem | **Required** | *Provided* |
/// | FontLoader | **Required** | *Provided* |
/// | Clipboard | *Optional* | *Provided* |
/// | GPUDriver | *Optional* | *Provided* |
/// | Logger | *Optional* | *Provided* |
/// | SurfaceDefinition | *Provided* | *Provided* |
///
/// The only Platform API handlers we are required to provide are file system and font loader.
///
/// In this sample we will use AppCore's font loader and file system via
/// ulEnablePlatformFontLoader() and ulEnablePlatformFileSystem() respectively.
///
/// You can replace these with your own implementations later.
///
ulEnablePlatformFontLoader();

///
/// Use AppCore's file system singleton to load file:/// URLs from the OS.
///
ULString base_dir = ulCreateString("./assets/");
ulEnablePlatformFileSystem(base_dir);
ulDestroyString(base_dir);

///
/// Use AppCore's defaut logger to write the log file to disk.
///
ULString log_path = ulCreateString("./ultralight.log");
ulEnableDefaultLogger(log_path);
ulDestroyString(log_path);

///
/// Create our renderer using the Config we just set up.
///
/// 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 any platform handlers before creating this.
///
ULRenderer renderer = ulCreateRenderer(config);

ulDestroyConfig(config);

///
/// Create our View.
///
/// Views are sized containers for loading and displaying web content.
///
/// Let's set a 2x DPI scale and disable GPU acceleration so we can render to a bitmap.
///
ULViewConfig view_config = ulCreateViewConfig();
ulViewConfigSetInitialDeviceScale(view_config, 2.0);
ulViewConfigSetIsAccelerated(view_config, false);

ULView view = ulCreateView(renderer, 1600, 800, view_config, 0);

ulDestroyViewConfig(view_config);

///
/// Register OnFinishLoading() callback with our View.
///
ulViewSetFinishLoadingCallback(view, &OnFinishLoading, 0);

///
/// Load a local HTML file into the View (uses the file system defined above).
///
/// @note:
/// This operation may not complete immediately-- we will call ulUpdate() continuously
/// and wait for the OnFinishLoading event before rendering our View.
///
/// Views can also load remote URLs, try replacing the code below with:
///
/// ULString url_string = ulCreateString("https://en.wikipedia.org");
/// ulViewLoadURL(view, url_string);
/// ulDestroyString(url_string);
///
ULString url_string = ulCreateString("file:///page.html");
ulViewLoadURL(view, url_string);
ulDestroyString(url_string);

printf("Starting Run(), waiting for page to load...\n");

///
/// Continuously update until OnFinishLoading() is called below (which sets done = true).
///
/// @note:
/// Calling ulUpdate() handles any pending network requests, resource loads, and
/// JavaScript timers.
///
do {
ulUpdate(renderer);
sleep_ms(10);
} while (!done);

///
/// Render our View.
///
/// @note:
/// Calling ulRender will render any dirty Views to their respective Surfaces.
///
ulRender(renderer);

///
/// Get our View's rendering surface.
///
ULSurface surface = ulViewGetSurface(view);

///
/// Get the underlying bitmap.
///
/// @note We're using the default surface definition which is BitmapSurface, you can override
/// the surface implementation via ulPlatformSetSurfaceDefinition()
///
ULBitmap bitmap = ulBitmapSurfaceGetBitmap(surface);

///
/// Write our bitmap to a PNG in the current working directory.
///
ulBitmapWritePNG(bitmap, "result.png");

printf("Saved a render of our page to result.png.\n");
}

///
/// This is called when a View finishes loading a page into a frame.
///
void OnFinishLoading(void* user_data, ULView caller, unsigned long long frame_id,
bool is_main_frame, ULString url) {
///
/// Our page is done when the main frame is finished loading.
///
if (is_main_frame) {
printf("Our page has loaded!\n");

///
/// Set our done flag to true to exit the Run loop.
///
done = true;
}
}
4 changes: 4 additions & 0 deletions samples/Sample 1 - Render to PNG/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,10 @@ add_custom_command(TARGET ${APP_NAME} POST_BUILD

set(ASSETS_PATH "$<TARGET_FILE_DIR:${APP_NAME}>/assets")

# Copy assets to assets directory
add_custom_command(TARGET ${APP_NAME} POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy_directory "${CMAKE_CURRENT_SOURCE_DIR}/assets/" "${ASSETS_PATH}")

# Copy resources to assets directory
add_custom_command(TARGET ${APP_NAME} POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy_directory "${ULTRALIGHT_RESOURCES_DIR}" "${ASSETS_PATH}/resources")
Loading

0 comments on commit c909371

Please sign in to comment.