1 /// License: MIT 2 module ultralight; 3 4 import std.conv: to; 5 import std.string: fromStringz, toStringz; 6 7 import ultralight.bindings; 8 public import ultralight.enums; 9 10 /// Global configuration singleton, manages user-defined configuration. 11 static Config config; 12 13 /// Create the `Renderer` singleton. 14 static this() { 15 config = Config(ulCreateConfig()); 16 } 17 18 /// See_Also: https://ultralig.ht/api/c/1_3_0/_c_a_p_i___string_8h.html 19 class String { 20 /// 21 ULString ptr; 22 23 package this(ULString str) { 24 assert(str); 25 ptr = str; 26 } 27 /// Create string from a D string. 28 this(string source) { 29 ptr = ulCreateString(source.toStringz); 30 } 31 /// Destroy string (you should destroy any strings you explicitly Create). 32 ~this() { 33 assert(ptr); 34 ulDestroyString(ptr); 35 ptr = null; 36 } 37 38 /// Create string from a UTF-8 buffer. 39 String utf8(string str) { 40 return new String(ulCreateStringUTF8(str.ptr, str.length)); 41 } 42 43 /// Create string from a UTF-16 buffer. 44 String utf16(wstring str) { 45 return new String(ulCreateStringUTF16(cast(ushort*) str.ptr, str.length)); 46 } 47 48 /// Create string from copy of this string. 49 String idup() { 50 return new String(ulCreateStringFromCopy(ptr)); 51 } 52 53 /// Whether this string is empty or not. 54 bool empty() const { 55 return ulStringIsEmpty(cast(C_String*) ptr); 56 } 57 58 /// Replaces the contents of this string with the contents of a string. 59 auto opAssign(T)(string str) { 60 ulStringAssignCString(ptr, str.toStringz); 61 return this; 62 } 63 64 /// Replaces the contents of this string with the contents of `str`. 65 auto opAssign(T)(String str) { 66 ulStringAssignString(ptr, str.ptr); 67 return this; 68 } 69 70 /// Replaces the contents of this string with the contents of `str`. 71 auto opAssign(T)(ULString str) { 72 ulStringAssignString(ptr, str); 73 return this; 74 } 75 76 /// 77 override string toString() const @trusted nothrow { 78 import std.exception : assumeWontThrow; 79 80 return assumeWontThrow( 81 ulStringGetData(cast(C_String*) ptr)[0 .. ulStringGetLength(cast(C_String*) ptr)].to!string 82 ); 83 } 84 } 85 86 /// Convert a `string` to an Ultralight `String`. 87 String toUlString(string str) { 88 return new String(str); 89 } 90 91 /// Convert an unmanaged Ultralight string directly to a managed `string`. 92 /// Remarks: This makes a copy of the unmanaged string. 93 string toString(ULString str) { 94 return ulStringGetData(str)[0 .. ulStringGetLength(str)].to!string.idup; 95 } 96 97 /// See_Also: https://ultralig.ht/api/c/1_3_0/_c_a_p_i___config_8h.html 98 struct Config { 99 /// 100 ULConfig ptr; 101 102 ~this() { 103 assert(ptr); 104 ulDestroyConfig(ptr); 105 ptr = null; 106 } 107 108 /// A writable OS file path to store persistent Session data in. 109 static void setCachePath(string cachePath) { 110 ulConfigSetCachePath(config.ptr, cachePath.toUlString.ptr); 111 } 112 113 /// The relative path to the resources folder (loaded via the FileSystem API). 114 static void setResourcePathPrefix(string resourcePathPrefix) { 115 ulConfigSetResourcePathPrefix(config.ptr, resourcePathPrefix.toUlString.ptr); 116 } 117 118 /// The winding order for front-facing triangles. 119 static void setFaceWinding(FaceWinding winding) { 120 ulConfigSetFaceWinding(config.ptr, winding); 121 } 122 123 /// The hinting algorithm to use when rendering fonts. 124 static void setFontHinting(FontHinting fontHinting) { 125 ulConfigSetFontHinting(config.ptr, fontHinting); 126 } 127 128 /// The gamma to use when compositing font glyphs, change this value to adjust contrast (Adobe and Apple prefer 1.8, others may prefer 2.2). 129 static void setFontGamma(double fontGamma) { 130 ulConfigSetFontGamma(config.ptr, fontGamma); 131 } 132 133 /// Global user-defined CSS string (included before any CSS on the page). 134 static void setUserStylesheet(string cssString) { 135 ulConfigSetUserStylesheet(config.ptr, cssString.toUlString.ptr); 136 } 137 138 /// Whether or not to continuously repaint any Views, regardless if they are dirty. 139 static void setForceRepaint(bool enabled) { 140 ulConfigSetForceRepaint(config.ptr, enabled); 141 } 142 143 /// The delay (in seconds) between every tick of a CSS animation. 144 static void setAnimationTimerDelay(double delay) { 145 ulConfigSetAnimationTimerDelay(config.ptr, delay); 146 } 147 148 /// The delay (in seconds) between every tick of a smooth scroll animation. 149 static void setScrollTimerDelay(double delay) { 150 ulConfigSetScrollTimerDelay(config.ptr, delay); 151 } 152 153 /// The delay (in seconds) between every call to the recycler. 154 static void setRecycleDelay(double delay) { 155 ulConfigSetRecycleDelay(config.ptr, delay); 156 } 157 158 /// The size of WebCore's memory cache in bytes. 159 static void setMemoryCacheSize(uint size) { 160 ulConfigSetMemoryCacheSize(config.ptr, size); 161 } 162 163 /// The number of pages to keep in the cache. 164 static void setPageCacheSize(uint size) { 165 ulConfigSetPageCacheSize(config.ptr, size); 166 } 167 168 /// The system's physical RAM size in bytes. 169 static void setOverrideRAMSize(uint size) { 170 ulConfigSetOverrideRAMSize(config.ptr, size); 171 } 172 173 /// The minimum size of large VM heaps in JavaScriptCore. 174 static void setMinLargeHeapSize(uint size) { 175 ulConfigSetMinLargeHeapSize(config.ptr, size); 176 } 177 178 /// The minimum size of small VM heaps in JavaScriptCore. 179 static void setMinSmallHeapSize(uint size) { 180 ulConfigSetMinSmallHeapSize(config.ptr, size); 181 } 182 183 /// The number of threads to use in the Renderer (for parallel painting on the CPU, etc.). 184 static void setNumRendererThreads(uint numRendererThreads) { 185 ulConfigSetNumRendererThreads(config.ptr, numRendererThreads); 186 } 187 188 /// The max amount of time (in seconds) to allow repeating timers to run during each call to `Renderer.update`. 189 static void setMaxUpdateTime(double maxUpdateTime) { 190 ulConfigSetMaxUpdateTime(config.ptr, maxUpdateTime); 191 } 192 193 /// The alignment (in bytes) of the BitmapSurface when using the CPU renderer. 194 static void setBitmapAlignment(uint bitmapAlignment) { 195 ulConfigSetBitmapAlignment(config.ptr, bitmapAlignment); 196 } 197 } 198 199 /// See_Also: https://ultralig.ht/api/c/1_3_0/_c_a_p_i___renderer_8h.html 200 class Renderer { 201 /// 202 ULRenderer ptr; 203 204 /// Create a new renderer given Ultralight's default configuration. 205 this() { 206 this(config); 207 } 208 /// Create a new renderer. 209 this(Config config) { 210 assert(config.ptr); 211 ptr = ulCreateRenderer(config.ptr); 212 } 213 ~this() { 214 ulDestroyRenderer(ptr); 215 } 216 217 /// Create a Session to store local data in (such as cookies, local storage, application cache, indexed db, etc). 218 Session createSession(bool isPersistent, string name) { 219 return this.createSession(isPersistent, name.toUlString); 220 } 221 /// ditto 222 Session createSession(bool isPersistent, String name) { 223 return new Session(ulCreateSession(ptr, isPersistent, name.ptr)); 224 } 225 226 /// Get the default session (persistent session named "default"). 227 Session defaultSession() { 228 return new Session(ulDefaultSession(ptr)); 229 } 230 231 /// Update timers and dispatch internal callbacks (JavaScript and network). 232 void update() { 233 ulUpdate(ptr); 234 } 235 236 /// Render all active Views. 237 void render() { 238 ulRender(ptr); 239 } 240 241 /// Attempt to release as much memory as possible. 242 void purgeMemory() { 243 ulPurgeMemory(ptr); 244 } 245 246 /// Print detailed memory usage statistics to the log. 247 void logMemoryUsage() { 248 ulLogMemoryUsage(ptr); 249 } 250 251 /// Start the remote inspector server. 252 bool startRemoteInspectorServer(string address, ushort port) { 253 return ulStartRemoteInspectorServer(ptr, address.toStringz, port); 254 } 255 256 /// Describe the details of a gamepad, to be used with `ulFireGamepadEvent` and related events below. 257 void setGamepadDetails(uint index, string id, uint axis_count, uint button_count) { 258 ulSetGamepadDetails(ptr, index, cast(C_String*) id.toStringz, axis_count, button_count); 259 } 260 261 /// Fire a gamepad event (connection / disconnection). 262 void fireGamepadEvent(ULGamepadEvent evt) { 263 ulFireGamepadEvent(ptr, evt); 264 } 265 266 /// Fire a gamepad axis event (to be called when an axis value is changed). 267 void fireGamepadAxisEvent(ULGamepadAxisEvent evt) { 268 ulFireGamepadAxisEvent(ptr, evt); 269 } 270 271 /// Fire a gamepad button event (to be called when a button value is changed). 272 void fireGamepadButtonEvent(ULGamepadButtonEvent evt) { 273 ulFireGamepadButtonEvent(ptr, evt); 274 } 275 } 276 277 /// Global platform singleton, manages user-defined platform handlers. 278 /// See_Also: https://ultralig.ht/api/c/1_3_0/_c_a_p_i___platform_8h.html 279 class Platform { 280 /// 281 static void enablePlatformFontLoader() { 282 ulEnablePlatformFontLoader(); 283 } 284 285 /// 286 static void enablePlatformFileSystem(string baseDir) { 287 ulEnablePlatformFileSystem(baseDir.toUlString.ptr); 288 } 289 290 /// Set a custom Logger implementation. 291 static void setLogger(ULLogger logger) { 292 ulPlatformSetLogger(logger); 293 } 294 295 /// Set a custom FileSystem implementation. 296 static void setFileSystem(ULFileSystem file_system) { 297 ulPlatformSetFileSystem(file_system); 298 } 299 300 /// Set a custom Surface implementation. 301 static void setSurfaceDefinition(ULSurfaceDefinition surface_definition) { 302 ulPlatformSetSurfaceDefinition(surface_definition); 303 } 304 305 /// Set a custom GPUDriver implementation. 306 static void setGPUDriver(ULGPUDriver gpu_driver) { 307 ulPlatformSetGPUDriver(gpu_driver); 308 } 309 310 /// Set a custom Clipboard implementation. 311 static void setClipboard(ULClipboard clipboard) { 312 ulPlatformSetClipboard(clipboard); 313 } 314 } 315 316 /// See_Also: `Renderer.createSession` 317 /// See_Also: `Renderer.defaultSession` 318 /// See_Also: https://ultralig.ht/api/c/1_3_0/_c_a_p_i___session_8h.html 319 class Session { 320 /// 321 ULSession ptr; 322 323 package this(ULSession ptr) { 324 assert(ptr); 325 this.ptr = ptr; 326 } 327 /// Destroy a Session. 328 ~this() { 329 ulDestroySession(ptr); 330 } 331 332 /// Whether or not is persistent (backed to disk). 333 bool isPersistent() { 334 return ulSessionIsPersistent(ptr); 335 } 336 337 /// Unique name identifying the session (used for unique disk path). 338 string name() { 339 return ulSessionGetName(ptr).toString; 340 } 341 342 /// Unique numeric ID for the session. 343 ulong getId() { 344 return ulSessionGetId(ptr); 345 } 346 347 /// The disk path to write to (used by persistent sessions only). 348 string getDiskPath() { 349 return ulSessionGetDiskPath(ptr).toString; 350 } 351 } 352 353 /// View is a web-page container rendered to an offscreen surface that you display yourself. 354 /// 355 /// The View object is responsible for loading and rendering web-pages to an offscreen surface. 356 /// It is completely isolated from the OS windowing system, you must forward all input events to it from your application. 357 /// 358 /// Remarks: The API is not thread-safe, all calls must be made on the same thread that the Renderer/App was created on. 359 /// See_Also: https://ultralig.ht/api/c/1_3_0/_c_a_p_i___view_8h.html 360 class View { 361 } 362 363 /// See_Also: https://ultralig.ht/api/c/1_3_0/_c_a_p_i___surface_8h.html 364 class Surface { 365 } 366 367 /// See_Also: https://ultralig.ht/api/c/1_3_0/_c_a_p_i___bitmap_8h.html 368 class Bitmap { 369 /// 370 ULBitmap ptr; 371 private bool owned = true; 372 373 /// Create empty bitmap. 374 this() { 375 this(ulCreateEmptyBitmap()); 376 } 377 /// Create bitmap with certain dimensions and pixel format. 378 this(uint width, uint height, BitmapFormat format) { 379 this(ulCreateBitmap(width, height, format)); 380 } 381 /// 382 package this(ULBitmap ptr) { 383 assert(ptr); 384 this.ptr = ptr; 385 this.owned = this.ownsPixels; 386 } 387 /// Destroy a bitmap. 388 /// Remarks: You should only destroy Bitmaps you have explicitly created via one of the creation functions above. 389 ~this() { 390 if (owned) 391 ulDestroyBitmap(ptr); 392 } 393 394 /// Create bitmap from existing pixel buffer. 395 static Bitmap fromPixels( 396 uint width, uint height, BitmapFormat format, uint row_bytes, ubyte[] pixels, bool should_copy = true 397 ) { 398 return new Bitmap( 399 ulCreateBitmapFromPixels(width, height, format, row_bytes, pixels.ptr, pixels.length, should_copy) 400 ); 401 } 402 403 /// Create bitmap from copy. 404 static Bitmap fromCopy(Bitmap existingBitmap) { 405 return new Bitmap(ulCreateBitmapFromCopy(existingBitmap.ptr)); 406 } 407 408 /// Get the width in pixels. 409 uint width() const { 410 return ulBitmapGetWidth(cast(C_Bitmap*) ptr); 411 } 412 413 /// Get the height in pixels. 414 uint height() const { 415 return ulBitmapGetHeight(cast(C_Bitmap*) ptr); 416 } 417 418 /// Get the pixel format. 419 BitmapFormat format() const { 420 return ulBitmapGetFormat(cast(C_Bitmap*) ptr).to!uint.to!BitmapFormat; 421 } 422 423 /// Get the bytes per pixel. 424 uint bpp() const { 425 return ulBitmapGetBpp(cast(C_Bitmap*) ptr); 426 } 427 428 /// Get the number of bytes per row. 429 uint rowBytes() const { 430 return ulBitmapGetRowBytes(cast(C_Bitmap*) ptr); 431 } 432 433 /// Get the size in bytes of the underlying pixel buffer. 434 size_t size() const { 435 return ulBitmapGetSize(cast(C_Bitmap*) ptr); 436 } 437 438 /// Whether or not this bitmap owns its own pixel buffer. 439 bool ownsPixels() const { 440 return ulBitmapOwnsPixels(cast(C_Bitmap*) ptr); 441 } 442 443 /// Lock pixels for reading/writing. 444 /// Returns: Slice of pixel buffer. 445 ubyte[] lockPixels() { 446 return cast(ubyte[]) ulBitmapLockPixels(ptr)[0 .. this.size]; 447 } 448 449 /// Unlock pixels after locking. 450 void unlockPixels() { 451 ulBitmapUnlockPixels(ptr); 452 } 453 454 /// Get raw pixel buffer. 455 /// 456 /// You should only call this if Bitmap is already locked. 457 ubyte[] rawPixels() { 458 return cast(ubyte[]) ulBitmapRawPixels(ptr)[0 .. this.size]; 459 } 460 461 /// Whether or not this bitmap is empty. 462 bool isEmpty() { 463 return ulBitmapIsEmpty(ptr); 464 } 465 466 /// Reset bitmap pixels to 0. 467 void erase() { 468 ulBitmapErase(ptr); 469 } 470 471 /// Write bitmap to a PNG on disk. 472 bool writePng(string path) { 473 return ulBitmapWritePNG(ptr, path.toStringz); 474 } 475 476 /// Converts a BGRA bitmap to RGBA bitmap and vice-versa by swapping the red and blue channels. 477 void swapRedBlueChannels() { 478 ulBitmapSwapRedBlueChannels(ptr); 479 } 480 } 481 482 /// See_Also: https://ultralig.ht/api/c/1_3_0/_c_a_p_i___mouse_event_8h.html 483 class MouseEvent { 484 /// 485 ULMouseEvent ptr; 486 487 /// Create a mouse event. 488 this() { 489 } 490 491 ~this() { 492 assert(ptr); 493 ulDestroyMouseEvent(ptr); 494 ptr = null; 495 } 496 } 497 498 /// See_Also: https://ultralig.ht/api/c/1_3_0/_c_a_p_i___key_event_8h.html 499 class KeyEvent { 500 /// 501 ULKeyEvent ptr; 502 503 /// Create a key event. 504 this() { 505 } 506 507 ~this() { 508 assert(ptr); 509 ulDestroyKeyEvent(ptr); 510 ptr = null; 511 } 512 } 513 514 /// See_Also: https://ultralig.ht/api/c/1_3_0/_c_a_p_i___scroll_event_8h.html 515 class ScrollEvent { 516 /// 517 ULScrollEvent ptr; 518 519 /// Create a scroll event. 520 this() { 521 } 522 523 ~this() { 524 assert(ptr); 525 ulDestroyScrollEvent(ptr); 526 ptr = null; 527 } 528 } 529 530 /// See_Also: https://ultralig.ht/api/c/1_3_0/_c_a_p_i___gamepad_event_8h.html 531 class GamepadEvent { 532 /// 533 ULGamepadEvent ptr; 534 535 /// Create a gamepad event. 536 this() { 537 } 538 539 ~this() { 540 assert(ptr); 541 ulDestroyGamepadEvent(ptr); 542 ptr = null; 543 } 544 } 545 546 /// Get the version string of the library in MAJOR.MINOR.PATCH format. 547 /// See_Also: https://ultralig.ht/api/c/1_3_0/_c_a_p_i___defines_8h.html 548 string version_() { 549 return ulVersionString().fromStringz.to!string; 550 } 551 552 /// Get the numeric major version of the library. 553 /// See_Also: https://ultralig.ht/api/c/1_3_0/_c_a_p_i___defines_8h.html 554 uint versionMajor() { 555 return ulVersionMajor(); 556 } 557 558 /// Get the numeric minor version of the library. 559 /// See_Also: https://ultralig.ht/api/c/1_3_0/_c_a_p_i___defines_8h.html 560 uint versionMinor() { 561 return ulVersionMinor(); 562 } 563 564 /// Get the numeric patch version of the library. 565 /// See_Also: https://ultralig.ht/api/c/1_3_0/_c_a_p_i___defines_8h.html 566 uint versionPatch() { 567 return ulVersionPatch(); 568 } 569 570 /// Get the full WebKit version string. 571 /// See_Also: https://ultralig.ht/api/c/1_3_0/_c_a_p_i___defines_8h.html 572 string webKitVersion() { 573 return ulWebKitVersionString().fromStringz.to!string; 574 }