Added MacOS SDK
This commit is contained in:
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
Reference in New Issue
Block a user