Changelog
Changes since the 1.4.0 release.
On this page
Last updated: October 2nd, 2026
📘 Upgrading from 2.0.0-beta.1?
See the 2.0.0-beta.2 changelog for changes since
2.0.0-beta.1
Highlights
- Photon, a new analytic vector renderer: paths, strokes, SVG, and text render directly in pixel shaders at any zoom or transform. Enabled by default on GPU Views.
- A new type-safe JavaScript API (
ultralight::js), native DOM API (ultralight::dom), and declarative data bindings API (ultralight::dom::data). - HTML5
<video>and<audio>playback (WebM, VP9, Opus). - GPU-accelerated HTML5 Canvas support,
OffscreenCanvas, canvas filters, and all SVG filters on the GPU. - Block-compressed
.ddstextures in<img>and CSS (Pro edition and above). - Text editing, IME composition, multi-format clipboard, and native editing conventions per platform.
- AppCore: a flexible panel layout replaces Overlay; windows gain custom chrome, native backdrop materials, per-pixel transparency, popups, and light/dark OS theming.
- Profiler and render-trace diagnostics (Perfetto), a
GCListener, memory profiles, and automatic idle reclamation. - The SDK ships as a CMake package (
find_package(Ultralight)), and the reference platform code (GPU drivers, font loaders, file systems, clipboards, audio outputs) is now Zlib-licensed source in the package'splatform/folder.
Full Changelog (since v1.4)
Major Improvements
Graphics & Compositor:
- Rewrite CPU renderer for better performance and accuracy
- Rewrite compositor to closely match upstream WebKit (now enabled by default)
- Apply the standard compositing policy on both renderers, so
will-change,translateZ(0), and painted canvases promote layers as they do in Safari and Chrome - Add a per-View render FPS cap (
ViewConfig::max_render_fps/View::set_max_render_fps()) that throttlesrequestAnimationFrame, CSS animations, smooth scroll, and paint as one rate - Add display-locked frame pacing: animation clocks sample the physical display's presentation time, and
Renderer::RefreshDisplay()accepts a target timestamp, a declared refresh rate, and a custom clock - Add
View::set_visible()to suspend off-screen Views (pauses animations, firesvisibilitychange, and optionally throttles JavaScript timers) - Render composited text sharply under animated transforms instead of resampling a raster
- Improve support for CSS, SVG, clipping, backgrounds, and filters across the board
- Improve box-shadow performance (closed-form Gaussian on both renderers, significantly faster on GPU) and memory usage
- Route rounded borders, ellipses, and rounded rects through an analytic primitive so they render resolution-independently
- Unify shader pipeline (HLSL is now ground-truth across all GPU renderers; stock shaders for every program ship in
platform/shaders) - Add single-channel (A8) render targets and explicit blend state per draw to the GPU driver interface
- Add
GPUDriver::GetDeviceCaps()so drivers can report MSAA support, texture limits, compressed formats, and partial redraw - Drop MSAA from compositor intermediate render targets (a 1080p blur filter drops from about 152 MB to about 17 MB of VRAM) and from the analytic vector path
Photon (analytic vector graphics and text):
- Add Photon, an analytic vector rendering pipeline for the GPU renderer: path fills, strokes, dashes, clips, and text are evaluated directly in the pixel shader from cached curve data instead of being tessellated
- Enable Photon by default (
Config::enable_photon,Config::enable_photon_text); text at or aboveConfig::photon_text_min_px(16 px) renders analytically on both renderers - Render text on the CPU renderer from the same unhinted outlines with fractional placement, so both renderers produce near-identical text
- Render text under rotation, skew, and non-uniform scale sharply at every size
- Add analytic Gaussian box shadows and blurred CSS
text-shadowon both renderers - Add conic gradients, gradient spread modes (pad, reflect, repeat), and gradient and pattern brushes on strokes, SVG paint servers, and text
Web Platform & CSS:
- Add support for CSS
mask-image - Add support for CSS
mix-blend-mode - Add GPU acceleration for SVG filters: all 17 primitives (
feGaussianBlur,feDropShadow,feMerge,feComposite,feBlend,feColorMatrix,feComponentTransfer,feFlood,feOffset,feTile,feImage,feMorphology,feConvolveMatrix,feDisplacementMap,feTurbulence,feDiffuseLighting,feSpecularLighting) run on GPU Views, as do SVG-content filters andbackdrop-filter: url()chains - Add
linearRGBcolor interpolation in SVG filters (color-interpolation-filters) - Add support for SVG
<mask>references and SVG2context-fill/context-stroke - Add CSS
conic-gradient(),repeating-conic-gradient(), and canvascreateConicGradient() - Add support for
background-clip: text - Add support for
background-repeat: space - Add support for
-webkit-text-strokeandCanvasRenderingContext2D.strokeText() - Add support for
image-rendering: pixelated/crisp-edgesand canvasimageSmoothingEnabled/imageSmoothingQuality(nearest sampling matches Chromium byte-for-byte on both renderers) - Unprefix
backdrop-filter(-webkit-backdrop-filterremains an alias) - Add the
app-regionCSS property,color-schemesupport with a per-View pin, andprefers-color-schemedriven byRenderer::set_system_color_scheme() - Turn on interactive form validation: an invalid control blocks submission, fires
invalid, and takes focus;reportValidity()is available (addnovalidatefor 1.4 behavior) - Fix the UA stylesheet so
preandcodesize at 13 px and the default font size setting takes effect to match mainstream browsers
Text & Fonts:
- Enable kerning and ligatures (text is now shaped through HarfBuzz)
- Add WOFF2 web font support
- Complete variable-font support:
font-weight,font-stretch,font-style: oblique,font-optical-sizing,font-variation-settings, and@font-facedescriptor ranges - Add color emoji (CBDT bitmap strikes and COLRv0 layers, including COLRv1 fonts with a COLRv0 fallback) rendered in color on both renderers
- Add synthetic bold and synthetic oblique for families without those faces
- Add font profiles (
Config::font_profile:Default,WindowsLike,MacOSLike,Light) with per-knob overrides (font_gamma,font_contrast,font_stem_darkening,font_embolden,font_blend_mode); AppCore picks the host platform's profile and generic font families automatically - Replace the per-glyph grid-fitting cascade with one glyph positioning policy at every size, so small text no longer shakes during scroll or animation
- Add the cursive, fantasy, and pictograph generic families and default font sizes to
ViewConfig - Open the requested face of a
.ttcfont collection: font loaders pass the face index throughFontFile::Create()
HTML5 Canvas:
- Enable GPU-accelerated HTML5 Canvas (
HTMLCanvasElement) - Enable
OffscreenCanvasAPI - Enable
OffscreenCanvaspainting on WebWorker threads - Add support for HTML5 Canvas filters (
CanvasRenderingContext2D.filter) - Add support for
willReadFrequentlyhint onCanvasRenderingContext2D(allows readback, forces CPU rendering) - Enable
createImageBitmap(canvas)in JavaScript - Share decoded image pixels and GPU textures across
drawImage()calls instead of copying per draw
Images & Compressed Textures (Pro edition and above):
- Add block-compressed textures:
.ddsfiles (BC1, BC2, BC3, BC7) load in<img>, CSSbackground-image, canvasdrawImage(), andcreateImageBitmap(), uploaded to the GPU as raw blocks with no decode step - Upload BCn natively in the Direct3D 11, Direct3D 12, Metal, and OpenGL reference drivers, with a software decompression fallback (parallel, 4K BC7 in about 12 ms) for the CPU renderer and drivers without the format
- Fix downscaled image drawing on both renderers
HTML5 Media (Pro edition and above):
- Add HTML5
<video>and<audio>playback (VP9 video, Opus audio, WebM container) - Add support for transparent video (VP9 alpha channel) in GPU and CPU renderers
- Add HTTP byte-range streaming for media with progressive buffering and preload support
- Add stylized media controls for
<video>/<audio>elements - Add the
AudioOutputplatform interface with reference implementations for Windows (WASAPI), macOS (CoreAudio), and Linux (PulseAudio) - Add
Config::media_profile(Balanced,FavorMemory,FavorPerformance) - Select video frames against the display's presentation time and use the audio device clock for A/V sync
JavaScript Bridge:
- Add
ultralight::js, a typed header-only C++ API for JavaScript interop: navigation-surviving API registries (js::API), typed function/property/constant bindings with automatic marshaling (aggregate structs and enums included), Promise-returning async bindings (coroutinejs::Task<T>or callback-stylejs::Resolver), native class binding, events, weak references, a worker pool, and zero-copy ArrayBuffer / typed-array interop - Add the ULJS C API (
<Ultralight/CAPI/CAPI_JS*.h>), the language-neutral core the C++ layer is built on (usable directly from C or via P/Invoke; future official language bindings build on the same core) - Add self-describing schema:
js::API::schema()/ulJSAPIGetSchema()emit versioned JSON, andtools/scripts/gen-typescript.pygenerates TypeScript declarations from it - Add per-registry diagnostics (Off/Warn/Strict, defaulting to
Config::diagnostics) with did-you-mean suggestions, lossy-conversion warnings, and a newNativeAPIconsole message source, plus theul.diagnosticspage-side registry - Add per-(registry, View) origin policy: app-content-only injection by default,
scheme://host[:port]allowlist rules, and a per-View filter callback - Add bindings that survive back/forward cache restore
- Extend the JavaScriptCore C API:
JSClassDefinitionversion 1000 with per-class private data and...Excallbacks,JSObjectMakeFunctionWithData(), UTF-8 batch property access, typed errors, promise inspection,JSArrayBufferDetach(), and external memory hints - Remove AppCore's JSHelpers (
<AppCore/JSHelpers.h>); the typed bridge replaces it (see the porting guide)
DOM API & Data Bindings (all editions):
- Add
ultralight::dom(<Ultralight/DOM.h>) and the ULDOM C API, a native DOM API with the same names and syntax as the JavaScript DOM: documents, elements, text nodes, fragments, inline and computed styles,classList,dataset, forms and form-control selection, geometry and scrolling, events (capture, once, passive, delegation, synthetic dispatch), ranges, selections, and the window. Works with JavaScript disabled - Add
dom::Triggers, navigation-surviving DOM wiring: selector-addressed delegated listeners and DOM-ready hooks that apply to every page a View loads - Add
ultralight::dom::data(<Ultralight/dom/data/Context.h>) and the ULDOMData C API, declarative data binding from schema-described C++ models toul-*markup and{{path}}templates, with two-way edits, actions, keyed lists, format pipes, and validators. A context belongs to your thread;Sync()publishes one atomic snapshot per tick - Add
ultralight::URL,ultralight::JSON, andultralight::Colorvalue types (with C mirrors), andultralight::Vector<T>, an ABI-safe container for the library boundary - Add
View::GetDOMDocument(),View::AttachDOMTriggers(),View::AttachDOMDataContext(), and DOM-to-JavaScript interop (dom::ToJS/dom::FromJS)
Text Editing, IME & Clipboard:
- Add
View::editor(), anEditorwith a curated command set (Execute()/CanExecute()), text insertion, caret and selection geometry, and text-offset queries for native text-input integrations - Add
EditorListenerwith editable-state events (element kind, mutability,inputmode,enterkeyhint, bounds) for native IME and on-screen keyboard integration - Add IME composition (
SetComposition()with styled segments,Commit,Finish,Cancel), with reference IME handlers for Windows (IMM32) and macOS (NSTextInputClient) in AppCore - Replace the plain-text
Clipboardinterface with multi-formatClipboardDatapayloads, so one copy carriestext/plainandtext/htmltogether; AppCore's clipboards map CF_HTML and MIME-named formats on Windows andtext/plain/text/htmlon macOS - Add
ViewConfig::clipboard_read_policygoverning script-initiated paste - Add
match_native_editing_behavior(ViewConfigand AppCoreSettings) so selection and caret behavior follow each host OS
Scrolling & Input:
- Rewrite smooth scroll animation using physics-based spring-mass system (matches macOS/iOS feel)
- Carry scroll positions at sub-pixel precision end to end, so composited scrolling is smooth at every device scale and
position: fixed/position: stickycontent no longer shakes at fractional scales - Add back/forward mouse button support
- Add cursor coordinates to
ScrollEventfor dispatching a scroll at a specific point - Add
View::is_settled()andLoadListener::OnPageSettled(), which fire once a page has stopped changing after load
Performance & Memory:
- Switch the WebCore and JavaScriptCore heap to bmalloc/libpas
- Add automatic idle memory reclamation (
Config::idle_gc_enabled): a heavy page followed by navigation returns to the recycle floor on its own (800 MB to 225 MB within 30 s in the reference scenario) - Add
Config::memory_profile(Balanced,LowMemory,Performance) andConfig::max_heap_size - Add
Renderer::Recycle(RecycleMode)(Lightweightis cheap enough to call every frame,Fullsuits idle periods) and make the automatic recycler run everyConfig::recycle_delayseconds - Add the
GCListener(Pro edition and above):OnRequestGC()lets you schedule the engine's collections onto a frame that hides the pause, withRenderer::CollectNow(),gc_status(), andCodeDropMode - Reduce Windows private commit
- Park contended locks in the kernel instead of spinning
- Speed up style recalculation on custom-property-heavy pages 2-3x
- Reduce CSS and SVG filter chain memory usage
- Stop pinning AppCore's window thread to CPU 0 (whoops!)
- Increase performance in multiple profiled bottlenecks via improved parallelism
Diagnostics & Profiling:
- Add
Config::diagnostics: a developer mode, the JavaScript and DOM diagnostics levels, and a minimum log level - Add the
FatalandDebuglog levels, and start every engine log message with a category tag ([render],[net], ...) - Add a memory usage reporting API (
Renderer::GetMemoryUsage()/LogMemoryUsage()) covering fonts, bitmaps, textures, caches, GPU resources by purpose, process working set and commit, and the allocator heaps - Add Profiler platform API and Render Trace diagnostic system (runtime-toggleable tracing, jank detection) (Profiler: Pro edition and above; Render Trace: Enterprise edition and above)
- Add a built-in Perfetto backend (
CreateProfilerPerfetto()) andSettings::enable_profilerfor AppCore apps - Add
App::GetGPUMemoryStats()reporting driver-tracked GPU allocations and OS-reported process video memory - Add compositor debug overlays (
ViewConfig::enable_compositor_debug_info) andConfig::paint_full_layers - Trace every GPU driver call, GC cycle, and recycle pass as its own scope with resource attribution
Networking & Security:
- Upgrade LibreSSL from 3.0.2 to 3.9.2 (enables TLS 1.3 and patches many security vulnerabilities)
- Enable Public Suffix List for improved site compatibility and security
- Add
Config::use_system_certificate_store(Windows) to verify TLS against the OS root store instead of the bundledcacert.pem - Add
Config::ignore_ssl_errorsfor development against self-signed certificates - Increase
CURL_MAX_WRITE_SIZEfor better HTTP/2 throughput - Report the real host platform in the default User-Agent string (1.4 reported Windows on every OS)
AppCore (Windows, Layout & Chrome):
- Replace
Overlaywith a flexible panel layout:Panel,Container(rows and columns with resizable dividers), and aForegroundlayer of floating panels with anchors and auto-dismissal, buildable in oneWindow::BuildLayout()expression, with a full C API (<AppCore/CAPI/CAPI_Layout.h>) - Add custom window chrome:
WindowFlags::CustomChrome, hit-test regions, CSSapp-region, window buttons,BeginDragMove()/BeginDragResize(), caption color, and corner styles - Add native backdrop materials (
Window::SetBackdrop(): Window, Popup, Overlay; Frosted or Matte; theme pin; Vivid rendition on Windows) - Add per-pixel transparent windows (
WindowFlags::Transparent) andWindow::SetBackgroundColor() - Add popup windows (
Window::CreatePopup()) with engine-owned auto dismissal andWindowFlags::Popup - Add window state control (
Maximize,Minimize,Restore) and theOnWindowStateChanged,OnActivationChanged,OnBackdropChanged,OnDismiss,OnClear, andOnPaintlistener callbacks - Move window and monitor geometry to logical pixels (
double), withdevice_width()/device_height()for device pixels andLogicalToDevice()/DeviceToLogical()conversions - Add multi-monitor enumeration (
App::monitor_count()/App::monitor()) and drive each View's refresh from its monitor's hardware display link, presenting capped frames on the display's frame lattice - Add
App::RunOnce(),PostTask(),PostDelayedTask(), andSetInterval()for running AppCore from an existing main loop - Add idle detection:
AppListener::OnIdle(),App::is_idle(),App::thread_utilization(), and theSettingsidle thresholds - Add
Window::TakeScreenshot(),Window::SetIcon(),Settings::app_icon,Settings::device_scale_override,Settings::headless_paint_fps, andSettings::full_speed_loop - Add the window-level editable-state stream (
Window::OnEditableStateChange()) and forward the hovered panel's page cursor automatically - Present and upload only the dirty region of CPU-rendered windows
- Add
Window::ShowWhenReady()to show a new window once its pages have finished loading - Update the Linux x64 port: OpenGL driver, GPU-less CPU windows, PulseAudio, X11 clipboard, and XIM input methods (X11; Wayland desktops through XWayland)
- Update the macOS port: Metal driver at parity with Direct3D 11 (two frames in flight, async presents), CADisplayLink / CVDisplayLink refresh, backdrop materials, popups, custom chrome, IME, CoreAudio, retina-correct text, and a GPU-less
force_cpu_rendererpath - Publish the reference platform implementations (GPU drivers and contexts, font loaders, file systems, clipboards, audio outputs, shaders) as Zlib-licensed source in the SDK's
platform/folder and theultralight-ux/Platformrepository
SDK, Build & Packaging:
- Ship a CMake package:
find_package(Ultralight), theUltralight::AppCore/Ultralight/WebCore/UltralightCoretargets, andultralight_copy_runtime_files()to stage the runtime files - Flatten the package layout (
bin/,lib/,include/,resources/,inspector/,samples/,tools/,platform/,license/) - Raise the toolchain floor to C++20 (Visual Studio 2022 or later on Windows, macOS 11.3 or later, GCC 11 or later or a C++20 clang on Linux)
- Build the Linux libraries against glibc 2.31 with a private copy of libc++, so apps can use either libstdc++ or libc++
- Add the generated
<Ultralight/Config.h>withUL_HAS(x)andUL_EDITION_AT_LEAST(x)for compile-time edition and feature checks - Enable Profile-Guided Optimization (PGO) and LTO in Release builds
- Switch to zlib-ng v2.3.2 for faster SIMD-accelerated decompression
- Patch ICU to avoid rare
call_oncedeadlock during early init on Windows - Adopt SemVer versioning scheme
Major API Changes
Breaking Changes:
- The C++ headers now require C++20 (Visual Studio 2022 or later on Windows)
Overlayand theulOverlay*C API are removed;Panelreplaces it (Window::AddPanel()/AdoptPanel(),ulWindowAddPanel()), and the layout tree arranges panels in rows, columns, and a floating foreground layer<AppCore/JSHelpers.h>is removed; useultralight::jsWindowandMonitorgeometry is logical pixels asdouble:Window::width()/height()andMonitor::width()/height()reported device pixels in 1.4.screen_width(),screen_height(),ScreenToPixels(), andPixelsToScreen()are removedWindowFlagsis anenum class(WindowFlags::Titled | WindowFlags::Resizable)WindowListener::OnKeyEvent(),OnMouseEvent(), andOnScrollEvent()take a leadingWindow*;OnResize()receives logicaldoubledimensionsClipboard::ReadPlainText()/WritePlainText()are replaced byRead()/Write()overClipboardData; the CULClipboardstruct changed shapeSurface::Scroll()is a new required method on custom surfaces (ULSurfaceDefinitiongains ascrollcallback,NULLis handled)GPUDriver::CreateTexture()takes aflagsparameter andUpdateTexture()takes adirty_rect; seven shader programs are required (FilterBasic,FilterBlur,FilterDropShadow,FillPhoton,FillPhotonGridjoinFillandFillPath);GPUStategains blend state,texture_4_id, anduniform_integer[8];CommandType::FlushandVertexBufferFormat::_2f_2uiare new- Every 1.4 C callback setter gained a trailing
destroy_user_dataparameter (the thirteenulViewSet*Callbackfunctions,ulAppSetUpdateCallback(),ulWindowSetCloseCallback(),ulWindowSetResizeCallback()) LogLevelgainsFatal(now the first value) andDebug(the last), soError,Warning, andInfochanged value; the CULLogLevelchanged the same wayRefPtr's boolean conversion isexplicitKeyEventis no longer trivially copyableConfig::animation_timer_delayandConfig::scroll_timer_delayare removed (useViewConfig::max_render_fps)ulCreateScrollEvent()takes two extra cursor-coordinate parameters (pass-1, -1for 1.4 behavior)
New Headers:
<Ultralight/JS.h>and<Ultralight/js/*.h>: the JavaScript bridge<Ultralight/DOM.h>and<Ultralight/dom/*.h>: the DOM API<Ultralight/dom/data/Context.h>: data bindings<Ultralight/Editor.h>,<Ultralight/ClipboardData.h>,<Ultralight/Color.h>,<Ultralight/URL.h>,<Ultralight/JSON.h>,<Ultralight/Vector.h>,<Ultralight/GCListener.h>,<Ultralight/HolderTraits.h>,<Ultralight/OriginRules.h>,<Ultralight/DiagnosticsLevel.h><Ultralight/platform/AudioOutput.h>(Pro edition and above),<Ultralight/platform/Profiler.h>(Pro edition and above)<Ultralight/Config.h>(generated edition and feature macros; distinct from<Ultralight/platform/Config.h>)<AppCore/Layout.h>and<AppCore/layout/*.h>: the layout tree<AppCore/GPUMemoryStats.h>- C API:
CAPI_JS*.h(5),CAPI_DOM*.h(9, not included by<Ultralight/CAPI.h>),CAPI_Editor.h,CAPI_Color.h,CAPI_URL.h,CAPI_AudioOutput.h,CAPI_Profiler.h,CAPI_ThreadFactory.h,<AppCore/CAPI/CAPI_Layout.h>
New Enums:
BlendFactor(Zero, One, SrcColor, InvSrcColor, SrcAlpha, InvSrcAlpha, DestColor, InvDestColor, DestAlpha, InvDestAlpha, SrcAlphaSaturate)BlendEquation(Add, Subtract, RevSubtract, Min, Max)GPUTextureFlags(RenderTarget, Antialiased, Immutable) andGPUCompressedFormatRecycleMode(Lightweight, Full) andCodeDropMode(Nothing, Linked, All)MemoryProfile(Balanced, LowMemory, Performance)DiagnosticsLevel(Off, Warn, Strict, Auto)MediaProfile(Balanced, FavorMemory, FavorPerformance) (Pro edition and above)FontProfile(Default, MacOSLike, WindowsLike, Light) andFontBlendMode(Profile, GammaCorrected, SRGB)ColorScheme(Auto, Light, Dark) andClipboardReadPolicy(Deny, AllowForAppContent, Allow)EditorCommand,EditableType,InputMode,EnterKeyHint- AppCore:
WindowFlags(now scoped, withTransparent,Popup,CustomChrome),WindowState,WindowButtons,BackdropMaterial,BackdropVariant,BackdropTheme,BackdropRendition,BackdropState,CornerStyle,HitRegionRole,ResizeEdge,Dismiss,FocusPolicy,AnchorCorner,AnchorAlign,AnchorFit
New Platform Interfaces:
AudioOutput(set viaPlatform::set_audio_output()): embedder-implementable audio sink for HTML5 media (Pro edition and above)Profiler(set viaPlatform::set_profiler()): embedder-implementable performance profiler (Pro edition and above)ThreadFactoryis now available from C (ulPlatformSetThreadFactory())
New API Functions:
Renderer::RefreshDisplay(display_id, target_timestamp),Renderer::SetDisplayRefreshRate(),Renderer::SetDisplayUsesCustomClock()Renderer::PostTask()/PostDelayedTask()(from any thread),Renderer::Recycle(RecycleMode),Renderer::GetMemoryUsage()Renderer::set_system_color_scheme()/system_color_scheme()Renderer::set_gc_listener(),gc_status(),CollectNow(),Recycle(RecycleMode, CodeDropMode)(Pro edition and above)Renderer::BeginRenderTrace()/EndRenderTrace()/is_render_trace_active()(Enterprise edition and above)View::set_visible()/is_visible(),View::set_max_render_fps()/max_render_fps(),View::set_preferred_color_scheme(),View::is_settled(),View::Resize(width, height, device_scale)View::editor(),View::set_editor_listener(),View::GetJSContext(),View::AttachJSAPI()/DetachJSAPI(),View::GetDOMDocument(),View::AttachDOMTriggers(),View::AttachDOMDataContext()View::set_compositor_debug_info_enabled()/compositor_debug_info_enabled()LoadListener::OnPageSettled(),EditorListener(OnChangeEditableState(),OnUpdateComposition(),OnDiscardComposition())Surface::Scroll(),Surface::ShiftPixels(),Surface::LockPixelsSafe(),Surface::dirty_rect_count()/dirty_rect()GPUDriver::GetDeviceCaps()FontFile::Create(path_or_buffer, face_index)andFontFile::face_index()Bitmap::is_compressed(),Bitmap::MaxDimension,GetBitmapFormatInfo(),IsCompressedFormat()WeakPtr<T>,WeakRefCounted,MakeRefPtr<T>(),Rect::FromXYWH()ul_malloc()/ul_free()and the aligned and realloc variants (the library allocator, exported)CreateProfilerPerfetto()/DestroyProfilerPerfetto()(Pro edition and above)App::RunOnce(),App::PostTask()/PostDelayedTask()/SetInterval(),App::is_idle()/thread_utilization(),App::monitor_count()/monitor(),App::GetGPUMemoryStats(),App::is_profiler_active()/profiler_trace_path(),AppListener::OnIdle()Window::CreatePopup(),Window::ShowWhenReady(),Window::AddPanel()/AdoptPanel()/BuildLayout()/layout()/foreground()/FindPanel()/focused_panel()/ClearFocus(),Window::SetBackdrop(),Window::SetBackgroundColor(),Window::SetCaptionColor(),Window::SetCornerStyle(),Window::SetHitTestRegions(),Window::SetWindowButtons(),Window::BeginDragMove()/BeginDragResize(),Window::Maximize()/Minimize()/Restore(),Window::SetIcon(),Window::TakeScreenshot(),Window::Invalidate(),Window::device_width()/device_height(),Window::LogicalToDevice()/DeviceToLogical(),Window::OnFocusChange()/OnEditableStateChange()Monitor::device_width()/device_height()- JavaScriptCore:
JSObjectMakeFunctionWithData(),JSObjectGetPropertiesUTF8()/SetPropertiesUTF8()/MakeWithPropertiesUTF8()/GetOwnEntriesUTF8()/DefinePropertyUTF8()/DefineAccessorUTF8(),JSObjectFreeze(),JSObjectMakeTypedError(),JSValueGetErrorDetails(),JSValueIsFunctionObject(),JSPromiseGetStatus()/GetResult()/MarkAsHandled(),JSArrayBufferDetach()/IsDetached(),JSObjectSetExternalMemoryHint(),JSClassGetPrivate()/SetPrivate()
Changes to Existing API:
View::LockJSContext(),View::JavaScriptVM(), andView::EvaluateScript()now accept an optionalframeparameter to target a specific frameGPUStatestruct has new fields:blend_src_factor,blend_dst_factor,blend_equation,texture_4_id,uniform_integer[8]ShaderTypehas five new values,VertexBufferFormathas_2f_2ui(withVertex_2f_2ui), andCommandTypehasFlushBitmapFormatenum has eight new values:RG8_UNORM,BC1_UNORM,BC2_UNORM,BC3_UNORM,BC7_UNORM,RGBA16F,RGBA16UI,RGBA32FMouseEvent::ButtonhaskButton_BackandkButton_Forward;ScrollEventhasxandy(default-1)MessageSourcehaskMessageSource_NativeAPIBitmapderives fromWeakRefCountedViewConfigstruct has new fields:background_color,preferred_color_scheme,enable_compositor_debug_info,enable_canvas_filters(default true),match_native_editing_behavior,clipboard_read_policy,enable_hidden_timer_throttling,max_render_fps,allow_universal_access_from_file_urls(default true),javascript_can_open_windows_automatically,font_family_cursive,font_family_fantasy,font_family_pictograph,font_size_default,font_size_fixedViewConfig::enable_compositordefault changed from false to true (compositor enabled by default)ViewConfig::user_agentdefaults toULTRALIGHT_USER_AGENT, which reports the host platformConfigstruct has new fields:font_profile,font_blend_mode,font_contrast,font_stem_darkening,font_embolden,enable_photon,enable_photon_text,photon_text_min_px,page_settle_delay,page_settle_cycles,page_settle_tick,idle_gc_enabled,idle_gc_idle_time,memory_profile,max_heap_size,ignore_ssl_errors,use_system_certificate_store,paint_full_layers,resource_sample_interval,diagnostics,media_profile(Pro edition and above)Config::memory_cache_sizedefault changed from 64 MiB to 256 MiBConfig::recycle_delaydefault changed from 4.0 to 0.5 seconds and is now the automatic recycle interval; 0 disables the automatic recyclerConfig::font_gammadefault changed from 1.8 to 0 (inherit fromfont_profile);Config::min_large_heap_sizedefault changed from 32 MiB to 0 (derive frommemory_profile)Settingsstruct has new fields:device_scale_override,auto_font_profile,auto_font_families,match_native_editing_behavior,idle_threshold,sustained_idle_time,idle_utilization_threshold,enable_profiler,headless_paint_fps,full_speed_loop,sync_animations_to_present,app_icon- Engine log messages start with a category tag, and
Debugmessages are not sent to theLoggerunlessConfig::diagnostics.min_log_levelis lowered Surface::set_dirty_bounds()adds to the dirty area instead of replacing itFontFilegains a pure virtualface_index()(only code that subclassesFontFileis affected)JSValueGetType()returns the newkJSTypeBigIntfor a BigInt (it returnedkJSTypeObject)Window::MoveTo(),x(), andy()use global screen coordinates spanning all monitors (1.4 was relative to the window's monitor)<AppCore/AppCore.h>no longer includes<JavaScriptCore/JavaScript.h>transitivelyJSClassDefinitiongainedprivateDataand the...Excallback union (version-0 definitions work unchanged; recompile)UL_COMPILER_GCC_LIKEis a presence macro (#if defined(...))- C API at full parity with the C++ API: every
Configfield has aulConfigSet*setter, and about 590 new functions cover the DOM, JavaScript, Editor, Layout, URL, Color, and window surfaces
Deprecated:
Renderer::RenderOnly()andulRenderOnly()(useRender(), which skips hidden Views, and hide a View withView::set_visible(false))
Removed:
Overlay(<AppCore/Overlay.h>) and theULOverlayC API, replaced byPanel(<AppCore/layout/Panel.h>,ULPanel)<AppCore/JSHelpers.h>and everything it declaredSettings::load_shaders_from_file_systemandulSettingsSetLoadShadersFromFileSystem(the setting had no effect; shaders are always loaded from memory)Config::animation_timer_delay,Config::scroll_timer_delay,ulConfigSetAnimationTimerDelay(),ulConfigSetScrollTimerDelay()Clipboard::ReadPlainText(),Clipboard::WritePlainText()Window::screen_width(),screen_height(),ScreenToPixels(),PixelsToScreen()and their C mirrors
Major Bugfixes
GPU Renderer:
- Fix issue with premultiplied alpha being applied twice when drawing glyphs in GPU renderer
- Fix issue with transforms not being applied to glyphs when drawing with GPU renderer
- Fix issue where inverse clipping masks were ignored in GPU renderer
- Fix issue with clipping, box shadows, drop shadows, and blurs in GPU renderer
- Fix clipping issue in
CanvasGPU(scissor rect wasn't being offset in created layers) - Fix Image synchronization issue in GPU renderer
- Fix GPU stroke rendering for collinear path segments
- Fix nested clips on the GPU canvas blanking the clipped content
- Fix
globalCompositeOperationbeing ignored insidectx.clip(), and destination-out / source-atop / xor / source-out falling through as source-over on direct GPU canvas draws - Fix
clearRect()ignoring an active path clip on the GPU canvas - Fix vector content inside opacity, mask, clip-path, and blend groups rendering without edge antialiasing
- Fix pooled render-target reuse corrupting transparency layers on some driver stacks (block dropouts on NVIDIA D3D11)
- Fix a draw sampling the texture that backs its own render target, which D3D11 and D3D12 silently voided
- Fix an access violation in the D3D12 driver on blend modes with a
*_COLORfactor (such as Screen) - Fix CSS repeating gradients clamping at 11 stops on the GPU
- Fix GPU radial gradients using an approximation instead of the exact two-point conical solve
- Fix dashed strokes at small user units (lost dots, dash-phase drift, fused subpaths) and seams at dash boundaries
- Fix an open path starting at the origin losing its first point, which cropped the leading half of rules and progress tracks
- Fix canvas-backed patterns rendering blank for dense fill regions
- Fix a hard crash when a box shadow spanning an extreme area exceeded
Bitmap::MaxDimension - Bound GPU path tessellation so pathological paths degrade instead of filling the geometry buffer
- Replace the modal message boxes the D3D11 and D3D12 drivers showed on GPU resource failures with logger warnings
CPU Renderer:
- Fix issue with
DrawCanvasnot applying alpha when drawing with CPU renderer - Fix canvas
globalAlphaand SVGstroke-opacitypainting fully opaque on the CPU renderer - Fix canvas full-canvas composite operations (
source-in,source-out,destination-in,destination-atop) rendering blank on the CPU canvas - Fix a crash and diagonal shear in CPU SVG reference filters when the filtered region width was not a multiple of 4 pixels
- Fix a transparent CPU View or popup hanging on first paint
- Fix issue with CPU renderer not using AVX2 during runtime when available
Canvas:
- Fix issue drawing CPU-backed ImageBuffers to GPU-backed GraphicsContext (texture corruption)
- Fix
CanvasRenderingContext2D.filteron detached canvases - Fix crash in
CanvasGPU.ccwhen drawing GPU canvases to other GPU canvases - Fix crash from unmatched save/restore in GPU canvas replay
- Fix canvas-source copies on the GPU backend (point-in-time snapshots,
OffscreenCanvasplaceholder commits, transferring contextless canvases)
Compositor & TextureMapper:
- Fix GPU
BitmapTexturePoolreusing textures while deferred commands still reference them - Fix issue with texture mapper updating tile with fractional device scale
- Fix issue with
TextureMapperlayers being clipped to document bounds - Fix stale tiles being retained across a tile-layout change, which composited content twice and double-blended transparent Views
- Fix
clip-pathrendering blank on composited layers and on SVG roots - Fix potential overflow in
TextureMapperTiledBackingStore::createOrDestroyTilesIfNeeded - Fix issue where logical frame rect wasn't properly rounded up with fractional device scale
- Fix black flash in compositor (force clear to white when View is not transparent)
- Fix flicker during
View::Resize - Fix inline text not repainting when block dimensions are unchanged
- Fix re-entrant layer flush requests being dropped, which caused occasional partial repaints
- Fix antialiasing being silently stripped from content tiles when the texture pool returned a single-sample intermediate
- Fix the backdrop-filter snapshot including content painted above the element
- Fix overlay scrollbars painting over elements stacked above their scroller
CSS, Layout & Text:
- Fix drawing issue with
background-clip: text - Fix
background-clip: textclipping under opacity - Fix CSS transitions losing to
!importantdeclarations (transitions now take precedence per the CSS cascade spec) - Fix dashed and dotted straight borders painting solid
- Fix thin rounded borders dropping a side, outlines on pill-shaped boxes painting square corners, and collapsed table borders disappearing at fractional device scales
- Fix SVG gradient rendering (apply gradient-space transform) and SVG
spreadMethodbeing dropped - Fix dashed SVG circles and ellipses (including
pathLengthprogress rings) rendering solid - Fix SVG markers placed at subdivision vertices instead of authored vertices, and markers dropped from gradient-stroked paths
- Fix SVG
clipPathshapes inobjectBoundingBoxunits clipping with visible facets - Fix bounding-box reporting for individual SVG
<tspan>elements - Fix SVG text fill covering a neighboring glyph's stroke
- Fix gradient and pattern brushes on SVG text stroke and canvas
strokeText()rendering black - Fix undefined SVG filter inputs failing the whole filter, filter output sized to the content box instead of the filter region, and
feConvolveMatrixbias being ignored on the GPU - Fix CSS basic filters being applied in premultiplied space (color correctness)
- Fix CSS non-separable blend modes (HSL, soft-light) to match the W3C spec
- Fix stroke state (dash, cap, join, miter) leaking between elements
- Fix sizing of absolutely-positioned replaced elements from
inset - Fix variable-font advance widths
- Fix macOS system font families always opening face 0 (all weights rendered the first face with synthetic bold and oblique) and Apple Color Emoji sitting about 1/8 em too high
- Fix COLRv1 color fonts rendering as monochrome outlines
- Fix a family inside a
.ttcfont collection rendering the collection's first face - Fix
system-uiandBlinkMacSystemFontfalling through to the fallback font on macOS - Fix the engine font cache serving the wrong face on a hash collision
- Fix crash with
color-mix()in color property - Fix hang in CSS gamut mapping with NaN inputs
- Fix progressive WebP decode corruption (large WebP images intermittently rendering blank or with doubled semi-transparent regions)
Stability & Crashes:
- Fix crash in path triangulation
- Fix use-after-free in the texture atlas during recycling
- Fix crash during resource loads
- Fix JS engine crash after idle footprint shrink in pages using JS modules
- Fix font thread-race crashes under WebWorker / OffscreenCanvas
- Fix a stack-overflow crash when a thread's first park was contended (customer map-search crash)
- Fix an intermittent hang at process exit (roughly one in 15-30 launches) in the allocator's thread-local cache teardown
- Fix a hang under heavy JavaScript JIT tier-up where a worker thread exiting mid-registration orphaned a global lock
- Fix the renderer freezing when a page constructed
Intl.DateTimeFormatfor a locale absent from the trimmed ICU data - Fix a crash in the matched-declarations cache sweep when a style resolver was destroyed mid-iteration (reproducible on Reddit)
- Fix
ReportingObserverkeeping whole documents alive after navigation (about 24 detached documents leaked per StackOverflow visit) - Fix a crash after destroying and re-creating a Renderer (ICU data ownership)
- Fix a crash in
View::LockJSContext()andView::JavaScriptVM()on Views with JavaScript disabled (both now return null) - Fix a View's Surface being destroyed through its destructor instead of
SurfaceFactory::DestroySurface() - Fix a teardown race where a worker thread could still be releasing engine objects while the painter was destroyed
- Fix
Config::min_large_heap_sizeandmin_small_heap_sizenever reaching JavaScriptCore
Media:
- Fix seeks that never finalized when the target was past the last video frame
- Fix a seek that resumed into the paused state never showing the post-seek frame
- Fix audio remaining audible ahead of the picture after a scrub, and a false
endedafter a seek - Fix
canPlayType()advertising Vorbis, for which no decoder exists
Input & Scrolling:
- Fix numerical instability in smooth scroll at low framerates
- Fix scroll wheel events not working properly with Retina DPI scaling on macOS
- Fix composited scroll advancing in groups of device pixels at scales other than 1.0
- Fix
position: fixedandposition: stickycontent drifting or shimmering during fractional-scale scroll - Fix issue where hover state wouldn't be updated when mouse leaves a View
- Fix
GetKeyFromVirtualKeyCodeto map space, escape, numpad, and special keys per W3C spec - Fix
ClearFocus()leaving a pending focus grant armed - Fix right-click not dispatching
contextmenuon the page - Fix Ctrl- and Shift-click when key events are built from Windows messages
- Fix the legacy
wheelDeltareading about 11520 per notch instead of 120 - Fix
gamepad.idbeing empty (the gamepad name was reported ingamepad.mapping)
View, Session & Downloads:
- Fix
window.close()never reachingViewListener::OnRequestClose(),View::CancelDownload()not stopping the transfer, andOnUpdateHistory()not firing - Fix every navigation download reporting id 0
- Fix in-memory Sessions writing
localStorageto disk and sharing it with any same-named Session
C API:
- Fix
ulCreateRenderer()returning a non-NULL handle when the renderer failed to create - Fix a second
ULViewhandle for the same View turning off the callbacks set through the first - Fix
ulViewSetCreateInspectorViewCallback()never firing
Platform & Build:
- Fix issue on Windows where idle run loop wouldn't wake on external
SendMessage()call - Fix a timer destroying itself from its own callback having its
user_datafreed while the callback ran - Fix
App::Create()installing the built-in profiler over one the embedder had set - Fix the reference
FileLoggerwriting from several threads without a lock - Fix POSIX absolute paths failing to load through
file:URLs - Fix
Lockhaving a layout that varied with the consumer'sNDEBUGsetting - Fix SDK build presets defaulting to Debug under the Visual Studio multi-config generator
- Fix
StringSTL'sConvert()failing to compile for string literals