Added MacOS SDK

This commit is contained in:
Andrew Zambazos
2026-06-11 14:04:52 +12:00
parent ffdc88608e
commit 553ab6537a
2151 changed files with 450464 additions and 0 deletions
+436
View File
@@ -0,0 +1,436 @@
/**************************************************************************************************
* This file is a part of Ultralight. *
* *
* See <https://ultralig.ht> for licensing and more. *
* *
* (C) 2024 Ultralight, Inc. *
**************************************************************************************************/
#pragma once
#include <Ultralight/Defines.h>
#include <Ultralight/RefPtr.h>
#include <Ultralight/Geometry.h>
#include <Ultralight/Buffer.h>
namespace ultralight {
///
/// The various Bitmap formats.
///
enum class BitmapFormat : uint8_t {
///
/// Alpha channel only, 8-bits per pixel.
///
/// Encoding: 8-bits per channel, unsigned normalized.
///
/// Color-space: Linear (no gamma), alpha-coverage only.
///
A8_UNORM,
///
/// Blue Green Red Alpha channels, 32-bits per pixel.
///
/// Encoding: 8-bits per channel, unsigned normalized.
///
/// Color-space: sRGB gamma with premultiplied linear alpha channel.
///
BGRA8_UNORM_SRGB,
};
///
/// Macro to get the bytes per pixel from a BitmapFormat
///
#define GetBytesPerPixel(x) (x == BitmapFormat::A8_UNORM ? 1 : 4)
///
/// Forward declaration for the LockedPixels class.
///
template<typename T>
class LockedPixels;
///
/// Function signature for a user-defined destruction callback to be optionally called when the
/// Bitmap is destroyed.
///
/// @param user_data Pointer to user-defined user-data (this will be the same value as what was
/// passed to Bitmap::Create, if any)
///
/// @param data Pointer to raw Bitmap pixel data.
///
typedef void (*DestroyBitmapCallback)(void* user_data, void* data);
///
/// A thread-safe container for pixel data.
///
/// The bitmap class is used to store pixel data in a variety of formats. It intelligently manages
/// the lifetime of the pixel buffer and provides thread-safe access to the pixel data.
///
/// ## Accessing Pixel Data
///
/// You can access the underlying pixel data by using the LockPixelsSafe() method. An example
/// follows:
///
/// ```
/// auto bitmap = Bitmap::Create(100, 100, BitmapFormat::BGRA8_UNORM_SRGB);
/// auto pixels = bitmap->LockPixelsSafe();
/// if (pixels && pixels.data()) {
/// // Zero out the pixel buffer by setting every byte to 0.
/// memset(pixels.data(), 0, pixels.size());
/// }
///
/// // 'pixels' is automatically unlocked when it goes out of scope.
/// ```
class UExport Bitmap : public RefCounted {
public:
///
/// Create an empty Bitmap. No pixels will be allocated.
///
static RefPtr<Bitmap> Create();
///
/// Create a Bitmap with a certain configuration. Pixels will be allocated but not initialized.
///
/// @param width The width in pixels.
///
/// @param height The height in pixels.
///
/// @param format The pixel format to use.
///
/// @return A ref-pointer to a new Bitmap instance.
///
static RefPtr<Bitmap> Create(uint32_t width, uint32_t height, BitmapFormat format);
///
/// Create an aligned Bitmap with a certain configuration. Pixels will be allocated but not
/// initialized. Row bytes will be padded to reach the specified alignment.
///
/// @param width The width in pixels.
///
/// @param height The height in pixels.
///
/// @param format The pixel format to use.
///
/// @param alignment The alignment (in bytes) to use. Row bytes will be padded to reach a
/// multiple of this value and the underlying storage will be allocated with
/// this alignment.
///
/// @return A ref-pointer to a new Bitmap instance.
///
static RefPtr<Bitmap> Create(uint32_t width, uint32_t height, BitmapFormat format,
uint32_t alignment);
///
/// Create a Bitmap with existing pixel data, a copy will be made unless should_copy is false.
///
/// @param width The width in pixels.
///
/// @param height The height in pixels.
///
/// @param format The pixel format to use.
///
/// @param row_bytes The number of bytes between each row (note that this value should be >=
/// width * bytes_per_pixel).
///
/// @param pixels Pointer to raw pixel buffer.
///
/// @param size Size of the raw pixel buffer.
///
/// @param should_copy Whether or not a copy should be made of the pixels. If this is false
/// the returned Bitmap will use the raw pixels passed in as its own, but
/// you are still responsible for destroying your buffer afterwards.
///
/// @return A ref-pointer to a new Bitmap instance.
///
static RefPtr<Bitmap> Create(uint32_t width, uint32_t height, BitmapFormat format,
uint32_t row_bytes, const void* pixels, size_t size,
bool should_copy = true);
///
/// Create a Bitmap that wraps existing pixel data, a user-defined destruction callback will be
/// called when the Bitmap wants to destroy the data.
///
/// @param width The width in pixels.
///
/// @param height The height in pixels.
///
/// @param format The pixel format to use.
///
/// @param row_bytes The number of bytes between each row (note that this value should be >=
/// width * bytes_per_pixel).
///
/// @param pixels Pointer to raw pixel buffer.
///
/// @param size Size of the raw pixel buffer.
///
/// @param user_data Optional user data that will be passed to destruction_callback when the
/// Bitmap wants to destroy the pixel data. (Pass nullptr to ignore)
///
/// @param destruction_callback Callback that will be called upon destruction.
///
/// @return A ref-pointer to a new Bitmap instance.
///
static RefPtr<Bitmap> Create(uint32_t width, uint32_t height, BitmapFormat format,
uint32_t row_bytes, const void* pixels, size_t size,
void* user_data, DestroyBitmapCallback destruction_callback);
///
/// Create a bitmap from a deep copy of another Bitmap.
///
static RefPtr<Bitmap> Create(const Bitmap& bitmap);
///
/// Get the width in pixels.
///
virtual uint32_t width() const = 0;
///
/// Get the height in pixels.
///
virtual uint32_t height() const = 0;
///
/// Get the bounds as an IntRect
///
virtual IntRect bounds() const = 0;
///
/// Get the pixel format.
///
virtual BitmapFormat format() const = 0;
///
/// Get the number of bytes per pixel.
///
virtual uint32_t bpp() const = 0;
///
/// Get the number of bytes between each row of pixels.
///
/// @note This value is usually calculated as width * bytes_per_pixel (bpp) but it may be larger
/// due to alignment rules in the allocator.
///
virtual uint32_t row_bytes() const = 0;
///
/// Get the size in bytes of the pixel buffer.
///
/// @note Size is calculated as row_bytes() * height().
///
virtual size_t size() const = 0;
///
/// Whether or not this Bitmap owns the pixel buffer and will destroy it at the end of its
/// lifetime.
///
virtual bool owns_pixels() const = 0;
///
/// Lock the pixel buffer for reading/writing (safe version, automatically unlocks).
///
/// @return A managed container that can be used to access the pixels (LockedPixels::data()).
/// This container will automatically unlock the pixels when it goes out of scope.
///
virtual LockedPixels<RefPtr<Bitmap>> LockPixelsSafe() const = 0;
///
/// Lock the pixel buffer for reading/writing.
///
/// @return A pointer to the pixel buffer.
///
virtual void* LockPixels() = 0;
///
/// Unlock the pixel buffer.
///
virtual void UnlockPixels() = 0;
///
/// Lock the pixel buffer for reading/writing. (const)
///
/// @return A const pointer to the pixel buffer.
///
virtual const void* LockPixels() const = 0;
///
/// Unlock the pixel buffer. (const)
///
virtual void UnlockPixels() const = 0;
///
/// Get the raw pixel buffer.
///
/// @note You should only call this if pixels are already locked.
///
virtual void* raw_pixels() = 0;
///
/// Whether or not this Bitmap is empty (no pixels allocated).
///
virtual bool IsEmpty() const = 0;
///
/// Erase the Bitmap (set all pixels to 0).
///
virtual void Erase() = 0;
///
/// Assign another bitmap to this one.
///
/// @param bitmap The bitmap to copy from.
///
virtual void Set(RefPtr<Bitmap> bitmap) = 0;
///
/// Draw another bitmap to this bitmap.
///
/// @note Formats do not need to match. Bitmap formats will be converted to one another
/// automatically. Note that when converting from BGRA8 to A8, only the Blue channel will
/// be used.
///
/// @param src_rect The source rectangle, relative to src bitmap.
///
/// @param dest_rect The destination rectangle, relative to this bitmap.
///
/// @param src The source bitmap.
///
/// @param pad_repeat Whether or not we should pad the drawn bitmap by one pixel of repeated
/// edge pixels from the source bitmap.
///
/// @return Whether or not the operation succeeded (this can fail if the src_rect and/or
/// dest_rect are invalid).
///
virtual bool DrawBitmap(IntRect src_rect, IntRect dest_rect, RefPtr<Bitmap> src, bool pad_repeat)
= 0;
///
/// Encode this Bitmap as a PNG image and store the encoded bytes in a Buffer.
///
/// @param convert_to_rgba The PNG format expects RGBA format but our bitmap is stored as BGRA,
/// set this to true to perform the conversion automatically.
///
/// @param convert_to_straight_alpha The PNG format expects semi-transparent values to be
/// stored as straight alpha instead of premultiplied alpha,
/// set this to true to perform the conversion automatically.
///
/// @return On success, a buffer containing the encoded bytes, otherwise a null RefPtr.
///
virtual RefPtr<Buffer> EncodePNG(bool convert_to_rgba = true,
bool convert_to_straight_alpha = true) const = 0;
///
/// Write this Bitmap out to a PNG image.
///
/// @param path The filepath to write to (opened with fopen())
///
/// @param convert_to_rgba The PNG format expects RGBA format but our bitmap is stored as BGRA,
/// set this to true to perform the conversion automatically.
///
/// @param convert_to_straight_alpha The PNG format expects semi-transparent values to be
/// stored as straight alpha instead of premultiplied alpha,
/// set this to true to perform the conversion automatically.
///
/// @return Whether or not the operation succeeded.
///
virtual bool WritePNG(const char* path, bool convert_to_rgba = true,
bool convert_to_straight_alpha = true) const = 0;
///
/// Make a resized copy of this bitmap by writing to a pre-allocated destination bitmap.
///
/// @param destination The bitmap to store the result in, the width and height of the
/// destination will be used.
///
/// @param high_quality Whether or not a high quality resampling will be used during the
/// resize. (Otherwise, just uses fast nearest-neighbor sampling)
///
/// @return Whether or not the operation succeeded. This operation is only valid if both formats
/// are BitmapFormat::BGRA8_UNORM_SRGB and the source and destination are non-empty.
///
virtual bool Resample(RefPtr<Bitmap> destination, bool high_quality) = 0;
///
/// Convert a BGRA bitmap to RGBA bitmap and vice-versa by swapping the red and blue channels.
///
/// @note Only valid if the format is BitmapFormat::BGRA8_UNORM_SRGB
///
virtual void SwapRedBlueChannels() = 0;
///
/// Convert a BGRA bitmap from premultiplied alpha (the default) to straight alpha.
///
/// @note Only valid if the format is BitmapFormat::BGRA8_UNORM_SRGB
///
virtual void ConvertToStraightAlpha() = 0;
///
/// Convert a BGRA bitmap from straight alpha to premultiplied alpha.
///
/// @note Only valid if the format is BitmapFormat::BGRA8_UNORM_SRGB
///
virtual void ConvertToPremultipliedAlpha() = 0;
protected:
Bitmap();
virtual ~Bitmap();
Bitmap(const Bitmap&);
void operator=(const Bitmap&);
};
template <typename T>
class LockedPixels {
public:
LockedPixels(const LockedPixels&) = delete;
LockedPixels& operator=(const LockedPixels&) = delete;
LockedPixels(int) = delete;
explicit LockedPixels(T& lockable) : lockable_(lockable), data_(nullptr), size_(0) { lock(); }
~LockedPixels() {
if (lockable_)
lockable_->UnlockPixels();
}
///
/// Access the locked pixel data.
///
void* data() { return data_; }
///
/// Access the size of the locked pixel data.
///
size_t size() { return size_; }
explicit operator bool() const { return !!lockable_; }
LockedPixels(LockedPixels&& other) : lockable_(other.lockable_), data_(other.data_),
size_(other.size_) {
other.lockable_ = nullptr;
other.data_ = nullptr;
other.size_ = 0;
}
LockedPixels& operator=(LockedPixels&& other) {
if (lockable_)
lockable_->UnlockPixels();
lockable_ = other.lockable_;
data_ = other.data_;
size_ = other.size_;
other.lockable_ = nullptr;
other.data_ = nullptr;
other.size_ = 0;
return *this;
}
private:
void lock() {
if (lockable_) {
data_ = lockable_->LockPixels();
size_ = lockable_->size();
}
}
T lockable_;
void* data_;
size_t size_;
};
} // namespace ultralight
+88
View File
@@ -0,0 +1,88 @@
/**************************************************************************************************
* This file is a part of Ultralight. *
* *
* See <https://ultralig.ht> for licensing and more. *
* *
* (C) 2024 Ultralight, Inc. *
**************************************************************************************************/
#pragma once
#include <Ultralight/Defines.h>
#include <Ultralight/RefPtr.h>
namespace ultralight {
///
/// Function signature for a user-defined destruction callback to optionally be called when Buffer
/// is destroyed. Users can use this to deallocate any data associated with the Buffer.
///
/// @param user_data Pointer to user-defined user-data (this will be the same value as what was
/// passed to Buffer::Create, if any)
///
/// @param data Pointer to raw Buffer data.
///
typedef void (*DestroyBufferCallback)(void* user_data, void* data);
///
/// A fixed-size container for raw byte data.
///
/// This class is used to represent raw data buffers in Ultralight. It intelligently manages the
/// lifetime of the data and can optionally call a user-supplied callback to deallocate the data
/// when the Buffer is destroyed.
///
class UExport Buffer : public RefCounted {
public:
///
/// Create a Buffer from existing, user-owned data without any copies. An optional, user-supplied
/// callback will be called to deallocate data upon destruction.
///
/// @param data A pointer to the data.
///
/// @param size Size of the data in bytes.
///
/// @param user_data Optional user data that will be passed to destruction_callback
/// when the returned Buffer is destroyed.
///
/// @param destruction_callback Optional callback that will be called upon destruction. Pass a
/// null pointer if you don't want to be informed of destruction.
///
///
/// @return A ref-counted Buffer object that wraps the existing data.
///
static RefPtr<Buffer> Create(void* data, size_t size, void* user_data,
DestroyBufferCallback destruction_callback);
///
/// Create a Buffer from existing data, a deep copy of data will be made.
///
static RefPtr<Buffer> CreateFromCopy(const void* data, size_t size);
///
/// Get a pointer to the raw byte data.
///
virtual void* data() = 0;
///
/// Get the size in bytes.
///
virtual size_t size() const = 0;
///
/// Get the user data associated with this Buffer, if any.
///
virtual void* user_data() = 0;
///
/// Check whether this Buffer owns its own data (Buffer was created via CreateFromCopy).
/// If this is false, Buffer will call the user-supplied destruction callback to deallocate data
/// when this Buffer instance is destroyed.
///
virtual bool owns_data() const = 0;
protected:
Buffer();
virtual ~Buffer();
Buffer(const Buffer&);
void operator=(const Buffer&);
};
} // namespace ultralight
+41
View File
@@ -0,0 +1,41 @@
/**************************************************************************************************
* This file is a part of Ultralight, an ultra-portable web-browser engine. *
* *
* See <https://ultralig.ht> for licensing and more. *
* *
* (C) 2024 Ultralight, Inc. *
**************************************************************************************************/
#ifndef ULTRALIGHT_CAPI_H
#define ULTRALIGHT_CAPI_H
/**************************************************************************************************
* API Note:
*
* You should only destroy objects that you explicitly create. Do not destroy any objects returned
* from the API or callbacks unless otherwise noted.
**************************************************************************************************/
#include <Ultralight/CAPI/CAPI_Defines.h>
#include <Ultralight/CAPI/CAPI_Bitmap.h>
#include <Ultralight/CAPI/CAPI_Buffer.h>
#include <Ultralight/CAPI/CAPI_Clipboard.h>
#include <Ultralight/CAPI/CAPI_Config.h>
#include <Ultralight/CAPI/CAPI_FileSystem.h>
#include <Ultralight/CAPI/CAPI_FontFile.h>
#include <Ultralight/CAPI/CAPI_FontLoader.h>
#include <Ultralight/CAPI/CAPI_Geometry.h>
#include <Ultralight/CAPI/CAPI_GPUDriver.h>
#include <Ultralight/CAPI/CAPI_ImageSource.h>
#include <Ultralight/CAPI/CAPI_KeyEvent.h>
#include <Ultralight/CAPI/CAPI_Logger.h>
#include <Ultralight/CAPI/CAPI_MouseEvent.h>
#include <Ultralight/CAPI/CAPI_Platform.h>
#include <Ultralight/CAPI/CAPI_Renderer.h>
#include <Ultralight/CAPI/CAPI_ScrollEvent.h>
#include <Ultralight/CAPI/CAPI_GamepadEvent.h>
#include <Ultralight/CAPI/CAPI_Session.h>
#include <Ultralight/CAPI/CAPI_String.h>
#include <Ultralight/CAPI/CAPI_Surface.h>
#include <Ultralight/CAPI/CAPI_View.h>
#endif // ULTRALIGHT_CAPI_H
+150
View File
@@ -0,0 +1,150 @@
/**************************************************************************************************
* This file is a part of Ultralight, an ultra-portable web-browser engine. *
* *
* See <https://ultralig.ht> for licensing and more. *
* *
* (C) 2024 Ultralight, Inc. *
**************************************************************************************************/
///
/// @file CAPI_Bitmap.h
///
/// A thread-safe container for pixel data.
///
/// `#include <Ultralight/CAPI/CAPI_Bitmap.h>`
///
/// The bitmap class is used to store pixel data in a variety of formats. It intelligently manages
/// the lifetime of the pixel buffer and provides thread-safe access to the pixel data.
///
/// ## Accessing Pixel Data
///
/// To access the pixel data, you must first lock the pixels using ulBitmapLockPixels(). This will
/// return a pointer to the pixel buffer. An example follows:
///
/// ```
/// void* pixels = ulBitmapLockPixels(bitmap);
/// if (pixels) {
/// // Zero out the pixel buffer
/// memset(pixels, 0, ulBitmapGetSize(bitmap));
/// }
///
/// // Unlock the pixels when you're done.
/// ulBitmapUnlockPixels(bitmap);
/// ```
///
#ifndef ULTRALIGHT_CAPI_BITMAP_H
#define ULTRALIGHT_CAPI_BITMAP_H
#include <Ultralight/CAPI/CAPI_Defines.h>
#ifdef __cplusplus
extern "C" {
#endif
/******************************************************************************
* Bitmap
*****************************************************************************/
///
/// Create empty bitmap.
///
ULExport ULBitmap ulCreateEmptyBitmap();
///
/// Create bitmap with certain dimensions and pixel format.
///
ULExport ULBitmap ulCreateBitmap(unsigned int width, unsigned int height, ULBitmapFormat format);
///
/// Create bitmap from existing pixel buffer. @see Bitmap for help using this function.
///
ULExport ULBitmap ulCreateBitmapFromPixels(unsigned int width, unsigned int height,
ULBitmapFormat format, unsigned int row_bytes,
const void* pixels, size_t size, bool should_copy);
///
/// Create bitmap from copy.
///
ULExport ULBitmap ulCreateBitmapFromCopy(ULBitmap existing_bitmap);
///
/// Destroy a bitmap (you should only destroy Bitmaps you have explicitly created via one of the
/// creation functions above.
///
ULExport void ulDestroyBitmap(ULBitmap bitmap);
///
/// Get the width in pixels.
///
ULExport unsigned int ulBitmapGetWidth(ULBitmap bitmap);
///
/// Get the height in pixels.
///
ULExport unsigned int ulBitmapGetHeight(ULBitmap bitmap);
///
/// Get the pixel format.
///
ULExport ULBitmapFormat ulBitmapGetFormat(ULBitmap bitmap);
///
/// Get the bytes per pixel.
///
ULExport unsigned int ulBitmapGetBpp(ULBitmap bitmap);
///
/// Get the number of bytes per row.
///
ULExport unsigned int ulBitmapGetRowBytes(ULBitmap bitmap);
///
/// Get the size in bytes of the underlying pixel buffer.
///
ULExport size_t ulBitmapGetSize(ULBitmap bitmap);
///
/// Whether or not this bitmap owns its own pixel buffer.
///
ULExport bool ulBitmapOwnsPixels(ULBitmap bitmap);
///
/// Lock pixels for reading/writing, returns pointer to pixel buffer.
///
ULExport void* ulBitmapLockPixels(ULBitmap bitmap);
///
/// Unlock pixels after locking.
///
ULExport void ulBitmapUnlockPixels(ULBitmap bitmap);
///
/// Get raw pixel buffer-- you should only call this if Bitmap is already locked.
///
ULExport void* ulBitmapRawPixels(ULBitmap bitmap);
///
/// Whether or not this bitmap is empty.
///
ULExport bool ulBitmapIsEmpty(ULBitmap bitmap);
///
/// Reset bitmap pixels to 0.
///
ULExport void ulBitmapErase(ULBitmap bitmap);
///
/// Write bitmap to a PNG on disk.
///
ULExport bool ulBitmapWritePNG(ULBitmap bitmap, const char* path);
///
/// This converts a BGRA bitmap to RGBA bitmap and vice-versa by swapping the red and blue channels.
///
ULExport void ulBitmapSwapRedBlueChannels(ULBitmap bitmap);
#ifdef __cplusplus
} // extern "C"
#endif
#endif // ULTRALIGHT_CAPI_BITMAP_H
+84
View File
@@ -0,0 +1,84 @@
/**************************************************************************************************
* This file is a part of Ultralight, an ultra-portable web-browser engine. *
* *
* See <https://ultralig.ht> for licensing and more. *
* *
* (C) 2024 Ultralight, Inc. *
**************************************************************************************************/
///
/// @file CAPI_Buffer.h
///
/// A fixed-size container for raw byte data.
///
/// `#include <Ultralight/CAPI/CAPI_Buffer.h>`
///
/// This class is used to represent raw data buffers in Ultralight. It intelligently manages the
/// lifetime of the data and can optionally call a user-supplied callback to deallocate the data
/// when the Buffer is destroyed.
///
#ifndef ULTRALIGHT_CAPI_BUFFER_H
#define ULTRALIGHT_CAPI_BUFFER_H
#include <Ultralight/CAPI/CAPI_Defines.h>
#ifdef __cplusplus
extern "C" {
#endif
typedef void (*ulDestroyBufferCallback)(void* user_data, void* data);
///
/// Create a Buffer from existing, user-owned data without any copies. An optional, user-supplied
/// callback will be called to deallocate data upon destruction.
///
/// @param data A pointer to the data.
///
/// @param size Size of the data in bytes.
///
/// @param user_data Optional user data that will be passed to destruction_callback
/// when the returned Buffer is destroyed.
///
/// @param destruction_callback Optional callback that will be called upon destruction. Pass a
/// null pointer if you don't want to be informed of destruction.
///
ULExport ULBuffer ulCreateBuffer(void* data, size_t size, void* user_data,
ulDestroyBufferCallback destruction_callback);
///
/// Create a Buffer from existing data, a deep copy of data will be made.
///
ULExport ULBuffer ulCreateBufferFromCopy(const void* data, size_t size);
///
/// Destroy buffer (you should destroy any buffers you explicitly Create).
///
ULExport void ulDestroyBuffer(ULBuffer buffer);
///
/// Get a pointer to the raw byte data.
///
ULExport void* ulBufferGetData(ULBuffer buffer);
///
/// Get the size in bytes.
///
ULExport size_t ulBufferGetSize(ULBuffer buffer);
///
/// Get the user data associated with this Buffer, if any.
///
ULExport void* ulBufferGetUserData(ULBuffer buffer);
///
/// Check whether this Buffer owns its own data (Buffer was created via ulCreateBufferFromCopy).
/// If this is false, Buffer will call the user-supplied destruction callback to deallocate data
/// when this Buffer instance is destroyed.
///
ULExport bool ulBufferOwnsData(ULBuffer buffer);
#ifdef __cplusplus
} // extern "C"
#endif
#endif // ULTRALIGHT_CAPI_BUFFER_H
+66
View File
@@ -0,0 +1,66 @@
/**************************************************************************************************
* This file is a part of Ultralight, an ultra-portable web-browser engine. *
* *
* See <https://ultralig.ht> for licensing and more. *
* *
* (C) 2024 Ultralight, Inc. *
**************************************************************************************************/
///
/// @file CAPI_Clipboard.h
///
/// User-defined clipboard interface.
///
/// `#include <Ultralight/CAPI/CAPI_Clipboard.h>`
///
/// The library uses this to read and write data to the system's clipboard.
///
/// @see ulPlatformSetClipboard()
///
#ifndef ULTRALIGHT_CAPI_CLIPBOARD_H
#define ULTRALIGHT_CAPI_CLIPBOARD_H
#include <Ultralight/CAPI/CAPI_Defines.h>
#ifdef __cplusplus
extern "C" {
#endif
/******************************************************************************
* Clipboard
*****************************************************************************/
///
/// The callback invoked when the library wants to clear the system's clipboard.
///
typedef void (*ULClipboardClearCallback)();
///
/// The callback invoked when the library wants to read from the system's clipboard.
///
/// You should store the result (if any) in 'result'.
///
typedef void (*ULClipboardReadPlainTextCallback)(ULString result);
///
/// The callback invoked when the library wants to write to the system's clipboard.
///
typedef void (*ULClipboardWritePlainTextCallback)(ULString text);
///
/// User-defined clipboard interface.
///
/// You should implement each of these callbacks, then pass an instance of this struct containing
/// your callbacks to ulPlatformSetClipboard().
///
typedef struct {
ULClipboardClearCallback clear;
ULClipboardReadPlainTextCallback read_plain_text;
ULClipboardWritePlainTextCallback write_plain_text;
} ULClipboard;
#ifdef __cplusplus
} // extern "C"
#endif
#endif // ULTRALIGHT_CAPI_CLIPBOARD_H
+235
View File
@@ -0,0 +1,235 @@
/**************************************************************************************************
* This file is a part of Ultralight, an ultra-portable web-browser engine. *
* *
* See <https://ultralig.ht> for licensing and more. *
* *
* (C) 2024 Ultralight, Inc. *
**************************************************************************************************/
///
/// @file CAPI_Config.h
///
/// Core configuration for the renderer.
///
/// `#include <Ultralight/CAPI/CAPI_Config.h>`
///
/// These are various configuration options that can be used to customize the behavior of the
/// library. These options can only be set once before creating the Renderer.
///
#ifndef ULTRALIGHT_CAPI_CONFIG_H
#define ULTRALIGHT_CAPI_CONFIG_H
#include <Ultralight/CAPI/CAPI_Defines.h>
#ifdef __cplusplus
extern "C" {
#endif
/******************************************************************************
* Config
*****************************************************************************/
///
/// Create config with default values (see <Ultralight/platform/Config.h>).
///
ULExport ULConfig ulCreateConfig();
///
/// Destroy config.
///
ULExport void ulDestroyConfig(ULConfig config);
///
/// A writable OS file path to store persistent Session data in.
///
/// This data may include cookies, cached network resources, indexed DB, etc.
///
/// @note Files are only written to the path when using a persistent Session.
///
ULExport void ulConfigSetCachePath(ULConfig config, ULString cache_path);
///
/// The relative path to the resources folder (loaded via the FileSystem API).
///
/// The library loads certain resources (SSL certs, ICU data, etc.) from the FileSystem API
/// during runtime (eg, `file:///resources/cacert.pem`).
///
/// You can customize the relative file path to the resources folder by modifying this setting.
///
/// (Default = "resources/")
///
ULExport void ulConfigSetResourcePathPrefix(ULConfig config, ULString resource_path_prefix);
///
/// The winding order for front-facing triangles.
///
/// @pre Only used when GPU rendering is enabled for the View.
///
/// (Default = kFaceWinding_CounterClockwise)
///
ULExport void ulConfigSetFaceWinding(ULConfig config, ULFaceWinding winding);
///
/// The hinting algorithm to use when rendering fonts. (Default = kFontHinting_Normal)
///
/// @see ULFontHinting
///
ULExport void ulConfigSetFontHinting(ULConfig config, ULFontHinting font_hinting);
///
/// The gamma to use when compositing font glyphs, change this value to adjust contrast (Adobe and
/// Apple prefer 1.8, others may prefer 2.2). (Default = 1.8)
///
ULExport void ulConfigSetFontGamma(ULConfig config, double font_gamma);
///
/// Global user-defined CSS string (included before any CSS on the page).
///
/// You can use this to override default styles for various elements on the page.
///
/// @note This is an actual string of CSS, not a file path.
///
ULExport void ulConfigSetUserStylesheet(ULConfig config, ULString css_string);
///
/// Whether or not to continuously repaint any Views, regardless if they are dirty.
///
/// This is mainly used to diagnose painting/shader issues and profile performance.
///
/// (Default = False)
///
ULExport void ulConfigSetForceRepaint(ULConfig config, bool enabled);
///
/// The delay (in seconds) between every tick of a CSS animation.
///
/// (Default = 1.0 / 60.0)
///
ULExport void ulConfigSetAnimationTimerDelay(ULConfig config, double delay);
///
/// The delay (in seconds) between every tick of a smooth scroll animation.
///
/// (Default = 1.0 / 60.0)
///
ULExport void ulConfigSetScrollTimerDelay(ULConfig config, double delay);
///
/// The delay (in seconds) between every call to the recycler.
///
/// The library attempts to reclaim excess memory during calls to the internal recycler. You can
/// change how often this is run by modifying this value.
///
/// (Default = 4.0)
///
ULExport void ulConfigSetRecycleDelay(ULConfig config, double delay);
///
/// The size of WebCore's memory cache in bytes.
///
/// @note You should increase this if you anticipate handling pages with large resources, Safari
/// typically uses 128+ MiB for its cache.
///
/// (Default = 64 * 1024 * 1024)
///
ULExport void ulConfigSetMemoryCacheSize(ULConfig config, unsigned int size);
///
/// The number of pages to keep in the cache. (Default: 0, none)
///
/// @note
/// \parblock
///
/// Safari typically caches about 5 pages and maintains an on-disk cache to support typical
/// web-browsing activities.
///
/// If you increase this, you should probably increase the memory cache size as well.
///
/// \endparblock
///
/// (Default = 0)
///
ULExport void ulConfigSetPageCacheSize(ULConfig config, unsigned int size);
///
/// The system's physical RAM size in bytes.
///
/// JavaScriptCore tries to detect the system's physical RAM size to set reasonable allocation
/// limits. Set this to anything other than 0 to override the detected value. Size is in bytes.
///
/// This can be used to force JavaScriptCore to be more conservative with its allocation strategy
/// (at the cost of some performance).
///
ULExport void ulConfigSetOverrideRAMSize(ULConfig config, unsigned int size);
///
/// The minimum size of large VM heaps in JavaScriptCore.
///
/// Set this to a lower value to make these heaps start with a smaller initial value.
///
/// (Default = 32 * 1024 * 1024)
///
ULExport void ulConfigSetMinLargeHeapSize(ULConfig config, unsigned int size);
///
/// The minimum size of small VM heaps in JavaScriptCore.
///
/// Set this to a lower value to make these heaps start with a smaller initial value.
///
/// (Default = 1 * 1024 * 1024)
///
ULExport void ulConfigSetMinSmallHeapSize(ULConfig config, unsigned int size);
///
/// The number of threads to use in the Renderer (for parallel painting on the CPU, etc.).
///
/// You can set this to a certain number to limit the number of threads to spawn.
///
/// @note
/// \parblock
///
/// If this value is 0, the number of threads will be determined at runtime using the following
/// formula:
///
/// ```
/// max(PhysicalProcessorCount() - 1, 1)
/// ```
///
/// \endparblock
///
ULExport void ulConfigSetNumRendererThreads(ULConfig config, unsigned int num_renderer_threads);
///
/// The max amount of time (in seconds) to allow repeating timers to run during each call to
/// Renderer::Update.
///
/// The library will attempt to throttle timers if this time budget is exceeded.
///
/// (Default = 1.0 / 200.0)
///
ULExport void ulConfigSetMaxUpdateTime(ULConfig config, double max_update_time);
///
/// The alignment (in bytes) of the BitmapSurface when using the CPU renderer.
///
/// The underlying bitmap associated with each BitmapSurface will have row_bytes padded to reach
/// this alignment.
///
/// Aligning the bitmap helps improve performance when using the CPU renderer. Determining the
/// proper value to use depends on the CPU architecture and max SIMD instruction set used.
///
/// We generally target the 128-bit SSE2 instruction set across most PC platforms so '16' is a safe
/// value to use.
///
/// You can set this to '0' to perform no padding (row_bytes will always be width * 4) at a slight
/// cost to performance.
///
/// (Default = 16)
///
ULExport void ulConfigSetBitmapAlignment(ULConfig config, unsigned int bitmap_alignment);
#ifdef __cplusplus
} // extern "C"
#endif
#endif // ULTRALIGHT_CAPI_CONFIG_H
+318
View File
@@ -0,0 +1,318 @@
/**************************************************************************************************
* This file is a part of Ultralight, an ultra-portable web-browser engine. *
* *
* See <https://ultralig.ht> for licensing and more. *
* *
* (C) 2024 Ultralight, Inc. *
**************************************************************************************************/
///
/// @file CAPI_Defines.h
///
/// Various defines and utility functions for the C API.
///
/// `#include <Ultralight/CAPI/CAPI_Defines.h>`
///
/// This file contains various defines, structures, and utility functions for the C API.
///
#ifndef ULTRALIGHT_CAPI_DEFINES_H
#define ULTRALIGHT_CAPI_DEFINES_H
#include <stddef.h>
#include <stdint.h>
#include <JavaScriptCore/JavaScript.h>
#ifdef __OBJC__
#import <AppKit/NSEvent.h>
#endif
#if defined(ULTRALIGHT_STATIC_BUILD)
#define ULExport
#else
#if defined(__WIN32__) || defined(_WIN32)
#if defined(ULTRALIGHT_IMPLEMENTATION)
#define ULExport __declspec(dllexport)
#else
#define ULExport __declspec(dllimport)
#endif
#else
#define ULExport __attribute__((visibility("default")))
#endif
#endif
#if defined(__WIN32__) || defined(_WIN32)
#define _thread_local __declspec(thread)
#ifndef _NATIVE_WCHAR_T_DEFINED
#define DISABLE_NATIVE_WCHAR_T
typedef unsigned short ULChar16;
#else
typedef wchar_t ULChar16;
#endif
#else
#define _thread_local __thread
typedef unsigned short ULChar16;
#endif
#ifdef __cplusplus
extern "C" {
#endif
typedef struct C_Config* ULConfig;
typedef struct C_Renderer* ULRenderer;
typedef struct C_Session* ULSession;
typedef struct C_ViewConfig* ULViewConfig;
typedef struct C_View* ULView;
typedef struct C_Bitmap* ULBitmap;
typedef struct C_String* ULString;
typedef struct C_Buffer* ULBuffer;
typedef struct C_KeyEvent* ULKeyEvent;
typedef struct C_MouseEvent* ULMouseEvent;
typedef struct C_ScrollEvent* ULScrollEvent;
typedef struct C_GamepadEvent* ULGamepadEvent;
typedef struct C_GamepadAxisEvent* ULGamepadAxisEvent;
typedef struct C_GamepadButtonEvent* ULGamepadButtonEvent;
typedef struct C_Surface* ULSurface;
typedef struct C_Surface* ULBitmapSurface;
typedef struct C_FontFile* ULFontFile;
typedef struct C_ImageSource* ULImageSource;
typedef enum {
kMessageSource_XML = 0,
kMessageSource_JS,
kMessageSource_Network,
kMessageSource_ConsoleAPI,
kMessageSource_Storage,
kMessageSource_AppCache,
kMessageSource_Rendering,
kMessageSource_CSS,
kMessageSource_Security,
kMessageSource_ContentBlocker,
kMessageSource_Media,
kMessageSource_MediaSource,
kMessageSource_WebRTC,
kMessageSource_ITPDebug,
kMessageSource_PrivateClickMeasurement,
kMessageSource_PaymentRequest,
kMessageSource_Other,
} ULMessageSource;
typedef enum {
kMessageLevel_Log = 0,
kMessageLevel_Warning,
kMessageLevel_Error,
kMessageLevel_Debug,
kMessageLevel_Info,
} ULMessageLevel;
typedef enum {
kCursor_Pointer = 0,
kCursor_Cross,
kCursor_Hand,
kCursor_IBeam,
kCursor_Wait,
kCursor_Help,
kCursor_EastResize,
kCursor_NorthResize,
kCursor_NorthEastResize,
kCursor_NorthWestResize,
kCursor_SouthResize,
kCursor_SouthEastResize,
kCursor_SouthWestResize,
kCursor_WestResize,
kCursor_NorthSouthResize,
kCursor_EastWestResize,
kCursor_NorthEastSouthWestResize,
kCursor_NorthWestSouthEastResize,
kCursor_ColumnResize,
kCursor_RowResize,
kCursor_MiddlePanning,
kCursor_EastPanning,
kCursor_NorthPanning,
kCursor_NorthEastPanning,
kCursor_NorthWestPanning,
kCursor_SouthPanning,
kCursor_SouthEastPanning,
kCursor_SouthWestPanning,
kCursor_WestPanning,
kCursor_Move,
kCursor_VerticalText,
kCursor_Cell,
kCursor_ContextMenu,
kCursor_Alias,
kCursor_Progress,
kCursor_NoDrop,
kCursor_Copy,
kCursor_None,
kCursor_NotAllowed,
kCursor_ZoomIn,
kCursor_ZoomOut,
kCursor_Grab,
kCursor_Grabbing,
kCursor_Custom
} ULCursor;
typedef enum {
///
/// Alpha channel only, 8-bits per pixel.
///
/// Encoding: 8-bits per channel, unsigned normalized.
///
/// Color-space: Linear (no gamma), alpha-coverage only.
///
kBitmapFormat_A8_UNORM,
///
/// Blue Green Red Alpha channels, 32-bits per pixel.
///
/// Encoding: 8-bits per channel, unsigned normalized.
///
/// Color-space: sRGB gamma with premultiplied linear alpha channel.
///
kBitmapFormat_BGRA8_UNORM_SRGB
} ULBitmapFormat;
typedef enum {
///
/// Key-Down event type. This type does **not** trigger accelerator commands in WebCore (eg,
/// Ctrl+C for copy is an accelerator command).
///
/// @warning You should probably use kKeyEventType_RawKeyDown instead. This type is only here for
/// historic compatibility with WebCore's key event types.
///
kKeyEventType_KeyDown,
///
/// Key-Up event type. Use this when a physical key is released.
///
kKeyEventType_KeyUp,
///
/// Raw Key-Down type. Use this when a physical key is pressed.
///
kKeyEventType_RawKeyDown,
///
/// Character input event type. Use this when the OS generates text from
/// a physical key being pressed (eg, WM_CHAR on Windows).
///
kKeyEventType_Char,
} ULKeyEventType;
typedef enum {
kMouseEventType_MouseMoved,
kMouseEventType_MouseDown,
kMouseEventType_MouseUp,
} ULMouseEventType;
typedef enum {
kMouseButton_None = 0,
kMouseButton_Left,
kMouseButton_Middle,
kMouseButton_Right,
} ULMouseButton;
typedef enum {
kScrollEventType_ScrollByPixel,
kScrollEventType_ScrollByPage,
} ULScrollEventType;
typedef enum {
kGamepadEventType_Connected,
kGamepadEventType_Disconnected,
} ULGamepadEventType;
typedef enum {
kFaceWinding_Clockwise,
kFaceWinding_CounterClockwise,
} ULFaceWinding;
typedef enum {
///
/// Lighter hinting algorithm-- glyphs are slightly fuzzier but better
/// resemble their original shape. This is achieved by snapping glyphs to the
/// pixel grid only vertically which better preserves inter-glyph spacing.
///
kFontHinting_Smooth,
///
/// Default hinting algorithm-- offers a good balance between sharpness and
/// shape at smaller font sizes.
///
kFontHinting_Normal,
///
/// Strongest hinting algorithm-- outputs only black/white glyphs. The result
/// is usually unpleasant if the underlying TTF does not contain hints for
/// this type of rendering.
///
kFontHinting_Monochrome,
} ULFontHinting;
typedef struct {
float left;
float top;
float right;
float bottom;
} ULRect;
typedef struct {
int left;
int top;
int right;
int bottom;
} ULIntRect;
///
/// Offscreen render target, used when rendering Views via the GPU renderer.
///
/// When a View is rendered via the GPU renderer (see ulViewIsAccelerated()), it will be rendered to
/// an offscreen render target (ulViewGetRenderTarget()) that you can display in your application.
///
/// This is intended to be used with a custom ULGPUDriver implementation in a game or similar
/// application (ulPlatformSetGPUDriver()).
///
typedef struct {
bool is_empty;
unsigned int width;
unsigned int height;
unsigned int texture_id;
unsigned int texture_width;
unsigned int texture_height;
ULBitmapFormat texture_format;
ULRect uv_coords;
unsigned int render_buffer_id;
} ULRenderTarget;
/******************************************************************************
* Version
*****************************************************************************/
///
/// Get the version string of the library in MAJOR.MINOR.PATCH format.
///
ULExport const char* ulVersionString();
///
/// Get the numeric major version of the library.
///
ULExport unsigned int ulVersionMajor();
///
/// Get the numeric minor version of the library.
///
ULExport unsigned int ulVersionMinor();
///
/// Get the numeric patch version of the library.
///
ULExport unsigned int ulVersionPatch();
///
/// Get the full WebKit version string.
///
ULExport const char* ulWebKitVersionString();
#ifdef __cplusplus
} // extern "C"
#endif
#endif // ULTRALIGHT_CAPI_DEFINES_H
+94
View File
@@ -0,0 +1,94 @@
/**************************************************************************************************
* This file is a part of Ultralight, an ultra-portable web-browser engine. *
* *
* See <https://ultralig.ht> for licensing and more. *
* *
* (C) 2024 Ultralight, Inc. *
**************************************************************************************************/
///
/// @file CAPI_FileSystem.h
///
/// User-defined file system interface.
///
/// `#include <Ultralight/CAPI/CAPI_FileSystem.h>`
///
/// The library uses this to load file data (ie, raw file bytes) for a given file URL
/// (eg, `file:///page.html`) .
///
/// You can provide the library with your own FileSystem implementation (ULFileSystem) so that file
/// data is provided directly by your application (eg, from memory, from a virtual file system,
/// etc).
///
/// @see ulPlatformSetFileSystem
///
#ifndef ULTRALIGHT_CAPI_FILESYSTEM_H
#define ULTRALIGHT_CAPI_FILESYSTEM_H
#include <Ultralight/CAPI/CAPI_Defines.h>
#ifdef __cplusplus
extern "C" {
#endif
/******************************************************************************
* File System
*****************************************************************************/
///
/// The callback invoked when the FileSystem wants to check if a file path exists, return true if it
/// exists.
///
typedef bool (*ULFileSystemFileExistsCallback)(ULString path);
///
/// Get the mime-type of the file (eg "text/html").
///
/// This is usually determined by analyzing the file extension.
///
/// If a mime-type cannot be determined, you should return "application/unknown" for this value.
///
/// The library will consume the result and call ulDestroyString() after this call returns.
///
typedef ULString (*ULFileSystemGetFileMimeTypeCallback)(ULString path);
///
/// Get the charset / encoding of the file (eg "utf-8").
///
/// This is only important for text-based files and is usually determined by analyzing the
/// contents of the file.
///
/// If a charset cannot be determined, it's usually safe to return "utf-8" for this value.
///
/// The library will consume the result and call ulDestroyString() after this call returns.
///
typedef ULString (*ULFileSystemGetFileCharsetCallback)(ULString path);
///
/// Open file for reading and map it to a Buffer.
///
/// To minimize copies, you should map the requested file into memory and use ulCreateBuffer()
/// to wrap the data pointer (unmapping should be performed in the destruction callback).
///
/// If the file was unable to be opened, you should return NULL for this value.
///
typedef ULBuffer (*ULFileSystemOpenFileCallback)(ULString path);
///
/// User-defined file system interface.
///
/// You should implement each of these callbacks, then pass an instance of this struct containing
/// your callbacks to ulPlatformSetFileSystem().
///
typedef struct {
ULFileSystemFileExistsCallback file_exists;
ULFileSystemGetFileMimeTypeCallback get_file_mime_type;
ULFileSystemGetFileCharsetCallback get_file_charset;
ULFileSystemOpenFileCallback open_file;
} ULFileSystem;
#ifdef __cplusplus
} // extern "C"
#endif
#endif // ULTRALIGHT_CAPI_FILESYSTEM_H
+52
View File
@@ -0,0 +1,52 @@
/**************************************************************************************************
* This file is a part of Ultralight, an ultra-portable web-browser engine. *
* *
* See <https://ultralig.ht> for licensing and more. *
* *
* (C) 2024 Ultralight, Inc. *
**************************************************************************************************/
///
/// @file CAPI_FontFile.h
///
/// Font file interface.
///
/// `#include <Ultralight/CAPI/CAPI_FontFile.h>`
///
/// The font file interface represents a font file: either on-disk path or in-memory file contents.
///
/// @see ULFontLoader
///
#ifndef ULTRALIGHT_CAPI_FONTFILE_H
#define ULTRALIGHT_CAPI_FONTFILE_H
#include <Ultralight/CAPI/CAPI_Defines.h>
#include <Ultralight/CAPI/CAPI_String.h>
#include <Ultralight/CAPI/CAPI_Buffer.h>
#ifdef __cplusplus
extern "C" {
#endif
///
/// Create a font file from an on-disk file path.
///
/// @note The file path should already exist.
///
ULExport ULFontFile ulFontFileCreateFromFilePath(ULString file_path);
///
/// Create a font file from an in-memory buffer.
///
ULExport ULFontFile ulFontFileCreateFromBuffer(ULBuffer buffer);
///
/// Destroy font file
///
ULExport void ulDestroyFontFile(ULFontFile font_file);
#ifdef __cplusplus
} // extern "C"
#endif
#endif // ULTRALIGHT_CAPI_FONTFILE_H
+99
View File
@@ -0,0 +1,99 @@
/**************************************************************************************************
* This file is a part of Ultralight, an ultra-portable web-browser engine. *
* *
* See <https://ultralig.ht> for licensing and more. *
* *
* (C) 2024 Ultralight, Inc. *
**************************************************************************************************/
///
/// @file CAPI_FontLoader.h
///
/// User-defined font loader interface.
///
/// `#include <Ultralight/CAPI/CAPI_FontLoader.h>`
///
/// The library uses this to load a font file (eg, `Arial.ttf`) for a given font description (eg,
/// `font-family: Arial;`).
///
/// Every OS has its own library of installed system fonts. The FontLoader interface is used to
/// lookup these fonts and fetch the actual font data (raw TTF/OTF file data) for a given font
/// description.
///
/// You can provide the library with your own font loader implementation so that you can bundle
/// fonts with your application rather than relying on the system's installed fonts.
///
/// @see ulPlatformSetFontLoader
///
#ifndef ULTRALIGHT_CAPI_FONTLOADER_H
#define ULTRALIGHT_CAPI_FONTLOADER_H
#include <Ultralight/CAPI/CAPI_Defines.h>
#include <Ultralight/CAPI/CAPI_FontFile.h>
#ifdef __cplusplus
extern "C" {
#endif
/******************************************************************************
* Font Loader
*****************************************************************************/
///
/// Fallback font family name. Will be used if all other fonts fail to load.
///
/// @note This font should be guaranteed to exist (eg, ULFontLoader::load should not fail when
/// when passed this font family name).
///
/// @note The returned ULString instance will be consumed (ulDestroyString will be called on it).
///
typedef ULString (*ULFontLoaderGetFallbackFont)();
///
/// Fallback font family name that can render the specified characters. This is mainly used to
/// support CJK (Chinese, Japanese, Korean) text display.
///
/// @param characters One or more UTF-16 characters. This is almost always a single character.
///
/// @param weight Font weight.
///
/// @param italic Whether or not italic is requested.
///
/// @return Should return a font family name that can render the text. The returned ULString
/// instance will be consumed (ulDestroyString will be called on it).
///
typedef ULString (*ULFontLoaderGetFallbackFontForCharacters)(ULString characters, int weight,
bool italic);
///
/// Get the actual font file data (TTF/OTF) for a given font description.
///
/// @param family Font family name.
///
/// @param weight Font weight.
///
/// @param italic Whether or not italic is requested.
///
/// @return A font file matching the given description (either an on-disk font filepath or an
/// in-memory file buffer). You can return NULL here and the loader will fallback to
/// another font.
///
typedef ULFontFile (*ULFontLoaderLoad)(ULString family, int weight, bool italic);
///
/// User-defined font loader interface.
///
/// You should implement each of these callbacks, then pass an instance of this struct containing
/// your callbacks to ulPlatformSetFontLoader().
///
typedef struct {
ULFontLoaderGetFallbackFont get_fallback_font;
ULFontLoaderGetFallbackFontForCharacters get_fallback_font_for_characters;
ULFontLoaderLoad load;
} ULFontLoader;
#ifdef __cplusplus
} // extern "C"
#endif
#endif // ULTRALIGHT_CAPI_FONTLOADER_H
+478
View File
@@ -0,0 +1,478 @@
/**************************************************************************************************
* This file is a part of Ultralight, an ultra-portable web-browser engine. *
* *
* See <https://ultralig.ht> for licensing and more. *
* *
* (C) 2024 Ultralight, Inc. *
**************************************************************************************************/
// clang-format off
///
/// @file CAPI_GPUDriver.h
///
/// User-defined GPU driver interface.
///
/// `#include <Ultralight/CAPI/CAPI_GPUDriver.h>`
///
/// The library uses this to optionally render Views on the GPU (see ulViewIsAccelerated()).
///
/// You can provide the library with your own GPU driver implementation so that all rendering is
/// performed using an existing GPU context (useful for game engines).
///
/// When a View is rendered on the GPU, you can retrieve the backing texture ID via
/// ulViewGetRenderTarget().
///
/// @see ulPlatformSetGPUDriver()
///
#ifndef ULTRALIGHT_CAPI_GPUDRIVER_H
#define ULTRALIGHT_CAPI_GPUDRIVER_H
#include <Ultralight/CAPI/CAPI_Defines.h>
#ifdef __cplusplus
extern "C" {
#endif
/******************************************************************************
* GPUDriver
*****************************************************************************/
///
/// Render buffer description.
///
/// This structure describes a render buffer that can be used as a target for drawing commands.
///
typedef struct {
unsigned int texture_id; ///< The backing texture for this RenderBuffer
unsigned int width; ///< The width of the RenderBuffer texture
unsigned int height; ///< The height of the RenderBuffer texture
bool has_stencil_buffer; ///< Currently unused, always false.
bool has_depth_buffer; ///< Currently unsued, always false.
} ULRenderBuffer;
/// \cond ignore
/// This pragma pack(push, 1) command is important!
/// GPU structs should not be padded with any bytes.
/// \endcond
#pragma pack(push, 1)
///
/// Vertex layout for path vertices.
///
/// This struct is the in-memory layout for each path vertex (useful for synthesizing or modifying
/// your own vertex data).
///
typedef struct {
float pos[2];
unsigned char color[4];
float obj[2];
} ULVertex_2f_4ub_2f;
///
/// Vertex layout for quad vertices.
///
/// This struct is the in-memory layout for each quad vertex (useful for synthesizing or modifying
/// your own vertex data).
///
typedef struct {
float pos[2];
unsigned char color[4];
float tex[2];
float obj[2];
float data0[4];
float data1[4];
float data2[4];
float data3[4];
float data4[4];
float data5[4];
float data6[4];
} ULVertex_2f_4ub_2f_2f_28f;
///
/// End single-byte alignment.
///
#pragma pack(pop)
///
/// Vertex buffer formats.
///
/// This enumeration describes the format of a vertex buffer.
///
typedef enum {
kVertexBufferFormat_2f_4ub_2f, ///< Vertex_2f_4ub_2f (used for path rendering)
kVertexBufferFormat_2f_4ub_2f_2f_28f, ///< Vertex_2f_4ub_2f_2f_28f (used for quad rendering)
} ULVertexBufferFormat;
///
/// Vertex buffer description.
///
/// @see ULGPUDriver::create_geometry
///
typedef struct {
ULVertexBufferFormat format; ///< The format of the vertex buffer.
unsigned int size; ///< The size of the vertex buffer in bytes.
unsigned char* data; ///< The raw vertex buffer data.
} ULVertexBuffer;
///
/// Vertex index type.
///
typedef unsigned int ULIndexType;
///
/// Index buffer description.
///
/// This structure describes an index buffer that can be used to index into a vertex buffer.
///
/// @note The index buffer is a simple array of IndexType values.
///
typedef struct {
unsigned int size; ///< The size of the index buffer in bytes.
unsigned char* data; ///< The raw index buffer data.
} ULIndexBuffer;
///
/// Shader program types, used with ULGPUState::shader_type
///
/// Each of these correspond to a vertex/pixel shader pair. You can find stock shader code for these
/// in the `shaders` folder of the AppCore repo.
///
typedef enum {
kShaderType_Fill, ///< Shader program for filling quad geometry.
kShaderType_FillPath, ///< Shader program for filling tesselated path geometry.
} ULShaderType;
///
/// Raw 4x4 matrix as an array of floats in column-major order.
///
typedef struct {
float data[16];
} ULMatrix4x4;
///
/// 4-component float vector
///
typedef struct {
float value[4];
} ULvec4;
///
/// The state of the GPU for a given draw command.
///
/// This structure describes the current state of the GPU for a given draw command.
///
typedef struct {
/// Viewport width in pixels
unsigned int viewport_width;
/// Viewport height in pixels
unsigned int viewport_height;
/// Transform matrix-- you should multiply this with the screen-space orthographic projection
/// matrix then pass to the vertex shader.
ULMatrix4x4 transform;
/// Whether or not we should enable texturing for the current draw command.
bool enable_texturing;
/// Whether or not we should enable blending for the current draw command. If blending is
/// disabled, any drawn pixels should overwrite existing. Mainly used so we can modify alpha
/// values of the RenderBuffer during scissored clears.
bool enable_blend;
/// The vertex/pixel shader program pair to use for the current draw command. You should cast this
/// to ShaderType to get the corresponding enum.
unsigned char shader_type;
/// The render buffer to use for the current draw command.
unsigned int render_buffer_id;
/// The texture id to bind to slot #1. (Will be 0 if none)
unsigned int texture_1_id;
/// The texture id to bind to slot #2. (Will be 0 if none)
unsigned int texture_2_id;
/// The texture id to bind to slot #3. (Will be 0 if none)
unsigned int texture_3_id;
/// The uniform scalars (passed to the pixel shader via uniforms).
float uniform_scalar[8];
/// The uniform vectors (passed to the pixel shader via uniforms).
ULvec4 uniform_vector[8];
/// The clip size (passed to the pixel shader via uniforms).
unsigned char clip_size;
/// The clip stack (passed to the pixel shader via uniforms).
ULMatrix4x4 clip[8];
/// Whether or not scissor testing should be used for the current draw command.
bool enable_scissor;
/// The scissor rect to use for scissor testing (units in pixels)
ULIntRect scissor_rect;
} ULGPUState;
///
/// The types of commands.
///
/// This enumeration describes the type of command to execute on the GPU. Used with
/// ULCommand::command_type
///
typedef enum {
kCommandType_ClearRenderBuffer, ///< Clear the specified render buffer.
kCommandType_DrawGeometry, ///< Draw the specified geometry to the specified render buffer.
} ULCommandType;
///
/// A command to execute on the GPU.
///
/// This structure describes a command to be executed on the GPU.
///
/// Commands are dispatched to the GPU driver asynchronously via ULGPUDriver::update_command_list,
/// the GPU driver should consume these commands and execute them at an appropriate time.
///
/// @see ULCommandList
///
typedef struct {
unsigned char command_type; ///< The type of command to dispatch.
ULGPUState gpu_state; ///< The current GPU state.
unsigned int geometry_id; ///< The geometry ID to bind. (used with kCommandType_DrawGeometry)
unsigned int indices_count; ///< The number of indices. (used with kCommandType_DrawGeometry)
unsigned int indices_offset; ///< The index to start from. (used with kCommandType_DrawGeometry)
} ULCommand;
///
/// List of commands to execute on the GPU.
///
/// @see ULGPUDriver::update_command_list
///
typedef struct {
unsigned int size; ///< The number of commands in the list.
ULCommand* commands; ///< The raw command list data.
} ULCommandList;
///
/// Callback for users to implement ULGPUDriver::begin_synchronize.
///
/// Called before any state (eg, create_texture(), update_texture(), destroy_texture(), etc.) is
/// updated during a call to ulRender().
///
/// This is a good time to prepare the GPU for any state updates.
///
typedef void (*ULGPUDriverBeginSynchronizeCallback)();
///
/// Callback for users to implement ULGPUDriver::end_synchronize.
///
/// Called after all state has been updated during a call to ulRender().
///
typedef void (*ULGPUDriverEndSynchronizeCallback)();
///
/// Callback for users to implement ULGPUDriver::next_texture_id.
///
/// Get the next available texture ID.
///
/// This is used to generate a unique texture ID for each texture created by the library. The
/// GPU driver implementation is responsible for mapping these IDs to a native ID.
///
/// @note Numbering should start at 1, 0 is reserved for "no texture".
///
/// @return Returns the next available texture ID.
///
typedef unsigned int (*ULGPUDriverNextTextureIdCallback)();
///
/// Callback for users to implement ULGPUDriver::create_texture.
///
/// Create a texture with a certain ID and optional bitmap.
///
/// @param texture_id The texture ID to use for the new texture.
///
/// @param bitmap The bitmap to initialize the texture with (can be empty).
///
/// @note If the Bitmap is empty (ulBitmapIsEmpty()), then a RTT Texture should be created instead.
/// This will be used as a backing texture for a new RenderBuffer.
///
/// @warning A deep copy of the bitmap data should be made if you are uploading it to the GPU
/// asynchronously, it will not persist beyond this call.
///
typedef void (*ULGPUDriverCreateTextureCallback)(unsigned int texture_id, ULBitmap bitmap);
///
/// Callback for users to implement ULGPUDriver::update_texture.
///
/// Update an existing non-RTT texture with new bitmap data.
///
/// @param texture_id The texture to update.
///
/// @param bitmap The new bitmap data.
///
/// @warning A deep copy of the bitmap data should be made if you are uploading it to the GPU
/// asynchronously, it will not persist beyond this call.
///
typedef void (*ULGPUDriverUpdateTextureCallback)(unsigned int texture_id, ULBitmap bitmap);
///
/// Callback for users to implement ULGPUDriver::destroy_texture.
///
/// Destroy a texture.
///
/// @param texture_id The texture to destroy.
///
typedef void (*ULGPUDriverDestroyTextureCallback)(unsigned int texture_id);
///
/// Callback for users to implement ULGPUDriver::next_render_buffer_id.
///
/// Get the next available render buffer ID.
///
/// This is used to generate a unique render buffer ID for each render buffer created by the
/// library. The GPU driver implementation is responsible for mapping these IDs to a native ID.
///
/// @note Numbering should start at 1, 0 is reserved for "no render buffer".
///
/// @return Returns the next available render buffer ID.
///
typedef unsigned int (*ULGPUDriverNextRenderBufferIdCallback)();
///
/// Callback for users to implement ULGPUDriver::create_render_buffer.
///
/// Create a render buffer with certain ID and buffer description.
///
/// @param render_buffer_id The render buffer ID to use for the new render buffer.
///
/// @param buffer The render buffer description.
///
typedef void (*ULGPUDriverCreateRenderBufferCallback)(unsigned int render_buffer_id,
ULRenderBuffer buffer);
///
/// Callback for users to implement ULGPUDriver::destroy_render_buffer.
///
/// Destroy a render buffer.
///
/// @param render_buffer_id The render buffer to destroy.
///
typedef void (*ULGPUDriverDestroyRenderBufferCallback)(unsigned int render_buffer_id);
///
/// Callback for users to implement ULGPUDriver::next_geometry_id.
///
/// Get the next available geometry ID.
///
/// This is used to generate a unique geometry ID for each geometry created by the library. The
/// GPU driver implementation is responsible for mapping these IDs to a native ID.
///
/// @note Numbering should start at 1, 0 is reserved for "no geometry".
///
/// @return Returns the next available geometry ID.
///
typedef unsigned int (*ULGPUDriverNextGeometryIdCallback)();
///
/// Callback for users to implement ULGPUDriver::create_geometry.
///
/// Create geometry with certain ID and vertex/index data.
///
/// @param geometry_id The geometry ID to use for the new geometry.
///
/// @param vertices The vertex buffer data.
///
/// @param indices The index buffer data.
///
/// @warning A deep copy of the vertex/index data should be made if you are uploading it to the
/// GPU asynchronously, it will not persist beyond this call.
///
typedef void (*ULGPUDriverCreateGeometryCallback)(unsigned int geometry_id, ULVertexBuffer vertices,
ULIndexBuffer indices);
///
/// Callback for users to implement ULGPUDriver::update_geometry.
///
/// Update existing geometry with new vertex/index data.
///
/// @param geometry_id The geometry to update.
///
/// @param vertices The new vertex buffer data.
///
/// @param indices The new index buffer data.
///
/// @warning A deep copy of the vertex/index data should be made if you are uploading it to the
/// GPU asynchronously, it will not persist beyond this call.
///
typedef void (*ULGPUDriverUpdateGeometryCallback)(unsigned int geometry_id, ULVertexBuffer vertices,
ULIndexBuffer indices);
///
/// Callback for users to implement ULGPUDriver::destroy_geometry.
///
/// Destroy geometry.
///
/// @param geometry_id The geometry to destroy.
///
typedef void (*ULGPUDriverDestroyGeometryCallback)(unsigned int geometry_id);
///
/// Callback for users to implement ULGPUDriver::update_command_list.
///
/// Update the pending command list with commands to execute on the GPU.
///
/// Commands are dispatched to the GPU driver asynchronously via this method. The GPU driver
/// implementation should consume these commands and execute them at an appropriate time.
///
/// @param list The list of commands to execute.
///
/// @warning Implementations should make a deep copy of the command list, it will not persist
/// beyond this call.
///
typedef void (*ULGPUDriverUpdateCommandListCallback)(ULCommandList list);
///
/// User-defined GPU driver interface.
///
/// You should implement each of these callbacks, then pass an instance of this struct containing
/// your callbacks to ulPlatformSetGPUDriver().
///
typedef struct {
ULGPUDriverBeginSynchronizeCallback begin_synchronize;
ULGPUDriverEndSynchronizeCallback end_synchronize;
ULGPUDriverNextTextureIdCallback next_texture_id;
ULGPUDriverCreateTextureCallback create_texture;
ULGPUDriverUpdateTextureCallback update_texture;
ULGPUDriverDestroyTextureCallback destroy_texture;
ULGPUDriverNextRenderBufferIdCallback next_render_buffer_id;
ULGPUDriverCreateRenderBufferCallback create_render_buffer;
ULGPUDriverDestroyRenderBufferCallback destroy_render_buffer;
ULGPUDriverNextGeometryIdCallback next_geometry_id;
ULGPUDriverCreateGeometryCallback create_geometry;
ULGPUDriverUpdateGeometryCallback update_geometry;
ULGPUDriverDestroyGeometryCallback destroy_geometry;
ULGPUDriverUpdateCommandListCallback update_command_list;
} ULGPUDriver;
///
/// Sets up an orthographic projection matrix with a certain viewport width and height, multiplies
/// it by 'transform', and returns the result.
///
/// This should be used to calculate the model-view projection matrix for the vertex shaders using
/// the current ULGPUState.
///
/// The 'flip_y' can be optionally used to flip the Y coordinate-space. (Usually flip_y == true for
/// OpenGL)
///
ULExport ULMatrix4x4 ulApplyProjection(ULMatrix4x4 transform, float viewport_width,
float viewport_height, bool flip_y);
#ifdef __cplusplus
} // extern "C"
#endif
#endif // ULTRALIGHT_CAPI_GPUDRIVER_H
// clang-format on
@@ -0,0 +1,77 @@
/**************************************************************************************************
* This file is a part of Ultralight, an ultra-portable web-browser engine. *
* *
* See <https://ultralig.ht> for licensing and more. *
* *
* (C) 2024 Ultralight, Inc. *
**************************************************************************************************/
///
/// @file CAPI_GamepadEvent.h
///
/// Gamepad event interface.
///
/// `#include <Ultralight/CAPI/CAPI_GamepadEvent.h>`
///
/// This file defines the C API for gamepad events.
///
/// @see ulFireGamepadEvent
///
#ifndef ULTRALIGHT_CAPI_GAMEPADEVENT_H
#define ULTRALIGHT_CAPI_GAMEPADEVENT_H
#include <Ultralight/CAPI/CAPI_Defines.h>
#ifdef __cplusplus
extern "C" {
#endif
/******************************************************************************
* Gamepad Event
*****************************************************************************/
///
/// Create a gamepad event, see GamepadEvent for help using this function.
///
ULExport ULGamepadEvent ulCreateGamepadEvent(unsigned int index, ULGamepadEventType type);
///
/// Destroy a gamepad event.
///
ULExport void ulDestroyGamepadEvent(ULGamepadEvent evt);
/******************************************************************************
* Gamepad Axis Event
*****************************************************************************/
///
/// Create a gamepad axis event, see GamepadAxisEvent for help using this function.
///
ULExport ULGamepadAxisEvent ulCreateGamepadAxisEvent(unsigned int index, unsigned int axis_index,
double value);
///
/// Destroy a gamepad axis event.
///
ULExport void ulDestroyGamepadAxisEvent(ULGamepadAxisEvent evt);
/******************************************************************************
* Gamepad Button Event
*****************************************************************************/
///
/// Create a gamepad button event, see GamepadButtonEvent for help using this function.
///
ULExport ULGamepadButtonEvent ulCreateGamepadButtonEvent(unsigned int index,
unsigned int button_index, double value);
///
/// Destroy a gamepad button event.
///
ULExport void ulDestroyGamepadButtonEvent(ULGamepadButtonEvent evt);
#ifdef __cplusplus
} // extern "C"
#endif
#endif // ULTRALIGHT_CAPI_GAMEPADEVENT_H
+59
View File
@@ -0,0 +1,59 @@
/**************************************************************************************************
* This file is a part of Ultralight, an ultra-portable web-browser engine. *
* *
* See <https://ultralig.ht> for licensing and more. *
* *
* (C) 2024 Ultralight, Inc. *
**************************************************************************************************/
///
/// @file CAPI_Geometry.h
///
/// Geometry utilities.
///
/// `#include <Ultralight/CAPI/CAPI_Geometry.h>`
///
/// This file defines the C API for various geometry utilities.
///
#ifndef ULTRALIGHT_CAPI_GEOMETRY_H
#define ULTRALIGHT_CAPI_GEOMETRY_H
#include <Ultralight/CAPI/CAPI_Defines.h>
#ifdef __cplusplus
extern "C" {
#endif
/******************************************************************************
* Rect
*****************************************************************************/
///
/// Whether or not a ULRect is empty (all members equal to 0)
///
ULExport bool ulRectIsEmpty(ULRect rect);
///
/// Create an empty ULRect (all members equal to 0)
///
ULExport ULRect ulRectMakeEmpty();
/******************************************************************************
* IntRect
*****************************************************************************/
///
/// Whether or not a ULIntRect is empty (all members equal to 0)
///
ULExport bool ulIntRectIsEmpty(ULIntRect rect);
///
/// Create an empty ULIntRect (all members equal to 0)
///
ULExport ULIntRect ulIntRectMakeEmpty();
#ifdef __cplusplus
} // extern "C"
#endif
#endif // ULTRALIGHT_CAPI_GEOMETRY_H
+147
View File
@@ -0,0 +1,147 @@
/**************************************************************************************************
* This file is a part of Ultralight, an ultra-portable web-browser engine. *
* *
* See <https://ultralig.ht> for licensing and more. *
* *
* (C) 2024 Ultralight, Inc. *
**************************************************************************************************/
///
/// @file CAPI_ImageSource.h
///
/// User-defined image source to display custom images on a web-page.
///
/// `#include <Ultralight/CAPI/CAPI_ImageSource.h>`
///
/// This API allows you to composite your own images into a web-page. This is useful for displaying
/// in-game textures, external image assets, or other custom content.
///
/// ## ImageSource File Format
///
/// To use an ImageSource, you must first create an `.imgsrc` file containing a string identifying
/// the image source. This string will be used to lookup the ImageSource from ImageSourceProvider
/// when it is loaded on a web-page.
///
/// The file format is as follows:
///
/// ```
/// IMGSRC-V1
/// <identifier>
/// ```
///
/// You can use the `.imgsrc` file anywhere in your web-page that typically accepts an image URL.
/// For example:
///
/// ```html
/// <img src="my_custom_image.imgsrc" />
/// ```
///
/// ## Creating from a GPU Texture
///
/// To composite your own GPU texture on a web-page, you should first reserve a texture ID from
/// ULGPUDriver::next_texture_id and then create an ImageSource from that texture ID. Next, you
/// should register the ImageSource with ImageSourceProvider using the identifier from the `.imgsrc`
/// file.
///
/// When the image element is drawn on the web-page, the library will draw geometry using the
/// specified texture ID and UV coordinates. You should bind your own texture when the specified
/// texture ID is used.
///
/// If the GPU renderer is not enabled for the View or pixel data is needed for other purposes, the
/// library will sample the backing bitmap instead.
///
/// ## Creating from a Bitmap
///
/// To composite your own bitmap on a web-page, you should create an ImageSource from a Bitmap.
/// Next, you should register the ImageSource with ImageSourceProvider using the identifier from
/// the `.imgsrc` file.
///
/// When the image element is drawn on the web-page, the library will sample this bitmap directly.
///
/// ## Invalidating Images
///
/// If you modify the texture or bitmap after creating the ImageSource, you should call
/// ulImageSourceInvalidate() to notify the library that the image should be redrawn.
///
#ifndef ULTRALIGHT_CAPI_IMAGESOURCE_H
#define ULTRALIGHT_CAPI_IMAGESOURCE_H
#include <Ultralight/CAPI/CAPI_Defines.h>
#ifdef __cplusplus
extern "C" {
#endif
/******************************************************************************
* ImageSource
*****************************************************************************/
///
/// Create an image source from a GPU texture with optional backing bitmap.
///
/// @param width The width of the image in pixels (used for layout).
///
/// @param height The height of the image in pixels (used for layout).
///
/// @param texture_id The GPU texture identifier to bind when drawing the quad for this image.
/// This should be non-zero and obtained from ULGPUDriver::next_texture_id.
///
/// @param texture_uv The UV coordinates of the texture.
///
/// @param bitmap Optional backing bitmap for this image source. This is used when drawing
/// the image using the CPU renderer or when pixel data is needed for other
/// purposes. You should update this bitmap when the texture changes.
///
/// @return A new image source instance.
///
ULExport ULImageSource ulCreateImageSourceFromTexture(unsigned int width, unsigned int height,
unsigned int texture_id, ULRect texture_uv,
ULBitmap bitmap);
///
/// Create an image source from a bitmap.
///
/// @param bitmap The backing bitmap for this image source.
///
/// @return A new image source instance.
///
ULExport ULImageSource ulCreateImageSourceFromBitmap(ULBitmap bitmap);
///
/// Destroy an image source.
///
/// @param image_source The image source to destroy.
///
ULExport void ulDestroyImageSource(ULImageSource image_source);
///
/// Invalidate the image source, notifying the library that the image has changed
/// and should be redrawn.
///
ULExport void ulImageSourceInvalidate(ULImageSource image_source);
/******************************************************************************
* ImageSourceProvider
*****************************************************************************/
///
/// Add an image source to the provider.
///
/// @param id The identifier of the image source.
///
/// @param image_source The image source to add.
///
ULExport void ulImageSourceProviderAddImageSource(ULString id, ULImageSource image_source);
///
/// Remove an image source from the provider.
///
/// @param id The identifier of the image source.
///
ULExport void ulImageSourceProviderRemoveImageSource(ULString id);
#ifdef __cplusplus
}
#endif
#endif // ULTRALIGHT_CAPI_IMAGESOURCE_H
+63
View File
@@ -0,0 +1,63 @@
/**************************************************************************************************
* This file is a part of Ultralight, an ultra-portable web-browser engine. *
* *
* See <https://ultralig.ht> for licensing and more. *
* *
* (C) 2024 Ultralight, Inc. *
**************************************************************************************************/
///
/// @file CAPI_KeyEvent.h
///
/// Key event interface.
///
/// `#include <Ultralight/CAPI/CAPI_KeyEvent.h>`
///
/// This file defines the C API for various key events.
///
#ifndef ULTRALIGHT_CAPI_KEYEVENT_H
#define ULTRALIGHT_CAPI_KEYEVENT_H
#include <Ultralight/CAPI/CAPI_Defines.h>
#ifdef __cplusplus
extern "C" {
#endif
/******************************************************************************
* Key Event
******************************************************************************/
///
/// Create a key event, see KeyEvent in the C++ API for help with the parameters.
///
ULExport ULKeyEvent ulCreateKeyEvent(ULKeyEventType type, unsigned int modifiers,
int virtual_key_code, int native_key_code, ULString text,
ULString unmodified_text, bool is_keypad, bool is_auto_repeat,
bool is_system_key);
#ifdef _WIN32
///
/// Create a key event from native Windows event.
///
ULExport ULKeyEvent ulCreateKeyEventWindows(ULKeyEventType type, uintptr_t wparam, intptr_t lparam,
bool is_system_key);
#endif
#ifdef __OBJC__
///
/// Create a key event from native macOS event.
///
ULExport ULKeyEvent ulCreateKeyEventMacOS(NSEvent* evt);
#endif
///
/// Destroy a key event.
///
ULExport void ulDestroyKeyEvent(ULKeyEvent evt);
#ifdef __cplusplus
} // extern "C"
#endif
#endif // ULTRALIGHT_CAPI_KEYEVENT_H
+50
View File
@@ -0,0 +1,50 @@
/**************************************************************************************************
* This file is a part of Ultralight, an ultra-portable web-browser engine. *
* *
* See <https://ultralig.ht> for licensing and more. *
* *
* (C) 2024 Ultralight, Inc. *
**************************************************************************************************/
///
/// @file CAPI_Logger.h
///
/// User-defined logging interface.
///
/// `#include <Ultralight/CAPI/CAPI_Logger.h>`
///
/// The library uses this to display log messages for debugging during development.
///
/// This is intended to be implemented by users and defined before creating the Renderer.
///
/// @see ulPlatformSetLogger()
///
#ifndef ULTRALIGHT_CAPI_LOGGER_H
#define ULTRALIGHT_CAPI_LOGGER_H
#include <Ultralight/CAPI/CAPI_Defines.h>
#ifdef __cplusplus
extern "C" {
#endif
/******************************************************************************
* Logger
*****************************************************************************/
typedef enum { kLogLevel_Error = 0, kLogLevel_Warning, kLogLevel_Info } ULLogLevel;
///
/// The callback invoked when the library wants to print a message to the log.
///
typedef void (*ULLoggerLogMessageCallback)(ULLogLevel log_level, ULString message);
typedef struct {
ULLoggerLogMessageCallback log_message;
} ULLogger;
#ifdef __cplusplus
} // extern "C"
#endif
#endif // ULTRALIGHT_CAPI_LOGGER_H
+45
View File
@@ -0,0 +1,45 @@
/**************************************************************************************************
* This file is a part of Ultralight, an ultra-portable web-browser engine. *
* *
* See <https://ultralig.ht> for licensing and more. *
* *
* (C) 2024 Ultralight, Inc. *
**************************************************************************************************/
///
/// @file CAPI_MouseEvent.h
///
/// Mouse event interface.
///
/// `#include <Ultralight/CAPI/CAPI_MouseEvent.h>`
///
/// This file defines the C API for mouse events.
///
#ifndef ULTRALIGHT_CAPI_MOUSEEVENT_H
#define ULTRALIGHT_CAPI_MOUSEEVENT_H
#include <Ultralight/CAPI/CAPI_Defines.h>
#ifdef __cplusplus
extern "C" {
#endif
/******************************************************************************
* Mouse Event
*****************************************************************************/
///
/// Create a mouse event, see MouseEvent in the C++ API for help using this function.
///
ULExport ULMouseEvent ulCreateMouseEvent(ULMouseEventType type, int x, int y, ULMouseButton button);
///
/// Destroy a mouse event.
///
ULExport void ulDestroyMouseEvent(ULMouseEvent evt);
#ifdef __cplusplus
} // extern "C"
#endif
#endif // ULTRALIGHT_CAPI_MOUSEEVENT_H
+168
View File
@@ -0,0 +1,168 @@
/**************************************************************************************************
* This file is a part of Ultralight, an ultra-portable web-browser engine. *
* *
* See <https://ultralig.ht> for licensing and more. *
* *
* (C) 2024 Ultralight, Inc. *
**************************************************************************************************/
///
/// @file CAPI_Platform.h
///
/// Global platform singleton, manages user-defined platform handlers..
///
/// `#include <Ultralight/CAPI/CAPI_Platform.h>`
///
/// The library uses the Platform API for most platform-specific operations (eg, file access,
/// clipboard, font loading, GPU access, pixel buffer transport, etc.).
///
/// ## Motivation
///
/// Ultralight is designed to work in as many platforms and environments as possible. To achieve
/// this, we've factored out most platform-specific code into a set of interfaces that you can
/// implement and set on the Platform singleton.
///
/// ## Default Implementations
///
/// We provide a number of default implementations for desktop platforms (eg, Windows, macOS, Linux)
/// for you when you call ulCreateApp(). These implementations are defined in the
/// [AppCore repository](https://github.com/ultralight-ux/AppCore/tree/master/src), we recommend
/// using their source code as a starting point for your own implementations.
///
/// ## Required Handlers
///
/// When using ulCreateRenderer() directly, you'll need to provide your own implementations for
/// ULFileSystem and ULFontLoader at a minimum.
///
/// @par Overview of which platform handlers are required / optional / provided:
///
/// | | ulCreateRenderer() | ulCreateApp() |
/// |---------------------|--------------------|---------------|
/// | ULFileSystem | **Required** | *Provided* |
/// | ULFontLoader | **Required** | *Provided* |
/// | ULClipboard | *Optional* | *Provided* |
/// | ULGPUDriver | *Optional* | *Provided* |
/// | ULLogger | *Optional* | *Provided* |
/// | ULSurfaceDefinition | *Provided* | *Provided* |
///
/// @note This singleton should be set up before creating the Renderer or App.
///
#ifndef ULTRALIGHT_CAPI_PLATFORM_H
#define ULTRALIGHT_CAPI_PLATFORM_H
#include <Ultralight/CAPI/CAPI_Defines.h>
#include <Ultralight/CAPI/CAPI_Logger.h>
#include <Ultralight/CAPI/CAPI_FileSystem.h>
#include <Ultralight/CAPI/CAPI_FontLoader.h>
#include <Ultralight/CAPI/CAPI_Surface.h>
#include <Ultralight/CAPI/CAPI_GPUDriver.h>
#include <Ultralight/CAPI/CAPI_Clipboard.h>
#ifdef __cplusplus
extern "C" {
#endif
/******************************************************************************
* Platform
*****************************************************************************/
///
/// Set a custom Logger implementation.
///
/// This is used to log debug messages to the console or to a log file.
///
/// You should call this before ulCreateRenderer() or ulCreateApp().
///
/// @note ulCreateApp() will use the default logger if you never call this.
///
/// @note If you're not using ulCreateApp(), (eg, using ulCreateRenderer()) you can still use the
/// default logger by calling ulEnableDefaultLogger() (@see <AppCore/CAPI.h>)
///
ULExport void ulPlatformSetLogger(ULLogger logger);
///
/// Set a custom FileSystem implementation.
///
/// The library uses this to load all file URLs (eg, <file:///page.html>).
///
/// You can provide the library with your own FileSystem implementation so that file assets are
/// loaded from your own pipeline.
///
/// You should call this before ulCreateRenderer() or ulCreateApp().
///
/// @warning This is required to be defined before calling ulCreateRenderer()
///
/// @note ulCreateApp() will use the default platform file system if you never call this.
///
/// @note If you're not using ulCreateApp(), (eg, using ulCreateRenderer()) you can still use the
/// default platform file system by calling ulEnablePlatformFileSystem()'
/// (@see <AppCore/CAPI.h>)
///
ULExport void ulPlatformSetFileSystem(ULFileSystem file_system);
///
/// Set a custom FontLoader implementation.
///
/// The library uses this to load all system fonts.
///
/// Every operating system has its own library of installed system fonts. The FontLoader interface
/// is used to lookup these fonts and fetch the actual font data (raw TTF/OTF file data) for a given
/// given font description.
///
/// You should call this before ulCreateRenderer() or ulCreateApp().
///
/// @warning This is required to be defined before calling ulCreateRenderer()
///
/// @note ulCreateApp() will use the default platform font loader if you never call this.
///
/// @note If you're not using ulCreateApp(), (eg, using ulCreateRenderer()) you can still use the
/// default platform font loader by calling ulEnablePlatformFontLoader()'
/// (@see <AppCore/CAPI.h>)
///
ULExport void ulPlatformSetFontLoader(ULFontLoader font_loader);
///
/// Set a custom Surface implementation.
///
/// This can be used to wrap a platform-specific GPU texture, Windows DIB, macOS CGImage, or any
/// other pixel buffer target for display on screen.
///
/// By default, the library uses a bitmap surface for all surfaces but you can override this by
/// providing your own surface definition here.
///
/// You should call this before ulCreateRenderer() or ulCreateApp().
///
ULExport void ulPlatformSetSurfaceDefinition(ULSurfaceDefinition surface_definition);
///
/// Set a custom GPUDriver implementation.
///
/// This should be used if you have enabled the GPU renderer in the Config and are using
/// ulCreateRenderer() (which does not provide its own GPUDriver implementation).
///
/// The GPUDriver interface is used by the library to dispatch GPU calls to your native GPU context
/// (eg, D3D11, Metal, OpenGL, Vulkan, etc.) There are reference implementations for this interface
/// in the AppCore repo.
///
/// You should call this before ulCreateRenderer().
///
ULExport void ulPlatformSetGPUDriver(ULGPUDriver gpu_driver);
///
/// Set a custom Clipboard implementation.
///
/// This should be used if you are using ulCreateRenderer() (which does not provide its own
/// clipboard implementation).
///
/// The Clipboard interface is used by the library to make calls to the system's native clipboard
/// (eg, cut, copy, paste).
///
/// You should call this before ulCreateRenderer().
///
ULExport void ulPlatformSetClipboard(ULClipboard clipboard);
#ifdef __cplusplus
} // extern "C"
#endif
#endif // ULTRALIGHT_CAPI_PLATFORM_H
+278
View File
@@ -0,0 +1,278 @@
/**************************************************************************************************
* This file is a part of Ultralight, an ultra-portable web-browser engine. *
* *
* See <https://ultralig.ht> for licensing and more. *
* *
* (C) 2024 Ultralight, Inc. *
**************************************************************************************************/
///
/// @file CAPI_Renderer.h
///
/// Core renderer singleton for the library, coordinates all library functions.
///
/// `#include <Ultralight/CAPI/CAPI_Renderer.h>`
///
/// The Renderer class is responsible for creating and painting Views, managing Sessions, as well
/// as coordinating network requests, events, JavaScript execution, and more.
///
/// ## Creating the Renderer
///
/// @note A Renderer will be created for you automatically when you call ulCreateApp (access it
/// via ulAppGetRenderer()).
///
/// @note ulCreateApp() is part of the AppCore API and automatically manages window creation, run
/// loop, input, painting, and most platform-specific functionality. (Available on desktop
/// platforms only)
/// \endparblock
///
/// ### Defining Platform Handlers
///
/// Before creating the Renderer, you should define your platform handlers via the Platform
/// singleton (see CAPI_Platform.h). This can be used to customize file loading, font loading,
/// clipboard access, and other functionality typically provided by the OS.
///
/// Default implementations for most platform handlers are available in the
/// [AppCore repo](https://github.com/ultralight-ux/AppCore/tree/master/src). You can use these
/// stock implementations by copying the code into your project, or you can write your own.
///
/// At a minimum, you should provide a ULFileSystem and ULFontLoader otherwise Renderer creation will
/// fail.
///
/// ### Creating the Renderer
///
/// Once you've set up the Platform handlers you can create the Renderer by calling
/// `ulCreateRenderer()`.
///
/// @par Example creation code
/// ```
/// // Setup our config.
/// ULConfig config = ulCreateConfig();
///
/// // Use AppCore's font loader.
/// ulEnablePlatformFontLoader();
///
/// // Use AppCore's file system to load file:/// URLs from the OS.
/// ULString base_dir = ulCreateString("./assets/");
/// ulEnablePlatformFileSystem(base_dir);
/// ulDestroyString(base_dir);
///
/// // Create the renderer.
/// ULRenderer renderer = ulCreateRenderer(config);
///
/// // Destroy the config.
/// ulDestroyConfig(config);
///
/// // Set up Views here...
/// ```
///
/// ## Updating Renderer Logic
///
/// You should call ulUpdate() from your main update loop as often as possible to give the
/// library an opportunity to dispatch events and timers:
///
/// @par Example update code
/// ```
/// void mainLoop()
/// {
/// while(true)
/// {
/// // Update program logic here
/// ulUpdate(renderer);
/// }
/// }
/// ```
///
/// ## Rendering Each Frame
///
/// When your program is ready to display a new frame (usually in synchrony with the monitor
/// refresh rate), you should call `ulRefreshDisplay()` and `ulRender` so the
/// library can render all active Views as needed.
///
/// @par Example per-frame render code
/// ```
/// void displayFrame()
/// {
/// // Notify the renderer that the main display has refreshed. This will update animations,
/// // smooth scroll, and window.requestAnimationFrame() for all Views matching the display id.
/// ulRefreshDisplay(renderer, 0);
///
/// // Render all Views as needed
/// ulRender(renderer);
///
/// // Each View will render to a
/// // - Pixel-Buffer Surface (ulViewGetSurface())
/// // or
/// // - GPU texture (ulViewGetRenderTarget())
/// // based on whether CPU or GPU rendering is used.
/// //
/// // You will need to display the image data here as needed.
/// }
/// }
/// ```
///
#ifndef ULTRALIGHT_CAPI_RENDERER_H
#define ULTRALIGHT_CAPI_RENDERER_H
#include <Ultralight/CAPI/CAPI_Defines.h>
#ifdef __cplusplus
extern "C" {
#endif
///
/// Create the core renderer singleton for the library.
///
/// You should set up the Platform singleton (see CAPI_Platform.h) before calling this function.
///
/// @note You do not need to the call this if you're using ulCreateApp() from AppCore.
///
/// \parblock
/// @warning You'll need to define a ULFontLoader and ULFileSystem within the Platform singleton
/// or else this call will fail.
/// \endparblock
///
/// \parblock
/// @warning You should only create one Renderer during the lifetime of your program.
/// \endparblock
///
/// @param config The configuration to use for the renderer.
///
/// @return Returns the new renderer instance.
///
ULExport ULRenderer ulCreateRenderer(ULConfig config);
///
/// Destroy the renderer.
///
/// @param renderer The renderer instance to destroy.
///
ULExport void ulDestroyRenderer(ULRenderer renderer);
///
/// Update timers and dispatch internal callbacks (JavaScript and network).
///
/// @param renderer The active renderer instance.
///
ULExport void ulUpdate(ULRenderer renderer);
///
/// Notify the renderer that a display has refreshed (you should call this after vsync).
///
/// This updates animations, smooth scroll, and window.requestAnimationFrame() for all Views
/// matching the display id.
///
/// @param renderer The active renderer instance.
///
/// @param display_id The display ID to refresh (0 by default).
///
ULExport void ulRefreshDisplay(ULRenderer renderer, unsigned int display_id);
///
/// Render all active Views to their respective surfaces and render targets.
///
/// @param renderer The active renderer instance.
///
ULExport void ulRender(ULRenderer renderer);
///
/// Attempt to release as much memory as possible. Don't call this from any callbacks or driver
/// code.
///
/// @param renderer The active renderer instance.
///
ULExport void ulPurgeMemory(ULRenderer renderer);
///
/// Print detailed memory usage statistics to the log. (@see ulPlatformSetLogger)
///
/// @param renderer The active renderer instance.
///
ULExport void ulLogMemoryUsage(ULRenderer renderer);
///
/// Start the remote inspector server.
///
/// While the remote inspector is active, Views that are loaded into this renderer
/// will be able to be remotely inspected from another Ultralight instance either locally
/// (another app on same machine) or remotely (over the network) by navigating a View to:
///
/// \code
/// inspector://<ADDRESS>:<PORT>
/// \endcode
///
/// @param renderer The active renderer instance.
///
/// @param address The address for the server to listen on (eg, "127.0.0.1")
///
/// @param port The port for the server to listen on (eg, 9222)
///
/// @return Returns whether the server started successfully or not.
///
ULExport bool ulStartRemoteInspectorServer(ULRenderer renderer, const char* address,
unsigned short port);
///
/// Describe the details of a gamepad, to be used with ulFireGamepadEvent and related
/// events below. This can be called multiple times with the same index if the details change.
///
/// @param renderer The active renderer instance.
///
/// @param index The unique index (or "connection slot") of the gamepad. For example,
/// controller #1 would be "1", controller #2 would be "2" and so on.
///
/// @param id A string ID representing the device, this will be made available
/// in JavaScript as gamepad.id
///
/// @param axis_count The number of axes on the device.
///
/// @param button_count The number of buttons on the device.
///
ULExport void ulSetGamepadDetails(ULRenderer renderer, unsigned int index, ULString id,
unsigned int axis_count, unsigned int button_count);
///
/// Fire a gamepad event (connection / disconnection).
///
/// @note The gamepad should first be described via ulSetGamepadDetails before calling this
/// function.
///
/// @param renderer The active renderer instance.
///
/// @param evt The event to fire.
///
/// @see <https://developer.mozilla.org/en-US/docs/Web/API/Gamepad>
///
ULExport void ulFireGamepadEvent(ULRenderer renderer, ULGamepadEvent evt);
///
/// Fire a gamepad axis event (to be called when an axis value is changed).
///
/// @note The gamepad should be connected via a previous call to ulFireGamepadEvent.
///
/// @param renderer The active renderer instance.
///
/// @param evt The event to fire.
///
/// @see <https://developer.mozilla.org/en-US/docs/Web/API/Gamepad/axes>
///
ULExport void ulFireGamepadAxisEvent(ULRenderer renderer, ULGamepadAxisEvent evt);
///
/// Fire a gamepad button event (to be called when a button value is changed).
///
/// @note The gamepad should be connected via a previous call to ulFireGamepadEvent.
///
/// @param renderer The active renderer instance.
///
/// @param evt The event to fire.
///
/// @see <https://developer.mozilla.org/en-US/docs/Web/API/Gamepad/buttons>
///
ULExport void ulFireGamepadButtonEvent(ULRenderer renderer, ULGamepadButtonEvent evt);
#ifdef __cplusplus
} // extern "C"
#endif
#endif // ULTRALIGHT_CAPI_RENDERER_H
@@ -0,0 +1,45 @@
/**************************************************************************************************
* This file is a part of Ultralight, an ultra-portable web-browser engine. *
* *
* See <https://ultralig.ht> for licensing and more. *
* *
* (C) 2024 Ultralight, Inc. *
**************************************************************************************************/
///
/// @file CAPI_ScrollEvent.h
///
/// Scroll event interface.
///
/// `#include <Ultralight/CAPI/CAPI_ScrollEvent.h>`
///
/// This file defines the C API for scroll events.
///
#ifndef ULTRALIGHT_CAPI_SCROLLEVENT_H
#define ULTRALIGHT_CAPI_SCROLLEVENT_H
#include <Ultralight/CAPI/CAPI_Defines.h>
#ifdef __cplusplus
extern "C" {
#endif
/******************************************************************************
* Scroll Event
*****************************************************************************/
///
/// Create a scroll event, see ScrollEvent in the C++ API for help using this function.
///
ULExport ULScrollEvent ulCreateScrollEvent(ULScrollEventType type, int delta_x, int delta_y);
///
/// Destroy a scroll event.
///
ULExport void ulDestroyScrollEvent(ULScrollEvent evt);
#ifdef __cplusplus
} // extern "C"
#endif
#endif // ULTRALIGHT_CAPI_SCROLLEVENT_H
+84
View File
@@ -0,0 +1,84 @@
/**************************************************************************************************
* This file is a part of Ultralight, an ultra-portable web-browser engine. *
* *
* See <https://ultralig.ht> for licensing and more. *
* *
* (C) 2024 Ultralight, Inc. *
**************************************************************************************************/
///
/// @file CAPI_Session.h
///
/// Storage for a browsing session (cookies, local storage, etc.).
///
/// `#include <Ultralight/CAPI/CAPI_Session.h>`
///
/// This class stores data for a unique browsing session (cookies, local storage, application cache,
/// indexed db. etc.). You can create multiple sessions to isolate data between different browsing
/// contexts.
///
/// ## Default Session
///
/// The library has a default session named "default" that is used if no session is specified when
/// when creating a View.
///
/// ## Session Lifetime
///
/// Sessions can be either temporary (in-memory only) or persistent (backed to disk).
///
#ifndef ULTRALIGHT_CAPI_SESSION_H
#define ULTRALIGHT_CAPI_SESSION_H
#include <Ultralight/CAPI/CAPI_Defines.h>
#ifdef __cplusplus
extern "C" {
#endif
/******************************************************************************
* Session
*****************************************************************************/
///
/// Create a Session to store local data in (such as cookies, local storage, application cache,
/// indexed db, etc).
///
ULExport ULSession ulCreateSession(ULRenderer renderer, bool is_persistent, ULString name);
///
/// Destroy a Session.
///
ULExport void ulDestroySession(ULSession session);
///
/// Get the default session (persistent session named "default").
///
/// @note This session is owned by the Renderer, you shouldn't destroy it.
///
ULExport ULSession ulDefaultSession(ULRenderer renderer);
///
/// Whether or not is persistent (backed to disk).
///
ULExport bool ulSessionIsPersistent(ULSession session);
///
/// Unique name identifying the session (used for unique disk path).
///
ULExport ULString ulSessionGetName(ULSession session);
///
/// Unique numeric Id for the session.
///
ULExport unsigned long long ulSessionGetId(ULSession session);
///
/// The disk path to write to (used by persistent sessions only).
///
ULExport ULString ulSessionGetDiskPath(ULSession session);
#ifdef __cplusplus
} // extern "C"
#endif
#endif // ULTRALIGHT_CAPI_SESSION_H
+86
View File
@@ -0,0 +1,86 @@
/**************************************************************************************************
* This file is a part of Ultralight, an ultra-portable web-browser engine. *
* *
* See <https://ultralig.ht> for licensing and more. *
* *
* (C) 2024 Ultralight, Inc. *
**************************************************************************************************/
///
/// @file CAPI_String.h
///
/// Unicode string container (natively UTF-8).
///
/// `#include <Ultralight/CAPI/CAPI_String.h>`
///
/// This class is used to represent strings in Ultralight. It can be created from a variety of
/// string types (ASCII, UTF-8, UTF-16) and accessed as a null-terminated UTF-8 buffer.
///
#ifndef ULTRALIGHT_CAPI_STRING_H
#define ULTRALIGHT_CAPI_STRING_H
#include <Ultralight/CAPI/CAPI_Defines.h>
#ifdef __cplusplus
extern "C" {
#endif
/******************************************************************************
* String
*****************************************************************************/
///
/// Create string from null-terminated ASCII C-string.
///
ULExport ULString ulCreateString(const char* str);
///
/// Create string from UTF-8 buffer.
///
ULExport ULString ulCreateStringUTF8(const char* str, size_t len);
///
/// Create string from UTF-16 buffer.
///
ULExport ULString ulCreateStringUTF16(ULChar16* str, size_t len);
///
/// Create string from copy of existing string.
///
ULExport ULString ulCreateStringFromCopy(ULString str);
///
/// Destroy string (you should destroy any strings you explicitly Create).
///
ULExport void ulDestroyString(ULString str);
///
/// Get native UTF-8 buffer data (always null-terminated).
///
ULExport char* ulStringGetData(ULString str);
///
/// Get length (in bytes) of the UTF-8 buffer data, not including null terminator.
///
ULExport size_t ulStringGetLength(ULString str);
///
/// Whether this string is empty or not.
///
ULExport bool ulStringIsEmpty(ULString str);
///
/// Replaces the contents of 'str' with the contents of 'new_str'
///
ULExport void ulStringAssignString(ULString str, ULString new_str);
///
/// Replaces the contents of 'str' with the contents of a C-string.
///
ULExport void ulStringAssignCString(ULString str, const char* c_str);
#ifdef __cplusplus
} // extern "C"
#endif
#endif // ULTRALIGHT_CAPI_STRING_H
+250
View File
@@ -0,0 +1,250 @@
/**************************************************************************************************
* This file is a part of Ultralight, an ultra-portable web-browser engine. *
* *
* See <https://ultralig.ht> for licensing and more. *
* *
* (C) 2024 Ultralight, Inc. *
**************************************************************************************************/
///
/// @file CAPI_Surface.h
///
/// User-defined pixel buffer surface.
///
/// `#include <Ultralight/CAPI/CAPI_Surface.h>`
///
/// The library uses this to store pixel data when rendering Views on the CPU (see
/// ulViewIsAccelerated()).
///
/// You can provide the library with your own Surface implementation to reduce the latency of
/// displaying pixels in your application (Views will be drawn directly to a block of memory
/// controlled by you).
///
/// When a View is rendered on the CPU, you can retrieve the backing Surface via ulViewGetSurface().
///
/// @pre This is automatically managed for you when using ulCreateApp(), if you want to override
/// ULSurfaceDefinition, you'll need to use ulCreateRenderer() instead.
///
/// ## Default Implementation
///
/// A default Surface implementation, BitmapSurface, is automatically provided by the library when
/// you call ulCreateRenderer() without defining a custom ULSurfaceDefinition.
///
/// You should cast the ULSurface to a ULBitmapSurface and call ulBitmapSurfaceGetBitmap() to access
/// the underlying Bitmap.
///
/// ## Setting the Surface Implementation
///
/// To define your own implementation, you should implement the ULSurfaceDefinition callbacks,
/// and then pass an instance of ULSurfaceDefinition containing your callbacks to
/// ulPlatformSetSurfaceDefinition() before calling ulCreateRenderer().
///
#ifndef ULTRALIGHT_CAPI_SURFACE_H
#define ULTRALIGHT_CAPI_SURFACE_H
#include <Ultralight/CAPI/CAPI_Defines.h>
#ifdef __cplusplus
extern "C" {
#endif
/******************************************************************************
* Surface
*****************************************************************************/
///
/// Width (in pixels).
///
ULExport unsigned int ulSurfaceGetWidth(ULSurface surface);
///
/// Height (in pixels).
///
ULExport unsigned int ulSurfaceGetHeight(ULSurface surface);
///
/// Number of bytes between rows (usually width * 4)
///
ULExport unsigned int ulSurfaceGetRowBytes(ULSurface surface);
///
/// Size in bytes.
///
ULExport size_t ulSurfaceGetSize(ULSurface surface);
///
/// Lock the pixel buffer and get a pointer to the beginning of the data for reading/writing.
///
/// Native pixel format is premultiplied BGRA 32-bit (8 bits per channel).
///
ULExport void* ulSurfaceLockPixels(ULSurface surface);
///
/// Unlock the pixel buffer.
///
ULExport void ulSurfaceUnlockPixels(ULSurface surface);
///
/// Resize the pixel buffer to a certain width and height (both in pixels).
///
/// This should never be called while pixels are locked.
///
ULExport void ulSurfaceResize(ULSurface surface, unsigned int width, unsigned int height);
///
/// Set the dirty bounds to a certain value.
///
/// This is called after the Renderer paints to an area of the pixel buffer. (The new value will be
/// joined with the existing dirty_bounds())
///
ULExport void ulSurfaceSetDirtyBounds(ULSurface surface, ULIntRect bounds);
///
/// Get the dirty bounds.
///
/// This value can be used to determine which portion of the pixel buffer has been updated since the
/// last call to ulSurfaceClearDirtyBounds().
///
/// The general algorithm to determine if a Surface needs display is:
/// <pre>
/// if (!ulIntRectIsEmpty(ulSurfaceGetDirtyBounds(surface))) {
/// // Surface pixels are dirty and needs display.
/// // Cast Surface to native Surface and use it here (pseudo code)
/// DisplaySurface(surface);
///
/// // Once you're done, clear the dirty bounds:
/// ulSurfaceClearDirtyBounds(surface);
/// }
/// </pre>
///
ULExport ULIntRect ulSurfaceGetDirtyBounds(ULSurface surface);
///
/// Clear the dirty bounds.
///
/// You should call this after you're done displaying the Surface.
///
ULExport void ulSurfaceClearDirtyBounds(ULSurface surface);
///
/// Get the underlying user data pointer (this is only valid if you have set a custom surface
/// implementation via ulPlatformSetSurfaceDefinition).
///
/// This will return nullptr if this surface is the default ULBitmapSurface.
///
ULExport void* ulSurfaceGetUserData(ULSurface surface);
/******************************************************************************
* BitmapSurface
*****************************************************************************/
///
/// Get the underlying Bitmap from the default Surface.
///
/// @note Do not call ulDestroyBitmap() on the returned value, it is owned by the surface.
///
ULExport ULBitmap ulBitmapSurfaceGetBitmap(ULBitmapSurface surface);
/******************************************************************************
* Surface Definition
*****************************************************************************/
///
/// The callback invoked when a Surface is created.
///
/// @param width The width in pixels.
/// @param height The height in pixels.
///
/// @return This callback should return a pointer to user-defined data for the instance. This user
/// data pointer will be passed to all other callbacks when operating on the instance.
///
typedef void* (*ULSurfaceDefinitionCreateCallback)(unsigned int width, unsigned int height);
///
/// The callback invoked when a Surface is destroyed.
///
/// @param user_data User data pointer uniquely identifying the surface.
///
typedef void (*ULSurfaceDefinitionDestroyCallback)(void* user_data);
///
/// The callback invoked when a Surface's width (in pixels) is requested.
///
/// @param user_data User data pointer uniquely identifying the surface.
///
typedef unsigned int (*ULSurfaceDefinitionGetWidthCallback)(void* user_data);
///
/// The callback invoked when a Surface's height (in pixels) is requested.
///
/// @param user_data User data pointer uniquely identifying the surface.
///
typedef unsigned int (*ULSurfaceDefinitionGetHeightCallback)(void* user_data);
///
/// The callback invoked when a Surface's row bytes is requested.
///
/// @note This value is also known as "stride". Usually width * 4.
///
/// @param user_data User data pointer uniquely identifying the surface.
///
typedef unsigned int (*ULSurfaceDefinitionGetRowBytesCallback)(void* user_data);
///
/// The callback invoked when a Surface's size (in bytes) is requested.
///
/// @param user_data User data pointer uniquely identifying the surface.
///
typedef size_t (*ULSurfaceDefinitionGetSizeCallback)(void* user_data);
///
/// The callback invoked when a Surface's pixel buffer is requested to be locked for reading/writing
/// (should return a pointer to locked bytes).
///
/// @param user_data User data pointer uniquely identifying the surface.
///
typedef void* (*ULSurfaceDefinitionLockPixelsCallback)(void* user_data);
///
/// The callback invoked when a Surface's pixel buffer is requested to be unlocked after previously
/// being locked.
///
/// @param user_data User data pointer uniquely identifying the surface.
///
typedef void (*ULSurfaceDefinitionUnlockPixelsCallback)(void* user_data);
///
/// The callback invoked when a Surface is requested to be resized to a certain width/height.
///
/// @param user_data User data pointer uniquely identifying the surface.
///
/// @param width Width in pixels.
///
/// @param height Height in pixels.
///
typedef void (*ULSurfaceDefinitionResizeCallback)(void* user_data, unsigned int width,
unsigned int height);
///
/// User-defined surface interface.
///
/// You should implement each of these callbacks, then pass an instance of this struct containing
/// your callbacks to ulPlatformSetSurfaceDefinition().
///
typedef struct {
ULSurfaceDefinitionCreateCallback create;
ULSurfaceDefinitionDestroyCallback destroy;
ULSurfaceDefinitionGetWidthCallback get_width;
ULSurfaceDefinitionGetHeightCallback get_height;
ULSurfaceDefinitionGetRowBytesCallback get_row_bytes;
ULSurfaceDefinitionGetSizeCallback get_size;
ULSurfaceDefinitionLockPixelsCallback lock_pixels;
ULSurfaceDefinitionUnlockPixelsCallback unlock_pixels;
ULSurfaceDefinitionResizeCallback resize;
} ULSurfaceDefinition;
#ifdef __cplusplus
} // extern "C"
#endif
#endif // ULTRALIGHT_CAPI_SURFACE_H
+554
View File
@@ -0,0 +1,554 @@
/**************************************************************************************************
* This file is a part of Ultralight, an ultra-portable web-browser engine. *
* *
* See <https://ultralig.ht> for licensing and more. *
* *
* (C) 2024 Ultralight, Inc. *
**************************************************************************************************/
///
/// @file CAPI_View.h
///
/// Web-page container rendered to an offscreen surface.
///
/// `#include <Ultralight/CAPI/CAPI_View.h>`
///
/// The View class is responsible for loading and rendering web-pages to an offscreen surface. It
/// is completely isolated from the OS windowing system, you must forward all input events to it
/// from your application.
///
/// ## Creating a View
///
/// You can create a View by calling ulCreateView():
///
/// ```
/// // Create a ULViewConfig with default values
/// ULViewConfig view_config = ulCreateViewConfig();
///
/// // Create a View, 500 by 500 pixels in size, using the default Session
/// ULView view = ulCreateView(renderer, 500, 500, view_config, NULL);
///
/// // Clean up the ULViewConfig
/// ulDestroyViewConfig(view_config);
/// ```
///
/// @note When using ulCreateApp(), the library will automatically create a View for you when you
/// call ulCreateOverlay().
///
#ifndef ULTRALIGHT_CAPI_VIEW_H
#define ULTRALIGHT_CAPI_VIEW_H
#include <Ultralight/CAPI/CAPI_Defines.h>
#ifdef __cplusplus
extern "C" {
#endif
/******************************************************************************
* ViewConfig
*****************************************************************************/
///
/// Create view configuration with default values (see <Ultralight/platform/View.h>).
///
ULExport ULViewConfig ulCreateViewConfig();
///
/// Destroy view configuration.
///
ULExport void ulDestroyViewConfig(ULViewConfig config);
///
/// Set a user-generated id of the display (monitor, TV, or screen) that the View will be shown on.
///
/// Animations are driven based on the physical refresh rate of the display. Multiple Views can
/// share the same display.
///
///
/// @note This is automatically managed for you when ulCreateApp() is used.
///
/// @see ulRefreshDisplay()
///
ULExport void ulViewConfigSetDisplayId(ULViewConfig config, unsigned int display_id);
///
/// Set whether to render using the GPU renderer (accelerated) or the CPU renderer (unaccelerated).
///
/// This option is only valid if you're managing the Renderer yourself (eg, you've previously
/// called ulCreateRenderer() instead of ulCreateApp()).
///
/// When true, the View will be rendered to an offscreen GPU texture using the GPU driver set in
/// ulPlatformSetGPUDriver(). You can fetch details for the texture via ulViewGetRenderTarget().
///
/// When false (the default), the View will be rendered to an offscreen pixel buffer using the
/// multithreaded CPU renderer. This pixel buffer can optionally be provided by the user--
/// for more info see ulViewGetSurface().
///
ULExport void ulViewConfigSetIsAccelerated(ULViewConfig config, bool is_accelerated);
///
/// Set whether images should be enabled (Default = True).
///
ULExport void ulViewConfigSetIsTransparent(ULViewConfig config, bool is_transparent);
///
/// Set the initial device scale, ie. the amount to scale page units to screen pixels. This should be
/// set to the scaling factor of the device that the View is displayed on. (Default = 1.0)
///
/// @note 1.0 is equal to 100% zoom (no scaling), 2.0 is equal to 200% zoom (2x scaling)
///
ULExport void ulViewConfigSetInitialDeviceScale(ULViewConfig config, double initial_device_scale);
///
/// Set whether or not the View should initially have input focus. (Default = True)
///
ULExport void ulViewConfigSetInitialFocus(ULViewConfig config, bool is_focused);
///
/// Set whether images should be enabled (Default = True).
///
ULExport void ulViewConfigSetEnableImages(ULViewConfig config, bool enabled);
///
/// Set whether JavaScript should be enabled (Default = True).
///
ULExport void ulViewConfigSetEnableJavaScript(ULViewConfig config, bool enabled);
///
/// Set default font-family to use (Default = Times New Roman).
///
ULExport void ulViewConfigSetFontFamilyStandard(ULViewConfig config, ULString font_name);
///
/// Set default font-family to use for fixed fonts, eg <pre> and <code>
/// (Default = Courier New).
///
ULExport void ulViewConfigSetFontFamilyFixed(ULViewConfig config, ULString font_name);
///
/// Set default font-family to use for serif fonts (Default = Times New Roman).
///
ULExport void ulViewConfigSetFontFamilySerif(ULViewConfig config, ULString font_name);
///
/// Set default font-family to use for sans-serif fonts (Default = Arial).
///
ULExport void ulViewConfigSetFontFamilySansSerif(ULViewConfig config, ULString font_name);
///
/// Set user agent string (See <Ultralight/platform/Config.h> for the default).
///
ULExport void ulViewConfigSetUserAgent(ULViewConfig config, ULString agent_string);
/******************************************************************************
* View
*****************************************************************************/
///
/// Create a View with certain size (in pixels).
///
/// @note You can pass null to 'session' to use the default session.
///
ULExport ULView ulCreateView(ULRenderer renderer, unsigned int width, unsigned int height,
ULViewConfig view_config, ULSession session);
///
/// Destroy a View.
///
ULExport void ulDestroyView(ULView view);
///
/// Get current URL.
///
/// @note Don't destroy the returned string, it is owned by the View.
///
ULExport ULString ulViewGetURL(ULView view);
///
/// Get current title.
///
/// @note Don't destroy the returned string, it is owned by the View.
///
ULExport ULString ulViewGetTitle(ULView view);
///
/// Get the width, in pixels.
///
ULExport unsigned int ulViewGetWidth(ULView view);
///
/// Get the height, in pixels.
///
ULExport unsigned int ulViewGetHeight(ULView view);
///
// Get the display id of the View.
///
ULExport unsigned int ulViewGetDisplayId(ULView view);
///
/// Set the display id of the View.
///
/// This should be called when the View is moved to another display.
///
ULExport void ulViewSetDisplayId(ULView view, unsigned int display_id);
///
/// Get the device scale, ie. the amount to scale page units to screen pixels.
///
/// For example, a value of 1.0 is equivalent to 100% zoom. A value of 2.0 is 200% zoom.
///
ULExport double ulViewGetDeviceScale(ULView view);
///
/// Set the device scale.
///
ULExport void ulViewSetDeviceScale(ULView view, double scale);
///
/// Whether or not the View is GPU-accelerated. If this is false, the page will be rendered
/// via the CPU renderer.
///
ULExport bool ulViewIsAccelerated(ULView view);
///
/// Whether or not the View supports transparent backgrounds.
///
ULExport bool ulViewIsTransparent(ULView view);
///
/// Check if the main frame of the page is currrently loading.
///
ULExport bool ulViewIsLoading(ULView view);
///
/// Get the RenderTarget for the View.
///
/// @note Only valid if this View is GPU accelerated.
///
/// You can use this with your GPUDriver implementation to bind and display the
/// corresponding texture in your application.
///
ULExport ULRenderTarget ulViewGetRenderTarget(ULView view);
///
/// Get the Surface for the View (native pixel buffer that the CPU renderer draws into).
///
/// @note This operation is only valid if you're managing the Renderer yourself (eg, you've
/// previously called ulCreateRenderer() instead of ulCreateApp()).
///
/// This function will return NULL if this View is GPU accelerated.
///
/// The default Surface is BitmapSurface but you can provide your own Surface implementation
/// via ulPlatformSetSurfaceDefinition.
///
/// When using the default Surface, you can retrieve the underlying bitmap by casting
/// ULSurface to ULBitmapSurface and calling ulBitmapSurfaceGetBitmap().
///
ULExport ULSurface ulViewGetSurface(ULView view);
///
/// Load a raw string of HTML.
///
ULExport void ulViewLoadHTML(ULView view, ULString html_string);
///
/// Load a URL into main frame.
///
ULExport void ulViewLoadURL(ULView view, ULString url_string);
///
/// Resize view to a certain width and height (in pixels).
///
ULExport void ulViewResize(ULView view, unsigned int width, unsigned int height);
///
/// Acquire the page's JSContext for use with JavaScriptCore API.
///
/// @note This call locks the context for the current thread. You should call
/// ulViewUnlockJSContext() after using the context so other worker threads can modify
/// JavaScript state.
///
/// @note The lock is recusive, it's okay to call this multiple times as long as you call
/// ulViewUnlockJSContext() the same number of times.
///
ULExport JSContextRef ulViewLockJSContext(ULView view);
///
/// Unlock the page's JSContext after a previous call to ulViewLockJSContext().
///
ULExport void ulViewUnlockJSContext(ULView view);
///
/// Evaluate a string of JavaScript and return result.
///
/// @param js_string The string of JavaScript to evaluate.
///
/// @param exception The address of a ULString to store a description of the last exception. Pass
/// NULL to ignore this. Don't destroy the exception string returned, it's owned
/// by the View.
///
/// @note Don't destroy the returned string, it's owned by the View. This value is reset with every
/// call-- if you want to retain it you should copy the result to a new string via
/// ulCreateStringFromCopy().
///
/// @note An example of using this API:
/// <pre>
/// ULString script = ulCreateString("1 + 1");
/// ULString exception;
/// ULString result = ulViewEvaluateScript(view, script, &exception);
/// /* Use the result ("2") and exception description (if any) here. */
/// ulDestroyString(script);
/// </pre>
///
ULExport ULString ulViewEvaluateScript(ULView view, ULString js_string, ULString* exception);
///
/// Check if can navigate backwards in history.
///
ULExport bool ulViewCanGoBack(ULView view);
///
/// Check if can navigate forwards in history.
///
ULExport bool ulViewCanGoForward(ULView view);
///
/// Navigate backwards in history.
///
ULExport void ulViewGoBack(ULView view);
///
/// Navigate forwards in history.
///
ULExport void ulViewGoForward(ULView view);
///
/// Navigate to arbitrary offset in history.
///
ULExport void ulViewGoToHistoryOffset(ULView view, int offset);
///
/// Reload current page.
///
ULExport void ulViewReload(ULView view);
///
/// Stop all page loads.
///
ULExport void ulViewStop(ULView view);
///
/// Give focus to the View.
///
/// You should call this to give visual indication that the View has input focus (changes active
/// text selection colors, for example).
///
ULExport void ulViewFocus(ULView view);
///
/// Remove focus from the View and unfocus any focused input elements.
///
/// You should call this to give visual indication that the View has lost input focus.
///
ULExport void ulViewUnfocus(ULView view);
///
/// Whether or not the View has focus.
///
ULExport bool ulViewHasFocus(ULView view);
///
/// Whether or not the View has an input element with visible keyboard focus (indicated by a
/// blinking caret).
///
/// You can use this to decide whether or not the View should consume keyboard input events (useful
/// in games with mixed UI and key handling).
///
ULExport bool ulViewHasInputFocus(ULView view);
///
/// Fire a keyboard event.
///
ULExport void ulViewFireKeyEvent(ULView view, ULKeyEvent key_event);
///
/// Fire a mouse event.
///
ULExport void ulViewFireMouseEvent(ULView view, ULMouseEvent mouse_event);
///
/// Fire a scroll event.
///
ULExport void ulViewFireScrollEvent(ULView view, ULScrollEvent scroll_event);
typedef void (*ULChangeTitleCallback)(void* user_data, ULView caller, ULString title);
///
/// Set callback for when the page title changes.
///
ULExport void ulViewSetChangeTitleCallback(ULView view, ULChangeTitleCallback callback,
void* user_data);
typedef void (*ULChangeURLCallback)(void* user_data, ULView caller, ULString url);
///
/// Set callback for when the page URL changes.
///
ULExport void ulViewSetChangeURLCallback(ULView view, ULChangeURLCallback callback,
void* user_data);
typedef void (*ULChangeTooltipCallback)(void* user_data, ULView caller, ULString tooltip);
///
/// Set callback for when the tooltip changes (usually result of a mouse hover).
///
ULExport void ulViewSetChangeTooltipCallback(ULView view, ULChangeTooltipCallback callback,
void* user_data);
typedef void (*ULChangeCursorCallback)(void* user_data, ULView caller, ULCursor cursor);
///
/// Set callback for when the mouse cursor changes.
///
ULExport void ulViewSetChangeCursorCallback(ULView view, ULChangeCursorCallback callback,
void* user_data);
typedef void (*ULAddConsoleMessageCallback)(void* user_data, ULView caller, ULMessageSource source,
ULMessageLevel level, ULString message,
unsigned int line_number, unsigned int column_number,
ULString source_id);
///
/// Set callback for when a message is added to the console (useful for JavaScript / network errors
/// and debugging).
///
ULExport void ulViewSetAddConsoleMessageCallback(ULView view, ULAddConsoleMessageCallback callback,
void* user_data);
typedef ULView (*ULCreateChildViewCallback)(void* user_data, ULView caller, ULString opener_url,
ULString target_url, bool is_popup,
ULIntRect popup_rect);
///
/// Set callback for when the page wants to create a new View.
///
/// This is usually the result of a user clicking a link with target="_blank" or by JavaScript
/// calling window.open(url).
///
/// To allow creation of these new Views, you should create a new View in this callback, resize it
/// to your container, and return it. You are responsible for displaying the returned View.
///
/// You should return NULL if you want to block the action.
///
ULExport void ulViewSetCreateChildViewCallback(ULView view, ULCreateChildViewCallback callback,
void* user_data);
typedef ULView (*ULCreateInspectorViewCallback)(void* user_data, ULView caller, bool is_local,
ULString inspected_url);
///
/// Set callback for when the page wants to create a new View to display the local inspector in.
///
/// You should create a new View in this callback, resize it to your
/// container, and return it. You are responsible for displaying the returned View.
///
ULExport void ulViewSetCreateInspectorViewCallback(ULView view, ULCreateInspectorViewCallback callback,
void* user_data);
typedef void (*ULBeginLoadingCallback)(void* user_data, ULView caller, unsigned long long frame_id,
bool is_main_frame, ULString url);
///
/// Set callback for when the page begins loading a new URL into a frame.
///
ULExport void ulViewSetBeginLoadingCallback(ULView view, ULBeginLoadingCallback callback,
void* user_data);
typedef void (*ULFinishLoadingCallback)(void* user_data, ULView caller, unsigned long long frame_id,
bool is_main_frame, ULString url);
///
/// Set callback for when the page finishes loading a URL into a frame.
///
ULExport void ulViewSetFinishLoadingCallback(ULView view, ULFinishLoadingCallback callback,
void* user_data);
typedef void (*ULFailLoadingCallback)(void* user_data, ULView caller, unsigned long long frame_id,
bool is_main_frame, ULString url, ULString description,
ULString error_domain, int error_code);
///
/// Set callback for when an error occurs while loading a URL into a frame.
///
ULExport void ulViewSetFailLoadingCallback(ULView view, ULFailLoadingCallback callback,
void* user_data);
typedef void (*ULWindowObjectReadyCallback)(void* user_data, ULView caller,
unsigned long long frame_id, bool is_main_frame,
ULString url);
///
/// Set callback for when the JavaScript window object is reset for a new page load.
///
/// This is called before any scripts are executed on the page and is the earliest time to setup any
/// initial JavaScript state or bindings.
///
/// The document is not guaranteed to be loaded/parsed at this point. If you need to make any
/// JavaScript calls that are dependent on DOM elements or scripts on the page, use DOMReady
/// instead.
///
/// The window object is lazily initialized (this will not be called on pages with no scripts).
///
ULExport void ulViewSetWindowObjectReadyCallback(ULView view, ULWindowObjectReadyCallback callback,
void* user_data);
typedef void (*ULDOMReadyCallback)(void* user_data, ULView caller, unsigned long long frame_id,
bool is_main_frame, ULString url);
///
/// Set callback for when all JavaScript has been parsed and the document is ready.
///
/// This is the best time to make any JavaScript calls that are dependent on DOM elements or scripts
/// on the page.
///
ULExport void ulViewSetDOMReadyCallback(ULView view, ULDOMReadyCallback callback, void* user_data);
typedef void (*ULUpdateHistoryCallback)(void* user_data, ULView caller);
///
/// Set callback for when the history (back/forward state) is modified.
///
ULExport void ulViewSetUpdateHistoryCallback(ULView view, ULUpdateHistoryCallback callback,
void* user_data);
///
/// Set whether or not a view should be repainted during the next call to ulRender.
///
/// @note This flag is automatically set whenever the page content changes but you can set it
/// directly in case you need to force a repaint.
///
ULExport void ulViewSetNeedsPaint(ULView view, bool needs_paint);
///
/// Whether or not a view should be painted during the next call to ulRender.
///
ULExport bool ulViewGetNeedsPaint(ULView view);
///
/// Create an Inspector View to inspect / debug this View locally.
///
/// This will only succeed if you have the inspector assets in your filesystem-- the inspector
/// will look for file:///inspector/Main.html when it first loads.
///
/// You must handle ulViewSetCreateInspectorViewCallback so that the library has a View to display
/// the inspector in. This function will call the callback only if an inspector view is not
/// currently active.
///
ULExport void ulViewCreateLocalInspectorView(ULView view);
#ifdef __cplusplus
} // extern "C"
#endif
#endif // ULTRALIGHT_CAPI_VIEW_H
+25
View File
@@ -0,0 +1,25 @@
// Generated by CMake - DO NOT EDIT
#pragma once
// Current edition level (see UltralightEdition enum below)
#define ULTRALIGHT_EDITION_LEVEL 0
// Edition name string
#define ULTRALIGHT_EDITION_NAME "Free"
// Edition defines
#define ULTRALIGHT_EDITION_FREE 0
#define ULTRALIGHT_EDITION_PLUS 1
#define ULTRALIGHT_EDITION_PRO 2
#define ULTRALIGHT_EDITION_ENTERPRISE 3
#define ULTRALIGHT_EDITION_UNLIMITED 4
// Edition check macros
#define UL_EDITION(x) (ULTRALIGHT_EDITION_LEVEL == ULTRALIGHT_EDITION_##x)
#define UL_EDITION_AT_LEAST(x) (ULTRALIGHT_EDITION_LEVEL >= ULTRALIGHT_EDITION_##x)
// Maximum FPS each View can render at (0 is uncapped)
#define ULTRALIGHT_EDITION_MAX_FPS 60
// Whether or not this is an evaluation build
#define ULTRALIGHT_EVALUATION 0
+125
View File
@@ -0,0 +1,125 @@
/**************************************************************************************************
* This file is a part of Ultralight, an ultra-portable web-browser engine. *
* *
* See <https://ultralig.ht> for licensing and more. *
* *
* (C) 2024 Ultralight, Inc. *
**************************************************************************************************/
#pragma once
#include <Ultralight/Defines.h>
#include <Ultralight/String.h>
#include <JavaScriptCore/JavaScript.h>
namespace ultralight {
///
/// MessageSource types
///
enum MessageSource {
kMessageSource_XML = 0,
kMessageSource_JS,
kMessageSource_Network,
kMessageSource_ConsoleAPI,
kMessageSource_Storage,
kMessageSource_AppCache,
kMessageSource_Rendering,
kMessageSource_CSS,
kMessageSource_Security,
kMessageSource_ContentBlocker,
kMessageSource_Media,
kMessageSource_MediaSource,
kMessageSource_WebRTC,
kMessageSource_ITPDebug,
kMessageSource_PrivateClickMeasurement,
kMessageSource_PaymentRequest,
kMessageSource_Other,
};
enum MessageType {
kMessageType_Log = 0,
kMessageType_Dir,
kMessageType_DirXML,
kMessageType_Table,
kMessageType_Trace,
kMessageType_StartGroup,
kMessageType_StartGroupCollapsed,
kMessageType_EndGroup,
kMessageType_Clear,
kMessageType_Assert,
kMessageType_Timing,
kMessageType_Profile,
kMessageType_ProfileEnd,
kMessageType_Image,
};
///
/// MessageLevel types
///
enum MessageLevel {
kMessageLevel_Log = 0,
kMessageLevel_Warning,
kMessageLevel_Error,
kMessageLevel_Debug,
kMessageLevel_Info,
};
///
/// @brief Interface for console messages.
///
class UExport ConsoleMessage {
public:
virtual ~ConsoleMessage() = default;
///
/// The source of the message.
///
virtual MessageSource source() const = 0;
///
/// The type of content displayed.
///
virtual MessageType type() const = 0;
///
/// The log level for the message.
///
virtual MessageLevel level() const = 0;
///
/// The message as a string-- for multi-argument calls to console.log() this just converts the
/// first parameter to a string.
///
virtual String message() const = 0;
///
/// The line number of the JavaScript associated with this call, if any.
///
virtual uint32_t line_number() const = 0;
///
/// The column number of the JavaScript associated with this call, if any.
///
virtual uint32_t column_number() const = 0;
///
/// The source id (eg, URL) of the page associated with this call, if any.
///
virtual String source_id() const = 0;
///
/// The JavaScript execution context for the arguments, if any.
///
virtual JSContextRef argument_context() const = 0;
///
/// The number of JavaScript arguments passed to console.log(), if any.
///
virtual uint32_t num_arguments() const = 0;
///
/// Get the JavaScript argument at a specific index (numbering starts at 0).
///
virtual JSValueRef argument_at(uint32_t idx) const = 0;
};
} // namespace ultralight
+139
View File
@@ -0,0 +1,139 @@
/**************************************************************************************************
* This file is a part of Ultralight. *
* *
* See <https://ultralig.ht> for licensing and more. *
* *
* (C) 2025 Ultralight, Inc. *
**************************************************************************************************/
#pragma once
// Needed for limit defines, like INTMAX_MAX, which is used by the std C++ library
#ifndef __STDC_LIMIT_MACROS
#define __STDC_LIMIT_MACROS
#endif
#include <cstdint>
#include <cstddef>
#include <limits.h>
#ifdef SWIG
#define UExport
#else
#include <Ultralight/Config.h>
#include <Ultralight/Exports.h>
// Require C++11 Support
#if defined(_MSC_VER)
# if _MSC_VER < 1800
# error This project needs at least Visual Studio 2013 to build
# endif
#elif __cplusplus <= 199711L
# error This project can only be compiled with a compiler that supports C++11
#endif
#if INTPTR_MAX == INT32_MAX
# define UL_ARCH_32_BIT
#elif INTPTR_MAX == INT64_MAX
# define UL_ARCH_64_BIT
#else
# error "Unknown CPU architecture: environment not 32 or 64-bit."
#endif
#if defined(__aarch64__)
# define UL_ARCH_ARM64
# if defined(__APPLE__)
# define UL_ARCH_ARM64_APPLE_SILICON
# endif
#endif
#if defined(__WIN32__) || defined(_WIN32)
# define _thread_local __declspec(thread)
# ifndef _NATIVE_WCHAR_T_DEFINED
# define DISABLE_NATIVE_WCHAR_T
# endif
#else
# define _thread_local __thread
#endif
#ifndef UL_COMPILER_GCC_LIKE
# if defined(__clang__) || defined(__GNUC__) || defined(__GNUG__)
# define UL_COMPILER_GCC_LIKE
# endif
#endif
#ifndef UL_ALWAYS_INLINE
#if defined(UL_COMPILER_GCC_LIKE) && defined(NDEBUG)
# define UL_ALWAYS_INLINE inline __attribute__((__always_inline__))
# elif defined(_MSC_VER) && defined(NDEBUG)
# define UL_ALWAYS_INLINE __forceinline
# else
# define UL_ALWAYS_INLINE inline
# endif
#endif
#ifndef UL_UNLIKELY
# if defined(UL_COMPILER_GCC_LIKE)
# define UL_UNLIKELY(x) __builtin_expect(!!(x), 0)
# else
# define UL_UNLIKELY(x) (x)
# endif
#endif
#ifndef UL_ALIGN
#if defined(UL_COMPILER_GCC_LIKE)
#define UL_ALIGN(x) __attribute__((aligned(x)))
#elif defined(__cplusplus) && __cplusplus >= 201103L
#define UL_ALIGN(x) alignas(x)
#elif defined(_MSC_VER)
#define UL_ALIGN(x) __declspec(align(x))
#else
#define UL_ALIGN(x)
#endif
#endif
#endif // #ifdef SWIG
#define ULTRALIGHT_VERSION "1.4.0"
#define ULTRALIGHT_VERSION_MAJOR 1
#define ULTRALIGHT_VERSION_MINOR 4
#define ULTRALIGHT_VERSION_PATCH 0
#define WEBKIT_VERSION "615.1.18.100.1"
#define WEBKIT_VERSION_MAJOR 615
#define WEBKIT_VERSION_MINOR 1
#define WEBKIT_VERSION_TINY 18
#define WEBKIT_VERSION_MICRO 100
#define WEBKIT_VERSION_NANO 1
#define ULTRALIGHT_USER_AGENT "Mozilla/5.0 (Windows NT 10.0; Win64; x64) " \
"AppleWebKit/615.1.18.100.1 (KHTML, like Gecko) " \
"Ultralight/1.4.0 Version/16.4.1 Safari/615.1.18.100.1"
#ifdef __cplusplus
extern "C" {
#endif
///
/// Full library version string (corresponds to ULTRALIGHT_VERSION)
///
UExport const char* UltralightVersionString();
UExport uint32_t UltralightVersionMajor();
UExport uint32_t UltralightVersionMinor();
UExport uint32_t UltralightVersionPatch();
///
/// Full WebKit version string (corresponds to WEBKIT_VERSION)
///
UExport const char* WebKitVersionString();
UExport uint32_t WebKitVersionMajor();
UExport uint32_t WebKitVersionMinor();
UExport uint32_t WebKitVersionTiny();
UExport uint32_t WebKitVersionMicro();
UExport uint32_t WebKitVersionNano();
#ifdef __cplusplus
}
#endif
+48
View File
@@ -0,0 +1,48 @@
/**************************************************************************************************
* This file is a part of Ultralight. *
* *
* See <https://ultralig.ht> for licensing and more. *
* *
* (C) 2024 Ultralight, Inc. *
**************************************************************************************************/
#ifndef __ULTRALIGHT_EXPORTS_H__
#define __ULTRALIGHT_EXPORTS_H__
#if defined(__WIN32__) || defined(_WIN32)
# if defined(ULTRALIGHT_STATIC_BUILD)
# define UExport
# else
# if defined(ULTRALIGHT_IMPLEMENTATION)
# define UExport __declspec(dllexport)
# else
# define UExport __declspec(dllimport)
# endif
# endif
#else
# if defined(ULTRALIGHT_STATIC_BUILD)
# define UExport
# else
# define UExport __attribute__((visibility("default")))
# endif
#endif
// UCExport is for symbols that are exported strictly by UltralightCore
#if defined(__WIN32__) || defined(_WIN32)
# if defined(ULTRALIGHT_STATIC_BUILD)
# define UCExport
# else
# if defined(ULTRALIGHT_IMPLEMENTATION) && defined(ULTRALIGHT_MODULE_ULTRALIGHTCORE)
# define UCExport __declspec(dllexport)
# else
# define UCExport __declspec(dllimport)
# endif
# endif
#else
# if defined(ULTRALIGHT_STATIC_BUILD)
# define UCExport
# else
# define UCExport __attribute__((visibility("default")))
# endif
#endif
#endif // __ULTRALIGHT_EXPORTS_H__
+109
View File
@@ -0,0 +1,109 @@
/**************************************************************************************************
* This file is a part of Ultralight, an ultra-portable web-browser engine. *
* *
* See <https://ultralig.ht> for licensing and more. *
* *
* (C) 2024 Ultralight, Inc. *
**************************************************************************************************/
#pragma once
#include <Ultralight/Defines.h>
#include <Ultralight/String.h>
namespace ultralight {
///
/// Event representing a change in gamepad connection state.
///
/// @see Renderer::FireGamepadEvent
///
class UExport GamepadEvent {
public:
///
/// The various GamepadEvent types.
///
enum Type {
///
/// This event type should be fired when a gamepad is connected.
///
/// @note You will need to previously declare the gamepad, its index, and details about
/// its axis and button layout via Renderer::SetGamepadDetails prior to calling
/// Renderer::FireGamepadEvent.
///
kType_GamepadConnected,
///
/// This event type should be fired when a gamepad is disconnected.
///
kType_GamepadDisconnected,
};
///
// The type of this GamepadEvent
///
Type type;
///
/// The index of the gamepad, this should match the value previously set in
/// Renderer::SetGamepadDetails.
///
uint32_t index;
};
///
/// Event representing a change in gamepad axis state (eg, pressing a stick in a certain direction).
///
/// @see Renderer::FireGamepadAxisEvent
///
class UExport GamepadAxisEvent {
public:
///
/// The index of the gamepad, this should match the value previously set in
/// Renderer::SetGamepadDetails.
///
uint32_t index;
///
/// The index of the axis whose value has changed.
///
/// This value should be in the range previously set in Renderer::SetGamepadDetails.
///
uint32_t axis_index;
///
/// The new value of the axis.
///
/// This value should be normalized to the range [-1.0, 1.0].
///
double value;
};
///
/// Event representing a change in gamepad button state (eg, pressing a button on a gamepad).
///
/// @see Renderer::FireGamepadButtonEvent
///
class UExport GamepadButtonEvent {
public:
///
/// The index of the gamepad, this should match the value previously set in
/// Renderer::SetGamepadDetails.
///
uint32_t index;
///
/// The index of the button whose value has changed.
///
/// This value should be in the range previously set in Renderer::SetGamepadDetails.
///
uint32_t button_index;
///
/// The new value of the button.
///
/// This value should be normalized to the range [-1.0, 1.0], with any value greater than
/// 0.0 to be considered "pressed".
///
double value;
};
} // namespace ultralight
+660
View File
@@ -0,0 +1,660 @@
/**************************************************************************************************
* This file is a part of Ultralight. *
* *
* See <https://ultralig.ht> for licensing and more. *
* *
* (C) 2024 Ultralight, Inc. *
**************************************************************************************************/
#pragma once
#include <Ultralight/Defines.h>
#include <memory.h>
#include <cmath>
#include <cstring>
#include <algorithm>
namespace ultralight {
///
/// 2D Vector Helper
///
struct UExport vec2 {
float x, y;
inline vec2() : x(0.0f), y(0.0f) { }
inline vec2(float x, float y) : x(x), y(y) {}
inline vec2(float x) : x(x), y(x) {}
inline vec2 yx() const { return { y, x }; }
inline vec2 xx() const { return { x, x }; }
inline vec2 yy() const { return { y, y }; }
inline friend vec2 operator+(vec2 lhs, const vec2& rhs) { lhs += rhs; return lhs; }
inline friend vec2 operator-(vec2 lhs, const vec2& rhs) { lhs -= rhs; return lhs; }
inline friend vec2 operator*(vec2 lhs, const vec2& rhs) { lhs *= rhs; return lhs; }
inline friend vec2 operator/(vec2 lhs, const vec2& rhs) { lhs /= rhs; return lhs; }
inline friend vec2 operator+(vec2 lhs, float rhs) { lhs += rhs; return lhs; }
inline friend vec2 operator-(vec2 lhs, float rhs) { lhs -= rhs; return lhs; }
inline friend vec2 operator*(vec2 lhs, float rhs) { lhs *= rhs; return lhs; }
inline friend vec2 operator/(vec2 lhs, float rhs) { lhs /= rhs; return lhs; }
inline vec2& operator+=(const vec2& rhs) {
x += rhs.x;
y += rhs.y;
return *this;
}
inline vec2& operator-=(const vec2& rhs) {
x -= rhs.x;
y -= rhs.y;
return *this;
}
inline vec2& operator*=(const vec2& rhs) {
x *= rhs.x;
y *= rhs.y;
return *this;
}
inline vec2& operator/=(const vec2& rhs) {
x /= rhs.x;
y /= rhs.y;
return *this;
}
inline vec2& operator+=(float rhs) {
x += rhs;
y += rhs;
return *this;
}
inline vec2& operator-=(float rhs) {
x -= rhs;
y -= rhs;
return *this;
}
inline vec2& operator*=(float rhs) {
x *= rhs;
y *= rhs;
return *this;
}
inline vec2& operator/=(float rhs) {
x /= rhs;
y /= rhs;
return *this;
}
inline friend bool operator==(const vec2& a, const vec2& b) {
return !memcmp(&a, &b, sizeof(a));
}
inline friend bool operator!=(const vec2& a, const vec2& b) {
return !(a == b);
}
inline friend vec2 min_(const vec2& a, const vec2& b) {
return{ (b.x < a.x) ? b.x : a.x,
(b.y < a.y) ? b.y : a.y };
}
inline friend vec2 max_(const vec2& a, const vec2& b) {
return{ (a.x < b.x) ? b.x : a.x,
(a.y < b.y) ? b.y : a.y };
}
inline friend vec2 clamp(const vec2& x, const vec2& minVal, const vec2& maxVal) {
return min_(max_(x, minVal), maxVal);
}
inline friend vec2 mix(const vec2& a, const vec2& b, float t) {
return a * (1.0f - t) + b * t;
}
inline friend float length(const vec2& a) {
return sqrtf(a.x * a.x + a.y * a.y);
}
// squared length
inline friend float length2(const vec2& a) {
return dot(a, a);
}
inline friend float distance(const vec2& a, const vec2& b) {
return length(a - b);
}
// squared distance
inline friend float distance2(const vec2& a, const vec2& b) {
return length2(a - b);
}
inline friend vec2 normalize(const vec2& a) {
return a / length(a);
}
inline friend float dot(const vec2& a, const vec2& b) {
return a.x * b.x + a.y * b.y;
}
};
///
/// 3D Vector Helper
///
struct UExport vec3 {
float x, y, z;
inline vec3() : x(0.0f), y(0.0f), z(0.0f) { }
inline vec3(float x, float y, float z) : x(x), y(y), z(z) {}
inline vec3(float x) : x(x), y(x), z(x) {}
inline friend vec3 operator+(vec3 lhs, const vec3& rhs) { lhs += rhs; return lhs; }
inline friend vec3 operator-(vec3 lhs, const vec3& rhs) { lhs -= rhs; return lhs; }
inline friend vec3 operator*(vec3 lhs, const vec3& rhs) { lhs *= rhs; return lhs; }
inline friend vec3 operator/(vec3 lhs, const vec3& rhs) { lhs /= rhs; return lhs; }
inline friend vec3 operator+(vec3 lhs, float rhs) { lhs += rhs; return lhs; }
inline friend vec3 operator-(vec3 lhs, float rhs) { lhs -= rhs; return lhs; }
inline friend vec3 operator*(vec3 lhs, float rhs) { lhs *= rhs; return lhs; }
inline friend vec3 operator/(vec3 lhs, float rhs) { lhs /= rhs; return lhs; }
inline vec3& operator+=(const vec3& rhs) {
x += rhs.x;
y += rhs.y;
z += rhs.z;
return *this;
}
inline vec3& operator-=(const vec3& rhs) {
x -= rhs.x;
y -= rhs.y;
z -= rhs.z;
return *this;
}
inline vec3& operator*=(const vec3& rhs) {
x *= rhs.x;
y *= rhs.y;
z *= rhs.z;
return *this;
}
inline vec3& operator/=(const vec3& rhs) {
x /= rhs.x;
y /= rhs.y;
z /= rhs.z;
return *this;
}
inline vec3& operator+=(float rhs) {
x += rhs;
y += rhs;
z += rhs;
return *this;
}
inline vec3& operator-=(float rhs) {
x -= rhs;
y -= rhs;
z -= rhs;
return *this;
}
inline vec3& operator*=(float rhs) {
x *= rhs;
y *= rhs;
z *= rhs;
return *this;
}
inline vec3& operator/=(float rhs) {
x /= rhs;
y /= rhs;
z /= rhs;
return *this;
}
inline friend bool operator==(const vec3& a, const vec3& b) {
return !memcmp(&a, &b, sizeof(a));
}
inline friend bool operator!=(const vec3& a, const vec3& b) {
return !(a == b);
}
inline friend vec3 min_(const vec3& a, const vec3& b) {
return{ (b.x < a.x) ? b.x : a.x,
(b.y < a.y) ? b.y : a.y,
(b.z < a.z) ? b.z : a.z };
}
inline friend vec3 max_(const vec3& a, const vec3& b) {
return{ (a.x < b.x) ? b.x : a.x,
(a.y < b.y) ? b.y : a.y,
(a.z < b.z) ? b.z : a.z };
}
inline friend vec3 clamp(const vec3& x, const vec3& minVal, const vec3& maxVal) {
return min_(max_(x, minVal), maxVal);
}
inline friend vec3 mix(const vec3& a, const vec3& b, float t) {
return a * (1.0f - t) + b * t;
}
inline friend float length(const vec3& a) {
return sqrtf(a.x * a.x + a.y * a.y + a.z * a.z);
}
inline friend float distance(const vec3& a, const vec3& b) {
return length(a - b);
}
inline friend vec3 normalize(const vec3& a) {
return a / length(a);
}
inline friend float dot(const vec3& a, const vec3& b) {
return a.x * b.x + a.y * b.y + a.z * b.z;
}
};
///
/// 4D Vector Helper
///
struct UExport vec4 {
float x, y, z, w;
inline vec4() : x(0.0f), y(0.0f), z(0.0f), w(0.0f) { }
inline vec4(float x, float y, float z, float w) : x(x), y(y), z(z), w(w) {}
inline vec4(float x) : x(x), y(x), z(x), w(x) {}
inline vec4(const float val[4]) : x(val[0]), y(val[1]), z(val[2]), w(val[3]) { }
inline friend bool operator==(const vec4& a, const vec4& b) {
return !memcmp(&a, &b, sizeof(a));
}
inline friend bool operator!=(const vec4& a, const vec4& b) {
return !(a == b);
}
inline friend vec4 operator+(vec4 lhs, const vec4& rhs) { lhs += rhs; return lhs; }
inline friend vec4 operator-(vec4 lhs, const vec4& rhs) { lhs -= rhs; return lhs; }
inline friend vec4 operator*(vec4 lhs, const vec4& rhs) { lhs *= rhs; return lhs; }
inline friend vec4 operator/(vec4 lhs, const vec4& rhs) { lhs /= rhs; return lhs; }
inline friend vec4 operator+(vec4 lhs, float rhs) { lhs += rhs; return lhs; }
inline friend vec4 operator-(vec4 lhs, float rhs) { lhs -= rhs; return lhs; }
inline friend vec4 operator*(vec4 lhs, float rhs) { lhs *= rhs; return lhs; }
inline friend vec4 operator/(vec4 lhs, float rhs) { lhs /= rhs; return lhs; }
inline vec4& operator+=(const vec4& rhs) {
x += rhs.x;
y += rhs.y;
z += rhs.z;
w += rhs.w;
return *this;
}
inline vec4& operator-=(const vec4& rhs) {
x -= rhs.x;
y -= rhs.y;
z -= rhs.z;
w -= rhs.w;
return *this;
}
inline vec4& operator*=(const vec4& rhs) {
x *= rhs.x;
y *= rhs.y;
z *= rhs.z;
w *= rhs.w;
return *this;
}
inline vec4& operator/=(const vec4& rhs) {
x /= rhs.x;
y /= rhs.y;
z /= rhs.z;
w /= rhs.w;
return *this;
}
inline vec4& operator+=(float rhs) {
x += rhs;
y += rhs;
z += rhs;
w += rhs;
return *this;
}
inline vec4& operator-=(float rhs) {
x -= rhs;
y -= rhs;
z -= rhs;
w -= rhs;
return *this;
}
inline vec4& operator*=(float rhs) {
x *= rhs;
y *= rhs;
z *= rhs;
w *= rhs;
return *this;
}
inline vec4& operator/=(float rhs) {
x /= rhs;
y /= rhs;
z /= rhs;
w /= rhs;
return *this;
}
inline friend vec4 min_(const vec4& a, const vec4& b) {
return{ (b.x < a.x) ? b.x : a.x,
(b.y < a.y) ? b.y : a.y,
(b.z < a.z) ? b.z : a.z,
(b.w < a.w) ? b.w : a.w };
}
inline friend vec4 max_(const vec4& a, const vec4& b) {
return{ (a.x < b.x) ? b.x : a.x,
(a.y < b.y) ? b.y : a.y,
(a.z < b.z) ? b.z : a.z,
(a.w < b.w) ? b.w : a.w };
}
inline void load(const float* val) {
x = val[0];
y = val[1];
z = val[2];
w = val[3];
}
inline void store(float* val) const {
val[0] = x;
val[1] = y;
val[2] = z;
val[3] = w;
}
};
///
/// Point is typedef'd to a 2D vector
///
typedef vec2 Point;
///
/// Float Rectangle Helper
///
struct UExport Rect {
float left, top, right, bottom;
static constexpr Rect MakeEmpty() { return Rect{ 0.0f, 0.0f, 0.0f, 0.0f }; }
inline float width() const { return right - left; }
inline float height() const { return bottom - top; }
inline float x() const { return left; }
inline float y() const { return top; }
inline float center_x() const { return (left + right) * 0.5f; }
inline float center_y() const { return (top + bottom) * 0.5f; }
inline Point origin() const { return { left, top }; }
inline void SetEmpty() { *this = MakeEmpty(); }
inline bool IsEmpty() const {
return *this == MakeEmpty();
}
inline bool IsValid() const {
return width() > 0 && height() > 0;
}
inline void Inset(float dx, float dy) {
left += dx;
top += dy;
right -= dx;
bottom -= dy;
}
inline void Outset(float dx, float dy) {
Inset(-dx, -dy);
}
inline void Move(float dx, float dy) {
left += dx;
top += dy;
right += dx;
bottom += dy;
}
inline float area() const {
return width() * height();
}
inline void Join(const Rect& rhs) {
// if we are empty, just assign
if (IsEmpty()) {
*this = rhs;
}
else {
if (rhs.left < left) left = rhs.left;
if (rhs.top < top) top = rhs.top;
if (rhs.right > right) right = rhs.right;
if (rhs.bottom > bottom) bottom = rhs.bottom;
}
}
inline void Join(const Point& p) {
// if we are empty, just assign
if (IsEmpty()) {
*this = { p.x, p.y, p.x, p.y };
}
else {
if (p.x < left) left = p.x;
if (p.y < top) top = p.y;
if (p.x > right) right = p.x;
if (p.y > bottom) bottom = p.y;
}
}
inline bool Contains(const Point& p) const {
return p.x >= left && p.x <= right &&
p.y >= top && p.y <= bottom;
}
inline bool Contains(const Rect& r) const {
return left <= r.left && top <= r.top &&
right >= r.right && bottom >= r.bottom;
}
inline bool Intersects(const Rect& rhs) const {
return !(rhs.left > right ||
rhs.right < left ||
rhs.top > bottom ||
rhs.bottom < top);
}
inline Rect Intersect(const Rect& other) const {
return{ (left < other.left) ? other.left : left,
(top < other.top) ? other.top : top,
(other.right < right) ? other.right : right,
(other.bottom < bottom) ? other.bottom : bottom };
}
friend inline bool operator==(const Rect& a, const Rect& b) {
return !memcmp(&a, &b, sizeof(a));
}
friend inline bool operator!=(const Rect& a, const Rect& b) {
return !(a == b);
}
inline vec4 ToVec4() { return vec4 { left, top, right, bottom }; }
};
///
/// Integer Rectangle Helper
///
struct UExport IntRect {
int left, top, right, bottom;
static constexpr IntRect MakeEmpty() { return IntRect{ 0, 0, 0, 0 }; }
inline int width() const { return right - left; }
inline int height() const { return bottom - top; }
inline int x() const { return left; }
inline int y() const { return top; }
inline int center_x() const { return (int)std::round((left + right) * 0.5f); }
inline int center_y() const { return (int)std::round((top + bottom) * 0.5f); }
inline Point origin() const { return Point{ (float)left, (float)top }; }
inline void SetEmpty() { *this = MakeEmpty(); }
inline bool IsEmpty() const {
return *this == MakeEmpty();
}
inline bool IsValid() const {
return width() > 0 && height() > 0;
}
inline void Inset(int dx, int dy) {
left += dx;
top += dy;
right -= dx;
bottom -= dy;
}
inline void Outset(int dx, int dy) {
Inset(-dx, -dy);
}
inline void Move(int dx, int dy) {
left += dx;
top += dy;
right += dx;
bottom += dy;
}
inline int area() const {
return width() * height();
}
inline void Join(const IntRect& rhs) {
// if we are empty, just assign
if (IsEmpty()) {
*this = rhs;
}
else {
if (rhs.left < left) left = rhs.left;
if (rhs.top < top) top = rhs.top;
if (rhs.right > right) right = rhs.right;
if (rhs.bottom > bottom) bottom = rhs.bottom;
}
}
inline void Join(const Point& p) {
// if we are empty, just assign
if (IsEmpty()) {
*this = { (int)std::floor(p.x), (int)std::floor(p.y), (int)std::ceil(p.x), (int)std::ceil(p.y) };
}
else {
if ((int)std::floor(p.x) < left) left = (int)std::floor(p.x);
if ((int)std::floor(p.y) < top) top = (int)std::floor(p.y);
if ((int)std::ceil(p.x) > right) right = (int)std::ceil(p.x);
if ((int)std::ceil(p.y) > bottom) bottom = (int)std::ceil(p.y);
}
}
inline bool Contains(const Point& p) const {
return p.x >= left && p.x <= right &&
p.y >= top && p.y <= bottom;
}
inline bool Contains(const IntRect& r) const {
return left <= r.left && top <= r.top &&
right >= r.right && bottom >= r.bottom;
}
inline bool Intersects(const IntRect& rhs) const {
// Since this is mostly used for pixel operations, we only count
// intersections that have width and height >= 1.
return !(rhs.left > right - 1 ||
rhs.right < left ||
rhs.top > bottom - 1 ||
rhs.bottom < top);
}
inline IntRect Intersect(const IntRect& other) const {
return{ (left < other.left) ? other.left : left,
(top < other.top) ? other.top : top,
(other.right < right) ? other.right : right,
(other.bottom < bottom) ? other.bottom : bottom };
}
friend inline bool operator==(const IntRect& a, const IntRect& b) {
return !memcmp(&a, &b, sizeof(a));
}
friend inline bool operator!=(const IntRect& a, const IntRect& b) {
return !(a == b);
}
};
///
/// Rounded Rectangle Helper
///
struct UExport RoundedRect {
Rect rect;
float radii_x[4];
float radii_y[4];
void SetEmpty();
bool IsRounded() const;
// Negative is inside, positive is outside.
float GetSignedDistance(const Point& p) const;
// Returns whether or not intersection is found. Can fail if the resulting
// geometry is not a rounded rectangle.
bool Intersect(const RoundedRect& other, RoundedRect& result) const;
void SnapToPixels();
Rect CalculateInterior() const;
};
} // namespace ultralight
+257
View File
@@ -0,0 +1,257 @@
/**************************************************************************************************
* This file is a part of Ultralight. *
* *
* See <https://ultralig.ht> for licensing and more. *
* *
* (C) 2024 Ultralight, Inc. *
**************************************************************************************************/
#pragma once
#include <Ultralight/Defines.h>
#include <Ultralight/Bitmap.h>
#include <Ultralight/Geometry.h>
#include <Ultralight/String.h>
namespace ultralight {
class ImageSourceListener;
class ImageSourceProviderListener;
///
/// User-defined image source to display custom images on a web-page.
///
/// This API allows you to composite your own images into a web-page. This is useful for displaying
/// in-game textures, external image assets, or other custom content.
///
/// ## ImageSource File Format
///
/// To use an ImageSource, you must first create an `.imgsrc` file containing a string identifying
/// the image source. This string will be used to lookup the ImageSource from ImageSourceProvider
/// when it is loaded on a web-page.
///
/// The file format is as follows:
///
/// ```
/// IMGSRC-V1
/// <identifier>
/// ```
///
/// You can use the `.imgsrc` file anywhere in your web-page that typically accepts an image URL.
/// For example:
///
/// ```html
/// <img src="my_custom_image.imgsrc" />
/// ```
///
/// ## Creating from a GPU Texture
///
/// To composite your own GPU texture on a web-page, you should first reserve a texture ID from
/// GPUDriver::NextTextureId() and then create an ImageSource from that texture ID. Next, you should
/// register the ImageSource with ImageSourceProvider using the identifier from the `.imgsrc` file.
///
/// When the image element is drawn on the web-page, the library will draw geometry using the
/// specified texture ID and UV coordinates. You should bind your own texture when the specified
/// texture ID is used.
///
//// @note If the GPU renderer is not enabled for the View or pixel data is needed for other
/// purposes, the library will sample the backing bitmap instead.
///
/// ## Creating from a Bitmap
///
/// To composite your own bitmap on a web-page, you should create an ImageSource from a Bitmap.
/// Next, you should register the ImageSource with ImageSourceProvider using the identifier from
/// the `.imgsrc` file.
///
/// When the image element is drawn on the web-page, the library will sample this bitmap directly.
///
/// ## Invalidating Images
///
/// If you modify the texture or bitmap pixels after creating the ImageSource, you should call
/// ImageSource::Invalidate() to notify the library that the image should be redrawn.
///
class UExport ImageSource : public RefCounted {
public:
///
/// Create an ImageSource from a GPU texture with optional backing bitmap.
///
/// @param width The width of the image in pixels (used for layout).
///
/// @param height The height of the image in pixels (used for layout).
///
/// @param texture_id The GPU texture identifier to bind when drawing the quad for this image.
/// This should be non-zero and obtained from GPUDriver::NextTextureId().
///
/// @param texture_uv The UV coordinates of the texture.
///
/// @param bitmap Optional backing bitmap for this image source. This is used when drawing
/// the image using the CPU renderer or when pixel data is needed for other
/// purposes. You should update this bitmap when the texture changes.
///
/// @return A new ImageSource instance.
///
static RefPtr<ImageSource> CreateFromTexture(uint32_t width, uint32_t height, uint32_t texture_id,
const Rect& texture_uv,
RefPtr<Bitmap> bitmap = nullptr);
///
/// Create an ImageSource from a Bitmap.
///
/// @param bitmap The backing bitmap for this image source.
///
/// @return A new ImageSource instance.
///
static RefPtr<ImageSource> CreateFromBitmap(RefPtr<Bitmap> bitmap);
///
/// Get the width of the image in pixels.
///
virtual uint32_t width() const = 0;
///
/// Get the height of the image in pixels.
///
virtual uint32_t height() const = 0;
///
/// Get the GPU texture identifier to bind when drawing the quad for this image.
///
/// @note This will be zero (0) if the image source was created from a bitmap.
///
virtual uint32_t texture_id() const = 0;
///
/// Get the UV coordinates of the texture.
///
virtual Rect texture_uv() const = 0;
///
/// Get the backing bitmap for this image source.
///
virtual RefPtr<Bitmap> bitmap() = 0;
///
/// Invalidate the image.
///
/// This will notify the library that the image has changed and should be redrawn.
///
virtual void Invalidate() = 0;
///
/// Add a listener to the image source.
///
/// @param listener The listener to add.
///
virtual void AddListener(ImageSourceListener* listener) = 0;
///
/// Remove a listener from the image source.
///
/// @param listener The listener to remove.
///
virtual void RemoveListener(ImageSourceListener* listener) = 0;
protected:
ImageSource() = default;
virtual ~ImageSource() = default;
ImageSource(const ImageSource&) = delete;
void operator=(const ImageSource&) = delete;
};
///
/// Listener for ImageSource events.
///
/// This is used to notify listeners when the image source is invalidated.
///
class UExport ImageSourceListener {
public:
virtual ~ImageSourceListener() = default;
///
/// Called when the image source is invalidated.
///
/// @param image_source The image source that was invalidated.
///
virtual void OnInvalidateImageSource(ImageSource* image_source) = 0;
};
///
/// Maps image sources to string identifiers.
///
/// This is used to lookup ImageSource instances when they are requested by a web-page.
///
class UExport ImageSourceProvider {
public:
///
/// Get the ImageSourceProvider singleton.
///
static ImageSourceProvider& instance();
///
/// Get an ImageSource by its identifier.
///
/// @param id The identifier of the image source.
///
/// @return The ImageSource instance or nullptr if not found.
///
virtual RefPtr<ImageSource> GetImageSource(const String& id) = 0;
///
/// Add an ImageSource to the provider.
///
/// @param id The identifier of the image source.
///
/// @param image_source The ImageSource instance.
///
virtual void AddImageSource(const String& id, RefPtr<ImageSource> image_source) = 0;
///
/// Remove an ImageSource from the provider.
///
/// @param id The identifier of the image source.
///
virtual void RemoveImageSource(const String& id) = 0;
///
/// Add a listener to the provider.
///
/// @param listener The listener to add.
///
virtual void AddListener(ImageSourceProviderListener* listener) = 0;
///
/// Remove a listener from the provider.
///
/// @param listener The listener to remove.
///
virtual void RemoveListener(ImageSourceProviderListener* listener) = 0;
protected:
virtual ~ImageSourceProvider() = default;
};
///
/// Listener for ImageSourceProvider events.
///
/// This is used to notify listeners when an ImageSource is added or removed from the provider.
///
class ImageSourceProviderListener {
public:
virtual ~ImageSourceProviderListener() = default;
///
/// Called when an ImageSource is added to the provider.
///
/// @param id The identifier of the image source.
///
/// @param image_source The ImageSource instance.
///
virtual void OnAddImageSource(const String& id, RefPtr<ImageSource> image_source) = 0;
///
/// Called when an ImageSource is removed from the provider.
///
/// @param id The identifier of the image source.
///
virtual void OnRemoveImageSource(const String& id) = 0;
};
} // namespace ultralight
+32
View File
@@ -0,0 +1,32 @@
/**************************************************************************************************
* This file is a part of Ultralight, an ultra-portable web-browser engine. *
* *
* See <https://ultralig.ht> for licensing and more. *
* *
* (C) 2024 Ultralight, Inc. *
**************************************************************************************************/
#pragma once
#include <JavaScriptCore/JavaScript.h>
#include <Ultralight/Defines.h>
#include <Ultralight/RefPtr.h>
#include <Ultralight/String.h>
namespace ultralight {
///
/// This class wraps a JSContextRef (a JavaScript execution context for use with JavaScriptCore)
/// and locks the context on the current thread for the duration of its lifetime.
///
class UExport JSContext : public RefCounted {
public:
/// Get the underlying JSContextRef for use with JavaScriptCore C API
virtual JSContextRef ctx() = 0;
/// Typecast to a JSContextRef for use with JavaScriptCore C API
operator JSContextRef();
protected:
virtual ~JSContext();
};
} // namespace ultralight
+532
View File
@@ -0,0 +1,532 @@
/**************************************************************************************************
* This file is a part of Ultralight, an ultra-portable web-browser engine. *
* *
* See <https://ultralig.ht> for licensing and more. *
* *
* (C) 2024 Ultralight, Inc. *
**************************************************************************************************/
#pragma once
namespace ultralight {
///
/// Namespace containing all the key-code definitions for KeyboardEvent.
/// Most of these correspond directly to the key-code values on Windows.
///
namespace KeyCodes {
// GK_BACK (08) BACKSPACE key
const int GK_BACK = 0x08;
// GK_TAB (09) TAB key
const int GK_TAB = 0x09;
// GK_CLEAR (0C) CLEAR key
const int GK_CLEAR = 0x0C;
// GK_RETURN (0D)
const int GK_RETURN = 0x0D;
// GK_SHIFT (10) SHIFT key
const int GK_SHIFT = 0x10;
// GK_CONTROL (11) CTRL key
const int GK_CONTROL = 0x11;
// GK_MENU (12) ALT key
const int GK_MENU = 0x12;
// GK_PAUSE (13) PAUSE key
const int GK_PAUSE = 0x13;
// GK_CAPITAL (14) CAPS LOCK key
const int GK_CAPITAL = 0x14;
// GK_KANA (15) Input Method Editor (IME) Kana mode
const int GK_KANA = 0x15;
// GK_HANGUEL (15) IME Hanguel mode (maintained for compatibility; use GK_HANGUL)
// GK_HANGUL (15) IME Hangul mode
const int GK_HANGUL = 0x15;
// GK_IME_ON (16) IME On
const int GK_IME_ON = 0x16;
// GK_JUNJA (17) IME Junja mode
const int GK_JUNJA = 0x17;
// GK_FINAL (18) IME final mode
const int GK_FINAL = 0x18;
// GK_HANJA (19) IME Hanja mode
const int GK_HANJA = 0x19;
// GK_KANJI (19) IME Kanji mode
const int GK_KANJI = 0x19;
// GK_IME_OFF (1A) IME Off
const int GK_IME_OFF = 0x1A;
// GK_ESCAPE (1B) ESC key
const int GK_ESCAPE = 0x1B;
// GK_CONVERT (1C) IME convert
const int GK_CONVERT = 0x1C;
// GK_NONCONVERT (1D) IME nonconvert
const int GK_NONCONVERT = 0x1D;
// GK_ACCEPT (1E) IME accept
const int GK_ACCEPT = 0x1E;
// GK_MODECHANGE (1F) IME mode change request
const int GK_MODECHANGE = 0x1F;
// GK_SPACE (20) SPACEBAR
const int GK_SPACE = 0x20;
// GK_PRIOR (21) PAGE UP key
const int GK_PRIOR = 0x21;
// GK_NEXT (22) PAGE DOWN key
const int GK_NEXT = 0x22;
// GK_END (23) END key
const int GK_END = 0x23;
// GK_HOME (24) HOME key
const int GK_HOME = 0x24;
// GK_LEFT (25) LEFT ARROW key
const int GK_LEFT = 0x25;
// GK_UP (26) UP ARROW key
const int GK_UP = 0x26;
// GK_RIGHT (27) RIGHT ARROW key
const int GK_RIGHT = 0x27;
// GK_DOWN (28) DOWN ARROW key
const int GK_DOWN = 0x28;
// GK_SELECT (29) SELECT key
const int GK_SELECT = 0x29;
// GK_PRINT (2A) PRINT key
const int GK_PRINT = 0x2A;
// GK_EXECUTE (2B) EXECUTE key
const int GK_EXECUTE = 0x2B;
// GK_SNAPSHOT (2C) PRINT SCREEN key
const int GK_SNAPSHOT = 0x2C;
// GK_INSERT (2D) INS key
const int GK_INSERT = 0x2D;
// GK_DELETE (2E) DEL key
const int GK_DELETE = 0x2E;
// GK_HELP (2F) HELP key
const int GK_HELP = 0x2F;
// (30) 0 key
const int GK_0 = 0x30;
// (31) 1 key
const int GK_1 = 0x31;
// (32) 2 key
const int GK_2 = 0x32;
// (33) 3 key
const int GK_3 = 0x33;
// (34) 4 key
const int GK_4 = 0x34;
// (35) 5 key;
const int GK_5 = 0x35;
// (36) 6 key
const int GK_6 = 0x36;
// (37) 7 key
const int GK_7 = 0x37;
// (38) 8 key
const int GK_8 = 0x38;
// (39) 9 key
const int GK_9 = 0x39;
// (41) A key
const int GK_A = 0x41;
// (42) B key
const int GK_B = 0x42;
// (43) C key
const int GK_C = 0x43;
// (44) D key
const int GK_D = 0x44;
// (45) E key
const int GK_E = 0x45;
// (46) F key
const int GK_F = 0x46;
// (47) G key
const int GK_G = 0x47;
// (48) H key
const int GK_H = 0x48;
// (49) I key
const int GK_I = 0x49;
// (4A) J key
const int GK_J = 0x4A;
// (4B) K key
const int GK_K = 0x4B;
// (4C) L key
const int GK_L = 0x4C;
// (4D) M key
const int GK_M = 0x4D;
// (4E) N key
const int GK_N = 0x4E;
// (4F) O key
const int GK_O = 0x4F;
// (50) P key
const int GK_P = 0x50;
// (51) Q key
const int GK_Q = 0x51;
// (52) R key
const int GK_R = 0x52;
// (53) S key
const int GK_S = 0x53;
// (54) T key
const int GK_T = 0x54;
// (55) U key
const int GK_U = 0x55;
// (56) V key
const int GK_V = 0x56;
// (57) W key
const int GK_W = 0x57;
// (58) X key
const int GK_X = 0x58;
// (59) Y key
const int GK_Y = 0x59;
// (5A) Z key
const int GK_Z = 0x5A;
// GK_LWIN (5B) Left Windows key (Microsoft Natural keyboard)
const int GK_LWIN = 0x5B;
// GK_RWIN (5C) Right Windows key (Natural keyboard)
const int GK_RWIN = 0x5C;
// GK_APPS (5D) Applications key (Natural keyboard)
const int GK_APPS = 0x5D;
// GK_SLEEP (5F) Computer Sleep key
const int GK_SLEEP = 0x5F;
// GK_NUMPAD0 (60) Numeric keypad 0 key
const int GK_NUMPAD0 = 0x60;
// GK_NUMPAD1 (61) Numeric keypad 1 key
const int GK_NUMPAD1 = 0x61;
// GK_NUMPAD2 (62) Numeric keypad 2 key
const int GK_NUMPAD2 = 0x62;
// GK_NUMPAD3 (63) Numeric keypad 3 key
const int GK_NUMPAD3 = 0x63;
// GK_NUMPAD4 (64) Numeric keypad 4 key
const int GK_NUMPAD4 = 0x64;
// GK_NUMPAD5 (65) Numeric keypad 5 key
const int GK_NUMPAD5 = 0x65;
// GK_NUMPAD6 (66) Numeric keypad 6 key
const int GK_NUMPAD6 = 0x66;
// GK_NUMPAD7 (67) Numeric keypad 7 key
const int GK_NUMPAD7 = 0x67;
// GK_NUMPAD8 (68) Numeric keypad 8 key
const int GK_NUMPAD8 = 0x68;
// GK_NUMPAD9 (69) Numeric keypad 9 key
const int GK_NUMPAD9 = 0x69;
// GK_MULTIPLY (6A) Multiply key
const int GK_MULTIPLY = 0x6A;
// GK_ADD (6B) Add key
const int GK_ADD = 0x6B;
// GK_SEPARATOR (6C) Separator key
const int GK_SEPARATOR = 0x6C;
// GK_SUBTRACT (6D) Subtract key
const int GK_SUBTRACT = 0x6D;
// GK_DECIMAL (6E) Decimal key
const int GK_DECIMAL = 0x6E;
// GK_DIVIDE (6F) Divide key
const int GK_DIVIDE = 0x6F;
// GK_F1 (70) F1 key
const int GK_F1 = 0x70;
// GK_F2 (71) F2 key
const int GK_F2 = 0x71;
// GK_F3 (72) F3 key
const int GK_F3 = 0x72;
// GK_F4 (73) F4 key
const int GK_F4 = 0x73;
// GK_F5 (74) F5 key
const int GK_F5 = 0x74;
// GK_F6 (75) F6 key
const int GK_F6 = 0x75;
// GK_F7 (76) F7 key
const int GK_F7 = 0x76;
// GK_F8 (77) F8 key
const int GK_F8 = 0x77;
// GK_F9 (78) F9 key
const int GK_F9 = 0x78;
// GK_F10 (79) F10 key
const int GK_F10 = 0x79;
// GK_F11 (7A) F11 key
const int GK_F11 = 0x7A;
// GK_F12 (7B) F12 key
const int GK_F12 = 0x7B;
// GK_F13 (7C) F13 key
const int GK_F13 = 0x7C;
// GK_F14 (7D) F14 key
const int GK_F14 = 0x7D;
// GK_F15 (7E) F15 key
const int GK_F15 = 0x7E;
// GK_F16 (7F) F16 key
const int GK_F16 = 0x7F;
// GK_F17 (80H) F17 key
const int GK_F17 = 0x80;
// GK_F18 (81H) F18 key
const int GK_F18 = 0x81;
// GK_F19 (82H) F19 key
const int GK_F19 = 0x82;
// GK_F20 (83H) F20 key
const int GK_F20 = 0x83;
// GK_F21 (84H) F21 key
const int GK_F21 = 0x84;
// GK_F22 (85H) F22 key
const int GK_F22 = 0x85;
// GK_F23 (86H) F23 key
const int GK_F23 = 0x86;
// GK_F24 (87H) F24 key
const int GK_F24 = 0x87;
// GK_NUMLOCK (90) NUM LOCK key
const int GK_NUMLOCK = 0x90;
// GK_SCROLL (91) SCROLL LOCK key
const int GK_SCROLL = 0x91;
// GK_LSHIFT (A0) Left SHIFT key
const int GK_LSHIFT = 0xA0;
// GK_RSHIFT (A1) Right SHIFT key
const int GK_RSHIFT = 0xA1;
// GK_LCONTROL (A2) Left CONTROL key
const int GK_LCONTROL = 0xA2;
// GK_RCONTROL (A3) Right CONTROL key
const int GK_RCONTROL = 0xA3;
// GK_LMENU (A4) Left MENU key
const int GK_LMENU = 0xA4;
// GK_RMENU (A5) Right MENU key
const int GK_RMENU = 0xA5;
// GK_BROWSER_BACK (A6) Windows 2000/XP: Browser Back key
const int GK_BROWSER_BACK = 0xA6;
// GK_BROWSER_FORWARD (A7) Windows 2000/XP: Browser Forward key
const int GK_BROWSER_FORWARD = 0xA7;
// GK_BROWSER_REFRESH (A8) Windows 2000/XP: Browser Refresh key
const int GK_BROWSER_REFRESH = 0xA8;
// GK_BROWSER_STOP (A9) Windows 2000/XP: Browser Stop key
const int GK_BROWSER_STOP = 0xA9;
// GK_BROWSER_SEARCH (AA) Windows 2000/XP: Browser Search key
const int GK_BROWSER_SEARCH = 0xAA;
// GK_BROWSER_FAVORITES (AB) Windows 2000/XP: Browser Favorites key
const int GK_BROWSER_FAVORITES = 0xAB;
// GK_BROWSER_HOME (AC) Windows 2000/XP: Browser Start and Home key
const int GK_BROWSER_HOME = 0xAC;
// GK_VOLUME_MUTE (AD) Windows 2000/XP: Volume Mute key
const int GK_VOLUME_MUTE = 0xAD;
// GK_VOLUME_DOWN (AE) Windows 2000/XP: Volume Down key
const int GK_VOLUME_DOWN = 0xAE;
// GK_VOLUME_UP (AF) Windows 2000/XP: Volume Up key
const int GK_VOLUME_UP = 0xAF;
// GK_MEDIA_NEXT_TRACK (B0) Windows 2000/XP: Next Track key
const int GK_MEDIA_NEXT_TRACK = 0xB0;
// GK_MEDIA_PREV_TRACK (B1) Windows 2000/XP: Previous Track key
const int GK_MEDIA_PREV_TRACK = 0xB1;
// GK_MEDIA_STOP (B2) Windows 2000/XP: Stop Media key
const int GK_MEDIA_STOP = 0xB2;
// GK_MEDIA_PLAY_PAUSE (B3) Windows 2000/XP: Play/Pause Media key
const int GK_MEDIA_PLAY_PAUSE = 0xB3;
// GK_LAUNCH_MAIL (B4) Windows 2000/XP: Start Mail key
const int GK_MEDIA_LAUNCH_MAIL = 0xB4;
// GK_LAUNCH_MEDIA_SELECT (B5) Windows 2000/XP: Select Media key
const int GK_MEDIA_LAUNCH_MEDIA_SELECT = 0xB5;
// GK_LAUNCH_APP1 (B6) Windows 2000/XP: Start Application 1 key
const int GK_MEDIA_LAUNCH_APP1 = 0xB6;
// GK_LAUNCH_APP2 (B7) Windows 2000/XP: Start Application 2 key
const int GK_MEDIA_LAUNCH_APP2 = 0xB7;
// GK_OEM_1 (BA) ';:' for US
const int GK_OEM_1 = 0xBA;
// GK_OEM_PLUS (BB) '=+' any country
const int GK_OEM_PLUS = 0xBB;
// GK_OEM_COMMA (BC) ',<' any country
const int GK_OEM_COMMA = 0xBC;
// GK_OEM_MINUS (BD) '-_' any country
const int GK_OEM_MINUS = 0xBD;
// GK_OEM_PERIOD (BE) '.>' any country
const int GK_OEM_PERIOD = 0xBE;
// GK_OEM_2 (BF) '/?' for US
const int GK_OEM_2 = 0xBF;
// GK_OEM_3 (C0) '`~' for US
const int GK_OEM_3 = 0xC0;
// GK_OEM_4 (DB) '[{' for US
const int GK_OEM_4 = 0xDB;
// GK_OEM_5 (DC) '\|' for US
const int GK_OEM_5 = 0xDC;
// GK_OEM_6 (DD) ']}' for US
const int GK_OEM_6 = 0xDD;
// GK_OEM_7 (DE) ''"' for US
const int GK_OEM_7 = 0xDE;
// GK_OEM_8 (DF) Used for miscellaneous characters; it can vary by keyboard.
const int GK_OEM_8 = 0xDF;
// GK_OEM_102 (E2) Windows 2000/XP: Either the angle bracket key or the backslash key on the RT
// 102-key keyboard
const int GK_OEM_102 = 0xE2;
// GK_PROCESSKEY (E5) Windows 95/98/Me, Windows NT 4.0, Windows 2000/XP: IME PROCESS key
const int GK_PROCESSKEY = 0xE5;
// GK_PACKET (E7) Windows 2000/XP: Used to pass Unicode characters as if they were keystrokes. The
// GK_PACKET key is the low word of a 32-bit Virtual Key value used for non-keyboard input methods.
// For more information, see Remark in KEYBDINPUT,SendInput, WM_KEYDOWN, and WM_KEYUP
const int GK_PACKET = 0xE7;
const int GK_OEM_ATTN = 0xF0;
// GK_ATTN (F6) Attn key
const int GK_ATTN = 0xF6;
// GK_CRSEL (F7) CrSel key
const int GK_CRSEL = 0xF7;
// GK_EXSEL (F8) ExSel key
const int GK_EXSEL = 0xF8;
// GK_EREOF (F9) Erase EOF key
const int GK_EREOF = 0xF9;
// GK_PLAY (FA) Play key
const int GK_PLAY = 0xFA;
// GK_ZOOM (FB) Zoom key
const int GK_ZOOM = 0xFB;
// GK_NONAME (FC) Reserved for future use
const int GK_NONAME = 0xFC;
// GK_PA1 (FD) PA1 key
const int GK_PA1 = 0xFD;
// GK_OEM_CLEAR (FE) Clear key
const int GK_OEM_CLEAR = 0xFE;
const int GK_UNKNOWN = 0;
} // namespace KeyCodes
} // namespace ultralight
+180
View File
@@ -0,0 +1,180 @@
/**************************************************************************************************
* This file is a part of Ultralight, an ultra-portable web-browser engine. *
* *
* See <https://ultralig.ht> for licensing and more. *
* *
* (C) 2024 Ultralight, Inc. *
**************************************************************************************************/
#pragma once
#include <Ultralight/Defines.h>
#include <Ultralight/KeyCodes.h>
#include <Ultralight/String.h>
#ifdef __OBJC__
#import <AppKit/NSEvent.h>
#endif
namespace ultralight {
///
/// Keyboard event representing a change in keyboard state.
///
/// @see View::FireKeyEvent
///
class UExport KeyEvent {
public:
///
/// The various KeyEvent types.
///
enum Type {
///
/// Key-Down event type. This type does **not** trigger accelerator commands in WebCore (eg,
/// Ctrl+C for copy is an accelerator command).
///
/// @warning You should probably use kType_RawKeyDown instead. This type is only here for
/// historic compatibility with WebCore's key event types.
///
kType_KeyDown,
///
/// Key-Up event type. Use this when a physical key is released.
///
kType_KeyUp,
///
/// Raw Key-Down type. Use this when a physical key is pressed.
///
kType_RawKeyDown,
///
/// Character input event type. Use this when the OS generates text from a physical key being
/// pressed (for example, this maps to WM_CHAR on Windows).
///
kType_Char,
};
///
/// Creates an empty KeyEvent, you will need to initialize its members
/// yourself. This is useful for synthesizing your own keyboard events.
///
KeyEvent();
#ifdef _WIN32
///
/// Create a KeyEvent directly from a Windows keyboard event.
///
KeyEvent(Type type, uintptr_t wparam, intptr_t lparam, bool is_system_key);
#endif
#ifdef __OBJC__
///
/// Create a KeyEvent directly from a macOS NSEvent.
///
KeyEvent(NSEvent* evt);
#endif
///
/// An enumeration of the different keyboard modifiers.
///
enum Modifiers : uint8_t {
/// Whether or not an ALT key is down
kMod_AltKey = 1 << 0,
/// Whether or not a Control key is down
kMod_CtrlKey = 1 << 1,
/// Whether or not a meta key (Command-key on Mac, Windows-key on Win) is down
kMod_MetaKey = 1 << 2,
/// Whether or not a Shift key is down
kMod_ShiftKey = 1 << 3,
};
///
/// The type of this KeyEvent.
///
Type type;
///
/// The current state of the keyboard. Modifiers may be OR'd together to represent multiple
/// values.
///
unsigned modifiers;
///
/// The virtual key-code associated with this keyboard event. This is either directly from the
/// event (ie, WPARAM on Windows) or via a mapping function. You can see a full list of the
/// possible virtual key-codes in KeyCodes.h
///
int virtual_key_code;
///
/// The actual key-code generated by the platform. The DOM spec primarily uses Windows-equivalent
/// codes (hence virtualKeyCode above) but it helps to also specify the platform-specific
/// key-code as well.
///
int native_key_code;
///
/// This is a string identifying the key that was pressed. This can be generated from the
/// virtual_key_code via the GetKeyIdentifierFromVirtualKeyCode() utility function. You can find
/// the full list of key identifiers at:
/// <https://www.w3.org/TR/2003/WD-DOM-Level-3-Events-20030331/keyset.html>
///
String key_identifier;
///
/// The actual text generated by this keyboard event. This is usually only a single character.
///
String text;
///
/// The text generated by this keyboard event before all modifiers except shift are applied. This
/// is used internally for working out shortcut keys. This is usually only a single character.
///
String unmodified_text;
///
/// Whether or not this is a keypad event.
///
bool is_keypad;
///
/// Whether or not this was generated as the result of an auto-repeat (eg, holding down a key).
///
bool is_auto_repeat;
///
/// Whether or not the pressed key is a "system key". This is a Windows-only concept and should
/// be "false" for all non-Windows platforms. For more information, see the following link:
/// <http://msdn.microsoft.com/en-us/library/ms646286(VS.85).aspx>
///
bool is_system_key;
};
///
/// Utility function for generating a key identifier string from a virtual
/// key-code.
///
/// @param virtual_key_code The virtual key-code to generate the key identifier from.
///
/// @param key_identifier_result The string to store the result in.
///
void UExport GetKeyIdentifierFromVirtualKeyCode(int virtual_key_code,
String& key_identifier_result);
///
/// Utility function for generating a key string from a virtual key-code.
///
/// @param virtual_key_code The virtual key-code to generate the key string from.
///
/// @param shift Whether or not the shift key is currently pressed.
///
/// @param key_result The string to store the result in.
///
/// @note This function assumes US keyboard layout.
///
/// @see <https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/key/Key_Values>
///
void UExport GetKeyFromVirtualKeyCode(int virtual_key_code, bool shift, String& key_result);
} // namespace ultralight
+350
View File
@@ -0,0 +1,350 @@
/**************************************************************************************************
* This file is a part of Ultralight, an ultra-portable web-browser engine. *
* *
* See <https://ultralig.ht> for licensing and more. *
* *
* (C) 2025 Ultralight, Inc. *
**************************************************************************************************/
#pragma once
#include <Ultralight/Defines.h>
#include <Ultralight/String.h>
#include <Ultralight/RefPtr.h>
#include <Ultralight/Geometry.h>
#include <Ultralight/Buffer.h>
#include <Ultralight/ConsoleMessage.h>
#include <Ultralight/NetworkRequest.h>
namespace ultralight {
class View;
///
/// Cursor types, @see ViewListener::OnChangeCursor
///
enum Cursor {
kCursor_Pointer = 0,
kCursor_Cross,
kCursor_Hand,
kCursor_IBeam,
kCursor_Wait,
kCursor_Help,
kCursor_EastResize,
kCursor_NorthResize,
kCursor_NorthEastResize,
kCursor_NorthWestResize,
kCursor_SouthResize,
kCursor_SouthEastResize,
kCursor_SouthWestResize,
kCursor_WestResize,
kCursor_NorthSouthResize,
kCursor_EastWestResize,
kCursor_NorthEastSouthWestResize,
kCursor_NorthWestSouthEastResize,
kCursor_ColumnResize,
kCursor_RowResize,
kCursor_MiddlePanning,
kCursor_EastPanning,
kCursor_NorthPanning,
kCursor_NorthEastPanning,
kCursor_NorthWestPanning,
kCursor_SouthPanning,
kCursor_SouthEastPanning,
kCursor_SouthWestPanning,
kCursor_WestPanning,
kCursor_Move,
kCursor_VerticalText,
kCursor_Cell,
kCursor_ContextMenu,
kCursor_Alias,
kCursor_Progress,
kCursor_NoDrop,
kCursor_Copy,
kCursor_None,
kCursor_NotAllowed,
kCursor_ZoomIn,
kCursor_ZoomOut,
kCursor_Grab,
kCursor_Grabbing,
kCursor_Custom
};
///
/// User-defined interface to handle general events for a View.
///
/// @see View::set_view_listener
///
class UExport ViewListener {
public:
virtual ~ViewListener() { }
///
/// Called when the page title changes
///
virtual void OnChangeTitle(ultralight::View* caller, const String& title) { }
///
/// Called when the page URL changes
///
virtual void OnChangeURL(ultralight::View* caller, const String& url) { }
///
/// Called when the tooltip changes (usually as result of a mouse hover)
///
virtual void OnChangeTooltip(ultralight::View* caller, const String& tooltip) { }
///
/// Called when the mouse cursor changes
///
virtual void OnChangeCursor(ultralight::View* caller, Cursor cursor) { }
///
/// Called when a message is added to the console (useful for errors / debug)
///
virtual void OnAddConsoleMessage(ultralight::View* caller,
const ultralight::ConsoleMessage& message) { }
///
/// Called when the page wants to create a new child View.
///
/// This is usually the result of a user clicking a link with target="_blank"
/// or by JavaScript calling window.open(url).
///
/// To allow creation of these new Views, you should create a new View in this callback (eg,
/// Renderer::CreateView()), resize it to your container, and return it. You are responsible for
/// displaying the returned View.
///
/// @param caller The View that called this event.
///
/// @param opener_url The URL of the page that initiated this request.
///
/// @param target_url The URL that the new View will navigate to.
///
/// @param is_popup Whether or not this was triggered by window.open().
///
/// @param popup_rect Popups can optionally request certain dimensions and coordinates via
/// window.open(). You can choose to respect these or not by resizing/moving
/// the View to this rect.
///
/// @return Returns a RefPtr to a created View to use to satisfy the the request (or return
/// nullptr if you want to block the action).
///
virtual RefPtr<View> OnCreateChildView(ultralight::View* caller, const String& opener_url,
const String& target_url, bool is_popup,
const IntRect& popup_rect);
///
/// Called when the page wants to create a new View to display the local inspector in.
///
/// You should create a new View in this callback (eg, Renderer::CreateView()), resize it to your
/// container, and return it. You are responsible for displaying the returned View.
///
/// @return Returns a RefPtr to a created View to use to satisfy the the request (or return
/// nullptr if you want to block the action).
///
virtual RefPtr<View> OnCreateInspectorView(ultralight::View* caller, bool is_local,
const String& inspected_url);
///
/// Called when the page requests to be closed.
///
virtual void OnRequestClose(ultralight::View* caller) { }
};
///
/// User-defined interface to handle load-related events for a View.
///
/// @see View::set_load_listener
///
class UExport LoadListener {
public:
virtual ~LoadListener() { }
///
/// Called when the page begins loading a new URL into a frame.
///
/// @param frame_id A unique ID for the frame.
///
/// @param is_main_frame Whether or not this is the main frame.
///
/// @param url The URL for the load.
///
/// @note This will be called for each frame on the page. You can filter for the main frame load
/// by checking if `is_main_frame` is `true`.
///
virtual void OnBeginLoading(ultralight::View* caller, uint64_t frame_id, bool is_main_frame,
const String& url) { }
///
/// Called when the page finishes loading a URL into a frame.
///
/// @param frame_id A unique ID for the frame.
///
/// @param is_main_frame Whether or not this is the main frame.
///
/// @param url The URL for the load.
///
/// @note This will be called for each frame on the page. You can filter for the main frame load
/// by checking if `is_main_frame` is `true`.
///
virtual void OnFinishLoading(ultralight::View* caller, uint64_t frame_id, bool is_main_frame,
const String& url) { }
///
/// Called when an error occurs while loading a URL into a frame.
///
/// @param frame_id A unique ID for the frame.
///
/// @param is_main_frame Whether or not this is the main frame.
///
/// @param url The URL for the load.
///
/// @param description A human-readable description of the error.
///
/// @param error_domain The name of the module that triggered the error.
///
/// @param error_code Internal error code generated by the module.
///
/// @note This will be called for each frame on the page. You can filter for the main frame load
/// by checking if `is_main_frame` is `true`.
///
virtual void OnFailLoading(ultralight::View* caller, uint64_t frame_id, bool is_main_frame,
const String& url, const String& description,
const String& error_domain, int error_code) { }
///
/// Called when the JavaScript window object is reset for a new page load.
///
/// This is called before any scripts are executed on the page and is the earliest time to setup
/// any initial JavaScript state or bindings.
///
/// The document is not guaranteed to be loaded/parsed at this point. If you need to make any
/// JavaScript calls that are dependent on DOM elements or scripts on the page, use OnDOMReady
/// instead.
///
/// The window object is lazily initialized (this will not be called on pages with no scripts).
///
/// @param frame_id A unique ID for the frame.
///
/// @param is_main_frame Whether or not this is the main frame.
///
/// @param url The URL for the load.
///
/// @note This will be called for each frame on the page. You can filter for the main frame load
/// by checking if `is_main_frame` is `true`.
///
virtual void OnWindowObjectReady(ultralight::View* caller, uint64_t frame_id, bool is_main_frame,
const String& url) { }
///
/// Called when all JavaScript has been parsed and the document is ready.
///
/// This is the best time to make any JavaScript calls that are dependent on DOM elements or
/// scripts on the page.
///
/// @param frame_id A unique ID for the frame.
///
/// @param is_main_frame Whether or not this is the main frame.
///
/// @param url The URL for the load.
///
/// @note This will be called for each frame on the page. You can filter for the main frame load
/// by checking if `is_main_frame` is `true`.
///
virtual void OnDOMReady(ultralight::View* caller, uint64_t frame_id, bool is_main_frame,
const String& url) { }
///
/// Called when the session history (back/forward state) is modified.
///
virtual void OnUpdateHistory(ultralight::View* caller) { }
};
///
/// A unique identifier representing an active download.
///
typedef uint32_t DownloadId;
///
/// User-defined interface to handle download-related events for a View.
///
/// You must implement this interface to handle downloads initiated by a View.
///
/// @see View::set_download_listener
///
class UExport DownloadListener {
public:
virtual ~DownloadListener() {}
///
/// Called when the View wants to generate a unique download id.
///
/// You should generally return an integer (starting at 0) that is incremented with each call
/// to this callback.
///
virtual DownloadId NextDownloadId(ultralight::View* caller) = 0;
///
/// Called when the View wants to start downloading a resource from the network.
///
/// You should return true to allow the download, or false to block the download.
///
virtual bool OnRequestDownload(ultralight::View* caller, DownloadId id, const String& url) = 0;
///
/// Called when the View begins downloading a resource from the network.
///
/// The View will not actually write any data to disk, you should open a file for writing
/// yourself and handle the OnReceiveDataForDownload callback below.
///
virtual void OnBeginDownload(ultralight::View* caller, DownloadId id, const String& url,
const String& filename, int64_t expected_content_length) = 0;
///
/// Called when the View receives data for a certain download from the network.
///
/// This may be called multiple times for each active download as data is streamed in.
///
/// You should write the data to the associated file in this callback.
///
virtual void OnReceiveDataForDownload(ultralight::View* caller, DownloadId id,
RefPtr<Buffer> data) = 0;
///
/// Called when the View finishes downloading a resource from the network.
///
/// You should close the associated file in this callback.
///
virtual void OnFinishDownload(ultralight::View* caller, DownloadId id) = 0;
///
/// Called when the View fails downloading a resource from the network.
///
/// You should close the associated file and delete it from disk in this callback.
///
virtual void OnFailDownload(ultralight::View* caller, DownloadId id) = 0;
};
///
/// User-defined interface to handle network-related events for a View.
///
/// @see View::set_network_listener
///
class UExport NetworkListener {
public:
virtual ~NetworkListener() { }
///
/// Called when the View is about to begin a network request.
///
/// You can use this to block or modify network requests before they are sent.
///
/// Return true to allow the request, return false to block it.
///
/// @pre This feature is only available in Ultralight Pro edition and above.
///
virtual bool OnNetworkRequest(ultralight::View* caller, NetworkRequest& request) = 0;
};
} // namespace ultralight
+53
View File
@@ -0,0 +1,53 @@
/**************************************************************************************************
* This file is a part of Ultralight. *
* *
* See <https://ultralig.ht> for licensing and more. *
* *
* (C) 2024 Ultralight, Inc. *
**************************************************************************************************/
#pragma once
#include <Ultralight/Defines.h>
#include <atomic>
#include <mutex> // for std::lock_guard<>
namespace ultralight {
///
/// Tiny, efficient spinlock that is optimized for short locking periods but will still
/// intelligently yield the current thread and save CPU if the lock is held longer.
///
/// Can be used in place of std::mutex since it implements the STL's Lockable interface.
///
class Lock {
public:
constexpr Lock() = default;
UL_ALWAYS_INLINE void lock() noexcept {
// Optimistically assume the lock is free on the first try
if (!lock_.exchange(true, std::memory_order_acquire))
return;
contended_lock();
}
UL_ALWAYS_INLINE bool try_lock() noexcept {
// First do a relaxed load to check if lock is free in order to prevent
// unnecessary cache misses if someone does while(!try_lock())
return !lock_.load(std::memory_order_relaxed)
&& !lock_.exchange(true, std::memory_order_acquire);
}
UL_ALWAYS_INLINE void unlock() noexcept { lock_.store(false, std::memory_order_release); }
protected:
Lock(const Lock&) = delete;
Lock& operator=(const Lock&) = delete;
void contended_lock() noexcept;
std::atomic<bool> lock_ = { 0 };
};
using LockHolder = std::lock_guard<Lock>;
} // namespace ultralight
+179
View File
@@ -0,0 +1,179 @@
/**************************************************************************************************
* This file is a part of Ultralight. *
* *
* See <https://ultralig.ht> for licensing and more. *
* *
* (C) 2025 Ultralight, Inc. *
**************************************************************************************************/
#pragma once
#include <Ultralight/Defines.h>
#include <Ultralight/RefPtr.h>
#include <Ultralight/Geometry.h>
namespace ultralight {
///
/// 4x4 Matrix Helper
///
struct UExport Matrix4x4 {
///
/// Raw 4x4 matrix as an array in column-major order.
///
float data[16];
///
/// Set to identity matrix.
///
void SetIdentity();
};
///
/// Transformation Matrix helper
///
struct UExport UL_ALIGN(16) Matrix {
typedef double Aligned4x4[4][4];
///
/// Raw matrix data in column-major order (eg, `data[column][row]`)
///
Aligned4x4 data;
///
/// Set to identity matrix.
///
void SetIdentity();
///
/// Set to an orthographic projection matrix suitable for use with our
/// vertex shaders. Optionally flip the y-coordinate space (eg, for OpenGL).
///
void SetOrthographicProjection(double screen_width, double screen_height,
bool flip_y);
///
/// Set to another matrix.
///
void Set(const Matrix& other);
///
/// Set to another matrix.
///
void Set(const Matrix4x4& other);
///
/// Set from raw affine members.
///
void Set(double a, double b, double c, double d, double e, double f);
///
/// Set from raw 4x4 components.
///
void Set(double m11, double m12, double m13, double m14,
double m21, double m22, double m23, double m24,
double m31, double m32, double m33, double m34,
double m41, double m42, double m43, double m44);
inline double m11() const { return data[0][0]; }
inline double m12() const { return data[0][1]; }
inline double m13() const { return data[0][2]; }
inline double m14() const { return data[0][3]; }
inline double m21() const { return data[1][0]; }
inline double m22() const { return data[1][1]; }
inline double m23() const { return data[1][2]; }
inline double m24() const { return data[1][3]; }
inline double m31() const { return data[2][0]; }
inline double m32() const { return data[2][1]; }
inline double m33() const { return data[2][2]; }
inline double m34() const { return data[2][3]; }
inline double m41() const { return data[3][0]; }
inline double m42() const { return data[3][1]; }
inline double m43() const { return data[3][2]; }
inline double m44() const { return data[3][3]; }
inline double a() const { return data[0][0]; }
inline double b() const { return data[0][1]; }
inline double c() const { return data[1][0]; }
inline double d() const { return data[1][1]; }
inline double e() const { return data[3][0]; }
inline double f() const { return data[3][1]; }
///
/// Whether or not this is an identity matrix.
///
bool IsIdentity() const;
///
/// Whether or not this is an identity matrix or translation.
///
bool IsIdentityOrTranslation() const;
///
/// Whether or not this matrix uses only affine transformations.
///
bool IsAffine() const;
///
/// Whether or not this is an identity, translation, or non-negative
/// uniform scale.
///
bool IsSimple() const;
///
/// Translate by x and y.
///
void Translate(double x, double y);
///
/// Scale by x and y.
///
void Scale(double x, double y);
///
/// Rotate matrix by theta (in degrees)
///
void Rotate(double theta);
///
/// Rotate matrix by x and y
///
void Rotate(double x, double y);
///
/// Transform (multiply) by another Matrix
///
void Transform(const Matrix& other);
///
/// Get the inverse of this matrix. May return false if not invertible.
///
bool GetInverse(Matrix& result) const;
///
/// Transform point by this matrix and get the result.
///
Point Apply(const Point& p) const;
///
/// Transform rect by this matrix and get the result as an axis-aligned rect.
///
Rect Apply(const Rect& r) const;
///
/// Get an integer hash of this matrix's members.
///
uint32_t Hash() const;
///
/// Get this matrix as unaligned 4x4 float components (for use passing to
/// GPU driver APIs).
///
Matrix4x4 GetMatrix4x4() const;
};
bool UExport operator==(const Matrix& a, const Matrix& b);
bool UExport operator!=(const Matrix& a, const Matrix& b);
bool UExport operator==(const Matrix4x4& a, const Matrix4x4& b);
bool UExport operator!=(const Matrix4x4& a, const Matrix4x4& b);
} // namespace ultralight
+71
View File
@@ -0,0 +1,71 @@
/**************************************************************************************************
* This file is a part of Ultralight, an ultra-portable web-browser engine. *
* *
* See <https://ultralig.ht> for licensing and more. *
* *
* (C) 2024 Ultralight, Inc. *
**************************************************************************************************/
#pragma once
#include <Ultralight/Defines.h>
namespace ultralight {
///
/// Mouse event representing a change in mouse state.
///
/// @see View::FireMouseEvent
///
class MouseEvent {
public:
///
/// The various MouseEvent types.
///
enum Type {
///
/// Mouse moved type
///
kType_MouseMoved,
///
/// Mouse button pressed type
///
kType_MouseDown,
///
/// Mouse button released type
///
kType_MouseUp,
};
///
/// The various mouse button types.
///
enum Button {
kButton_None = 0,
kButton_Left,
kButton_Middle,
kButton_Right,
};
///
/// The type of this MouseEvent
///
Type type;
///
/// The current x-position of the mouse, relative to the View
///
int x;
///
/// The current y-position of the mouse, relative to the View
///
int y;
///
/// The mouse button that was pressed/released, if any.
///
Button button;
};
} // namespace ultralight
+63
View File
@@ -0,0 +1,63 @@
/**************************************************************************************************
* This file is a part of Ultralight, an ultra-portable web-browser engine. *
* *
* See <https://ultralig.ht> for licensing and more. *
* *
* (C) 2024 Ultralight, Inc. *
**************************************************************************************************/
#pragma once
#include <Ultralight/Defines.h>
namespace ultralight {
///
/// @brief Interface for Network requests.
///
class UExport NetworkRequest {
public:
virtual ~NetworkRequest() { }
///
/// URL of the request.
///
virtual String url() const = 0;
///
/// The host portion of the URL.
///
virtual String urlHost() const = 0;
///
/// The protocol of the URL (eg, "http")
///
virtual String urlProtocol() const = 0;
///
/// The HTTP method (eg, "POST" or "GET")
///
virtual String httpMethod() const = 0;
///
/// The origin of the request.
///
virtual String httpOrigin() const = 0;
///
/// The user-agent of the request.
///
virtual String httpUserAgent() const = 0;
///
/// Enforce additional TLS/SSL certificate validation by verifying the
/// server's pinned public key.
///
/// The public key string can be any number of base64 encoded sha256 hashes
/// preceded by "sha256//" and separated by ";".
///
/// For more info see the cURL docs:
/// <https://curl.se/libcurl/c/CURLOPT_PINNEDPUBLICKEY.html>
///
virtual void EnforcePinnedPublicKey(const String& public_key) = 0;
};
} // namespace ultralight
+325
View File
@@ -0,0 +1,325 @@
/**************************************************************************************************
* This file is a part of Ultralight. *
* *
* See <https://ultralig.ht> for licensing and more. *
* *
* (C) 2024 Ultralight, Inc. *
**************************************************************************************************/
/*
* Portions of the below code are derived from 'RefPtr.h' from Apple's WTF,
* with the following license header:
*
* Copyright (C) 2013-2014 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGE.
*/
#pragma once
#include <Ultralight/Defines.h>
#include <assert.h>
#include <utility>
namespace ultralight {
///
/// @brief Interface for all ref-counted objects that will be managed using
/// the RefPtr<> smart pointer.
///
class UExport RefCounted {
public:
virtual void AddRef() const = 0;
virtual void Release() const = 0;
virtual int ref_count() const = 0;
protected:
virtual ~RefCounted();
};
template<typename T> class RefPtr;
///
/// @brief Helper for wrapping new objects with the RefPtr smart pointer.
///
/// All ref-counted object are created with an initial ref-count of '1'.
/// The AdoptRef() helper returns a RefPtr<T> without calling AddRef().
/// This is used for creating new objects, like so:
///
/// RefPtr<Object> ref = AdoptRef(*new ObjectImpl());
///
template<typename T>
RefPtr<T> AdoptRef(T& reference)
{
return RefPtr<T>(reference, RefPtr<T>::Adopt);
}
///
/// @brief A nullable smart pointer.
///
/// This smart pointer automatically manages the lifetime of a RefCounted
/// object. The managed instance may be NULL.
///
template<typename T> class RefPtr {
public:
///
/// Construct a NULL ref-pointer.
///
constexpr RefPtr()
: instance_(nullptr)
{
}
///
/// Construct a NULL ref-pointer.
///
inline RefPtr(std::nullptr_t)
: instance_(nullptr)
{
}
///
/// Construct from a pointer. (Will increment ref-count by one)
///
inline RefPtr(T* other)
: instance_(other)
{
if (instance_)
instance_->AddRef();
}
///
/// Copy constructor.
///
inline RefPtr(const RefPtr& other)
: instance_(other.instance_)
{
if (instance_)
instance_->AddRef();
}
///
/// Copy constructor with internal type conversion.
///
template<typename U>
RefPtr(const RefPtr<U>& other)
: instance_(other.instance_)
{
if (instance_)
instance_->AddRef();
}
///
/// Move constructor.
///
inline RefPtr(RefPtr&& other)
: instance_(other.LeakRef())
{
}
///
/// Move constructor.
///
template<typename U>
RefPtr(RefPtr<U>&& other)
: instance_(other.LeakRef())
{
}
///
/// Destroy RefPtr (wll decrement ref-count by one)
///
inline ~RefPtr()
{
T* old_value = std::move(instance_);
instance_ = std::forward<T*>(nullptr);
if (old_value)
old_value->Release();
}
///
/// Get a pointer to wrapped object.
///
inline T* get() const { return instance_; }
T* LeakRef() {
T* result = std::move(instance_);
instance_ = std::forward<T*>(nullptr);
return result;
}
T& operator*() const { assert(instance_); return *instance_; }
inline T* operator->() const { return instance_; }
bool operator!() const { return !instance_; }
// This conversion operator allows implicit conversion to bool but not to other integer types.
typedef T* (RefPtr::*UnspecifiedBoolType);
operator UnspecifiedBoolType() const { return instance_ ? &RefPtr::instance_ : nullptr; }
RefPtr& operator=(const RefPtr&);
RefPtr& operator=(T*);
RefPtr& operator=(std::nullptr_t);
template<typename U> RefPtr& operator=(const RefPtr<U>&);
RefPtr& operator=(RefPtr&&);
template<typename U> RefPtr& operator=(RefPtr<U>&&);
friend inline bool operator==(const RefPtr& a, const RefPtr& b) {
return a.instance_ == b.instance_;
}
friend inline bool operator!=(const RefPtr& a, const RefPtr& b) {
return a.instance_ != b.instance_;
}
friend inline bool operator<(const RefPtr& a, const RefPtr& b) {
return a.instance_ < b.instance_;
}
///
/// Releases the ownership of the managed object, if any
///
void reset();
///
/// Replaces the managed object with another.
///
void reset(T* obj);
///
/// Exchanges the stored pointer values and the ownerships of *this and ptr.
/// Reference counts, if any, are not adjusted.
///
void swap(RefPtr& ptr);
protected:
friend RefPtr AdoptRef<T>(T&);
enum AdoptTag { Adopt };
RefPtr(T& object, AdoptTag) : instance_(&object) { }
private:
T* instance_;
};
template<typename T>
RefPtr<T>& RefPtr<T>::operator=(const RefPtr& other)
{
RefPtr ptr = other;
swap(ptr);
return *this;
}
template<typename T>
template<typename U>
RefPtr<T>& RefPtr<T>::operator=(const RefPtr<U>& other)
{
RefPtr ptr = other;
swap(ptr);
return *this;
}
template<typename T>
RefPtr<T>& RefPtr<T>::operator=(T* object)
{
RefPtr ptr = object;
swap(ptr);
return *this;
}
template<typename T>
RefPtr<T>& RefPtr<T>::operator=(std::nullptr_t)
{
T* old_instance = std::move(instance_);
instance_ = std::forward<T*>(nullptr);
if (old_instance)
old_instance->Release();
return *this;
}
template<typename T>
RefPtr<T>& RefPtr<T>::operator=(RefPtr&& other)
{
RefPtr ptr = std::move(other);
swap(ptr);
return *this;
}
template<typename T>
template<typename U>
RefPtr<T>& RefPtr<T>::operator=(RefPtr<U>&& other)
{
RefPtr ptr = std::move(other);
swap(ptr);
return *this;
}
template <typename T> void RefPtr<T>::reset() { *this = nullptr; }
template <typename T> void RefPtr<T>::reset(T* obj) { *this = obj; }
template<typename T>
void RefPtr<T>::swap(RefPtr& other)
{
std::swap(instance_, other.instance_);
}
template<class T>
void swap(RefPtr<T>& a, RefPtr<T>& b)
{
a.swap(b);
}
template<typename T, typename U>
bool operator==(const RefPtr<T>& a, const RefPtr<U>& b)
{
return a.get() == b.get();
}
template<typename T, typename U>
bool operator==(const RefPtr<T>& a, const U* b)
{
return a.get() == b;
}
template<typename T, typename U>
bool operator==(const T* a, const RefPtr<U>& b)
{
return a == b.get();
}
template<typename T, typename U>
bool operator!=(const RefPtr<T>& a, const RefPtr<U>& b)
{
return a.get() != b.get();
}
template<typename T, typename U>
bool operator!=(const RefPtr<T>& a, const U* b)
{
return a.get() != b;
}
template<typename T, typename U>
bool operator!=(const T* a, const RefPtr<U>& b)
{
return a != b.get();
}
} // namespace ultralight
+86
View File
@@ -0,0 +1,86 @@
/**************************************************************************************************
* This file is a part of Ultralight. *
* *
* See <https://ultralig.ht> for licensing and more. *
* *
* (C) 2024 Ultralight, Inc. *
**************************************************************************************************/
#pragma once
#include <Ultralight/Defines.h>
#include <Ultralight/Bitmap.h>
#include <Ultralight/Geometry.h>
namespace ultralight {
#pragma pack(push, 1)
///
/// Offscreen render target, used when rendering Views via the GPU renderer.
///
/// When a View is rendered via the GPU renderer (see View::is_accelerated), it will be rendered to
/// an offscreen render target (View::render_target) that you can display in your application.
///
/// This is intended to be used with a custom GPUDriver implementation in a game or similar
/// application.
///
/// ## Displaying the Render Target
///
/// To display the View's render target, you should:
///
/// 1. Retrieve the underlying texture via RenderTarget::texture_id().
/// 2. Bind the texture using your custom GPUDriver implementation.
/// 3. Draw a textured quad with the provided UV coordinates (RenderTarget::uv_coords()).
///
struct UExport RenderTarget {
///
/// Whether this target is empty (null texture)
///
bool is_empty;
///
/// The viewport width (in device coordinates).
///
uint32_t width;
///
/// The viewport height (in device coordinates).
///
uint32_t height;
///
/// The GPUDriver-specific texture ID (you should bind the texture using your custom GPUDriver
/// implementation before drawing a quad).
///
uint32_t texture_id;
///
/// The texture width (in pixels). This may be padded.
///
uint32_t texture_width;
///
/// The texture height (in pixels). This may be padded.
///
uint32_t texture_height;
///
/// The pixel format of the texture.
///
BitmapFormat texture_format;
///
/// UV coordinates of the texture (this is needed because the texture may be padded).
///
Rect uv_coords;
///
/// The GPUDriver-specific render buffer ID.
///
uint32_t render_buffer_id;
RenderTarget();
};
#pragma pack(pop)
} // namespace ultralight
+307
View File
@@ -0,0 +1,307 @@
/**************************************************************************************************
* This file is a part of Ultralight, an ultra-portable web-browser engine. *
* *
* See <https://ultralig.ht> for licensing and more. *
* *
* (C) 2024 Ultralight, Inc. *
**************************************************************************************************/
#pragma once
#include <Ultralight/Defines.h>
#include <Ultralight/RefPtr.h>
#include <Ultralight/Session.h>
#include <Ultralight/View.h>
#include <Ultralight/GamepadEvent.h>
namespace ultralight {
///
/// Core renderer singleton for the library, coordinates all library functions.
///
/// The Renderer class is responsible for creating and painting View%s, managing Session%s, as well
/// as coordinating network requests, events, JavaScript execution, and more.
///
/// ## Creating the Renderer
///
/// @note A Renderer will be created for you automatically when you call App::Create() (access it
/// via App::renderer).
///
/// @note App::Create() is part of the AppCore API and automatically manages window creation, run
/// loop, input, painting, and most platform-specific functionality. (Available on desktop
/// platforms only)
/// \endparblock
///
/// ### Defining Platform Handlers
///
/// Before creating the Renderer, you should define your platform handlers via the Platform
/// singleton. This can be used to customize file loading, font loading, clipboard access, and other
/// functionality typically provided by the OS.
///
/// Default implementations for most platform handlers are available in the
/// [AppCore repo](https://github.com/ultralight-ux/AppCore/tree/master/src). You can use these
/// stock implementations by copying the code into your project, or you can write your own.
///
/// At a minimum, you should provide a FileSystem and FontLoader otherwise Renderer creation will
/// fail.
///
/// ### Setting Up the Config
///
/// You can configure various library options by creating a Config object and passing it to
/// `Platform::instance().set_config()`.
///
/// ### Creating the Renderer
///
/// Once you've set up the Platform handlers and Config, you can create the Renderer by calling
/// `Renderer::Create()`. You should store the result in a RefPtr to keep it alive.
///
/// @par Example creation code
/// ```
/// // Get the Platform singleton (maintains global library state)
/// auto& platform = Platform::instance();
///
/// // Setup config
/// Config my_config;
/// platform.set_config(my_config);
///
/// // Create platform handlers (these are the minimum required)
/// // (This is pseudo-code, you will need to define your own)
/// MyFileSystem* file_system = new MyFileSystem();
/// MyFontLoader* font_loader = new MyFontLoader();
///
/// // Setup platform handlers
/// platform.set_file_system(file_system);
/// platform.set_font_loader(font_loader);
///
/// // Create the Renderer
/// RefPtr<Renderer> renderer = Renderer::Create();
///
/// // Create Views here
/// ```
///
/// ## Updating Renderer Logic
///
/// You should call Renderer::Update() from your main update loop as often as possible to give the
/// library an opportunity to dispatch events and timers:
///
/// @par Example update code
/// ```
/// void mainLoop()
/// {
/// while(true)
/// {
/// // Update program logic here
/// renderer.Update();
/// }
/// }
/// ```
///
/// ## Rendering Each Frame
///
/// When your program is ready to display a new frame (usually in synchrony with the monitor
/// refresh rate), you should call `Renderer::RefreshDisplay()` and `Renderer::Render()` so the
/// library can render all active View%s as needed.
///
/// @par Example per-frame render code
/// ```
/// void displayFrame()
/// {
/// // Notify the renderer that the main display has refreshed. This will update animations,
/// // smooth scroll, and window.requestAnimationFrame() for all Views matching the display id.
/// renderer.RefreshDisplay(0);
///
/// // Render all Views as needed
/// renderer.Render();
///
/// // Each View will render to a
/// // - Pixel-Buffer Surface (View::surface())
/// // or
/// // - GPU texture (View::render_target())
/// // based on whether CPU or GPU rendering is used.
/// //
/// // You will need to display the image data here as needed.
/// }
/// }
/// ```
///
class UExport Renderer : public RefCounted {
public:
///
/// Create the core renderer singleton for the library.
///
/// You should set up the Platform singleton before calling this function.
///
/// @note You do not need to the call this if you're using the App class from AppCore.
///
/// \parblock
/// @warning You'll need to define a FontLoader and FileSystem within the Platform singleton
/// or else this call will fail.
/// \endparblock
///
/// \parblock
/// @warning You should only create one Renderer during the lifetime of your program.
/// \endparblock
///
/// @return Renderer is ref-counted. This method returns a ref-pointer to a new instance, you
/// should store it in a RefPtr to keep the instance alive.
///
static RefPtr<Renderer> Create();
///
/// Create a unique, named Session to store browsing data in (cookies, local storage,
/// application cache, indexed db, etc).
///
/// @note A default, persistent Session is already created for you. You only need to call this
/// if you want to create private, in-memory session or use a separate session for each
/// View.
///
/// @param is_persistent Whether or not to store the session on disk. Persistent sessions will
/// be written to the path set in Config::cache_path
///
/// @param name A unique name for this session, this will be used to generate a unique disk
/// path for persistent sessions.
///
virtual RefPtr<Session> CreateSession(bool is_persistent, const String& name) = 0;
///
/// Get the default Session. This session is persistent (backed to disk) and has the name
/// "default".
///
virtual RefPtr<Session> default_session() = 0;
///
/// Create a new View to load and display web pages in.
///
/// Views are similar to a tab in a browser. They have certain dimensions but are rendered to an
/// offscreen surface and must be forwarded all input events.
///
/// @param width The initial width, in pixels.
///
/// @param height The initial height, in pixels.
///
/// @param config Configuration details for the View.
///
/// @param session The session to store local data in. Pass a nullptr to use the default
/// session.
///
/// @return Returns a ref-pointer to a new View instance.
///
virtual RefPtr<View> CreateView(uint32_t width, uint32_t height, const ViewConfig& config,
RefPtr<Session> session)
= 0;
///
/// Update timers and dispatch callbacks.
///
/// You should call this as often as you can from your application's run loop.
///
virtual void Update() = 0;
///
/// Notify the renderer that a display has refreshed (you should call this after vsync).
///
/// This updates animations, smooth scroll, and window.requestAnimationFrame() for all Views
/// matching the display id.
///
virtual void RefreshDisplay(uint32_t display_id) = 0;
///
/// Render all active views to their respective render-targets/surfaces.
///
/// @note Views are only repainted if they actually need painting.
///
virtual void Render() = 0;
///
/// Render a subset of views to their respective surfaces and render targets.
///
/// @param view_array A C-array containing a list of View pointers.
///
/// @param view_array_len The length of the C-array.
///
virtual void RenderOnly(View** view_array, size_t view_array_len) = 0;
///
/// Attempt to release as much memory as possible.
///
/// @warning Don't call this from any callbacks or driver code.
///
virtual void PurgeMemory() = 0;
///
/// Print detailed memory usage statistics to the log.
///
/// @see Platform::set_logger
///
virtual void LogMemoryUsage() = 0;
///
/// Start the remote inspector server.
///
/// @pre This feature is only available in Ultralight Pro edition and above.
///
/// While the remote inspector is active, Views that are loaded into this renderer
/// will be able to be remotely inspected from another Ultralight instance either locally
/// (another app on same machine) or remotely (over the network) by navigating a View to:
///
/// \code
/// inspector://<ADDRESS>:<PORT>
/// \endcode
///
/// @param address The address for the server to listen on (eg, "127.0.0.1")
///
/// @param port The port for the server to listen on (eg, 9222)
///
/// @return Returns whether the server started successfully or not.
///
virtual bool StartRemoteInspectorServer(const char* address, uint16_t port) = 0;
///
/// Describe the details of a gamepad, to be used with FireGamepadEvent and related
/// events below. This can be called multiple times with the same index if the details change.
///
/// @param index The unique index (or "connection slot") of the gamepad. For example,
/// controller #1 would be "1", controller #2 would be "2" and so on.
///
/// @param id A string ID representing the device, this will be made available
/// in JavaScript as gamepad.id
///
/// @param axis_count The number of axes on the device.
///
/// @param button_count The number of buttons on the device.
///
virtual void SetGamepadDetails(uint32_t index, const String& id, uint32_t axis_count,
uint32_t button_count)
= 0;
///
/// Fire a gamepad event (connection / disconnection).
///
/// @note The gamepad should first be described via SetGamepadDetails before calling this
/// function.
///
/// @see <https://developer.mozilla.org/en-US/docs/Web/API/Gamepad>
///
virtual void FireGamepadEvent(const GamepadEvent& evt) = 0;
///
/// Fire a gamepad axis event (to be called when an axis value is changed).
///
/// @note The gamepad should be connected via a previous call to FireGamepadEvent.
///
/// @see <https://developer.mozilla.org/en-US/docs/Web/API/Gamepad/axes>
///
virtual void FireGamepadAxisEvent(const GamepadAxisEvent& evt) = 0;
///
/// Fire a gamepad button event (to be called when a button value is changed).
///
/// @note The gamepad should be connected via a previous call to FireGamepadEvent.
///
/// @see <https://developer.mozilla.org/en-US/docs/Web/API/Gamepad/buttons>
///
virtual void FireGamepadButtonEvent(const GamepadButtonEvent& evt) = 0;
protected:
virtual ~Renderer();
};
} // namespace ultralight
+44
View File
@@ -0,0 +1,44 @@
/**************************************************************************************************
* This file is a part of Ultralight, an ultra-portable web-browser engine. *
* *
* See <https://ultralig.ht> for licensing and more. *
* *
* (C) 2024 Ultralight, Inc. *
**************************************************************************************************/
#pragma once
#include <Ultralight/Defines.h>
namespace ultralight {
///
/// Scroll event representing a change in scroll state.
///
/// @see View::FireScrollEvent
///
class ScrollEvent {
public:
///
/// The scroll event granularity type
///
enum Type {
kType_ScrollByPixel, ///< The delta value will be interpreted as number of pixels to scroll.
kType_ScrollByPage, ///< The delta value will be interpreted as number of pages to scroll.
};
///
/// Scroll granularity type
///
Type type;
///
/// Horizontal scroll amount
///
int delta_x;
///
/// Vertical scroll amount
///
int delta_y;
};
} // namespace ultralight
+59
View File
@@ -0,0 +1,59 @@
/**************************************************************************************************
* This file is a part of Ultralight, an ultra-portable web-browser engine. *
* *
* See <https://ultralig.ht> for licensing and more. *
* *
* (C) 2024 Ultralight, Inc. *
**************************************************************************************************/
#pragma once
#include <Ultralight/Defines.h>
#include <Ultralight/RefPtr.h>
#include <Ultralight/String.h>
namespace ultralight {
///
/// Storage for a browsing session (cookies, local storage, etc.).
///
/// This class stores data for a unique browsing session (cookies, local storage, application cache,
/// indexed db. etc.). You can create multiple sessions to isolate data between different browsing
/// contexts.
///
/// ## Default Session
///
/// The Renderer has a default session named "default" that is used if no session is specified when
/// when creating a View.
///
/// ## Session Lifetime
///
/// Sessions can be either temporary (in-memory only) or persistent (backed to disk).
///
/// @see Renderer::CreateSession
///
class UExport Session : public RefCounted {
public:
///
/// Whether or not this session is written to disk.
///
virtual bool is_persistent() const = 0;
///
/// A unique name identifying this session.
///
virtual String name() const = 0;
///
/// A unique numeric ID identifying this session.
///
virtual uint64_t id() const = 0;
///
/// The disk path of this session (only valid for persistent sessions).
///
virtual String disk_path() const = 0;
protected:
virtual ~Session();
};
} // namespace ultralight
+158
View File
@@ -0,0 +1,158 @@
/**************************************************************************************************
* This file is a part of Ultralight. *
* *
* See <https://ultralig.ht> for licensing and more. *
* *
* (C) 2024 Ultralight, Inc. *
**************************************************************************************************/
#pragma once
#include <Ultralight/Defines.h>
#include <Ultralight/String8.h>
#include <Ultralight/String16.h>
#include <Ultralight/String32.h>
namespace ultralight {
///
/// Unicode string container with conversions for UTF-8, UTF-16, and UTF-32.
///
/// This class is used to represent strings in Ultralight. It can be created from a variety of
/// string types and converted to a number of unicode string types.
///
/// ## Accessing string data
///
/// Strings are natively stored in a null-terminated UTF-8 format. You can access the UTF-8 bytes
/// using the `utf8()` method:
///
/// ```
/// String str("Hello, world!");
///
/// // Print the UTF-8 data (guaranteed to be null-terminated)
/// printf("%s\n", str.utf8().data());
/// ```
///
class UExport String {
public:
///
/// Create empty string
///
String();
///
/// Create from null-terminated, ASCII C-string
///
String(const char* str);
///
/// Create from raw, UTF-8 string with certain length
///
String(const char* str, size_t len);
///
/// Create from existing String8 (UTF-8).
///
String(const String8& str);
///
/// Create from raw UTF-16 string with certain length
///
String(const Char16* str, size_t len);
///
/// Create from existing String16 (UTF-16)
///
String(const String16& str);
///
/// Create from existing String32 (UTF-32)
///
String(const String32& str);
///
/// Copy constructor
///
String(const String& other);
///
/// Move constructor
///
String(String&& other);
///
/// Destructor
///
~String();
///
/// Assign string from another, copy is made
///
String& operator=(const String& other);
///
/// Move assignment operator
///
String& operator=(String&& other);
///
/// Append string with another
///
String& operator+=(const String& other);
///
/// Concatenation operator
///
inline friend String operator+(String lhs, const String& rhs) {
lhs += rhs;
return lhs;
}
///
/// Get native UTF-8 string
///
String8& utf8() { return str_; }
///
/// Get native UTF-8 string
///
const String8& utf8() const { return str_; }
///
/// Convert to UTF-16 string
///
String16 utf16() const;
///
/// Convert to UTF-32 string
///
String32 utf32() const;
///
/// Check if string is empty or not
///
bool empty() const { return str_.empty(); }
///
/// Hash function
///
size_t Hash() const;
///
/// Comparison operator
///
bool operator<(const String& other) const;
///
/// Equality operator
///
bool operator==(const String& other) const;
///
/// Inequality operator
///
bool operator!=(const String& other) const;
private:
String8 str_;
};
} // namespace ultralight
+152
View File
@@ -0,0 +1,152 @@
/**************************************************************************************************
* This file is a part of Ultralight. *
* *
* See <https://ultralig.ht> for licensing and more. *
* *
* (C) 2024 Ultralight, Inc. *
**************************************************************************************************/
#pragma once
#include <Ultralight/Defines.h>
#include <Ultralight/RefPtr.h>
#include <stddef.h>
namespace ultralight {
class String8;
class String32;
namespace detail {
template<int> struct selector;
template<> struct selector<4> { typedef char16_t Char16; };
template<> struct selector<2> { typedef wchar_t Char16; };
}
#ifdef DISABLE_NATIVE_WCHAR_T
// Force Char16 type to use char16_t, used on Windows when native wchar_t support is disabled.
typedef char16_t Char16;
#else
// We use wchar_t if size == 2, otherwise use char16_t
typedef detail::selector<sizeof(wchar_t)>::Char16 Char16;
#endif
///
/// A null-terminated UTF-16 string container.
///
class UExport String16 {
public:
// Native character type
typedef Char16 CharType;
// Make an empty String16
String16();
// Make a String16 from raw UTF-16 buffer with certain length
String16(const Char16* str, size_t len);
// Make a String16 from raw unsigned short UTF-16 buffer with certain length. Useful on Windows
// when native support for wchar_t is disabled (eg, /Zc:wchar_t-).
String16(const unsigned short* str, size_t len);
// Make a deep copy of String16
String16(const String16& other);
// Move constructor
String16(String16&& other);
// Destructor
~String16();
// Assign a String16 to this one, deep copy is made
String16& operator=(const String16& other);
// Move assignment operator
String16& operator=(String16&& other);
// Append a String16 to this one.
String16& operator+=(const String16& other);
// Concatenation operator
inline friend String16 operator+(String16 lhs, const String16& rhs) { lhs += rhs; return lhs; }
// Get raw UTF-16 data
Char16* data() { return data_; }
// Get raw UTF-16 data (const)
const Char16* data() const { return data_; }
// Get raw UTF-16 data as unsigned short. This is useful on Windows if you compile without native
// support for wchar_t (eg, /Zc:wchar_t-)
unsigned short* udata() { return reinterpret_cast<unsigned short*>(data_); }
// Get raw UTF-16 data as unsigned short (const).
const unsigned short* udata() const { return reinterpret_cast<const unsigned short*>(data_); }
// Get length in characters.
size_t length() const { return length_; }
// Get size in characters (synonym for length)
size_t size() const { return length_; }
// Get size in bytes
size_t sizeBytes() const { return length_ * sizeof(Char16); }
// Check if string is empty.
bool empty() const { return !data_ || length_ == 0; }
// Get character at specific position
Char16& operator[](size_t pos) { return data_[pos]; }
// Get character at specific position (const)
const Char16& operator[](size_t pos) const { return data_[pos]; }
// Get a UTF-8 copy of this string
String8 utf8() const;
// Get a UTF-32 copy of this string
String32 utf32() const;
// Hash function
size_t Hash() const;
// Comparison operator
bool operator<(const String16& other) const;
// Equality operator
bool operator==(const String16& other) const;
// Inequality operator
bool operator!=(const String16& other) const;
private:
Char16* data_;
size_t length_;
};
///
/// @brief A UTF-16 string vector.
///
class UExport String16Vector : public RefCounted {
public:
// Create an empty string vector
static RefPtr<String16Vector> Create();
// Create a string vector from an existing array (a deep copy is made)
static RefPtr<String16Vector> Create(const String16* stringArray, size_t len);
// Add an element to the back of the string vector
virtual void push_back(const String16& val) = 0;
// Get raw String16 vector array
virtual String16* data() = 0;
// Get the number of elements in vector
virtual size_t size() const = 0;
protected:
String16Vector();
virtual ~String16Vector();
String16Vector(const String16Vector&);
void operator=(const String16Vector&);
};
} // namespace ultralight
+99
View File
@@ -0,0 +1,99 @@
/**************************************************************************************************
* This file is a part of Ultralight. *
* *
* See <https://ultralig.ht> for licensing and more. *
* *
* (C) 2024 Ultralight, Inc. *
**************************************************************************************************/
#pragma once
#include <Ultralight/Defines.h>
#include <stddef.h>
namespace ultralight {
class String8;
class String16;
///
/// A null-terminated UTF-32 string container.
///
class UExport String32 {
public:
// Native character type
typedef char32_t CharType;
// Make an empty String32
String32();
// Make a String32 from raw UTF-32 string with certain length
String32(const char32_t* c_str, size_t len);
// Make a deep copy of String32
String32(const String32& other);
// Move constructor
String32(String32&& other);
// Destructor
~String32();
// Assign a String32 to this one, deep copy is made
String32& operator=(const String32& other);
// Move assignment operator
String32& operator=(String32&& other);
// Append a String32 to this one.
String32& operator+=(const String32& other);
// Concatenation operator
inline friend String32 operator+(String32 lhs, const String32& rhs) { lhs += rhs; return lhs; }
// Get raw UTF-32 data
char32_t* data() { return data_; }
// Get raw UTF-32 data (const)
const char32_t* data() const { return data_; }
// Get length in characters.
size_t length() const { return length_; }
// Get size in characters (synonym for length)
size_t size() const { return length_; }
// Get size in bytes
size_t sizeBytes() const { return length_ * sizeof(char32_t); }
// Check if string is empty.
bool empty() const { return !data_ || length_ == 0; }
// Get character at specific position
char32_t& operator[](size_t pos) { return data_[pos]; }
// Get character at specific position (const)
const char32_t& operator[](size_t pos) const { return data_[pos]; }
// Get a UTF-8 copy of this string
String8 utf8() const;
// Get a UTF-16 copy of this string
String16 utf16() const;
// Hash function
size_t Hash() const;
// Comparison operator
bool operator<(const String32& other) const;
// Equality operator
bool operator==(const String32& other) const;
// Inequality operator
bool operator!=(const String32& other) const;
private:
char32_t* data_;
size_t length_;
};
} // namespace ultralight
+102
View File
@@ -0,0 +1,102 @@
/**************************************************************************************************
* This file is a part of Ultralight. *
* *
* See <https://ultralig.ht> for licensing and more. *
* *
* (C) 2024 Ultralight, Inc. *
**************************************************************************************************/
#pragma once
#include <Ultralight/Defines.h>
#include <stddef.h>
namespace ultralight {
class String16;
class String32;
///
/// A null-terminated UTF-8 string container.
//
class UExport String8 {
public:
// Native character type
typedef char CharType;
// Make an empty String8
String8();
// Make a String8 from raw, null-terminated UTF-8 string
String8(const char* c_str);
// Make a String8 from raw UTF-8 string with certain length
String8(const char* c_str, size_t len);
// Make a deep copy of String8
String8(const String8& other);
// Move constructor
String8(String8&& other);
// Destructor
~String8();
// Assign a String8 to this one, deep copy is made
String8& operator=(const String8& other);
// Move assignment operator
String8& operator=(String8&& other);
// Append a String8 to this one.
String8& operator+=(const String8& other);
// Concatenation operator
inline friend String8 operator+(String8 lhs, const String8& rhs) { lhs += rhs; return lhs; }
// Get raw UTF-8 data
char* data() { return data_; }
// Get raw UTF-8 data (const)
const char* data() const { return data_; }
// Get length in characters.
size_t length() const { return length_; }
// Get size in characters (synonym for length)
size_t size() const { return length_; }
// Get size in bytes
size_t sizeBytes() const { return length_ * sizeof(char); }
// Check if string is empty.
bool empty() const { return !data_ || length_ == 0; }
// Get character at specific position
char& operator[](size_t pos) { return data_[pos]; }
// Get character at specific position (const)
const char& operator[](size_t pos) const { return data_[pos]; }
// Get a UTF-16 copy of this string
String16 utf16() const;
// Get a UTF-32 copy of this string
String32 utf32() const;
// Hash function
size_t Hash() const;
// Comparison operator
bool operator<(const String8& other) const;
// Equality operator
bool operator==(const String8& other) const;
// Inequality operator
bool operator!=(const String8& other) const;
private:
char* data_;
size_t length_;
};
} // namespace ultralight
+199
View File
@@ -0,0 +1,199 @@
/**************************************************************************************************
* This file is a part of Ultralight. *
* *
* See <https://ultralig.ht> for licensing and more. *
* *
* (C) 2024 Ultralight, Inc. *
**************************************************************************************************/
///
/// @file StringSTL.h
///
/// STL compatibility header for ultralight::String.
///
/// `#include <Ultralight/StringSTL.h>`
///
/// This optional header provides utility functions for converting between ultralight::String,
/// std::string, and std::string_view. It also provides support for using ultralight::String
/// with standard library containers and stream operators.
///
/// @pre This header requires C++17 or later.
///
/// ## Example
///
/// ```cpp
/// #include <Ultralight/StringSTL.h>
/// #include <string>
/// #include <iostream>
///
/// ultralight::String myStr("Hello, world!");
///
/// // Convert ultralight::String to std::string
/// std::string stdStr = ultralight::Convert(myStr);
///
/// // Convert std::string to ultralight::String
/// ultralight::String backToUl = ultralight::Convert(stdStr);
///
/// // Print ultralight::String to std::cout
/// std::cout << myStr << std::endl;
/// ```
///
#pragma once
#include <Ultralight/String.h>
#include <string>
#include <string_view>
#include <type_traits>
namespace ultralight {
///
/// Trait to check if a type is a supported string-like type.
///
template <typename T>
struct is_string_type : std::false_type {};
template <> struct is_string_type<String> : std::true_type {};
template <> struct is_string_type<std::string> : std::true_type {};
template <> struct is_string_type<std::string_view> : std::true_type {};
template <> struct is_string_type<const char*> : std::true_type {};
///
/// Convert between string types.
///
/// This function provides efficient conversion between different string types.
/// It supports ultralight::String, std::string, std::string_view, and const char*.
///
/// The following type conversions are automatically deduced (no template argument needed):
/// - ultralight::String -> std::string
/// - std::string -> ultralight::String
/// - std::string_view -> ultralight::String
/// - const char* -> ultralight::String
///
/// For explicit conversion to std::string_view, use Convert<std::string_view>().
///
/// @tparam To The target string type (optional, deduced in common cases)
/// @tparam From The source string type (optional)
///
/// @param from The string to convert
///
/// @return The converted string in the target type
///
/// ## Example
///
/// ```cpp
/// ultralight::String myStr("Hello, world!");
///
/// // ultralight::String -> std::string
/// std::string stdStr = ultralight::Convert(myStr);
///
/// // ultralight::String -> std::string_view
/// std::string_view svStr = ultralight::Convert<std::string_view>(myStr);
///
/// // std::string -> ultralight::String
/// ultralight::String backToUl = ultralight::Convert(stdStr);
///
/// // std::string_view -> ultralight::String
/// ultralight::String fromView = ultralight::Convert(std::string_view("View"));
/// ```
///
template <typename To = void, typename From>
auto Convert(const From& from) {
static_assert(is_string_type<std::remove_cv_t<std::remove_reference_t<From>>>::value,
"Convert only supports String, std::string, std::string_view, and const char*");
if constexpr (std::is_same_v<To, void>) {
// Automatic deduction
if constexpr (std::is_same_v<From, String>) {
return std::string(from.utf8().data(), from.utf8().length());
} else if constexpr (std::is_same_v<From, std::string> ||
std::is_same_v<From, std::string_view>) {
return String(from.data(), from.length());
} else if constexpr (std::is_same_v<From, const char*>) {
return String(from); // String constructor handles null-termination
} else {
// This case should never be reached due to the static_assert
return From{};
}
} else {
// Explicit conversion
static_assert(is_string_type<To>::value,
"Convert only supports String, std::string, std::string_view, and const char*");
if constexpr (std::is_same_v<To, From>) {
return from;
} else if constexpr (std::is_same_v<To, String>) {
if constexpr (std::is_same_v<From, const char*>) {
return String(from); // String constructor handles null-termination
} else {
return String(from.data(), from.length());
}
} else if constexpr (std::is_same_v<To, std::string>) {
if constexpr (std::is_same_v<From, String>) {
return std::string(from.utf8().data(), from.utf8().length());
} else if constexpr (std::is_same_v<From, const char*>) {
return std::string(from); // std::string constructor handles null-termination
} else {
return std::string(from);
}
} else if constexpr (std::is_same_v<To, std::string_view>) {
if constexpr (std::is_same_v<From, String>) {
return std::string_view(from.utf8().data(), from.utf8().length());
} else if constexpr (std::is_same_v<From, const char*>) {
return std::string_view(from); // std::string_view constructor handles null-termination
} else {
return std::string_view(from);
}
} else if constexpr (std::is_same_v<To, const char*>) {
static_assert(!std::is_same_v<To, const char*>,
"Direct conversion to const char* is not supported due to ownership issues. "
"Convert to String, std::string, or std::string_view instead.");
} else {
// This case should never be reached due to the static_assert
return To{};
}
}
}
} // namespace ultralight
namespace std {
///
/// Hash specialization for ultralight::String
///
template<>
struct hash<ultralight::String> {
size_t operator()(const ultralight::String& str) const {
return str.Hash();
}
};
} // namespace std
///
/// Stream output operator for ultralight::String.
///
/// @param os The output stream.
//
/// @param str The string to output.
///
/// @return The output stream.
///
inline std::ostream& operator<<(std::ostream& os, const ultralight::String& str) {
return os << ultralight::Convert<std::string_view>(str);
}
///
/// Stream input operator for ultralight::String.
///
/// @param is The input stream.
///
/// @param str The string to input into.
///
/// @return The input stream.
///
inline std::istream& operator>>(std::istream& is, ultralight::String& str) {
std::string temp;
is >> temp;
str = ultralight::Convert<ultralight::String>(temp);
return is;
}
+39
View File
@@ -0,0 +1,39 @@
/**************************************************************************************************
* This file is a part of Ultralight, an ultra-portable web-browser engine. *
* *
* See <https://ultralig.ht> for licensing and more. *
* *
* (C) 2024 Ultralight, Inc. *
**************************************************************************************************/
#pragma once
#include <Ultralight/Defines.h>
#include <Ultralight/RefPtr.h>
#include <Ultralight/String8.h>
#include <Ultralight/String16.h>
#include <Ultralight/String32.h>
#include <Ultralight/String.h>
#include <Ultralight/Bitmap.h>
#include <Ultralight/Buffer.h>
#include <Ultralight/View.h>
#include <Ultralight/Session.h>
#include <Ultralight/KeyCodes.h>
#include <Ultralight/KeyEvent.h>
#include <Ultralight/Listener.h>
#include <Ultralight/Matrix.h>
#include <Ultralight/MouseEvent.h>
#include <Ultralight/NetworkRequest.h>
#include <Ultralight/ConsoleMessage.h>
#include <Ultralight/Renderer.h>
#include <Ultralight/Geometry.h>
#include <Ultralight/RenderTarget.h>
#include <Ultralight/ImageSource.h>
#include <Ultralight/ScrollEvent.h>
#include <Ultralight/GamepadEvent.h>
#include <Ultralight/platform/Platform.h>
#include <Ultralight/platform/Config.h>
#include <Ultralight/platform/GPUDriver.h>
#include <Ultralight/platform/FileSystem.h>
#include <Ultralight/platform/FontLoader.h>
#include <Ultralight/platform/Surface.h>
#include <Ultralight/platform/Clipboard.h>
#include <Ultralight/platform/Logger.h>
+526
View File
@@ -0,0 +1,526 @@
/**************************************************************************************************
* This file is a part of Ultralight, an ultra-portable web-browser engine. *
* *
* See <https://ultralig.ht> for licensing and more. *
* *
* (C) 2025 Ultralight, Inc. *
**************************************************************************************************/
#pragma once
#include <Ultralight/Defines.h>
#include <Ultralight/RefPtr.h>
#include <Ultralight/KeyEvent.h>
#include <Ultralight/JavaScript.h>
#include <Ultralight/MouseEvent.h>
#include <Ultralight/ScrollEvent.h>
#include <Ultralight/GamepadEvent.h>
#include <Ultralight/RenderTarget.h>
#include <Ultralight/Bitmap.h>
#include <Ultralight/Listener.h>
#include <Ultralight/platform/Surface.h>
namespace ultralight {
///
/// View-specific configuration settings.
///
/// @see Renderer::CreateView
///
struct UExport ViewConfig {
///
/// A user-generated id for the display (monitor, TV, or screen) that this View will be shown on.
///
/// Animations are driven based on the physical refresh rate of the display. Multiple Views can
/// share the same display.
///
/// @note This is automatically managed for you when App::Create() is used.
///
/// @see Renderer::RefreshDisplay.
///
uint32_t display_id = 0;
///
/// Whether to render using the GPU renderer (accelerated) or the CPU renderer (unaccelerated).
///
/// When true, the View will be rendered to an offscreen GPU texture using the GPU driver set in
/// Platform::set_gpu_driver. You can fetch details for the texture via View::render_target.
///
/// When false (the default), the View will be rendered to an offscreen pixel buffer using the
/// multithreaded CPU renderer. This pixel buffer can optionally be provided by the user--
/// for more info see Platform::set_surface_factory and View::surface.
///
/// @note This is automatically managed for you when App::Create() is used.
///
bool is_accelerated = false;
///
/// The initial device scale, ie. the amount to scale page units to screen pixels. This should
/// be set to the scaling factor of the device that the View is displayed on.
///
/// @note 1.0 is equal to 100% zoom (no scaling), 2.0 is equal to 200% zoom (2x scaling)
///
/// @note This is automatically managed for you when App::Create() is used.
///
double initial_device_scale = 1.0;
///
/// Whether or not this View should support transparency.
///
/// @note Make sure to also set the following CSS on the page:
///
/// html, body { background: transparent; }
///
bool is_transparent = false;
///
/// Whether or not the View should initially have input focus, @see View::Focus()
///
bool initial_focus = true;
///
/// Whether or not images should be enabled.
///
bool enable_images = true;
///
/// Whether or not JavaScript should be enabled.
///
bool enable_javascript = true;
///
/// Whether or not compositing should be enabled.
///
bool enable_compositor = false;
///
/// Default font-family to use.
///
String font_family_standard = "Times New Roman";
///
/// Default font-family to use for fixed fonts. (pre/code)
///
String font_family_fixed = "Courier New";
///
/// Default font-family to use for serif fonts.
///
String font_family_serif = "Times New Roman";
///
/// Default font-family to use for sans-serif fonts.
///
String font_family_sans_serif = "Arial";
///
/// Custom user-agent string. You can use this to override the default user-agent string.
///
/// @pre This feature is only available in Ultralight Pro edition and above.
///
String user_agent = ULTRALIGHT_USER_AGENT;
};
///
/// Web-page container rendered to an offscreen surface.
///
/// The View class is responsible for loading and rendering web-pages to an offscreen surface. It
/// is completely isolated from the OS windowing system, you must forward all input events to it
/// from your application.
///
/// ## Creating a View
///
/// You can create a View using Renderer::CreateView.
///
/// ```
/// // Create a ViewConfig with the desired settings
/// ViewConfig view_config;
///
/// // Create a View, 500 by 500 pixels in size, using the default Session
/// RefPtr<View> view = renderer->CreateView(500, 500, view_config, nullptr);
/// ```
///
/// @note When using App::Create, the library will automatically create a View for you when you
/// call Overlay::Create.
///
/// ## Loading Content into a View
///
/// You can load content asynchronously into a View using View::LoadURL().
///
/// ```
/// // Load a URL into the View
/// view->LoadURL("https://en.wikipedia.org/wiki/Main_Page");
/// ```
///
/// ### Local File URLs
///
/// Local file URLs (eg, `file:///page.html`) will be loaded via FileSystem. You can provide your
/// own FileSystem implementation so these files can be loaded from your application's resources.
///
/// ### Displaying Views in Your Application
///
/// Views are rendered either to a pixel-buffer (View::surface) or a GPU texture
/// (View::render_target) depending on whether CPU or GPU rendering is used (see
/// ViewConfig::is_accelerated).
///
/// You can use the Surface or RenderTarget to display the View in your application.
///
/// ```
/// // Get the Surface for the View (assuming CPU rendering)
/// Surface* surface = view->surface();
///
/// // Check if the Surface is dirty (pixels have changed)
/// if (!surface->dirty_bounds().IsEmpty()) {
/// // Cast to the default Surface implementation (BitmapSurface) and get
/// // the underlying Bitmap.
/// RefPtr<Bitmap> bitmap = static_cast<BitmapSurface*>(surface)->bitmap();
///
/// // Use the bitmap pixels here...
///
/// // Clear the dirty bounds after you're done displaying the pixels
/// surface->ClearDirtyBounds();
/// }
/// ```
///
/// ## Input Events
///
/// You must forward all input events to the View from your application. This includes keyboard,
/// mouse, and scroll events.
///
/// ```
/// // Forward a mouse-move event to the View
/// MouseEvent evt;
/// evt.type = MouseEvent::kType_MouseMoved;
/// evt.x = 100;
/// evt.y = 100;
/// evt.button = MouseEvent::kButton_None;
/// view->FireMouseEvent(evt);
/// ```
///
/// @note The View API is not thread-safe, all calls must be made on the same thread that the
/// Renderer or App was created on.
///
class UExport View : public RefCounted {
public:
///
/// Get the URL of the current page loaded into this View, if any.
///
virtual String url() = 0;
///
/// Get the title of the current page loaded into this View, if any.
///
virtual String title() = 0;
///
/// Get the width of the View, in pixels.
///
virtual uint32_t width() const = 0;
///
/// Get the height of the View, in pixels.
///
virtual uint32_t height() const = 0;
///
/// Get the display id of the View.
///
/// @see ViewConfig::display_id
///
virtual uint32_t display_id() const = 0;
///
/// Set the display id of the View.
///
/// This should be called when the View is moved to another display.
///
virtual void set_display_id(uint32_t id) = 0;
///
/// Get the device scale, ie. the amount to scale page units to screen pixels.
///
/// For example, a value of 1.0 is equivalent to 100% zoom. A value of 2.0 is 200% zoom.
///
virtual double device_scale() const = 0;
///
/// Set the device scale.
///
virtual void set_device_scale(double scale) = 0;
///
/// Whether or not the View is GPU-accelerated. If this is false, the page will be rendered
/// via the CPU renderer.
///
virtual bool is_accelerated() const = 0;
///
/// Whether or not the View supports transparent backgrounds.
///
virtual bool is_transparent() const = 0;
///
/// Check if the main frame of the page is currently loading.
///
virtual bool is_loading() = 0;
///
/// Get the RenderTarget for the View.
///
/// @pre Only valid if this View is using the GPU renderer (see ViewConfig::is_accelerated).
///
/// @note You can use this with your GPUDriver implementation to bind and display the
/// corresponding texture in your application.
///
virtual RenderTarget render_target() = 0;
///
/// Get the Surface for the View (native pixel buffer that the CPU renderer draws into).
///
/// @pre This operation is only valid if the View is using the CPU renderer, (eg, it is
/// **not** GPU accelerated, see ViewConfig::is_accelerated). This function will return
/// return nullptr if the View is using the GPU renderer.
///
/// @note The default Surface is BitmapSurface but you can provide your own Surface
/// implementation via Platform::set_surface_factory().
///
virtual Surface* surface() = 0;
///
/// Load a raw string of HTML, the View will navigate to it as a new page.
///
/// @param html The raw HTML string to load.
///
/// @param url An optional URL for this load (to make it appear as if we we loaded this HTML
/// from a certain URL). Can be used for resolving relative URLs and cross-origin
/// rules.
///
/// @param add_to_history Whether or not this load should be added to the session's history
/// (eg, the back/forward list).
///
virtual void LoadHTML(const String& html, const String& url = "", bool add_to_history = false)
= 0;
///
/// Load a URL, the View will navigate to it as a new page.
///
/// @note You can use File URLs (eg, file:///page.html) but you must define your own FileSystem
/// implementation if you are not using AppCore. @see Platform::set_file_system
///
virtual void LoadURL(const String& url) = 0;
///
/// Resize View to a certain size.
///
/// @param width The initial width, in pixels.
///
/// @param height The initial height, in pixels.
///
///
virtual void Resize(uint32_t width, uint32_t height) = 0;
///
/// Acquire the page's JSContext for use with the JavaScriptCore API
///
/// @note You can use the underlying JSContextRef with the JavaScriptCore C API. This allows you
/// to marshall C/C++ objects to/from JavaScript, bind callbacks, and call JS functions
/// directly.
///
/// @note The JSContextRef gets reset after each page navigation. You should initialize your
/// JavaScript state within the OnWindowObjectReady and OnDOMReady events,
/// @see ViewListener.
///
/// @note This call locks the internal context for the current thread. It will be unlocked when
/// the returned JSContext's ref-count goes to zero. The lock is recursive, you can call
/// this multiple times.
///
virtual RefPtr<JSContext> LockJSContext() = 0;
///
/// Get a handle to the internal JavaScriptCore VM.
///
virtual void* JavaScriptVM() = 0;
///
/// Helper function to evaluate a raw string of JavaScript and return the result as a String.
///
/// @param script A string of JavaScript to evaluate in the main frame.
///
/// @param exception A string to store the exception in, if any. Pass a nullptr if you don't
/// care about exceptions.
///
/// @return Returns the JavaScript result typecast to a String.
///
///
/// @note You do not need to lock the JS context, it is done automatically.
///
/// @note If you need lower-level access to native JavaScript values, you should instead lock
/// the JS context and call JSEvaluateScript() in the JavaScriptCore C API.
/// @see <JavaScriptCore/JSBase.h>
///
virtual String EvaluateScript(const String& script, String* exception = nullptr) = 0;
///
/// Whether or not we can navigate backwards in history
///
virtual bool CanGoBack() = 0;
///
/// Whether or not we can navigate forwards in history
///
virtual bool CanGoForward() = 0;
///
/// Navigate backwards in history
///
virtual void GoBack() = 0;
///
/// Navigate forwards in history
///
virtual void GoForward() = 0;
///
/// Navigate to an arbitrary offset in history
///
virtual void GoToHistoryOffset(int offset) = 0;
///
/// Reload current page
///
virtual void Reload() = 0;
///
/// Stop all page loads
///
virtual void Stop() = 0;
///
/// Give focus to the View.
///
/// You should call this to give visual indication that the View has input focus (changes active
/// text selection colors, for example).
///
virtual void Focus() = 0;
///
/// Remove focus from the View and unfocus any focused input elements.
///
/// You should call this to give visual indication that the View has lost input focus.
///
virtual void Unfocus() = 0;
///
/// Whether or not the View has focus.
///
virtual bool HasFocus() = 0;
///
/// Whether or not the View has an input element with visible keyboard focus (indicated by a
/// blinking caret).
///
/// You can use this to decide whether or not the View should consume keyboard input events
/// (useful in games with mixed UI and key handling).
///
virtual bool HasInputFocus() = 0;
///
/// Fire a keyboard event
///
/// @note Only 'Char' events actually generate text in input fields.
///
virtual void FireKeyEvent(const KeyEvent& evt) = 0;
///
/// Fire a mouse event
///
virtual void FireMouseEvent(const MouseEvent& evt) = 0;
///
/// Fire a scroll event
///
virtual void FireScrollEvent(const ScrollEvent& evt) = 0;
///
/// Set a ViewListener to receive callbacks for View-related events.
///
/// @note Ownership remains with the caller.
///
virtual void set_view_listener(ViewListener* listener) = 0;
///
/// Get the active ViewListener, if any
///
virtual ViewListener* view_listener() const = 0;
///
/// Set a LoadListener to receive callbacks for Load-related events.
///
/// @note Ownership remains with the caller.
///
virtual void set_load_listener(LoadListener* listener) = 0;
///
/// Get the active LoadListener, if any
///
virtual LoadListener* load_listener() const = 0;
///
/// Set a DownloadListener to receive callbacks for download-related events.
///
/// @note Ownership remains with the caller.
///
virtual void set_download_listener(DownloadListener* listener) = 0;
///
/// Get the active DownloadListener, if any
///
virtual DownloadListener* download_listener() const = 0;
///
/// Cancel an active download.
///
virtual void CancelDownload(DownloadId id) = 0;
///
/// Set a NetworkListener to receive callbacks for network-related events.
///
/// @note Ownership remains with the caller.
///
virtual void set_network_listener(NetworkListener* listener) = 0;
///
/// Get the active NetworkListener, if any
///
virtual NetworkListener* network_listener() const = 0;
///
/// Set whether or not this View should be repainted during the next call to Renderer::Render
///
/// @note This flag is automatically set whenever the page content changes but you can set it
/// directly in case you need to force a repaint.
///
virtual void set_needs_paint(bool needs_paint) = 0;
///
/// Whether or not this View should be repainted during the next call to
/// Renderer::Render.
///
virtual bool needs_paint() const = 0;
///
/// Create an Inspector View to inspect / debug this View locally.
///
/// This will only succeed if you have the inspector assets in your filesystem-- the inspector
/// will look for file:///inspector/Main.html when it first loads.
///
/// You must handle ViewListener::OnCreateInspectorView so that the library has a View to display
/// the inspector in. This function will call this event only if an inspector view is not
/// currently active.
///
virtual void CreateLocalInspectorView() = 0;
protected:
virtual ~View();
};
} // namespace ultralight
+106
View File
@@ -0,0 +1,106 @@
/**************************************************************************************************
* This file is a part of Ultralight. *
* *
* See <https://ultralig.ht> for licensing and more. *
* *
* (C) 2024 Ultralight, Inc. *
**************************************************************************************************/
#ifndef ULTRALIGHT_ALLOCATOR_H
#define ULTRALIGHT_ALLOCATOR_H
#include <stddef.h>
#include <stdbool.h>
#include <Ultralight/Exports.h>
#ifdef __cplusplus
extern "C" {
#endif
///
/// User-defined allocator interface.
///
/// @pre This API is only available in the Pro edition when the UL_ENABLE_ALLOCATOR_OVERRIDE
/// build option is enabled.
///
/// The library uses this to allocate memory. You can override the default allocator functions
/// by setting the ulAllocator object with your own functions.
///
/// This should be done before calling any other library functions.
///
/// @see ulAllocator
///
typedef struct {
//
// Allocate a block of memory of at least |bytes| size.
//
void* (*malloc)(size_t bytes);
//
// Reallocate a block of memory to at least |bytes| size.
//
void* (*realloc)(void* address, size_t bytes);
//
// Free a block of memory allocated with malloc or realloc.
//
void (*free)(void* address);
//
// Allocate a block of memory of at least |bytes| size, aligned to |alignment|.
//
void* (*aligned_malloc)(size_t bytes, size_t alignment);
//
// Reallocate a block of memory to at least |bytes| size, aligned to |alignment|.
//
void* (*aligned_realloc)(void* address, size_t bytes, size_t alignment);
//
// Free a block of memory allocated with aligned_malloc or aligned_realloc.
//
void (*aligned_free)(void* address);
//
// Get the size of the memory block that backs the allocation at |address|. The memory
// block size is always at least as large as the allocation it backs, and may be larger.
// * Windows equivalent: _msize
// * POSIX equivalent: malloc_size
//
size_t (*get_size_estimate)(void* address);
} ULAllocator;
///
/// Get the allocator interface object for the library.
///
/// @pre This API is only available in the Pro edition when the UL_ENABLE_ALLOCATOR_OVERRIDE
/// build option is enabled.
///
/// The C functions set in this object will be used for allocating memory inside the library
/// when the `UL_ENABLE_ALLOCATOR_OVERRIDE` build option is enabled.
///
/// Default functions are already set for all of these but you can override them with your own.
///
/// Platform specific notes:
/// * __Windows__: The default functions use `HeapAlloc` / `HeapReAlloc` / `HeapFree`.
///
extern UCExport ULAllocator ulAllocator;
#ifdef _WIN32
///
/// Get the handle to the private heap used by the library.
///
/// This is the handle returned by `HeapCreate()`, you should destroy it after unloading the library
/// by calling `HeapDestroy()`.
///
/// This is only valid if the UL_ENABLE_ALLOCATOR_OVERRIDE build option is enabled and the default
/// functions are set in the ulAllocator object.
///
UCExport void* ulGetHeapHandle();
#endif
#ifdef __cplusplus
}
#endif
#endif // ULTRALIGHT_ALLOCATOR_H
+49
View File
@@ -0,0 +1,49 @@
/**************************************************************************************************
* This file is a part of Ultralight. *
* *
* See <https://ultralig.ht> for licensing and more. *
* *
* (C) 2024 Ultralight, Inc. *
**************************************************************************************************/
#pragma once
#include <Ultralight/Defines.h>
#include <Ultralight/String.h>
namespace ultralight {
///
/// User-defined clipboard interface.
///
/// The library uses this to read and write data to the system's clipboard.
///
/// AppCore automatically provides a platform-specific implementation of this that cuts, copies,
/// and pastes to the OS clipboard when you call App::Create().
///
/// If you are using Renderer::Create() instead of App::Create(), you will need to provide your own
/// implementation of this. @see Platform::set_clipboard().
///
class UExport Clipboard {
public:
virtual ~Clipboard();
///
/// Clear the clipboard.
///
virtual void Clear() = 0;
///
/// Read plain text from the clipboard
///
/// This is called when the library wants to read text from the OS clipboard.
///
virtual String ReadPlainText() = 0;
///
/// Write plain text to the clipboard.
///
/// This is called when the library wants to write text to the OS clipboard.
///
virtual void WritePlainText(const String& text) = 0;
};
} // namespace ultralight
+274
View File
@@ -0,0 +1,274 @@
/**************************************************************************************************
* This file is a part of Ultralight. *
* *
* See <https://ultralig.ht> for licensing and more. *
* *
* (C) 2025 Ultralight, Inc. *
**************************************************************************************************/
#pragma once
#include <Ultralight/Defines.h>
#include <Ultralight/String.h>
namespace ultralight {
///
/// The winding order for front-facing triangles. (Only used when the GPU renderer is used)
///
enum class FaceWinding : uint8_t {
///
/// Clockwise Winding (Direct3D, etc.)
///
Clockwise,
///
/// Counter-Clockwise Winding (OpenGL, etc.)
///
CounterClockwise,
};
enum class FontHinting : uint8_t {
///
/// Lighter hinting algorithm-- glyphs are slightly fuzzier but better resemble their original
/// shape. This is achieved by snapping glyphs to the pixel grid only vertically which better
/// preserves inter-glyph spacing.
///
Smooth,
///
/// Default hinting algorithm-- offers a good balance between sharpness and shape at smaller font
/// sizes.
///
Normal,
///
/// Strongest hinting algorithm-- outputs only black/white glyphs. The result is usually
/// unpleasant if the underlying TTF does not contain hints for this type of rendering.
///
Monochrome,
///
/// No hinting is performed-- fonts may be blurry at smaller font sizes.
///
None,
};
enum class EffectQuality : uint8_t {
///
/// Fastest effect quality-- uses the lowest quality effects (half-resolution, fewer passes, etc.)
///
Low,
///
/// Default effect quality-- strikes a good balance between quality and performance.
///
Medium,
///
/// Highest effect quality-- favors quality over performance.
///
High,
};
///
/// Core configuration for the renderer.
///
/// These are various configuration options that can be used to customize the behavior of the
/// library. These options can only be set once before creating the Renderer.
///
/// ## Setting the Config
///
/// You should create an instance of the Config struct, set its members, and then call
/// Platform::set_config() before creating the Renderer at the beginning of your
/// application's lifetime.
///
/// @par Example usage
/// ```
/// Config config;
/// config.user_stylesheet = "body { background: purple; }";
///
/// Platform::instance().set_config(config);
/// // (Setup other Platform interfaces here.)
///
/// auto renderer = Renderer::Create();
/// ```
///
struct UExport Config {
///
/// A writable OS file path to store persistent Session data in.
///
/// This data may include cookies, cached network resources, indexed DB, etc.
///
/// @note Files are only written to the path when using a persistent Session.
///
/// @see Renderer::CreateSession()
///
String cache_path;
///
/// The relative path to the resources folder (loaded via the FileSystem API).
///
/// The library loads certain resources (SSL certs, ICU data, etc.) from the FileSystem API
/// during runtime (eg, `file:///resources/cacert.pem`).
///
/// You can customize the relative file path to the resources folder by modifying this setting.
///
/// @see FileSystem
///
String resource_path_prefix = "resources/";
///
/// The winding order for front-facing triangles.
///
/// @pre Only used when GPU rendering is enabled for the View.
///
/// @see FaceWinding
///
FaceWinding face_winding = FaceWinding::CounterClockwise;
///
/// The hinting algorithm to use when rendering fonts.
///
/// @see FontHinting
///
FontHinting font_hinting = FontHinting::Normal;
///
/// The gamma to use when compositing font glyphs.
///
/// You can change this value to adjust font contrast (Adobe and Apple prefer 1.8).
///
double font_gamma = 1.8;
///
/// Global user-defined CSS string (included before any CSS on the page).
///
/// You can use this to override default styles for various elements on the page.
///
/// @note This is an actual string of CSS, not a file path.
///
String user_stylesheet;
///
/// Whether or not to continuously repaint any Views, regardless if they are dirty.
///
/// This is mainly used to diagnose painting/shader issues and profile performance.
///
bool force_repaint = false;
///
/// The delay (in seconds) between every tick of a CSS animation. (Default: 60 FPS)
///
double animation_timer_delay = 1.0 / 60.0;
///
/// The delay (in seconds) between every tick of a smooth scroll animation. (Default: 60 FPS)
///
double scroll_timer_delay = 1.0 / 60.0;
///
/// The delay (in seconds) between every call to the recycler.
///
/// The library attempts to reclaim excess memory during calls to the internal recycler. You can
/// change how often this is run by modifying this value.
///
double recycle_delay = 4.0;
///
/// The size of WebCore's memory cache in bytes.
///
/// @note You should increase this if you anticipate handling pages with large resources, Safari
/// typically uses 128+ MiB for its cache.
///
uint32_t memory_cache_size = 64 * 1024 * 1024;
///
/// The number of pages to keep in the cache. (Default: 0, none)
///
/// @note
/// \parblock
///
/// Safari typically caches about 5 pages and maintains an on-disk cache to support typical
/// web-browsing activities.
///
/// If you increase this, you should probably increase the memory cache size as well.
///
/// \endparblock
///
uint32_t page_cache_size = 0;
///
/// The system's physical RAM size in bytes.
///
/// JavaScriptCore tries to detect the system's physical RAM size to set reasonable allocation
/// limits. Set this to anything other than 0 to override the detected value. Size is in bytes.
///
/// This can be used to force JavaScriptCore to be more conservative with its allocation strategy
/// (at the cost of some performance).
///
uint32_t override_ram_size = 0;
///
/// The minimum size of large VM heaps in JavaScriptCore.
///
/// Set this to a lower value to make these heaps start with a smaller initial value.
///
uint32_t min_large_heap_size = 32 * 1024 * 1024;
///
/// The minimum size of small VM heaps in JavaScriptCore.
///
/// Set this to a lower value to make these heaps start with a smaller initial value.
///
uint32_t min_small_heap_size = 1 * 1024 * 1024;
///
/// The number of threads to use in the Renderer (for parallel painting on the CPU, etc.).
///
/// You can set this to a certain number to limit the number of threads to spawn.
///
/// @note
/// \parblock
///
/// If this value is 0, the number of threads will be determined at runtime using the following
/// formula:
///
/// ```
/// max(PhysicalProcessorCount() - 1, 1)
/// ```
///
/// \endparblock
///
uint32_t num_renderer_threads = 0;
///
/// The max amount of time (in seconds) to allow repeating timers to run during each call to
/// Renderer::Update.
///
/// The library will attempt to throttle timers if this time budget is exceeded.
///
double max_update_time = 1.0 / 200.0;
///
/// The alignment (in bytes) of the BitmapSurface when using the CPU renderer.
///
/// The underlying bitmap associated with each BitmapSurface will have row_bytes padded to reach
/// this alignment.
///
/// Aligning the bitmap helps improve performance when using the CPU renderer. Determining the
/// proper value to use depends on the CPU architecture and max SIMD instruction set used.
///
/// We generally target the 128-bit SSE2 instruction set across most PC platforms so '16' is
/// a safe value to use.
///
/// You can set this to '0' to perform no padding (row_bytes will always be width * 4) at a
/// slight cost to performance.
///
uint32_t bitmap_alignment = 16;
///
/// The quality of effects (blurs, CSS filters, SVG filters, etc.) to use when rendering.
///
EffectQuality effect_quality = EffectQuality::Medium;
};
} // namespace ultralight
+105
View File
@@ -0,0 +1,105 @@
/**************************************************************************************************
* This file is a part of Ultralight. *
* *
* See <https://ultralig.ht> for licensing and more. *
* *
* (C) 2024 Ultralight, Inc. *
**************************************************************************************************/
#pragma once
#include <Ultralight/Defines.h>
#include <Ultralight/String.h>
#include <Ultralight/Buffer.h>
namespace ultralight {
///
/// User-defined file system interface.
///
/// The library uses this to load file data (ie, raw file bytes) for a given file URL
/// (eg, `file:///page.html`) .
///
/// You can provide the library with your own FileSystem implementation so that file data is
/// provided directly by your application (eg, from memory, from a virtual file system, etc).
///
/// ## Default Implementation
///
/// A platform-specific implementation of FileSystem is provided for you when you call
/// App::Create().
///
/// If you are using Renderer::Create(), you **must** provide your own. You can still use AppCore's
/// implementation however-- see the helper functions defined in <AppCore/Platform.h>.
///
/// ## Setting the File System
///
/// To provide your own custom FileSystem implementation, you should inherit from this class,
/// handle the virtual member functions, and then pass an instance of your class to
/// Platform::set_file_system() before calling Renderer::Create() or App::Create().
///
class UExport FileSystem {
public:
virtual ~FileSystem();
///
/// Check if a file exists within the file system.
///
/// @param file_path Relative file path (the string following the file:/// prefix)
///
/// @return Returns whether or not a file exists at the path specified.
///
virtual bool FileExists(const String& file_path) = 0;
///
/// Get the mime-type of a file (eg "text/html").
///
/// This is usually determined by analyzing the file extension.
///
/// If a mime-type cannot be determined, this should return "application/unknown".
///
/// @param file_path Relative file path (the string following the file:/// prefix)
///
/// @return Returns whether or not a file exists at the path specified.
///
virtual String GetFileMimeType(const String& file_path) = 0;
///
/// Get the charset / encoding of a file (eg "utf-8", "iso-8859-1").
///
/// @note This is only applicable for text-based files (eg, "text/html", "text/plain") and is
/// usually determined by analyzing the contents of the file.
///
/// @param file_path Relative file path (the string following the file:/// prefix)
///
/// @return Returns the charset of the specified file. If a charset cannot be determined, a safe
/// default to return is "utf-8".
///
virtual String GetFileCharset(const String& file_path) = 0;
///
/// Open a file for reading and map it to a Buffer.
///
/// To minimize copies, you should map the requested file into memory and use Buffer::Create()
/// to wrap the data pointer (unmapping should be performed in the destruction callback).
///
/// @note
/// \parblock
/// File data addresses returned from this function should generally be aligned to 16-byte
/// boundaries (the default alignment on most operating systems-- if you're using C stdlib or
/// C++ STL functions this is already handled for you).
///
/// This requirement is currently necessary when loading the ICU data file (eg, icudt67l.dat),
/// and may be relaxed for other files (but you may still see a performance benefit due to cache
/// line alignment).
///
/// If you can't guarantee alignment or are unsure, you can use Buffer::CreateFromCopy to copy
/// the file data content to an aligned block (at the expense of data duplication).
/// \endparblock
///
/// @param file_path Relative file path (the string following the file:/// prefix)
///
/// @return If the file was able to be opened, this returns a Buffer object representing the
/// contents of the file. If the file was unable to be opened, you should return nullptr.
///
virtual RefPtr<Buffer> OpenFile(const String& file_path) = 0;
};
} // namespace ultralight
+129
View File
@@ -0,0 +1,129 @@
/**************************************************************************************************
* This file is a part of Ultralight. *
* *
* See <https://ultralig.ht> for licensing and more. *
* *
* (C) 2024 Ultralight, Inc. *
**************************************************************************************************/
#pragma once
#include <Ultralight/Defines.h>
#include <Ultralight/String.h>
#include <Ultralight/Buffer.h>
namespace ultralight {
///
/// Represents a font file, either on-disk path or in-memory file contents.
///
class UExport FontFile : public RefCounted {
public:
///
/// Create a font file from an on-disk file path.
///
/// @note The file path should already exist.
///
static RefPtr<FontFile> Create(const String& filepath);
///
/// Create a font file from an in-memory buffer.
///
static RefPtr<FontFile> Create(RefPtr<Buffer> buffer);
///
/// Whether or not this font file was created from an in-memory buffer.
///
virtual bool is_in_memory() const = 0;
///
/// The file path (if any).
///
virtual String filepath() const = 0;
///
/// The in-memory buffer (if any).
///
virtual RefPtr<Buffer> buffer() const = 0;
///
/// Unique hash (if this is a filepath, only the path string is hashed).
///
virtual uint32_t hash() const = 0;
protected:
FontFile();
virtual ~FontFile();
FontFile(const FontFile&);
void operator=(const FontFile&);
};
///
/// User-defined font loader interface.
///
/// The library uses this to load a font file (eg, `Arial.ttf`) for a given font description (eg,
/// `font-family: Arial;`).
///
/// Every OS has its own library of installed system fonts. The FontLoader interface is used to
/// lookup these fonts and fetch the actual font data (raw TTF/OTF file data) for a given font
/// description.
///
/// You can provide the library with your own font loader implementation so that you can bundle
/// fonts with your application rather than relying on the system's installed fonts.
///
/// ## Default Implementation
///
/// A platform-specific implementation of FontLoader is provided for you when you call
/// App::Create().
///
/// If you are using Renderer::Create(), you **must** provide your own. You can still use AppCore's
/// implementation however-- see the helper functions defined in <AppCore/Platform.h>.
///
/// ## Setting the Font Loader
///
/// To provide your own custom FontLoader implementation, you should inherit from this class,
/// handle the virtual member functions, and then pass an instance of your class to
/// Platform::set_font_loader() before calling Renderer::Create() or App::Create().
///
class UExport FontLoader {
public:
virtual ~FontLoader();
///
/// Fallback font family name. Will be used if all other fonts fail to load.
///
/// @note This font should be guaranteed to exist (eg, FontLoader::Load won't fail when passed
/// this font family name).
///
virtual String fallback_font() const = 0;
///
/// Fallback font family name that can render the specified characters. Mainly used to support
/// CJK (Chinese, Japanese, Korean) text display.
///
/// @param characters One or more UTF-16 characters. This is almost always a single character.
///
/// @param weight Font weight.
///
/// @param italic Whether or not italic is requested.
///
/// @return Returns a font family name that can render the text.
///
virtual String fallback_font_for_characters(const String& characters, int weight,
bool italic) const = 0;
///
/// Get the actual font file data (TTF/OTF) for a given font description.
///
/// @param family Font family name.
///
/// @param weight Font weight.
///
/// @param italic Whether or not italic is requested.
///
/// @return A font file matching the given description (either an on-disk font filepath or an
/// in-memory file contents). You can return NULL here and the loader will fallback to
/// another font.
///
virtual RefPtr<FontFile> Load(const String& family, int weight, bool italic) = 0;
};
} // namespace ultralight
+436
View File
@@ -0,0 +1,436 @@
/**************************************************************************************************
* This file is a part of Ultralight. *
* *
* See <https://ultralig.ht> for licensing and more. *
* *
* (C) 2024 Ultralight, Inc. *
**************************************************************************************************/
// clang-format off
#pragma once
#pragma warning(disable : 4251)
#include <Ultralight/Defines.h>
#include <Ultralight/Geometry.h>
#include <Ultralight/Matrix.h>
#include <Ultralight/Bitmap.h>
namespace ultralight {
/// \cond ignore
/// This pragma pack(push, 1) command is important!
/// GPU structs should not be padded with any bytes.
/// \endcond
#pragma pack(push, 1)
///
/// Render buffer description.
///
/// This structure describes a render buffer that can be used as a target for drawing commands.
///
/// @see GPUDriver::CreateRenderBuffer.
///
struct UExport RenderBuffer {
uint32_t texture_id; ///< The backing texture for this RenderBuffer
uint32_t width; ///< The width of the RenderBuffer texture
uint32_t height; ///< The height of the RenderBuffer texture
bool has_stencil_buffer; ///< Currently unused, always false.
bool has_depth_buffer; ///< Currently unsued, always false.
};
///
/// Vertex layout for path vertices.
///
/// This struct is the in-memory layout for each path vertex (useful for synthesizing or modifying
/// your own vertex data).
///
struct Vertex_2f_4ub_2f {
float pos[2];
unsigned char color[4];
float obj[2];
};
///
/// Vertex layout for quad vertices.
///
/// This struct is the in-memory layout for each quad vertex (useful for synthesizing or modifying
/// your own vertex data).
///
struct Vertex_2f_4ub_2f_2f_28f {
float pos[2];
unsigned char color[4];
float tex[2];
float obj[2];
float data0[4];
float data1[4];
float data2[4];
float data3[4];
float data4[4];
float data5[4];
float data6[4];
};
///
/// Vertex buffer formats.
///
/// This enumeration describes the format of a vertex buffer.
///
/// @note Identifiers start with an underscore due to C++ naming rules.
///
/// @see VertexBuffer
///
enum class VertexBufferFormat : uint8_t {
_2f_4ub_2f, ///< Vertex_2f_4ub_2f (used for path rendering)
_2f_4ub_2f_2f_28f, ///< Vertex_2f_4ub_2f_2f_28f (used for quad rendering)
};
///
/// Vertex buffer description.
///
/// @see GPUDriver::CreateGeometry
///
struct UExport VertexBuffer {
VertexBufferFormat format; ///< The format of the vertex buffer.
uint32_t size; ///< The size of the vertex buffer in bytes.
uint8_t* data; ///< The raw vertex buffer data.
};
///
/// Vertex index type.
///
typedef uint32_t IndexType;
///
/// Index buffer description.
///
/// This structure describes an index buffer that can be used to index into a vertex buffer.
///
/// @note The index buffer is a simple array of IndexType values.
///
/// @see GPUDriver::CreateGeometry
///
struct UExport IndexBuffer {
uint32_t size; ///< The size of the index buffer in bytes.
uint8_t* data; ///< The raw index buffer data.
};
///
/// Shader program types.
///
/// Each of these correspond to a vertex/pixel shader pair. You can find stock shader code for
/// these in the `shaders` folder of the AppCore repo.
///
/// @see GPUState::shader_type
///
enum class ShaderType : uint8_t {
Fill, ///< Shader program for filling quad geometry.
FillPath, ///< Shader program for filling tesselated path geometry.
};
///
/// The state of the GPU for a given draw command.
///
/// This structure describes the current state of the GPU for a given draw command.
///
/// @see Command::gpu_state
///
struct UExport GPUState {
/// Viewport width in pixels
uint32_t viewport_width;
/// Viewport height in pixels
uint32_t viewport_height;
/// Transform matrix-- you should multiply this with the screen-space orthographic projection
/// matrix then pass to the vertex shader.
Matrix4x4 transform;
/// Whether or not we should enable texturing for the current draw command.
bool enable_texturing;
/// Whether or not we should enable blending for the current draw command. If blending is
/// disabled, any drawn pixels should overwrite existing. This is mainly used so we can modify
/// alpha values of the RenderBuffer during scissored clears.
bool enable_blend;
/// The vertex/pixel shader program pair to use for the current draw command.
ShaderType shader_type;
/// The render buffer to use for the current draw command.
uint32_t render_buffer_id;
/// The texture id to bind to slot #1. (Will be 0 if none)
uint32_t texture_1_id;
/// The texture id to bind to slot #2. (Will be 0 if none)
uint32_t texture_2_id;
/// The texture id to bind to slot #3. (Will be 0 if none)
uint32_t texture_3_id;
/// The uniform scalars (passed to the pixel shader via uniforms).
float uniform_scalar[8];
/// The uniform vectors (passed to the pixel shader via uniforms).
vec4 uniform_vector[8];
/// The clip size (passed to the pixel shader via uniforms).
uint8_t clip_size;
/// The clip stack (passed to the pixel shader via uniforms).
Matrix4x4 clip[8];
/// Whether or not scissor testing should be used for the current draw command.
bool enable_scissor;
/// The scissor rect to use for scissor testing (units in pixels)
IntRect scissor_rect;
};
///
/// The types of commands.
///
/// This enumeration describes the type of command to execute on the GPU.
///
/// @see Command
///
enum class CommandType : uint8_t {
ClearRenderBuffer, ///< Clear the specified render buffer.
DrawGeometry, ///< Draw the specified geometry to the specified render buffer.
};
///
/// A command to execute on the GPU.
///
/// This structure describes a command to be executed on the GPU.
///
/// Commands are dispatched to the GPU driver asynchronously via GPUDriver::UpdateCommandList(),
/// the GPU driver should consume these commands and execute them at an appropriate time.
///
/// @see CommandList
///
struct UExport Command {
CommandType command_type; ///< The type of command to dispatch.
GPUState gpu_state; ///< The current GPU state.
uint32_t geometry_id; ///< The geometry ID to bind. (used with CommandType::DrawGeometry)
uint32_t indices_count; ///< The number of indices. (used with CommandType::DrawGeometry)
uint32_t indices_offset; ///< The index to start from. (used with CommandType::DrawGeometry)
};
///
/// List of commands to execute on the GPU.
///
/// @see GPUDriver::UpdateCommandList
///
struct UExport CommandList {
uint32_t size; ///< The number of commands in the list.
Command* commands; ///< The raw command list data.
};
#pragma pack(pop)
///
/// User-defined GPU driver interface.
///
/// The library uses this to optionally render Views on the GPU (see ViewConfig::is_accelerated).
///
/// You can provide the library with your own GPU driver implementation so that all rendering is
/// performed using an existing GPU context (useful for game engines).
///
/// When a View is rendered on the GPU, you can retrieve the backing texture ID via
/// View::render_target().
///
/// ## Default Implementation
///
/// A platform-specific implementation of GPUDriver is provided for you when you call App::Create(),
/// (currently D3D11, Metal, and OpenGL). We recommend using these classes as a starting point for
/// your own implementation (available open-source in the AppCore repository on GitHub).
///
/// ## Setting the GPU Driver
///
/// When using Renderer::Create(), you can provide your own implementation of this
/// class via Platform::set_gpu_driver().
///
/// ## State Synchronization
///
/// During each call to Renderer::Render(), the library will update the state of the GPU driver
/// (textures, render buffers, geometry, command lists, etc.) to match the current state of the
/// library.
///
/// ### Detecting State Changes
///
/// The library will call BeginSynchronize() before any state is updated and EndSynchronize() after
/// all state is updated. All `Create` / `Update` / `Destroy` calls will be made between these two
/// calls.
///
/// This allows the GPU driver implementation to prepare the GPU for any state changes.
///
/// ## Drawing
///
/// All drawing is done via command lists (UpdateCommandList()) to allow asynchronous execution
/// of commands on the GPU.
///
/// The library will dispatch a list of commands to the GPU driver during state synchronization. The
/// GPU driver implementation should periodically consume the command list and execute the commands
/// at an appropriate time.
///
/// @see Platform::set_gpu_driver()
///
class UExport GPUDriver {
public:
virtual ~GPUDriver();
///
/// Called before any state (eg, CreateTexture(), UpdateTexture(), DestroyTexture(), etc.) is
/// updated during a call to Renderer::Render().
///
/// This is a good time to prepare the GPU for any state updates.
///
virtual void BeginSynchronize() = 0;
///
/// Called after all state has been updated during a call to Renderer::Render().
///
virtual void EndSynchronize() = 0;
///
/// Get the next available texture ID.
///
/// This is used to generate a unique texture ID for each texture created by the library. The
/// GPU driver implementation is responsible for mapping these IDs to a native ID.
///
/// @note Numbering should start at 1, 0 is reserved for "no texture".
///
/// @return Returns the next available texture ID.
///
virtual uint32_t NextTextureId() = 0;
///
/// Create a texture with a certain ID and optional bitmap.
///
/// @param texture_id The texture ID to use for the new texture.
///
/// @param bitmap The bitmap to initialize the texture with (can be empty).
///
/// @note If the Bitmap is empty (Bitmap::IsEmpty), then a RTT Texture should be created instead.
/// This will be used as a backing texture for a new RenderBuffer.
///
/// @warning A deep copy of the bitmap data should be made if you are uploading it to the GPU
/// asynchronously, it will not persist beyond this call.
///
virtual void CreateTexture(uint32_t texture_id, RefPtr<Bitmap> bitmap) = 0;
///
/// Update an existing non-RTT texture with new bitmap data.
///
/// @param texture_id The texture to update.
///
/// @param bitmap The new bitmap data.
///
/// @warning A deep copy of the bitmap data should be made if you are uploading it to the GPU
/// asynchronously, it will not persist beyond this call.
///
virtual void UpdateTexture(uint32_t texture_id, RefPtr<Bitmap> bitmap) = 0;
///
/// Destroy a texture.
///
/// @param texture_id The texture to destroy.
///
virtual void DestroyTexture(uint32_t texture_id) = 0;
///
/// Get the next available render buffer ID.
///
/// This is used to generate a unique render buffer ID for each render buffer created by the
/// library. The GPU driver implementation is responsible for mapping these IDs to a native ID.
///
/// @note Numbering should start at 1, 0 is reserved for "no render buffer".
///
/// @return Returns the next available render buffer ID.
///
virtual uint32_t NextRenderBufferId() = 0;
///
/// Create a render buffer with certain ID and buffer description.
///
/// @param render_buffer_id The render buffer ID to use for the new render buffer.
///
/// @param buffer The render buffer description.
///
virtual void CreateRenderBuffer(uint32_t render_buffer_id, const RenderBuffer& buffer) = 0;
///
/// Destroy a render buffer.
///
/// @param render_buffer_id The render buffer to destroy.
///
virtual void DestroyRenderBuffer(uint32_t render_buffer_id) = 0;
///
/// Get the next available geometry ID.
///
/// This is used to generate a unique geometry ID for each geometry created by the library. The
/// GPU driver implementation is responsible for mapping these IDs to a native ID.
///
/// @note Numbering should start at 1, 0 is reserved for "no geometry".
///
/// @return Returns the next available geometry ID.
///
virtual uint32_t NextGeometryId() = 0;
///
/// Create geometry with certain ID and vertex/index data.
///
/// @param geometry_id The geometry ID to use for the new geometry.
///
/// @param vertices The vertex buffer data.
///
/// @param indices The index buffer data.
///
/// @warning A deep copy of the vertex/index data should be made if you are uploading it to the
/// GPU asynchronously, it will not persist beyond this call.
///
virtual void CreateGeometry(uint32_t geometry_id, const VertexBuffer& vertices,
const IndexBuffer& indices)
= 0;
///
/// Update existing geometry with new vertex/index data.
///
/// @param geometry_id The geometry to update.
///
/// @param vertices The new vertex buffer data.
///
/// @param indices The new index buffer data.
///
/// @warning A deep copy of the vertex/index data should be made if you are uploading it to the
/// GPU asynchronously, it will not persist beyond this call.
///
virtual void UpdateGeometry(uint32_t geometry_id, const VertexBuffer& vertices,
const IndexBuffer& indices)
= 0;
///
/// Destroy geometry.
///
/// @param geometry_id The geometry to destroy.
///
virtual void DestroyGeometry(uint32_t geometry_id) = 0;
///
/// Update the pending command list with commands to execute on the GPU.
///
/// Commands are dispatched to the GPU driver asynchronously via this method. The GPU driver
/// implementation should consume these commands and execute them at an appropriate time.
///
/// @param list The list of commands to execute.
///
/// @warning Implementations should make a deep copy of the command list, it will not persist
/// beyond this call.
///
virtual void UpdateCommandList(const CommandList& list) = 0;
};
} // namespace ultralight
// clang-format on
+42
View File
@@ -0,0 +1,42 @@
/**************************************************************************************************
* This file is a part of Ultralight. *
* *
* See <https://ultralig.ht> for licensing and more. *
* *
* (C) 2024 Ultralight, Inc. *
**************************************************************************************************/
#pragma once
#include <Ultralight/Defines.h>
#include <Ultralight/String.h>
namespace ultralight {
///
/// Log levels, used with Logger::LogMessage
///
enum class LogLevel : uint8_t {
Error,
Warning,
Info
};
///
/// User-defined logging interface.
///
/// The library uses this to display log messages for debugging during development.
///
/// This is intended to be implemented by users and defined before creating the Renderer.
///
/// @see Platform::set_logger()
///
class UExport Logger {
public:
virtual ~Logger();
///
/// Called when the library wants to display a log message.
///
virtual void LogMessage(LogLevel log_level, const String& message) = 0;
};
} // namespace ultralight
+182
View File
@@ -0,0 +1,182 @@
/**************************************************************************************************
* This file is a part of Ultralight. *
* *
* See <https://ultralig.ht> for licensing and more. *
* *
* (C) 2024 Ultralight, Inc. *
**************************************************************************************************/
#pragma once
#include <Ultralight/Defines.h>
namespace ultralight {
struct Config;
class Logger;
class GPUDriver;
class FontLoader;
class FileSystem;
class Clipboard;
class SurfaceFactory;
class ThreadFactory;
///
/// Global platform singleton, manages user-defined platform handlers and global config.
///
/// The library uses the Platform API for most platform-specific operations (eg, file access,
/// clipboard, font loading, GPU access, pixel buffer transport, etc.).
///
/// ## Motivation
///
/// Ultralight is designed to work in as many platforms and environments as possible. To achieve
/// this, we've factored out most platform-specific code into a set of interfaces that you can
/// implement and set on the Platform singleton.
///
/// ## Default Implementations
///
/// We provide a number of default implementations for desktop platforms (eg, Windows, macOS, Linux)
/// for you when you call App::Create(). These implementations are defined in the
/// [AppCore repository](https://github.com/ultralight-ux/AppCore/tree/master/src), we recommend
/// using their source code as a starting point for your own implementations.
///
/// ## Required Handlers
///
/// When using Renderer::Create() directly, you'll need to provide your own implementations for
/// FileSystem and FontLoader at a minimum.
///
/// @par Overview of which platform handlers are required / optional / provided:
///
/// | | Renderer::Create() | App::Create() |
/// |----------------|--------------------|---------------|
/// | FileSystem | **Required** | *Provided* |
/// | FontLoader | **Required** | *Provided* |
/// | Clipboard | *Optional* | *Provided* |
/// | GPUDriver | *Optional* | *Provided* |
/// | Logger | *Optional* | *Provided* |
/// | SurfaceFactory | *Provided* | *Provided* |
/// | ThreadFactory | *Optional* | *Optional* |
///
/// @note This singleton should be set up before creating the Renderer or App.
///
class UExport Platform {
public:
///
/// Get the Platform singleton
///
static Platform& instance();
virtual ~Platform();
///
/// Set the Config
///
virtual void set_config(const Config& config) = 0;
///
/// Get the Config
///
virtual const Config& config() const = 0;
///
/// Set the Logger (to handle error messages and debug output).
///
/// @param logger A user-defined Logger implementation, ownership remains with the caller.
///
virtual void set_logger(Logger* logger) = 0;
///
/// Get the Logger
///
virtual Logger* logger() const = 0;
///
/// Set the GPU Driver (will handle all rendering)
///
/// @param gpu_driver A user-defined GPUDriver implementation, ownership remains with the
/// caller.
///
virtual void set_gpu_driver(GPUDriver* gpu_driver) = 0;
///
/// Get the GPU Driver
///
virtual GPUDriver* gpu_driver() const = 0;
///
/// Set the Font Loader (will be used to map font families to actual fonts)
///
/// @param font_loader A user-defined FontLoader implementation, ownership remains with the
/// caller.
///
virtual void set_font_loader(FontLoader* font_loader) = 0;
///
/// Get the Font Loader
///
virtual FontLoader* font_loader() const = 0;
///
/// Set the File System (will be used for all file system operations)
///
/// @param file_system A user-defined FileSystem implementation, ownership remains with the
/// caller.
///
virtual void set_file_system(FileSystem* file_system) = 0;
///
/// Get the File System
///
virtual FileSystem* file_system() const = 0;
///
/// Set the Clipboard (will be used for all clipboard operations)
///
/// @param clipboard A user-defined Clipboard implementation, ownership remains with the
/// caller.
///
virtual void set_clipboard(Clipboard* clipboard) = 0;
///
/// Get the Clipboard
///
virtual Clipboard* clipboard() const = 0;
///
/// Set the SurfaceFactory
///
/// This can be used to provide a platform-specific bitmap surface for View to paint into when
/// the CPU renderer is enabled. See View::surface().
///
/// @param surface_factory A user-defined SurfaceFactory implementation, ownership remains with
/// the caller.
///
/// @note A default BitmapSurfaceFactory is defined if you never call this, View::surface() can
/// be safely cast to BitmapSurface.
///
virtual void set_surface_factory(SurfaceFactory* surface_factory) = 0;
///
/// Get the SurfaceFactory
///
/// @note A default BitmapSurfaceFactory is set by default, View::surface() can be safely cast
/// to BitmapSurface if you don't define your own.
///
virtual SurfaceFactory* surface_factory() const = 0;
///
/// Set the ThreadFactory
///
/// This can be used to provide a platform-specific ThreadFactory implementation for the library
/// to use when creating threads.
///
/// @param thread_factory A user-defined ThreadFactory implementation, ownership remains with the
/// caller.
///
virtual void set_thread_factory(ThreadFactory* thread_factory) = 0;
///
/// Get the ThreadFactory
///
virtual ThreadFactory* thread_factory() const = 0;
};
} // namespace ultralight
+204
View File
@@ -0,0 +1,204 @@
/**************************************************************************************************
* This file is a part of Ultralight. *
* *
* See <https://ultralig.ht> for licensing and more. *
* *
* (C) 2024 Ultralight, Inc. *
**************************************************************************************************/
#pragma once
#include <Ultralight/Defines.h>
#include <Ultralight/RefPtr.h>
#include <Ultralight/Bitmap.h>
#include <Ultralight/Geometry.h>
namespace ultralight {
///
/// User-defined pixel buffer surface.
///
/// The library uses this to store pixel data when rendering Views on the CPU (see
/// ViewConfig::is_accelerated).
///
/// You can provide the library with your own Surface implementation to reduce the latency of
/// displaying pixels in your application (Views will be drawn directly to a block of memory
/// controlled by you).
///
/// When a View is rendered on the CPU, you can retrieve the backing Surface via View::surface().
///
/// @pre This is automatically managed for you when using App::Create(), if you want to override
/// Surface or SurfaceFactory, you'll need to use Renderer::Create() instead.
///
/// ## Default Implementation
///
/// A default Surface implementation, BitmapSurface, is automatically provided by the library when
/// you call Renderer::Create() without defining a custom SurfaceFactory.
///
/// You should cast the Surface to a BitmapSurface to access the underlying Bitmap.
///
/// ## Setting the Surface Implementation
///
/// To define your own implementation, you should inherit from this class, handle the virtual
/// member functions, and then define a custom SurfaceFactory that creates/destroys an
/// instance of your class.
///
/// After that, you should pass an instance of your custom SurfaceFactory class to
/// Platform::set_surface_factory() before calling Renderer::Create().
///
class UExport Surface {
public:
virtual ~Surface();
///
/// Width (in pixels).
///
virtual uint32_t width() const = 0;
///
/// Height (in pixels).
///
virtual uint32_t height() const = 0;
///
/// Number of bytes between rows (usually width * 4)
///
virtual uint32_t row_bytes() const = 0;
///
/// Size in bytes.
///
virtual size_t size() const = 0;
///
/// Lock the pixel buffer and get a pointer to the beginning of the data for reading/writing.
///
/// @note Native pixel format is premultiplied BGRA 32-bit (8 bits per channel).
///
virtual void* LockPixels() = 0;
///
/// Unlock the pixel buffer.
///
virtual void UnlockPixels() = 0;
///
/// Resize the pixel buffer to a certain width and height (both in pixels).
///
/// This should never be called while pixels are locked.
///
virtual void Resize(uint32_t width, uint32_t height) = 0;
///
/// Set the dirty bounds to a certain value.
///
/// This is called after the Renderer paints to an area of the pixel buffer. (The new value will
/// be joined with the existing dirty_bounds())
///
virtual void set_dirty_bounds(const IntRect& bounds);
///
/// Get the dirty bounds.
///
/// This value can be used to determine which portion of the pixel buffer has been updated since
/// the last call to ClearDirtyBounds().
///
/// The general algorithm to determine if a Surface needs display is:
/// <pre>
/// if (!surface.dirty_bounds().IsEmpty()) {
/// // Surface pixels are dirty and needs display.
/// // Cast Surface to native Surface and use it here (pseudo code)
/// DisplaySurface(surface);
///
/// // Once you're done, clear the dirty bounds:
/// surface.ClearDirtyBounds();
/// }
/// </pre>
///
virtual IntRect dirty_bounds() const;
///
/// Clear the dirty bounds.
///
/// You should call this after you're done displaying the Surface.
///
virtual void ClearDirtyBounds();
protected:
Surface();
IntRect dirty_bounds_;
};
///
/// User-defined factory to provide your own surface implementation.
///
/// The library uses this to create/destroy Surface instances when rendering Views on the CPU.
///
/// @pre This is automatically managed for you when using App::Create(), if you want to override
/// Surface or SurfaceFactory, you'll need to use Renderer::Create() instead.
///
/// ## Setting the Surface Factory
///
/// The default factory creates/destroys a BitmapSurface but you can override this by providing your
/// own factory to Platform::set_surface_factory().
///
class UExport SurfaceFactory {
public:
virtual ~SurfaceFactory();
///
/// Create a native Surface with a certain width and height (in pixels).
///
virtual Surface* CreateSurface(uint32_t width, uint32_t height) = 0;
///
/// Destroy a native Surface previously created by CreateSurface().
///
virtual void DestroySurface(Surface* surface) = 0;
};
///
/// The default surface implementation, backed by a bitmap.
///
/// This is automatically provided by the library when you call Renderer::Create() without defining
/// a custom SurfaceFactory.
///
/// This implementation uses a Bitmap to store pixel data (retrieve it via BitmapSurface::bitmap()).
///
class UExport BitmapSurface : public Surface {
public:
virtual uint32_t width() const override;
virtual uint32_t height() const override;
virtual uint32_t row_bytes() const override;
virtual size_t size() const override;
virtual void* LockPixels() override;
virtual void UnlockPixels() override;
virtual void Resize(uint32_t width, uint32_t height) override;
///
/// Get the underlying Bitmap.
///
RefPtr<Bitmap> bitmap();
protected:
BitmapSurface(uint32_t width, uint32_t height);
virtual ~BitmapSurface();
BitmapSurface(const BitmapSurface&) = delete;
void operator=(const BitmapSurface&) = delete;
friend class BitmapSurfaceFactory;
void* impl_;
};
///
/// Get the default Bitmap Surface Factory singleton. (Do not destroy this, this singleton is owned
/// by the library).
///
UExport SurfaceFactory* GetBitmapSurfaceFactory();
} // namespace ultralight
+93
View File
@@ -0,0 +1,93 @@
/**************************************************************************************************
* This file is a part of Ultralight. *
* *
* See <https://ultralig.ht> for licensing and more. *
* *
* (C) 2024 Ultralight, Inc. *
**************************************************************************************************/
#pragma once
#include <Ultralight/Defines.h>
namespace ultralight {
///
/// Unique id of the thread, used for referencing the created thread later.
/// * on Windows this should match the thread identifier returned by either _beginthreadex()
/// or GetCurrentThreadId()
/// * on POSIX this can be whatever unique id you want
///
typedef uint32_t ThreadId;
///
/// Platform-specific handle
/// * on Windows this is HANDLE
/// * on POSIX this is pthread_t
///
typedef uint64_t ThreadHandle;
///
/// Entry point for the thread, this function should be called by the thread once it is active
/// and should be passed entry_point_data as the argument.
///
typedef void (*ThreadEntryPoint)(void*);
///
/// The type of thread, you can choose to optionally handle these for better performance.
///
enum class ThreadType : uint8_t {
Unknown = 0,
JavaScript,
Compiler,
GarbageCollection,
Network,
Graphics,
Audio,
};
///
/// Result of creating a new thread.
///
/// This struct is used to return the id and handle of the created thread.
///
struct UExport CreateThreadResult {
ThreadId id; ///< The unique id of the thread. @see ThreadId
ThreadHandle handle; ///< The platform-specific handle of the thread. @see ThreadHandle
};
///
/// User-defined factory for creating new threads.
///
/// You can implement this interface so that the library will use your own implementation for
/// creating threads (useful for tracking thread creation, setting thread names, etc).
///
/// ## Default Implementation
///
/// When no factory is defined, the library will create threads using the default platform-specific
/// thread creation functions (eg, `_beginthreadex()` on Windows, `pthread_create()` on POSIX).
///
/// ## Setting the Thread Factory
///
/// To provide your own custom ThreadFactory implementation, you should inherit from this class,
/// handle the virtual member functions, and then pass an instance to
/// Platform::set_thread_factory().
///
class UExport ThreadFactory {
public:
virtual ~ThreadFactory() = default;
///
/// Create a new thread.
///
/// @param name The name of the thread (can be nullptr).
/// @param type The type of thread.
/// @param entry_point The entry point for the thread.
/// @param entry_point_data The data to pass to the entry point.
/// @param result The resulting id and handle of the thread creation.
///
/// @return Returns whether or not the thread was created successfully.
///
virtual bool CreateThread(const char* name, ThreadType type, ThreadEntryPoint entry_point,
void* entry_point_data, CreateThreadResult& result) = 0;
};
} // namespace ultralight