diff options
Diffstat (limited to '')
930 files changed, 47116 insertions, 0 deletions
diff --git a/gfx/wr/wrench/.gitignore b/gfx/wr/wrench/.gitignore new file mode 100644 index 0000000000..341d13d0f7 --- /dev/null +++ b/gfx/wr/wrench/.gitignore @@ -0,0 +1,7 @@ +Cargo.lock +target/ +*# +*~ +yaml_frames/ +json_frames/ +bin_frames/ diff --git a/gfx/wr/wrench/Cargo.toml b/gfx/wr/wrench/Cargo.toml new file mode 100644 index 0000000000..0b3bafc0e7 --- /dev/null +++ b/gfx/wr/wrench/Cargo.toml @@ -0,0 +1,68 @@ +[package] +name = "wrench" +version = "0.3.0" +authors = ["Vladimir Vukicevic <vladimir@pobox.com>"] +build = "build.rs" +license = "MPL-2.0" +edition = "2018" + +[dependencies] +base64 = "0.12" +env_logger = { version = "0.5", optional = true } +gleam = "0.13" +glutin = "0.21" +clap = { version = "2", features = ["yaml"] } +log = "0.4" +yaml-rust = "0.4" +serde_json = "1.0" +time = "0.1" +chrono = "0.2" +crossbeam = "0.2" +osmesa-sys = { version = "0.1.2", optional = true } +osmesa-src = { version = "0.2", git = "https://github.com/servo/osmesa-src", optional = true } +webrender = { path = "../webrender", features = ["capture", "replay", "debugger", "png", "profiler", "no_static_freetype", "leak_checks"] } +winit = "0.19" +serde = { version = "1.0", features = ["derive"] } +semver = "0.9.0" +swgl = { path = "../swgl", optional = true } +tracy-rs = "0.1.2" + +[dependencies.image] +version = "0.23" +default-features = false +features = ["png"] + +[target.'cfg(target_os = "macos")'.dependencies] +core-graphics = "0.22" +core-foundation = "0.9" + +[features] +default = [ "env_logger" ] +headless = [ "osmesa-sys", "osmesa-src" ] +software = [ "swgl" ] + +[target.'cfg(target_os = "windows")'.dependencies] +dwrote = "0.11" +mozangle = { version = "0.3.2", features = ["egl"] } + +[target.'cfg(all(unix, not(target_os = "android")))'.dependencies] +font-loader = "0.11" + +# Configuration information used when building wrench as an APK. +[package.metadata.android] +package_name = "org.mozilla.wrench" +label = "Wrench" +android_version = 29 +target_sdk_version = 18 +min_sdk_version = 18 +fullscreen = true +build_targets = [ "armv7-linux-androideabi", "i686-linux-android" ] +opengles_version_major = 3 +opengles_version_minor = 0 +[package.metadata.android.application_attributes] +"android:hardwareAccelerated" = "true" +[package.metadata.android.activity_attributes] +"android:screenOrientation" = "unspecified" +"android:uiOptions" = "none" +[[package.metadata.android.permission]] +name = "android.permission.READ_EXTERNAL_STORAGE" diff --git a/gfx/wr/wrench/README.md b/gfx/wr/wrench/README.md new file mode 100644 index 0000000000..6a60c6bb56 --- /dev/null +++ b/gfx/wr/wrench/README.md @@ -0,0 +1,26 @@ +# wrench + +`wrench` is a tool for debugging webrender outside of a browser engine. + +## Build + +Build `wrench` with `cargo build --release` within the `wrench` directory. + +## headless + +`wrench` has an optional headless mode for use in continuous integration. To run in headless mode, instead of using `cargo run -- args`, use `./headless.py args`. + +## `show` + +If you are working on gecko integration you can capture a frame via the following steps. +* Visit about:support and check that the "Compositing" value in the "Graphics" table says "WebRender". Enable `gfx.webrender.all` in about:config if necessary to enable WebRender. +* Hit ctrl-shift-3 to capture the frame. The data will be put in `~/wr-capture`. +* View the capture with `wrench show ~/wr-capture`. + +## `reftest` + +Wrench also has a reftest system for catching regressions. +* To run all reftests, run `script/headless.py reftest` +* To run specific reftests, run `script/headless.py reftest path/to/test/or/dir` +* To examine test failures, use the [reftest analyzer](https://hg.mozilla.org/mozilla-central/raw-file/tip/layout/tools/reftest/reftest-analyzer.xhtml) +* To add a new reftest, create an example frame and a reference frame in `reftests/` and then add an entry to `reftests/reftest.list` diff --git a/gfx/wr/wrench/android.txt b/gfx/wr/wrench/android.txt new file mode 100644 index 0000000000..35f5863c91 --- /dev/null +++ b/gfx/wr/wrench/android.txt @@ -0,0 +1,94 @@ +Running Wrench on Android devices. +================================== + +Setting up the environment: +--------------------------- + +Follow the steps at https://github.com/rust-windowing/android-rs-glue#setting-up-your-environment, with exceptions: + - No need to download the Android NDK and SDK, we will use the ones downloaded by Gecko in ~/.mozbuild/ + + - Install both the i686-linux-android and armv7-linux-androideabi rust + targets, as the APK will include native libraries with both architectures. + + - Don't install currently published version of cargo-apk as it doesn't work with the + version of winit and glutin we are using. + Instead, install the git master version of our fork like so: + cargo install --git https://github.com/jamienicol/android-rs-glue cargo-apk + + - Consider adding ~/.mozbuild/android-sdk-linux/platform-tools to your path, for the adb commands below. + +Compiling and running: +---------------------- + + Compile wrench: + cd wrench + export ANDROID_HOME=$HOME/.mozbuild/android-sdk-linux # exact path may vary + export NDK_HOME=$HOME/.mozbuild/android-ndk-r17b # exact path may vary + cargo apk build + + Install the APK: + adb install -r ../target/android-artifacts/debug/apk/wrench.apk + + Set command line arguments and env vars for wrench: + adb shell + mkdir /sdcard/wrench + echo "load reftests/aa/rounded-rects.yaml" >/sdcard/wrench/args + echo "env: WRENCH_REFTEST_CONDITION_EMULATOR=1" >>/sdcard/wrench/args # If you're using the emulator + echo "env: WRENCH_REFTEST_CONDITION_DEVICE=1" >>/sdcard/wrench/args # If you're using a device + exit + + Push reftests (if you need these files for what you're doing): + adb push reftests /sdcard/wrench/ + + Run the application: + adb shell am start -n org.mozilla.wrench/android.app.NativeActivity + (or click the icon in the launcher) + +Release mode: +------------- + + Building in release does work as well. Use the following steps to compile wrench: + cd wrench + export ANDROID_HOME=$HOME/.mozbuild/android-sdk-linux # exact path may vary + export NDK_HOME=$HOME/.mozbuild/android-ndk # exact path may vary + cargo apk build --release + + Now the APK at ../target/android-artifacts/release/apk/wrench.apk + should be signed and installable (you may need to uninstall the debug APK first if you + have that installed). + +Running reftests like a boss (on a local emulator): +--------------------------------------------------- + + First, compile wrench as described above (debug mode). + Then, from the root gecko source dir, run: + ./mach python testing/mozharness/scripts/android_wrench.py --config testing/mozharness/configs/android/wrench.py + This will automatically do the following: + - Download the blessed android AVDs from taskcluster + - Start the emulator (using your ~/.mozbuild/android-sdk-linux emulator binaries) + - Install the debug APK (from gfx/wr/wrench/target/android-artifacts/debug/apk/wrench.apk) + - Copy the reftests to the sdcard + - Write an args file to the sdcard + - Run wrench + - Wait for wrench to finish running + - Scrape the logcat for reftest output + Other logs (e.g. full logcat) can be found in your ~/.wrench/logs folder. Note that + this will also leave the android emulator running, so repeating the command will be + even faster the next time around as it won't need to redownload the AVDs or restart + the emulator. It will reinstall the APK and re-push the reftests folder though. + + If you want to use a release APK (runs much faster), build it as per the "Release mode" + instructions above and set the WRENCH_APK env var to point to the APK: + to point to it: + export WRENCH_APK=gfx/wr/target/android-artifacts/release/apk/wrench.apk + ./mach python testing/mozharness/scripts/android_wrench.py --config testing/mozharness/configs/android/wrench.py + +Running reftests like a boss (on a local device): +------------------------------------------------- + + Same steps as running on a local emulator, except you need to do this: + export DEVICE_SERIAL=<your device's serial> + before running the `./mach python` command. You can get the serial of + your device by running `adb devices` with the device plugged in. When running + on a device, the android_emulator_wrench.py script will skip the steps to + download the AVDs and start the emulator. diff --git a/gfx/wr/wrench/benchmarks/aligned-gradient.yaml b/gfx/wr/wrench/benchmarks/aligned-gradient.yaml new file mode 100644 index 0000000000..b0e2f0a645 --- /dev/null +++ b/gfx/wr/wrench/benchmarks/aligned-gradient.yaml @@ -0,0 +1,62 @@ +root: + items: + - type: gradient + bounds: [ 0, 0, 1980, 1080] + start: [ 0, -2000 ] + end: [ 0, 4000 ] + stops: [ 0.0, red, 1.0, green ] + repeat: false + - type: gradient + bounds: [ 0, 0, 1980, 1080] + start: [ 0, -2000 ] + end: [ 0, 4000 ] + stops: [ 0.0, red, 1.0, green ] + repeat: false + - type: gradient + bounds: [ 0, 0, 1980, 1080] + start: [ 0, -2000 ] + end: [ 0, 4000 ] + stops: [ 0.0, red, 1.0, green ] + repeat: false + - type: gradient + bounds: [ 0, 0, 1980, 1080] + start: [ 0, -2000 ] + end: [ 0, 4000 ] + stops: [ 0.0, red, 1.0, green ] + repeat: false + - type: gradient + bounds: [ 0, 0, 1980, 1080] + start: [ 0, -2000 ] + end: [ 0, 4000 ] + stops: [ 0.0, red, 1.0, green ] + repeat: false + - type: gradient + bounds: [ 0, 0, 1980, 1080] + start: [ 0, -2000 ] + end: [ 0, 4000 ] + stops: [ 0.0, red, 1.0, green ] + repeat: false + - type: gradient + bounds: [ 0, 0, 1980, 1080] + start: [ 0, -2000 ] + end: [ 0, 4000 ] + stops: [ 0.0, red, 1.0, green ] + repeat: false + - type: gradient + bounds: [ 0, 0, 1980, 1080] + start: [ 0, -2000 ] + end: [ 0, 4000 ] + stops: [ 0.0, red, 1.0, green ] + repeat: false + - type: gradient + bounds: [ 0, 0, 1980, 1080] + start: [ 0, -2000 ] + end: [ 0, 4000 ] + stops: [ 0.0, red, 1.0, green ] + repeat: false + - type: gradient + bounds: [ 0, 0, 1980, 1080] + start: [ 0, -2000 ] + end: [ 0, 4000 ] + stops: [ 0.0, red, 1.0, green ] + repeat: false diff --git a/gfx/wr/wrench/benchmarks/benchmarks.list b/gfx/wr/wrench/benchmarks/benchmarks.list new file mode 100644 index 0000000000..c7235dcfd2 --- /dev/null +++ b/gfx/wr/wrench/benchmarks/benchmarks.list @@ -0,0 +1,11 @@ +aligned-gradient.yaml +unaligned-gradient.yaml +simple-batching.yaml +large-boxshadow-ellipse.yaml +large-boxshadow-ellipse-2.yaml +large-clip-rect.yaml +transforms-simple.yaml +text-rendering.yaml +many-images.yaml +large-blur-radius.yaml + diff --git a/gfx/wr/wrench/benchmarks/box-shadow-large.yaml b/gfx/wr/wrench/benchmarks/box-shadow-large.yaml new file mode 100644 index 0000000000..83c8ce5326 --- /dev/null +++ b/gfx/wr/wrench/benchmarks/box-shadow-large.yaml @@ -0,0 +1,17 @@ +--- +root: + items: + - type: stacking-context + bounds: [0, 0, 1000, 1000] + items: + - type: box-shadow + bounds: [ 100, 100, 800, 800 ] + blur-radius: 20 + border-radius: { + top-left: [20, 20], + top-right: [10, 10], + bottom-left: [25, 25], + bottom-right: [100, 100], + } + color: blue + clip-mode: outset diff --git a/gfx/wr/wrench/benchmarks/clip-clear.yaml b/gfx/wr/wrench/benchmarks/clip-clear.yaml new file mode 100644 index 0000000000..f23440a3f1 --- /dev/null +++ b/gfx/wr/wrench/benchmarks/clip-clear.yaml @@ -0,0 +1,48 @@ +# Benchmark to test the cost of clears on a clip mask target that +# is large but has low usage. +--- +root: + items: + - + bounds: 0 0 1000 1000 + type: stacking-context + items: + - type: clip + bounds: [50, 50, 300, 300] + complex: + - rect: [50, 50, 300, 300] + radius: 50 + items: + - type: rect + bounds: 50 50 300 300 + color: red + - type: rect + bounds: 50 50 300 300 + color: red + - type: rect + bounds: 50 50 300 300 + color: red + - type: rect + bounds: 50 50 300 300 + color: red + - type: rect + bounds: 50 50 300 300 + color: red + - type: rect + bounds: 50 50 300 300 + color: red + - type: rect + bounds: 50 50 300 300 + color: red + - type: rect + bounds: 50 50 300 300 + color: red + - type: rect + bounds: 50 50 300 300 + color: red + - type: rect + bounds: 50 50 300 300 + color: red + - type: rect + bounds: 50 50 300 300 + color: red diff --git a/gfx/wr/wrench/benchmarks/large-blur-radius.yaml b/gfx/wr/wrench/benchmarks/large-blur-radius.yaml new file mode 100644 index 0000000000..55cfec7643 --- /dev/null +++ b/gfx/wr/wrench/benchmarks/large-blur-radius.yaml @@ -0,0 +1,10 @@ +--- +root: + items: + - type: stacking-context + bounds: 100 100 1024 1024 + filters: blur(100, 100) + items: + - type: rect + bounds: 0 0 1024 1024 + color: red diff --git a/gfx/wr/wrench/benchmarks/large-boxshadow-ellipse-2.yaml b/gfx/wr/wrench/benchmarks/large-boxshadow-ellipse-2.yaml new file mode 100644 index 0000000000..bcb57434ec --- /dev/null +++ b/gfx/wr/wrench/benchmarks/large-boxshadow-ellipse-2.yaml @@ -0,0 +1,15 @@ +--- +root: + items: + - type: box-shadow + bounds: [ 0, 0, 1024, 1024 ] + color: green + clip-mode: inset + blur-radius: 10000 + border-radius: { + top-left: [500, 700], + top-right: [500, 700], + bottom-left: [600, 400], + bottom-right: [600, 400], + } + diff --git a/gfx/wr/wrench/benchmarks/large-boxshadow-ellipse.yaml b/gfx/wr/wrench/benchmarks/large-boxshadow-ellipse.yaml new file mode 100644 index 0000000000..a9670f78fa --- /dev/null +++ b/gfx/wr/wrench/benchmarks/large-boxshadow-ellipse.yaml @@ -0,0 +1,15 @@ +--- +root: + items: + - type: box-shadow + bounds: [ 0, 0, 1024, 1024 ] + color: green + clip-mode: outset + blur-radius: 10 + border-radius: { + top-left: [10, 30], + top-right: [10, 30], + bottom-left: [30, 10], + bottom-right: [30, 10], + } + diff --git a/gfx/wr/wrench/benchmarks/large-clip-rect.yaml b/gfx/wr/wrench/benchmarks/large-clip-rect.yaml new file mode 100644 index 0000000000..7bd8f1f6a5 --- /dev/null +++ b/gfx/wr/wrench/benchmarks/large-clip-rect.yaml @@ -0,0 +1,33 @@ +--- +root: + items: + - type: clip + bounds: [0, 0, 1024, 1024] + complex: + - rect: [0, 0, 1024, 1024] + radius: 16 + items: + - type: rect + bounds: [0, 0, 1024, 1024] + color: red + - type: rect + bounds: [0, 0, 1024, 1024] + color: red + - type: rect + bounds: [0, 0, 1024, 1024] + color: red + - type: rect + bounds: [0, 0, 1024, 1024] + color: red + - type: rect + bounds: [0, 0, 1024, 1024] + color: red + - type: rect + bounds: [0, 0, 1024, 1024] + color: red + - type: rect + bounds: [0, 0, 1024, 1024] + color: red + - type: rect + bounds: [0, 0, 1024, 1024] + color: red diff --git a/gfx/wr/wrench/benchmarks/many-box-shadows.yaml b/gfx/wr/wrench/benchmarks/many-box-shadows.yaml new file mode 100644 index 0000000000..424c8379a2 --- /dev/null +++ b/gfx/wr/wrench/benchmarks/many-box-shadows.yaml @@ -0,0 +1,125 @@ +--- +root: + items: + - + type: "stacking-context" + items: + - + bounds: [68, 431, 539, 805] + "clip-rect": [5, 390, 665, 932] + "clip-and-scroll": 0 + "backface-visible": true + type: "box-shadow" + "box-bounds": [68, 431, 539, 805] + offset: [0, 22.5] + color: 0 0 0 0.1020 + "blur-radius": 45 + "spread-radius": 0 + "clip-mode": outset + - + bounds: [668, 431, 539, 805] + "clip-rect": [605, 390, 665, 932] + "clip-and-scroll": 0 + "backface-visible": true + type: "box-shadow" + "box-bounds": [668, 431, 539, 805] + offset: [0, 22.5] + color: 0 0 0 0.1020 + "blur-radius": 45 + "spread-radius": 0 + "clip-mode": outset + - + bounds: [1268, 431, 540, 805] + "clip-rect": [1205, 390, 666, 932] + "clip-and-scroll": 0 + "backface-visible": true + type: "box-shadow" + "box-bounds": [1268, 431, 540, 805] + offset: [0, 22.5] + color: 0 0 0 0.1020 + "blur-radius": 45 + "spread-radius": 0 + "clip-mode": outset + - + bounds: [68, 1284, 539, 771] + "clip-rect": [5, 1244, 665, 897] + "clip-and-scroll": 0 + "backface-visible": true + type: "box-shadow" + "box-bounds": [68, 1284, 539, 771] + offset: [0, 22.5] + color: 0 0 0 0.1020 + "blur-radius": 45 + "spread-radius": 0 + "clip-mode": outset + - + bounds: [668, 1284, 539, 771] + "clip-rect": [605, 1244, 665, 897] + "clip-and-scroll": 0 + "backface-visible": true + type: "box-shadow" + "box-bounds": [668, 1284, 539, 771] + offset: [0, 22.5] + color: 0 0 0 0.1020 + "blur-radius": 45 + "spread-radius": 0 + "clip-mode": outset + - + bounds: [1268, 1284, 540, 771] + "clip-rect": [1205, 1244, 666, 897] + "clip-and-scroll": 0 + "backface-visible": true + type: "box-shadow" + "box-bounds": [1268, 1284, 540, 771] + offset: [0, 22.5] + color: 0 0 0 0.1020 + "blur-radius": 45 + "spread-radius": 0 + "clip-mode": outset + - + bounds: [68, 2103, 539, 839] + "clip-rect": [5, 2063, 665, 965] + "clip-and-scroll": 0 + "backface-visible": true + type: "box-shadow" + "box-bounds": [68, 2103, 539, 839] + offset: [0, 22.5] + color: 0 0 0 0.1020 + "blur-radius": 45 + "spread-radius": 0 + "clip-mode": outset + - + bounds: [668, 2103, 539, 839] + "clip-rect": [605, 2063, 665, 965] + "clip-and-scroll": 0 + "backface-visible": true + type: "box-shadow" + "box-bounds": [668, 2103, 539, 839] + offset: [0, 22.5] + color: 0 0 0 0.1020 + "blur-radius": 45 + "spread-radius": 0 + "clip-mode": outset + - + bounds: [1268, 2103, 540, 839] + "clip-rect": [1205, 2063, 666, 965] + "clip-and-scroll": 0 + "backface-visible": true + type: "box-shadow" + "box-bounds": [1268, 2103, 540, 839] + offset: [0, 22.5] + color: 0 0 0 0.1020 + "blur-radius": 45 + "spread-radius": 0 + "clip-mode": outset + - + bounds: [0, 0, 1875, 154] + "clip-rect": [-2, 0, 1879, 158] + "clip-and-scroll": 0 + type: "box-shadow" + "box-bounds": [0, 0, 1875, 154] + offset: [0, 1.5] + color: 0 0 0 0.4000 + "blur-radius": 1.5 + "spread-radius": 0 + "clip-mode": outset diff --git a/gfx/wr/wrench/benchmarks/many-images.yaml b/gfx/wr/wrench/benchmarks/many-images.yaml new file mode 100644 index 0000000000..963fdef881 --- /dev/null +++ b/gfx/wr/wrench/benchmarks/many-images.yaml @@ -0,0 +1,16386 @@ +root: + items: + - image: solid-color(0, 0, 0, 255, 8, 8) + bounds: 0 0 8 8 + - image: solid-color(1, 0, 0, 255, 8, 8) + bounds: 8 0 8 8 + - image: solid-color(2, 0, 0, 255, 8, 8) + bounds: 16 0 8 8 + - image: solid-color(3, 0, 0, 255, 8, 8) + bounds: 24 0 8 8 + - image: solid-color(4, 0, 0, 255, 8, 8) + bounds: 32 0 8 8 + - image: solid-color(5, 0, 0, 255, 8, 8) + bounds: 40 0 8 8 + - image: solid-color(6, 0, 0, 255, 8, 8) + bounds: 48 0 8 8 + - image: solid-color(7, 0, 0, 255, 8, 8) + bounds: 56 0 8 8 + - image: solid-color(8, 0, 0, 255, 8, 8) + bounds: 64 0 8 8 + - image: solid-color(9, 0, 0, 255, 8, 8) + bounds: 72 0 8 8 + - image: solid-color(10, 0, 0, 255, 8, 8) + bounds: 80 0 8 8 + - image: solid-color(11, 0, 0, 255, 8, 8) + bounds: 88 0 8 8 + - image: solid-color(12, 0, 0, 255, 8, 8) + bounds: 96 0 8 8 + - image: solid-color(13, 0, 0, 255, 8, 8) + bounds: 104 0 8 8 + - image: solid-color(14, 0, 0, 255, 8, 8) + bounds: 112 0 8 8 + - image: solid-color(15, 0, 0, 255, 8, 8) + bounds: 120 0 8 8 + - image: solid-color(16, 0, 0, 255, 8, 8) + bounds: 128 0 8 8 + - image: solid-color(17, 0, 0, 255, 8, 8) + bounds: 136 0 8 8 + - image: solid-color(18, 0, 0, 255, 8, 8) + bounds: 144 0 8 8 + - image: solid-color(19, 0, 0, 255, 8, 8) + bounds: 152 0 8 8 + - image: solid-color(20, 0, 0, 255, 8, 8) + bounds: 160 0 8 8 + - image: solid-color(21, 0, 0, 255, 8, 8) + bounds: 168 0 8 8 + - image: solid-color(22, 0, 0, 255, 8, 8) + bounds: 176 0 8 8 + - image: solid-color(23, 0, 0, 255, 8, 8) + bounds: 184 0 8 8 + - image: solid-color(24, 0, 0, 255, 8, 8) + bounds: 192 0 8 8 + - image: solid-color(25, 0, 0, 255, 8, 8) + bounds: 200 0 8 8 + - image: solid-color(26, 0, 0, 255, 8, 8) + bounds: 208 0 8 8 + - image: solid-color(27, 0, 0, 255, 8, 8) + bounds: 216 0 8 8 + - image: solid-color(28, 0, 0, 255, 8, 8) + bounds: 224 0 8 8 + - image: solid-color(29, 0, 0, 255, 8, 8) + bounds: 232 0 8 8 + - image: solid-color(30, 0, 0, 255, 8, 8) + bounds: 240 0 8 8 + - image: solid-color(31, 0, 0, 255, 8, 8) + bounds: 248 0 8 8 + - image: solid-color(32, 0, 0, 255, 8, 8) + bounds: 256 0 8 8 + - image: solid-color(33, 0, 0, 255, 8, 8) + bounds: 264 0 8 8 + - image: solid-color(34, 0, 0, 255, 8, 8) + bounds: 272 0 8 8 + - image: solid-color(35, 0, 0, 255, 8, 8) + bounds: 280 0 8 8 + - image: solid-color(36, 0, 0, 255, 8, 8) + bounds: 288 0 8 8 + - image: solid-color(37, 0, 0, 255, 8, 8) + bounds: 296 0 8 8 + - image: solid-color(38, 0, 0, 255, 8, 8) + bounds: 304 0 8 8 + - image: solid-color(39, 0, 0, 255, 8, 8) + bounds: 312 0 8 8 + - image: solid-color(40, 0, 0, 255, 8, 8) + bounds: 320 0 8 8 + - image: solid-color(41, 0, 0, 255, 8, 8) + bounds: 328 0 8 8 + - image: solid-color(42, 0, 0, 255, 8, 8) + bounds: 336 0 8 8 + - image: solid-color(43, 0, 0, 255, 8, 8) + bounds: 344 0 8 8 + - image: solid-color(44, 0, 0, 255, 8, 8) + bounds: 352 0 8 8 + - image: solid-color(45, 0, 0, 255, 8, 8) + bounds: 360 0 8 8 + - image: solid-color(46, 0, 0, 255, 8, 8) + bounds: 368 0 8 8 + - image: solid-color(47, 0, 0, 255, 8, 8) + bounds: 376 0 8 8 + - image: solid-color(48, 0, 0, 255, 8, 8) + bounds: 384 0 8 8 + - image: solid-color(49, 0, 0, 255, 8, 8) + bounds: 392 0 8 8 + - image: solid-color(50, 0, 0, 255, 8, 8) + bounds: 400 0 8 8 + - image: solid-color(51, 0, 0, 255, 8, 8) + bounds: 408 0 8 8 + - image: solid-color(52, 0, 0, 255, 8, 8) + bounds: 416 0 8 8 + - image: solid-color(53, 0, 0, 255, 8, 8) + bounds: 424 0 8 8 + - image: solid-color(54, 0, 0, 255, 8, 8) + bounds: 432 0 8 8 + - image: solid-color(55, 0, 0, 255, 8, 8) + bounds: 440 0 8 8 + - image: solid-color(56, 0, 0, 255, 8, 8) + bounds: 448 0 8 8 + - image: solid-color(57, 0, 0, 255, 8, 8) + bounds: 456 0 8 8 + - image: solid-color(58, 0, 0, 255, 8, 8) + bounds: 464 0 8 8 + - image: solid-color(59, 0, 0, 255, 8, 8) + bounds: 472 0 8 8 + - image: solid-color(60, 0, 0, 255, 8, 8) + bounds: 480 0 8 8 + - image: solid-color(61, 0, 0, 255, 8, 8) + bounds: 488 0 8 8 + - image: solid-color(62, 0, 0, 255, 8, 8) + bounds: 496 0 8 8 + - image: solid-color(63, 0, 0, 255, 8, 8) + bounds: 504 0 8 8 + - image: solid-color(64, 0, 0, 255, 8, 8) + bounds: 512 0 8 8 + - image: solid-color(65, 0, 0, 255, 8, 8) + bounds: 520 0 8 8 + - image: solid-color(66, 0, 0, 255, 8, 8) + bounds: 528 0 8 8 + - image: solid-color(67, 0, 0, 255, 8, 8) + bounds: 536 0 8 8 + - image: solid-color(68, 0, 0, 255, 8, 8) + bounds: 544 0 8 8 + - image: solid-color(69, 0, 0, 255, 8, 8) + bounds: 552 0 8 8 + - image: solid-color(70, 0, 0, 255, 8, 8) + bounds: 560 0 8 8 + - image: solid-color(71, 0, 0, 255, 8, 8) + bounds: 568 0 8 8 + - image: solid-color(72, 0, 0, 255, 8, 8) + bounds: 576 0 8 8 + - image: solid-color(73, 0, 0, 255, 8, 8) + bounds: 584 0 8 8 + - image: solid-color(74, 0, 0, 255, 8, 8) + bounds: 592 0 8 8 + - image: solid-color(75, 0, 0, 255, 8, 8) + bounds: 600 0 8 8 + - image: solid-color(76, 0, 0, 255, 8, 8) + bounds: 608 0 8 8 + - image: solid-color(77, 0, 0, 255, 8, 8) + bounds: 616 0 8 8 + - image: solid-color(78, 0, 0, 255, 8, 8) + bounds: 624 0 8 8 + - image: solid-color(79, 0, 0, 255, 8, 8) + bounds: 632 0 8 8 + - image: solid-color(80, 0, 0, 255, 8, 8) + bounds: 640 0 8 8 + - image: solid-color(81, 0, 0, 255, 8, 8) + bounds: 648 0 8 8 + - image: solid-color(82, 0, 0, 255, 8, 8) + bounds: 656 0 8 8 + - image: solid-color(83, 0, 0, 255, 8, 8) + bounds: 664 0 8 8 + - image: solid-color(84, 0, 0, 255, 8, 8) + bounds: 672 0 8 8 + - image: solid-color(85, 0, 0, 255, 8, 8) + bounds: 680 0 8 8 + - image: solid-color(86, 0, 0, 255, 8, 8) + bounds: 688 0 8 8 + - image: solid-color(87, 0, 0, 255, 8, 8) + bounds: 696 0 8 8 + - image: solid-color(88, 0, 0, 255, 8, 8) + bounds: 704 0 8 8 + - image: solid-color(89, 0, 0, 255, 8, 8) + bounds: 712 0 8 8 + - image: solid-color(90, 0, 0, 255, 8, 8) + bounds: 720 0 8 8 + - image: solid-color(91, 0, 0, 255, 8, 8) + bounds: 728 0 8 8 + - image: solid-color(92, 0, 0, 255, 8, 8) + bounds: 736 0 8 8 + - image: solid-color(93, 0, 0, 255, 8, 8) + bounds: 744 0 8 8 + - image: solid-color(94, 0, 0, 255, 8, 8) + bounds: 752 0 8 8 + - image: solid-color(95, 0, 0, 255, 8, 8) + bounds: 760 0 8 8 + - image: solid-color(96, 0, 0, 255, 8, 8) + bounds: 768 0 8 8 + - image: solid-color(97, 0, 0, 255, 8, 8) + bounds: 776 0 8 8 + - image: solid-color(98, 0, 0, 255, 8, 8) + bounds: 784 0 8 8 + - image: solid-color(99, 0, 0, 255, 8, 8) + bounds: 792 0 8 8 + - image: solid-color(100, 0, 0, 255, 8, 8) + bounds: 800 0 8 8 + - image: solid-color(101, 0, 0, 255, 8, 8) + bounds: 808 0 8 8 + - image: solid-color(102, 0, 0, 255, 8, 8) + bounds: 816 0 8 8 + - image: solid-color(103, 0, 0, 255, 8, 8) + bounds: 824 0 8 8 + - image: solid-color(104, 0, 0, 255, 8, 8) + bounds: 832 0 8 8 + - image: solid-color(105, 0, 0, 255, 8, 8) + bounds: 840 0 8 8 + - image: solid-color(106, 0, 0, 255, 8, 8) + bounds: 848 0 8 8 + - image: solid-color(107, 0, 0, 255, 8, 8) + bounds: 856 0 8 8 + - image: solid-color(108, 0, 0, 255, 8, 8) + bounds: 864 0 8 8 + - image: solid-color(109, 0, 0, 255, 8, 8) + bounds: 872 0 8 8 + - image: solid-color(110, 0, 0, 255, 8, 8) + bounds: 880 0 8 8 + - image: solid-color(111, 0, 0, 255, 8, 8) + bounds: 888 0 8 8 + - image: solid-color(112, 0, 0, 255, 8, 8) + bounds: 896 0 8 8 + - image: solid-color(113, 0, 0, 255, 8, 8) + bounds: 904 0 8 8 + - image: solid-color(114, 0, 0, 255, 8, 8) + bounds: 912 0 8 8 + - image: solid-color(115, 0, 0, 255, 8, 8) + bounds: 920 0 8 8 + - image: solid-color(116, 0, 0, 255, 8, 8) + bounds: 928 0 8 8 + - image: solid-color(117, 0, 0, 255, 8, 8) + bounds: 936 0 8 8 + - image: solid-color(118, 0, 0, 255, 8, 8) + bounds: 944 0 8 8 + - image: solid-color(119, 0, 0, 255, 8, 8) + bounds: 952 0 8 8 + - image: solid-color(120, 0, 0, 255, 8, 8) + bounds: 960 0 8 8 + - image: solid-color(121, 0, 0, 255, 8, 8) + bounds: 968 0 8 8 + - image: solid-color(122, 0, 0, 255, 8, 8) + bounds: 976 0 8 8 + - image: solid-color(123, 0, 0, 255, 8, 8) + bounds: 984 0 8 8 + - image: solid-color(124, 0, 0, 255, 8, 8) + bounds: 992 0 8 8 + - image: solid-color(125, 0, 0, 255, 8, 8) + bounds: 1000 0 8 8 + - image: solid-color(126, 0, 0, 255, 8, 8) + bounds: 1008 0 8 8 + - image: solid-color(127, 0, 0, 255, 8, 8) + bounds: 1016 0 8 8 + - image: solid-color(0, 1, 0, 255, 8, 8) + bounds: 0 8 8 8 + - image: solid-color(1, 1, 0, 255, 8, 8) + bounds: 8 8 8 8 + - image: solid-color(2, 1, 0, 255, 8, 8) + bounds: 16 8 8 8 + - image: solid-color(3, 1, 0, 255, 8, 8) + bounds: 24 8 8 8 + - image: solid-color(4, 1, 0, 255, 8, 8) + bounds: 32 8 8 8 + - image: solid-color(5, 1, 0, 255, 8, 8) + bounds: 40 8 8 8 + - image: solid-color(6, 1, 0, 255, 8, 8) + bounds: 48 8 8 8 + - image: solid-color(7, 1, 0, 255, 8, 8) + bounds: 56 8 8 8 + - image: solid-color(8, 1, 0, 255, 8, 8) + bounds: 64 8 8 8 + - image: solid-color(9, 1, 0, 255, 8, 8) + bounds: 72 8 8 8 + - image: solid-color(10, 1, 0, 255, 8, 8) + bounds: 80 8 8 8 + - image: solid-color(11, 1, 0, 255, 8, 8) + bounds: 88 8 8 8 + - image: solid-color(12, 1, 0, 255, 8, 8) + bounds: 96 8 8 8 + - image: solid-color(13, 1, 0, 255, 8, 8) + bounds: 104 8 8 8 + - image: solid-color(14, 1, 0, 255, 8, 8) + bounds: 112 8 8 8 + - image: solid-color(15, 1, 0, 255, 8, 8) + bounds: 120 8 8 8 + - image: solid-color(16, 1, 0, 255, 8, 8) + bounds: 128 8 8 8 + - image: solid-color(17, 1, 0, 255, 8, 8) + bounds: 136 8 8 8 + - image: solid-color(18, 1, 0, 255, 8, 8) + bounds: 144 8 8 8 + - image: solid-color(19, 1, 0, 255, 8, 8) + bounds: 152 8 8 8 + - image: solid-color(20, 1, 0, 255, 8, 8) + bounds: 160 8 8 8 + - image: solid-color(21, 1, 0, 255, 8, 8) + bounds: 168 8 8 8 + - image: solid-color(22, 1, 0, 255, 8, 8) + bounds: 176 8 8 8 + - image: solid-color(23, 1, 0, 255, 8, 8) + bounds: 184 8 8 8 + - image: solid-color(24, 1, 0, 255, 8, 8) + bounds: 192 8 8 8 + - image: solid-color(25, 1, 0, 255, 8, 8) + bounds: 200 8 8 8 + - image: solid-color(26, 1, 0, 255, 8, 8) + bounds: 208 8 8 8 + - image: solid-color(27, 1, 0, 255, 8, 8) + bounds: 216 8 8 8 + - image: solid-color(28, 1, 0, 255, 8, 8) + bounds: 224 8 8 8 + - image: solid-color(29, 1, 0, 255, 8, 8) + bounds: 232 8 8 8 + - image: solid-color(30, 1, 0, 255, 8, 8) + bounds: 240 8 8 8 + - image: solid-color(31, 1, 0, 255, 8, 8) + bounds: 248 8 8 8 + - image: solid-color(32, 1, 0, 255, 8, 8) + bounds: 256 8 8 8 + - image: solid-color(33, 1, 0, 255, 8, 8) + bounds: 264 8 8 8 + - image: solid-color(34, 1, 0, 255, 8, 8) + bounds: 272 8 8 8 + - image: solid-color(35, 1, 0, 255, 8, 8) + bounds: 280 8 8 8 + - image: solid-color(36, 1, 0, 255, 8, 8) + bounds: 288 8 8 8 + - image: solid-color(37, 1, 0, 255, 8, 8) + bounds: 296 8 8 8 + - image: solid-color(38, 1, 0, 255, 8, 8) + bounds: 304 8 8 8 + - image: solid-color(39, 1, 0, 255, 8, 8) + bounds: 312 8 8 8 + - image: solid-color(40, 1, 0, 255, 8, 8) + bounds: 320 8 8 8 + - image: solid-color(41, 1, 0, 255, 8, 8) + bounds: 328 8 8 8 + - image: solid-color(42, 1, 0, 255, 8, 8) + bounds: 336 8 8 8 + - image: solid-color(43, 1, 0, 255, 8, 8) + bounds: 344 8 8 8 + - image: solid-color(44, 1, 0, 255, 8, 8) + bounds: 352 8 8 8 + - image: solid-color(45, 1, 0, 255, 8, 8) + bounds: 360 8 8 8 + - image: solid-color(46, 1, 0, 255, 8, 8) + bounds: 368 8 8 8 + - image: solid-color(47, 1, 0, 255, 8, 8) + bounds: 376 8 8 8 + - image: solid-color(48, 1, 0, 255, 8, 8) + bounds: 384 8 8 8 + - image: solid-color(49, 1, 0, 255, 8, 8) + bounds: 392 8 8 8 + - image: solid-color(50, 1, 0, 255, 8, 8) + bounds: 400 8 8 8 + - image: solid-color(51, 1, 0, 255, 8, 8) + bounds: 408 8 8 8 + - image: solid-color(52, 1, 0, 255, 8, 8) + bounds: 416 8 8 8 + - image: solid-color(53, 1, 0, 255, 8, 8) + bounds: 424 8 8 8 + - image: solid-color(54, 1, 0, 255, 8, 8) + bounds: 432 8 8 8 + - image: solid-color(55, 1, 0, 255, 8, 8) + bounds: 440 8 8 8 + - image: solid-color(56, 1, 0, 255, 8, 8) + bounds: 448 8 8 8 + - image: solid-color(57, 1, 0, 255, 8, 8) + bounds: 456 8 8 8 + - image: solid-color(58, 1, 0, 255, 8, 8) + bounds: 464 8 8 8 + - image: solid-color(59, 1, 0, 255, 8, 8) + bounds: 472 8 8 8 + - image: solid-color(60, 1, 0, 255, 8, 8) + bounds: 480 8 8 8 + - image: solid-color(61, 1, 0, 255, 8, 8) + bounds: 488 8 8 8 + - image: solid-color(62, 1, 0, 255, 8, 8) + bounds: 496 8 8 8 + - image: solid-color(63, 1, 0, 255, 8, 8) + bounds: 504 8 8 8 + - image: solid-color(64, 1, 0, 255, 8, 8) + bounds: 512 8 8 8 + - image: solid-color(65, 1, 0, 255, 8, 8) + bounds: 520 8 8 8 + - image: solid-color(66, 1, 0, 255, 8, 8) + bounds: 528 8 8 8 + - image: solid-color(67, 1, 0, 255, 8, 8) + bounds: 536 8 8 8 + - image: solid-color(68, 1, 0, 255, 8, 8) + bounds: 544 8 8 8 + - image: solid-color(69, 1, 0, 255, 8, 8) + bounds: 552 8 8 8 + - image: solid-color(70, 1, 0, 255, 8, 8) + bounds: 560 8 8 8 + - image: solid-color(71, 1, 0, 255, 8, 8) + bounds: 568 8 8 8 + - image: solid-color(72, 1, 0, 255, 8, 8) + bounds: 576 8 8 8 + - image: solid-color(73, 1, 0, 255, 8, 8) + bounds: 584 8 8 8 + - image: solid-color(74, 1, 0, 255, 8, 8) + bounds: 592 8 8 8 + - image: solid-color(75, 1, 0, 255, 8, 8) + bounds: 600 8 8 8 + - image: solid-color(76, 1, 0, 255, 8, 8) + bounds: 608 8 8 8 + - image: solid-color(77, 1, 0, 255, 8, 8) + bounds: 616 8 8 8 + - image: solid-color(78, 1, 0, 255, 8, 8) + bounds: 624 8 8 8 + - image: solid-color(79, 1, 0, 255, 8, 8) + bounds: 632 8 8 8 + - image: solid-color(80, 1, 0, 255, 8, 8) + bounds: 640 8 8 8 + - image: solid-color(81, 1, 0, 255, 8, 8) + bounds: 648 8 8 8 + - image: solid-color(82, 1, 0, 255, 8, 8) + bounds: 656 8 8 8 + - image: solid-color(83, 1, 0, 255, 8, 8) + bounds: 664 8 8 8 + - image: solid-color(84, 1, 0, 255, 8, 8) + bounds: 672 8 8 8 + - image: solid-color(85, 1, 0, 255, 8, 8) + bounds: 680 8 8 8 + - image: solid-color(86, 1, 0, 255, 8, 8) + bounds: 688 8 8 8 + - image: solid-color(87, 1, 0, 255, 8, 8) + bounds: 696 8 8 8 + - image: solid-color(88, 1, 0, 255, 8, 8) + bounds: 704 8 8 8 + - image: solid-color(89, 1, 0, 255, 8, 8) + bounds: 712 8 8 8 + - image: solid-color(90, 1, 0, 255, 8, 8) + bounds: 720 8 8 8 + - image: solid-color(91, 1, 0, 255, 8, 8) + bounds: 728 8 8 8 + - image: solid-color(92, 1, 0, 255, 8, 8) + bounds: 736 8 8 8 + - image: solid-color(93, 1, 0, 255, 8, 8) + bounds: 744 8 8 8 + - image: solid-color(94, 1, 0, 255, 8, 8) + bounds: 752 8 8 8 + - image: solid-color(95, 1, 0, 255, 8, 8) + bounds: 760 8 8 8 + - image: solid-color(96, 1, 0, 255, 8, 8) + bounds: 768 8 8 8 + - image: solid-color(97, 1, 0, 255, 8, 8) + bounds: 776 8 8 8 + - image: solid-color(98, 1, 0, 255, 8, 8) + bounds: 784 8 8 8 + - image: solid-color(99, 1, 0, 255, 8, 8) + bounds: 792 8 8 8 + - image: solid-color(100, 1, 0, 255, 8, 8) + bounds: 800 8 8 8 + - image: solid-color(101, 1, 0, 255, 8, 8) + bounds: 808 8 8 8 + - image: solid-color(102, 1, 0, 255, 8, 8) + bounds: 816 8 8 8 + - image: solid-color(103, 1, 0, 255, 8, 8) + bounds: 824 8 8 8 + - image: solid-color(104, 1, 0, 255, 8, 8) + bounds: 832 8 8 8 + - image: solid-color(105, 1, 0, 255, 8, 8) + bounds: 840 8 8 8 + - image: solid-color(106, 1, 0, 255, 8, 8) + bounds: 848 8 8 8 + - image: solid-color(107, 1, 0, 255, 8, 8) + bounds: 856 8 8 8 + - image: solid-color(108, 1, 0, 255, 8, 8) + bounds: 864 8 8 8 + - image: solid-color(109, 1, 0, 255, 8, 8) + bounds: 872 8 8 8 + - image: solid-color(110, 1, 0, 255, 8, 8) + bounds: 880 8 8 8 + - image: solid-color(111, 1, 0, 255, 8, 8) + bounds: 888 8 8 8 + - image: solid-color(112, 1, 0, 255, 8, 8) + bounds: 896 8 8 8 + - image: solid-color(113, 1, 0, 255, 8, 8) + bounds: 904 8 8 8 + - image: solid-color(114, 1, 0, 255, 8, 8) + bounds: 912 8 8 8 + - image: solid-color(115, 1, 0, 255, 8, 8) + bounds: 920 8 8 8 + - image: solid-color(116, 1, 0, 255, 8, 8) + bounds: 928 8 8 8 + - image: solid-color(117, 1, 0, 255, 8, 8) + bounds: 936 8 8 8 + - image: solid-color(118, 1, 0, 255, 8, 8) + bounds: 944 8 8 8 + - image: solid-color(119, 1, 0, 255, 8, 8) + bounds: 952 8 8 8 + - image: solid-color(120, 1, 0, 255, 8, 8) + bounds: 960 8 8 8 + - image: solid-color(121, 1, 0, 255, 8, 8) + bounds: 968 8 8 8 + - image: solid-color(122, 1, 0, 255, 8, 8) + bounds: 976 8 8 8 + - image: solid-color(123, 1, 0, 255, 8, 8) + bounds: 984 8 8 8 + - image: solid-color(124, 1, 0, 255, 8, 8) + bounds: 992 8 8 8 + - image: solid-color(125, 1, 0, 255, 8, 8) + bounds: 1000 8 8 8 + - image: solid-color(126, 1, 0, 255, 8, 8) + bounds: 1008 8 8 8 + - image: solid-color(127, 1, 0, 255, 8, 8) + bounds: 1016 8 8 8 + - image: solid-color(0, 2, 0, 255, 8, 8) + bounds: 0 16 8 8 + - image: solid-color(1, 2, 0, 255, 8, 8) + bounds: 8 16 8 8 + - image: solid-color(2, 2, 0, 255, 8, 8) + bounds: 16 16 8 8 + - image: solid-color(3, 2, 0, 255, 8, 8) + bounds: 24 16 8 8 + - image: solid-color(4, 2, 0, 255, 8, 8) + bounds: 32 16 8 8 + - image: solid-color(5, 2, 0, 255, 8, 8) + bounds: 40 16 8 8 + - image: solid-color(6, 2, 0, 255, 8, 8) + bounds: 48 16 8 8 + - image: solid-color(7, 2, 0, 255, 8, 8) + bounds: 56 16 8 8 + - image: solid-color(8, 2, 0, 255, 8, 8) + bounds: 64 16 8 8 + - image: solid-color(9, 2, 0, 255, 8, 8) + bounds: 72 16 8 8 + - image: solid-color(10, 2, 0, 255, 8, 8) + bounds: 80 16 8 8 + - image: solid-color(11, 2, 0, 255, 8, 8) + bounds: 88 16 8 8 + - image: solid-color(12, 2, 0, 255, 8, 8) + bounds: 96 16 8 8 + - image: solid-color(13, 2, 0, 255, 8, 8) + bounds: 104 16 8 8 + - image: solid-color(14, 2, 0, 255, 8, 8) + bounds: 112 16 8 8 + - image: solid-color(15, 2, 0, 255, 8, 8) + bounds: 120 16 8 8 + - image: solid-color(16, 2, 0, 255, 8, 8) + bounds: 128 16 8 8 + - image: solid-color(17, 2, 0, 255, 8, 8) + bounds: 136 16 8 8 + - image: solid-color(18, 2, 0, 255, 8, 8) + bounds: 144 16 8 8 + - image: solid-color(19, 2, 0, 255, 8, 8) + bounds: 152 16 8 8 + - image: solid-color(20, 2, 0, 255, 8, 8) + bounds: 160 16 8 8 + - image: solid-color(21, 2, 0, 255, 8, 8) + bounds: 168 16 8 8 + - image: solid-color(22, 2, 0, 255, 8, 8) + bounds: 176 16 8 8 + - image: solid-color(23, 2, 0, 255, 8, 8) + bounds: 184 16 8 8 + - image: solid-color(24, 2, 0, 255, 8, 8) + bounds: 192 16 8 8 + - image: solid-color(25, 2, 0, 255, 8, 8) + bounds: 200 16 8 8 + - image: solid-color(26, 2, 0, 255, 8, 8) + bounds: 208 16 8 8 + - image: solid-color(27, 2, 0, 255, 8, 8) + bounds: 216 16 8 8 + - image: solid-color(28, 2, 0, 255, 8, 8) + bounds: 224 16 8 8 + - image: solid-color(29, 2, 0, 255, 8, 8) + bounds: 232 16 8 8 + - image: solid-color(30, 2, 0, 255, 8, 8) + bounds: 240 16 8 8 + - image: solid-color(31, 2, 0, 255, 8, 8) + bounds: 248 16 8 8 + - image: solid-color(32, 2, 0, 255, 8, 8) + bounds: 256 16 8 8 + - image: solid-color(33, 2, 0, 255, 8, 8) + bounds: 264 16 8 8 + - image: solid-color(34, 2, 0, 255, 8, 8) + bounds: 272 16 8 8 + - image: solid-color(35, 2, 0, 255, 8, 8) + bounds: 280 16 8 8 + - image: solid-color(36, 2, 0, 255, 8, 8) + bounds: 288 16 8 8 + - image: solid-color(37, 2, 0, 255, 8, 8) + bounds: 296 16 8 8 + - image: solid-color(38, 2, 0, 255, 8, 8) + bounds: 304 16 8 8 + - image: solid-color(39, 2, 0, 255, 8, 8) + bounds: 312 16 8 8 + - image: solid-color(40, 2, 0, 255, 8, 8) + bounds: 320 16 8 8 + - image: solid-color(41, 2, 0, 255, 8, 8) + bounds: 328 16 8 8 + - image: solid-color(42, 2, 0, 255, 8, 8) + bounds: 336 16 8 8 + - image: solid-color(43, 2, 0, 255, 8, 8) + bounds: 344 16 8 8 + - image: solid-color(44, 2, 0, 255, 8, 8) + bounds: 352 16 8 8 + - image: solid-color(45, 2, 0, 255, 8, 8) + bounds: 360 16 8 8 + - image: solid-color(46, 2, 0, 255, 8, 8) + bounds: 368 16 8 8 + - image: solid-color(47, 2, 0, 255, 8, 8) + bounds: 376 16 8 8 + - image: solid-color(48, 2, 0, 255, 8, 8) + bounds: 384 16 8 8 + - image: solid-color(49, 2, 0, 255, 8, 8) + bounds: 392 16 8 8 + - image: solid-color(50, 2, 0, 255, 8, 8) + bounds: 400 16 8 8 + - image: solid-color(51, 2, 0, 255, 8, 8) + bounds: 408 16 8 8 + - image: solid-color(52, 2, 0, 255, 8, 8) + bounds: 416 16 8 8 + - image: solid-color(53, 2, 0, 255, 8, 8) + bounds: 424 16 8 8 + - image: solid-color(54, 2, 0, 255, 8, 8) + bounds: 432 16 8 8 + - image: solid-color(55, 2, 0, 255, 8, 8) + bounds: 440 16 8 8 + - image: solid-color(56, 2, 0, 255, 8, 8) + bounds: 448 16 8 8 + - image: solid-color(57, 2, 0, 255, 8, 8) + bounds: 456 16 8 8 + - image: solid-color(58, 2, 0, 255, 8, 8) + bounds: 464 16 8 8 + - image: solid-color(59, 2, 0, 255, 8, 8) + bounds: 472 16 8 8 + - image: solid-color(60, 2, 0, 255, 8, 8) + bounds: 480 16 8 8 + - image: solid-color(61, 2, 0, 255, 8, 8) + bounds: 488 16 8 8 + - image: solid-color(62, 2, 0, 255, 8, 8) + bounds: 496 16 8 8 + - image: solid-color(63, 2, 0, 255, 8, 8) + bounds: 504 16 8 8 + - image: solid-color(64, 2, 0, 255, 8, 8) + bounds: 512 16 8 8 + - image: solid-color(65, 2, 0, 255, 8, 8) + bounds: 520 16 8 8 + - image: solid-color(66, 2, 0, 255, 8, 8) + bounds: 528 16 8 8 + - image: solid-color(67, 2, 0, 255, 8, 8) + bounds: 536 16 8 8 + - image: solid-color(68, 2, 0, 255, 8, 8) + bounds: 544 16 8 8 + - image: solid-color(69, 2, 0, 255, 8, 8) + bounds: 552 16 8 8 + - image: solid-color(70, 2, 0, 255, 8, 8) + bounds: 560 16 8 8 + - image: solid-color(71, 2, 0, 255, 8, 8) + bounds: 568 16 8 8 + - image: solid-color(72, 2, 0, 255, 8, 8) + bounds: 576 16 8 8 + - image: solid-color(73, 2, 0, 255, 8, 8) + bounds: 584 16 8 8 + - image: solid-color(74, 2, 0, 255, 8, 8) + bounds: 592 16 8 8 + - image: solid-color(75, 2, 0, 255, 8, 8) + bounds: 600 16 8 8 + - image: solid-color(76, 2, 0, 255, 8, 8) + bounds: 608 16 8 8 + - image: solid-color(77, 2, 0, 255, 8, 8) + bounds: 616 16 8 8 + - image: solid-color(78, 2, 0, 255, 8, 8) + bounds: 624 16 8 8 + - image: solid-color(79, 2, 0, 255, 8, 8) + bounds: 632 16 8 8 + - image: solid-color(80, 2, 0, 255, 8, 8) + bounds: 640 16 8 8 + - image: solid-color(81, 2, 0, 255, 8, 8) + bounds: 648 16 8 8 + - image: solid-color(82, 2, 0, 255, 8, 8) + bounds: 656 16 8 8 + - image: solid-color(83, 2, 0, 255, 8, 8) + bounds: 664 16 8 8 + - image: solid-color(84, 2, 0, 255, 8, 8) + bounds: 672 16 8 8 + - image: solid-color(85, 2, 0, 255, 8, 8) + bounds: 680 16 8 8 + - image: solid-color(86, 2, 0, 255, 8, 8) + bounds: 688 16 8 8 + - image: solid-color(87, 2, 0, 255, 8, 8) + bounds: 696 16 8 8 + - image: solid-color(88, 2, 0, 255, 8, 8) + bounds: 704 16 8 8 + - image: solid-color(89, 2, 0, 255, 8, 8) + bounds: 712 16 8 8 + - image: solid-color(90, 2, 0, 255, 8, 8) + bounds: 720 16 8 8 + - image: solid-color(91, 2, 0, 255, 8, 8) + bounds: 728 16 8 8 + - image: solid-color(92, 2, 0, 255, 8, 8) + bounds: 736 16 8 8 + - image: solid-color(93, 2, 0, 255, 8, 8) + bounds: 744 16 8 8 + - image: solid-color(94, 2, 0, 255, 8, 8) + bounds: 752 16 8 8 + - image: solid-color(95, 2, 0, 255, 8, 8) + bounds: 760 16 8 8 + - image: solid-color(96, 2, 0, 255, 8, 8) + bounds: 768 16 8 8 + - image: solid-color(97, 2, 0, 255, 8, 8) + bounds: 776 16 8 8 + - image: solid-color(98, 2, 0, 255, 8, 8) + bounds: 784 16 8 8 + - image: solid-color(99, 2, 0, 255, 8, 8) + bounds: 792 16 8 8 + - image: solid-color(100, 2, 0, 255, 8, 8) + bounds: 800 16 8 8 + - image: solid-color(101, 2, 0, 255, 8, 8) + bounds: 808 16 8 8 + - image: solid-color(102, 2, 0, 255, 8, 8) + bounds: 816 16 8 8 + - image: solid-color(103, 2, 0, 255, 8, 8) + bounds: 824 16 8 8 + - image: solid-color(104, 2, 0, 255, 8, 8) + bounds: 832 16 8 8 + - image: solid-color(105, 2, 0, 255, 8, 8) + bounds: 840 16 8 8 + - image: solid-color(106, 2, 0, 255, 8, 8) + bounds: 848 16 8 8 + - image: solid-color(107, 2, 0, 255, 8, 8) + bounds: 856 16 8 8 + - image: solid-color(108, 2, 0, 255, 8, 8) + bounds: 864 16 8 8 + - image: solid-color(109, 2, 0, 255, 8, 8) + bounds: 872 16 8 8 + - image: solid-color(110, 2, 0, 255, 8, 8) + bounds: 880 16 8 8 + - image: solid-color(111, 2, 0, 255, 8, 8) + bounds: 888 16 8 8 + - image: solid-color(112, 2, 0, 255, 8, 8) + bounds: 896 16 8 8 + - image: solid-color(113, 2, 0, 255, 8, 8) + bounds: 904 16 8 8 + - image: solid-color(114, 2, 0, 255, 8, 8) + bounds: 912 16 8 8 + - image: solid-color(115, 2, 0, 255, 8, 8) + bounds: 920 16 8 8 + - image: solid-color(116, 2, 0, 255, 8, 8) + bounds: 928 16 8 8 + - image: solid-color(117, 2, 0, 255, 8, 8) + bounds: 936 16 8 8 + - image: solid-color(118, 2, 0, 255, 8, 8) + bounds: 944 16 8 8 + - image: solid-color(119, 2, 0, 255, 8, 8) + bounds: 952 16 8 8 + - image: solid-color(120, 2, 0, 255, 8, 8) + bounds: 960 16 8 8 + - image: solid-color(121, 2, 0, 255, 8, 8) + bounds: 968 16 8 8 + - image: solid-color(122, 2, 0, 255, 8, 8) + bounds: 976 16 8 8 + - image: solid-color(123, 2, 0, 255, 8, 8) + bounds: 984 16 8 8 + - image: solid-color(124, 2, 0, 255, 8, 8) + bounds: 992 16 8 8 + - image: solid-color(125, 2, 0, 255, 8, 8) + bounds: 1000 16 8 8 + - image: solid-color(126, 2, 0, 255, 8, 8) + bounds: 1008 16 8 8 + - image: solid-color(127, 2, 0, 255, 8, 8) + bounds: 1016 16 8 8 + - image: solid-color(0, 3, 0, 255, 8, 8) + bounds: 0 24 8 8 + - image: solid-color(1, 3, 0, 255, 8, 8) + bounds: 8 24 8 8 + - image: solid-color(2, 3, 0, 255, 8, 8) + bounds: 16 24 8 8 + - image: solid-color(3, 3, 0, 255, 8, 8) + bounds: 24 24 8 8 + - image: solid-color(4, 3, 0, 255, 8, 8) + bounds: 32 24 8 8 + - image: solid-color(5, 3, 0, 255, 8, 8) + bounds: 40 24 8 8 + - image: solid-color(6, 3, 0, 255, 8, 8) + bounds: 48 24 8 8 + - image: solid-color(7, 3, 0, 255, 8, 8) + bounds: 56 24 8 8 + - image: solid-color(8, 3, 0, 255, 8, 8) + bounds: 64 24 8 8 + - image: solid-color(9, 3, 0, 255, 8, 8) + bounds: 72 24 8 8 + - image: solid-color(10, 3, 0, 255, 8, 8) + bounds: 80 24 8 8 + - image: solid-color(11, 3, 0, 255, 8, 8) + bounds: 88 24 8 8 + - image: solid-color(12, 3, 0, 255, 8, 8) + bounds: 96 24 8 8 + - image: solid-color(13, 3, 0, 255, 8, 8) + bounds: 104 24 8 8 + - image: solid-color(14, 3, 0, 255, 8, 8) + bounds: 112 24 8 8 + - image: solid-color(15, 3, 0, 255, 8, 8) + bounds: 120 24 8 8 + - image: solid-color(16, 3, 0, 255, 8, 8) + bounds: 128 24 8 8 + - image: solid-color(17, 3, 0, 255, 8, 8) + bounds: 136 24 8 8 + - image: solid-color(18, 3, 0, 255, 8, 8) + bounds: 144 24 8 8 + - image: solid-color(19, 3, 0, 255, 8, 8) + bounds: 152 24 8 8 + - image: solid-color(20, 3, 0, 255, 8, 8) + bounds: 160 24 8 8 + - image: solid-color(21, 3, 0, 255, 8, 8) + bounds: 168 24 8 8 + - image: solid-color(22, 3, 0, 255, 8, 8) + bounds: 176 24 8 8 + - image: solid-color(23, 3, 0, 255, 8, 8) + bounds: 184 24 8 8 + - image: solid-color(24, 3, 0, 255, 8, 8) + bounds: 192 24 8 8 + - image: solid-color(25, 3, 0, 255, 8, 8) + bounds: 200 24 8 8 + - image: solid-color(26, 3, 0, 255, 8, 8) + bounds: 208 24 8 8 + - image: solid-color(27, 3, 0, 255, 8, 8) + bounds: 216 24 8 8 + - image: solid-color(28, 3, 0, 255, 8, 8) + bounds: 224 24 8 8 + - image: solid-color(29, 3, 0, 255, 8, 8) + bounds: 232 24 8 8 + - image: solid-color(30, 3, 0, 255, 8, 8) + bounds: 240 24 8 8 + - image: solid-color(31, 3, 0, 255, 8, 8) + bounds: 248 24 8 8 + - image: solid-color(32, 3, 0, 255, 8, 8) + bounds: 256 24 8 8 + - image: solid-color(33, 3, 0, 255, 8, 8) + bounds: 264 24 8 8 + - image: solid-color(34, 3, 0, 255, 8, 8) + bounds: 272 24 8 8 + - image: solid-color(35, 3, 0, 255, 8, 8) + bounds: 280 24 8 8 + - image: solid-color(36, 3, 0, 255, 8, 8) + bounds: 288 24 8 8 + - image: solid-color(37, 3, 0, 255, 8, 8) + bounds: 296 24 8 8 + - image: solid-color(38, 3, 0, 255, 8, 8) + bounds: 304 24 8 8 + - image: solid-color(39, 3, 0, 255, 8, 8) + bounds: 312 24 8 8 + - image: solid-color(40, 3, 0, 255, 8, 8) + bounds: 320 24 8 8 + - image: solid-color(41, 3, 0, 255, 8, 8) + bounds: 328 24 8 8 + - image: solid-color(42, 3, 0, 255, 8, 8) + bounds: 336 24 8 8 + - image: solid-color(43, 3, 0, 255, 8, 8) + bounds: 344 24 8 8 + - image: solid-color(44, 3, 0, 255, 8, 8) + bounds: 352 24 8 8 + - image: solid-color(45, 3, 0, 255, 8, 8) + bounds: 360 24 8 8 + - image: solid-color(46, 3, 0, 255, 8, 8) + bounds: 368 24 8 8 + - image: solid-color(47, 3, 0, 255, 8, 8) + bounds: 376 24 8 8 + - image: solid-color(48, 3, 0, 255, 8, 8) + bounds: 384 24 8 8 + - image: solid-color(49, 3, 0, 255, 8, 8) + bounds: 392 24 8 8 + - image: solid-color(50, 3, 0, 255, 8, 8) + bounds: 400 24 8 8 + - image: solid-color(51, 3, 0, 255, 8, 8) + bounds: 408 24 8 8 + - image: solid-color(52, 3, 0, 255, 8, 8) + bounds: 416 24 8 8 + - image: solid-color(53, 3, 0, 255, 8, 8) + bounds: 424 24 8 8 + - image: solid-color(54, 3, 0, 255, 8, 8) + bounds: 432 24 8 8 + - image: solid-color(55, 3, 0, 255, 8, 8) + bounds: 440 24 8 8 + - image: solid-color(56, 3, 0, 255, 8, 8) + bounds: 448 24 8 8 + - image: solid-color(57, 3, 0, 255, 8, 8) + bounds: 456 24 8 8 + - image: solid-color(58, 3, 0, 255, 8, 8) + bounds: 464 24 8 8 + - image: solid-color(59, 3, 0, 255, 8, 8) + bounds: 472 24 8 8 + - image: solid-color(60, 3, 0, 255, 8, 8) + bounds: 480 24 8 8 + - image: solid-color(61, 3, 0, 255, 8, 8) + bounds: 488 24 8 8 + - image: solid-color(62, 3, 0, 255, 8, 8) + bounds: 496 24 8 8 + - image: solid-color(63, 3, 0, 255, 8, 8) + bounds: 504 24 8 8 + - image: solid-color(64, 3, 0, 255, 8, 8) + bounds: 512 24 8 8 + - image: solid-color(65, 3, 0, 255, 8, 8) + bounds: 520 24 8 8 + - image: solid-color(66, 3, 0, 255, 8, 8) + bounds: 528 24 8 8 + - image: solid-color(67, 3, 0, 255, 8, 8) + bounds: 536 24 8 8 + - image: solid-color(68, 3, 0, 255, 8, 8) + bounds: 544 24 8 8 + - image: solid-color(69, 3, 0, 255, 8, 8) + bounds: 552 24 8 8 + - image: solid-color(70, 3, 0, 255, 8, 8) + bounds: 560 24 8 8 + - image: solid-color(71, 3, 0, 255, 8, 8) + bounds: 568 24 8 8 + - image: solid-color(72, 3, 0, 255, 8, 8) + bounds: 576 24 8 8 + - image: solid-color(73, 3, 0, 255, 8, 8) + bounds: 584 24 8 8 + - image: solid-color(74, 3, 0, 255, 8, 8) + bounds: 592 24 8 8 + - image: solid-color(75, 3, 0, 255, 8, 8) + bounds: 600 24 8 8 + - image: solid-color(76, 3, 0, 255, 8, 8) + bounds: 608 24 8 8 + - image: solid-color(77, 3, 0, 255, 8, 8) + bounds: 616 24 8 8 + - image: solid-color(78, 3, 0, 255, 8, 8) + bounds: 624 24 8 8 + - image: solid-color(79, 3, 0, 255, 8, 8) + bounds: 632 24 8 8 + - image: solid-color(80, 3, 0, 255, 8, 8) + bounds: 640 24 8 8 + - image: solid-color(81, 3, 0, 255, 8, 8) + bounds: 648 24 8 8 + - image: solid-color(82, 3, 0, 255, 8, 8) + bounds: 656 24 8 8 + - image: solid-color(83, 3, 0, 255, 8, 8) + bounds: 664 24 8 8 + - image: solid-color(84, 3, 0, 255, 8, 8) + bounds: 672 24 8 8 + - image: solid-color(85, 3, 0, 255, 8, 8) + bounds: 680 24 8 8 + - image: solid-color(86, 3, 0, 255, 8, 8) + bounds: 688 24 8 8 + - image: solid-color(87, 3, 0, 255, 8, 8) + bounds: 696 24 8 8 + - image: solid-color(88, 3, 0, 255, 8, 8) + bounds: 704 24 8 8 + - image: solid-color(89, 3, 0, 255, 8, 8) + bounds: 712 24 8 8 + - image: solid-color(90, 3, 0, 255, 8, 8) + bounds: 720 24 8 8 + - image: solid-color(91, 3, 0, 255, 8, 8) + bounds: 728 24 8 8 + - image: solid-color(92, 3, 0, 255, 8, 8) + bounds: 736 24 8 8 + - image: solid-color(93, 3, 0, 255, 8, 8) + bounds: 744 24 8 8 + - image: solid-color(94, 3, 0, 255, 8, 8) + bounds: 752 24 8 8 + - image: solid-color(95, 3, 0, 255, 8, 8) + bounds: 760 24 8 8 + - image: solid-color(96, 3, 0, 255, 8, 8) + bounds: 768 24 8 8 + - image: solid-color(97, 3, 0, 255, 8, 8) + bounds: 776 24 8 8 + - image: solid-color(98, 3, 0, 255, 8, 8) + bounds: 784 24 8 8 + - image: solid-color(99, 3, 0, 255, 8, 8) + bounds: 792 24 8 8 + - image: solid-color(100, 3, 0, 255, 8, 8) + bounds: 800 24 8 8 + - image: solid-color(101, 3, 0, 255, 8, 8) + bounds: 808 24 8 8 + - image: solid-color(102, 3, 0, 255, 8, 8) + bounds: 816 24 8 8 + - image: solid-color(103, 3, 0, 255, 8, 8) + bounds: 824 24 8 8 + - image: solid-color(104, 3, 0, 255, 8, 8) + bounds: 832 24 8 8 + - image: solid-color(105, 3, 0, 255, 8, 8) + bounds: 840 24 8 8 + - image: solid-color(106, 3, 0, 255, 8, 8) + bounds: 848 24 8 8 + - image: solid-color(107, 3, 0, 255, 8, 8) + bounds: 856 24 8 8 + - image: solid-color(108, 3, 0, 255, 8, 8) + bounds: 864 24 8 8 + - image: solid-color(109, 3, 0, 255, 8, 8) + bounds: 872 24 8 8 + - image: solid-color(110, 3, 0, 255, 8, 8) + bounds: 880 24 8 8 + - image: solid-color(111, 3, 0, 255, 8, 8) + bounds: 888 24 8 8 + - image: solid-color(112, 3, 0, 255, 8, 8) + bounds: 896 24 8 8 + - image: solid-color(113, 3, 0, 255, 8, 8) + bounds: 904 24 8 8 + - image: solid-color(114, 3, 0, 255, 8, 8) + bounds: 912 24 8 8 + - image: solid-color(115, 3, 0, 255, 8, 8) + bounds: 920 24 8 8 + - image: solid-color(116, 3, 0, 255, 8, 8) + bounds: 928 24 8 8 + - image: solid-color(117, 3, 0, 255, 8, 8) + bounds: 936 24 8 8 + - image: solid-color(118, 3, 0, 255, 8, 8) + bounds: 944 24 8 8 + - image: solid-color(119, 3, 0, 255, 8, 8) + bounds: 952 24 8 8 + - image: solid-color(120, 3, 0, 255, 8, 8) + bounds: 960 24 8 8 + - image: solid-color(121, 3, 0, 255, 8, 8) + bounds: 968 24 8 8 + - image: solid-color(122, 3, 0, 255, 8, 8) + bounds: 976 24 8 8 + - image: solid-color(123, 3, 0, 255, 8, 8) + bounds: 984 24 8 8 + - image: solid-color(124, 3, 0, 255, 8, 8) + bounds: 992 24 8 8 + - image: solid-color(125, 3, 0, 255, 8, 8) + bounds: 1000 24 8 8 + - image: solid-color(126, 3, 0, 255, 8, 8) + bounds: 1008 24 8 8 + - image: solid-color(127, 3, 0, 255, 8, 8) + bounds: 1016 24 8 8 + - image: solid-color(0, 4, 0, 255, 8, 8) + bounds: 0 32 8 8 + - image: solid-color(1, 4, 0, 255, 8, 8) + bounds: 8 32 8 8 + - image: solid-color(2, 4, 0, 255, 8, 8) + bounds: 16 32 8 8 + - image: solid-color(3, 4, 0, 255, 8, 8) + bounds: 24 32 8 8 + - image: solid-color(4, 4, 0, 255, 8, 8) + bounds: 32 32 8 8 + - image: solid-color(5, 4, 0, 255, 8, 8) + bounds: 40 32 8 8 + - image: solid-color(6, 4, 0, 255, 8, 8) + bounds: 48 32 8 8 + - image: solid-color(7, 4, 0, 255, 8, 8) + bounds: 56 32 8 8 + - image: solid-color(8, 4, 0, 255, 8, 8) + bounds: 64 32 8 8 + - image: solid-color(9, 4, 0, 255, 8, 8) + bounds: 72 32 8 8 + - image: solid-color(10, 4, 0, 255, 8, 8) + bounds: 80 32 8 8 + - image: solid-color(11, 4, 0, 255, 8, 8) + bounds: 88 32 8 8 + - image: solid-color(12, 4, 0, 255, 8, 8) + bounds: 96 32 8 8 + - image: solid-color(13, 4, 0, 255, 8, 8) + bounds: 104 32 8 8 + - image: solid-color(14, 4, 0, 255, 8, 8) + bounds: 112 32 8 8 + - image: solid-color(15, 4, 0, 255, 8, 8) + bounds: 120 32 8 8 + - image: solid-color(16, 4, 0, 255, 8, 8) + bounds: 128 32 8 8 + - image: solid-color(17, 4, 0, 255, 8, 8) + bounds: 136 32 8 8 + - image: solid-color(18, 4, 0, 255, 8, 8) + bounds: 144 32 8 8 + - image: solid-color(19, 4, 0, 255, 8, 8) + bounds: 152 32 8 8 + - image: solid-color(20, 4, 0, 255, 8, 8) + bounds: 160 32 8 8 + - image: solid-color(21, 4, 0, 255, 8, 8) + bounds: 168 32 8 8 + - image: solid-color(22, 4, 0, 255, 8, 8) + bounds: 176 32 8 8 + - image: solid-color(23, 4, 0, 255, 8, 8) + bounds: 184 32 8 8 + - image: solid-color(24, 4, 0, 255, 8, 8) + bounds: 192 32 8 8 + - image: solid-color(25, 4, 0, 255, 8, 8) + bounds: 200 32 8 8 + - image: solid-color(26, 4, 0, 255, 8, 8) + bounds: 208 32 8 8 + - image: solid-color(27, 4, 0, 255, 8, 8) + bounds: 216 32 8 8 + - image: solid-color(28, 4, 0, 255, 8, 8) + bounds: 224 32 8 8 + - image: solid-color(29, 4, 0, 255, 8, 8) + bounds: 232 32 8 8 + - image: solid-color(30, 4, 0, 255, 8, 8) + bounds: 240 32 8 8 + - image: solid-color(31, 4, 0, 255, 8, 8) + bounds: 248 32 8 8 + - image: solid-color(32, 4, 0, 255, 8, 8) + bounds: 256 32 8 8 + - image: solid-color(33, 4, 0, 255, 8, 8) + bounds: 264 32 8 8 + - image: solid-color(34, 4, 0, 255, 8, 8) + bounds: 272 32 8 8 + - image: solid-color(35, 4, 0, 255, 8, 8) + bounds: 280 32 8 8 + - image: solid-color(36, 4, 0, 255, 8, 8) + bounds: 288 32 8 8 + - image: solid-color(37, 4, 0, 255, 8, 8) + bounds: 296 32 8 8 + - image: solid-color(38, 4, 0, 255, 8, 8) + bounds: 304 32 8 8 + - image: solid-color(39, 4, 0, 255, 8, 8) + bounds: 312 32 8 8 + - image: solid-color(40, 4, 0, 255, 8, 8) + bounds: 320 32 8 8 + - image: solid-color(41, 4, 0, 255, 8, 8) + bounds: 328 32 8 8 + - image: solid-color(42, 4, 0, 255, 8, 8) + bounds: 336 32 8 8 + - image: solid-color(43, 4, 0, 255, 8, 8) + bounds: 344 32 8 8 + - image: solid-color(44, 4, 0, 255, 8, 8) + bounds: 352 32 8 8 + - image: solid-color(45, 4, 0, 255, 8, 8) + bounds: 360 32 8 8 + - image: solid-color(46, 4, 0, 255, 8, 8) + bounds: 368 32 8 8 + - image: solid-color(47, 4, 0, 255, 8, 8) + bounds: 376 32 8 8 + - image: solid-color(48, 4, 0, 255, 8, 8) + bounds: 384 32 8 8 + - image: solid-color(49, 4, 0, 255, 8, 8) + bounds: 392 32 8 8 + - image: solid-color(50, 4, 0, 255, 8, 8) + bounds: 400 32 8 8 + - image: solid-color(51, 4, 0, 255, 8, 8) + bounds: 408 32 8 8 + - image: solid-color(52, 4, 0, 255, 8, 8) + bounds: 416 32 8 8 + - image: solid-color(53, 4, 0, 255, 8, 8) + bounds: 424 32 8 8 + - image: solid-color(54, 4, 0, 255, 8, 8) + bounds: 432 32 8 8 + - image: solid-color(55, 4, 0, 255, 8, 8) + bounds: 440 32 8 8 + - image: solid-color(56, 4, 0, 255, 8, 8) + bounds: 448 32 8 8 + - image: solid-color(57, 4, 0, 255, 8, 8) + bounds: 456 32 8 8 + - image: solid-color(58, 4, 0, 255, 8, 8) + bounds: 464 32 8 8 + - image: solid-color(59, 4, 0, 255, 8, 8) + bounds: 472 32 8 8 + - image: solid-color(60, 4, 0, 255, 8, 8) + bounds: 480 32 8 8 + - image: solid-color(61, 4, 0, 255, 8, 8) + bounds: 488 32 8 8 + - image: solid-color(62, 4, 0, 255, 8, 8) + bounds: 496 32 8 8 + - image: solid-color(63, 4, 0, 255, 8, 8) + bounds: 504 32 8 8 + - image: solid-color(64, 4, 0, 255, 8, 8) + bounds: 512 32 8 8 + - image: solid-color(65, 4, 0, 255, 8, 8) + bounds: 520 32 8 8 + - image: solid-color(66, 4, 0, 255, 8, 8) + bounds: 528 32 8 8 + - image: solid-color(67, 4, 0, 255, 8, 8) + bounds: 536 32 8 8 + - image: solid-color(68, 4, 0, 255, 8, 8) + bounds: 544 32 8 8 + - image: solid-color(69, 4, 0, 255, 8, 8) + bounds: 552 32 8 8 + - image: solid-color(70, 4, 0, 255, 8, 8) + bounds: 560 32 8 8 + - image: solid-color(71, 4, 0, 255, 8, 8) + bounds: 568 32 8 8 + - image: solid-color(72, 4, 0, 255, 8, 8) + bounds: 576 32 8 8 + - image: solid-color(73, 4, 0, 255, 8, 8) + bounds: 584 32 8 8 + - image: solid-color(74, 4, 0, 255, 8, 8) + bounds: 592 32 8 8 + - image: solid-color(75, 4, 0, 255, 8, 8) + bounds: 600 32 8 8 + - image: solid-color(76, 4, 0, 255, 8, 8) + bounds: 608 32 8 8 + - image: solid-color(77, 4, 0, 255, 8, 8) + bounds: 616 32 8 8 + - image: solid-color(78, 4, 0, 255, 8, 8) + bounds: 624 32 8 8 + - image: solid-color(79, 4, 0, 255, 8, 8) + bounds: 632 32 8 8 + - image: solid-color(80, 4, 0, 255, 8, 8) + bounds: 640 32 8 8 + - image: solid-color(81, 4, 0, 255, 8, 8) + bounds: 648 32 8 8 + - image: solid-color(82, 4, 0, 255, 8, 8) + bounds: 656 32 8 8 + - image: solid-color(83, 4, 0, 255, 8, 8) + bounds: 664 32 8 8 + - image: solid-color(84, 4, 0, 255, 8, 8) + bounds: 672 32 8 8 + - image: solid-color(85, 4, 0, 255, 8, 8) + bounds: 680 32 8 8 + - image: solid-color(86, 4, 0, 255, 8, 8) + bounds: 688 32 8 8 + - image: solid-color(87, 4, 0, 255, 8, 8) + bounds: 696 32 8 8 + - image: solid-color(88, 4, 0, 255, 8, 8) + bounds: 704 32 8 8 + - image: solid-color(89, 4, 0, 255, 8, 8) + bounds: 712 32 8 8 + - image: solid-color(90, 4, 0, 255, 8, 8) + bounds: 720 32 8 8 + - image: solid-color(91, 4, 0, 255, 8, 8) + bounds: 728 32 8 8 + - image: solid-color(92, 4, 0, 255, 8, 8) + bounds: 736 32 8 8 + - image: solid-color(93, 4, 0, 255, 8, 8) + bounds: 744 32 8 8 + - image: solid-color(94, 4, 0, 255, 8, 8) + bounds: 752 32 8 8 + - image: solid-color(95, 4, 0, 255, 8, 8) + bounds: 760 32 8 8 + - image: solid-color(96, 4, 0, 255, 8, 8) + bounds: 768 32 8 8 + - image: solid-color(97, 4, 0, 255, 8, 8) + bounds: 776 32 8 8 + - image: solid-color(98, 4, 0, 255, 8, 8) + bounds: 784 32 8 8 + - image: solid-color(99, 4, 0, 255, 8, 8) + bounds: 792 32 8 8 + - image: solid-color(100, 4, 0, 255, 8, 8) + bounds: 800 32 8 8 + - image: solid-color(101, 4, 0, 255, 8, 8) + bounds: 808 32 8 8 + - image: solid-color(102, 4, 0, 255, 8, 8) + bounds: 816 32 8 8 + - image: solid-color(103, 4, 0, 255, 8, 8) + bounds: 824 32 8 8 + - image: solid-color(104, 4, 0, 255, 8, 8) + bounds: 832 32 8 8 + - image: solid-color(105, 4, 0, 255, 8, 8) + bounds: 840 32 8 8 + - image: solid-color(106, 4, 0, 255, 8, 8) + bounds: 848 32 8 8 + - image: solid-color(107, 4, 0, 255, 8, 8) + bounds: 856 32 8 8 + - image: solid-color(108, 4, 0, 255, 8, 8) + bounds: 864 32 8 8 + - image: solid-color(109, 4, 0, 255, 8, 8) + bounds: 872 32 8 8 + - image: solid-color(110, 4, 0, 255, 8, 8) + bounds: 880 32 8 8 + - image: solid-color(111, 4, 0, 255, 8, 8) + bounds: 888 32 8 8 + - image: solid-color(112, 4, 0, 255, 8, 8) + bounds: 896 32 8 8 + - image: solid-color(113, 4, 0, 255, 8, 8) + bounds: 904 32 8 8 + - image: solid-color(114, 4, 0, 255, 8, 8) + bounds: 912 32 8 8 + - image: solid-color(115, 4, 0, 255, 8, 8) + bounds: 920 32 8 8 + - image: solid-color(116, 4, 0, 255, 8, 8) + bounds: 928 32 8 8 + - image: solid-color(117, 4, 0, 255, 8, 8) + bounds: 936 32 8 8 + - image: solid-color(118, 4, 0, 255, 8, 8) + bounds: 944 32 8 8 + - image: solid-color(119, 4, 0, 255, 8, 8) + bounds: 952 32 8 8 + - image: solid-color(120, 4, 0, 255, 8, 8) + bounds: 960 32 8 8 + - image: solid-color(121, 4, 0, 255, 8, 8) + bounds: 968 32 8 8 + - image: solid-color(122, 4, 0, 255, 8, 8) + bounds: 976 32 8 8 + - image: solid-color(123, 4, 0, 255, 8, 8) + bounds: 984 32 8 8 + - image: solid-color(124, 4, 0, 255, 8, 8) + bounds: 992 32 8 8 + - image: solid-color(125, 4, 0, 255, 8, 8) + bounds: 1000 32 8 8 + - image: solid-color(126, 4, 0, 255, 8, 8) + bounds: 1008 32 8 8 + - image: solid-color(127, 4, 0, 255, 8, 8) + bounds: 1016 32 8 8 + - image: solid-color(0, 5, 0, 255, 8, 8) + bounds: 0 40 8 8 + - image: solid-color(1, 5, 0, 255, 8, 8) + bounds: 8 40 8 8 + - image: solid-color(2, 5, 0, 255, 8, 8) + bounds: 16 40 8 8 + - image: solid-color(3, 5, 0, 255, 8, 8) + bounds: 24 40 8 8 + - image: solid-color(4, 5, 0, 255, 8, 8) + bounds: 32 40 8 8 + - image: solid-color(5, 5, 0, 255, 8, 8) + bounds: 40 40 8 8 + - image: solid-color(6, 5, 0, 255, 8, 8) + bounds: 48 40 8 8 + - image: solid-color(7, 5, 0, 255, 8, 8) + bounds: 56 40 8 8 + - image: solid-color(8, 5, 0, 255, 8, 8) + bounds: 64 40 8 8 + - image: solid-color(9, 5, 0, 255, 8, 8) + bounds: 72 40 8 8 + - image: solid-color(10, 5, 0, 255, 8, 8) + bounds: 80 40 8 8 + - image: solid-color(11, 5, 0, 255, 8, 8) + bounds: 88 40 8 8 + - image: solid-color(12, 5, 0, 255, 8, 8) + bounds: 96 40 8 8 + - image: solid-color(13, 5, 0, 255, 8, 8) + bounds: 104 40 8 8 + - image: solid-color(14, 5, 0, 255, 8, 8) + bounds: 112 40 8 8 + - image: solid-color(15, 5, 0, 255, 8, 8) + bounds: 120 40 8 8 + - image: solid-color(16, 5, 0, 255, 8, 8) + bounds: 128 40 8 8 + - image: solid-color(17, 5, 0, 255, 8, 8) + bounds: 136 40 8 8 + - image: solid-color(18, 5, 0, 255, 8, 8) + bounds: 144 40 8 8 + - image: solid-color(19, 5, 0, 255, 8, 8) + bounds: 152 40 8 8 + - image: solid-color(20, 5, 0, 255, 8, 8) + bounds: 160 40 8 8 + - image: solid-color(21, 5, 0, 255, 8, 8) + bounds: 168 40 8 8 + - image: solid-color(22, 5, 0, 255, 8, 8) + bounds: 176 40 8 8 + - image: solid-color(23, 5, 0, 255, 8, 8) + bounds: 184 40 8 8 + - image: solid-color(24, 5, 0, 255, 8, 8) + bounds: 192 40 8 8 + - image: solid-color(25, 5, 0, 255, 8, 8) + bounds: 200 40 8 8 + - image: solid-color(26, 5, 0, 255, 8, 8) + bounds: 208 40 8 8 + - image: solid-color(27, 5, 0, 255, 8, 8) + bounds: 216 40 8 8 + - image: solid-color(28, 5, 0, 255, 8, 8) + bounds: 224 40 8 8 + - image: solid-color(29, 5, 0, 255, 8, 8) + bounds: 232 40 8 8 + - image: solid-color(30, 5, 0, 255, 8, 8) + bounds: 240 40 8 8 + - image: solid-color(31, 5, 0, 255, 8, 8) + bounds: 248 40 8 8 + - image: solid-color(32, 5, 0, 255, 8, 8) + bounds: 256 40 8 8 + - image: solid-color(33, 5, 0, 255, 8, 8) + bounds: 264 40 8 8 + - image: solid-color(34, 5, 0, 255, 8, 8) + bounds: 272 40 8 8 + - image: solid-color(35, 5, 0, 255, 8, 8) + bounds: 280 40 8 8 + - image: solid-color(36, 5, 0, 255, 8, 8) + bounds: 288 40 8 8 + - image: solid-color(37, 5, 0, 255, 8, 8) + bounds: 296 40 8 8 + - image: solid-color(38, 5, 0, 255, 8, 8) + bounds: 304 40 8 8 + - image: solid-color(39, 5, 0, 255, 8, 8) + bounds: 312 40 8 8 + - image: solid-color(40, 5, 0, 255, 8, 8) + bounds: 320 40 8 8 + - image: solid-color(41, 5, 0, 255, 8, 8) + bounds: 328 40 8 8 + - image: solid-color(42, 5, 0, 255, 8, 8) + bounds: 336 40 8 8 + - image: solid-color(43, 5, 0, 255, 8, 8) + bounds: 344 40 8 8 + - image: solid-color(44, 5, 0, 255, 8, 8) + bounds: 352 40 8 8 + - image: solid-color(45, 5, 0, 255, 8, 8) + bounds: 360 40 8 8 + - image: solid-color(46, 5, 0, 255, 8, 8) + bounds: 368 40 8 8 + - image: solid-color(47, 5, 0, 255, 8, 8) + bounds: 376 40 8 8 + - image: solid-color(48, 5, 0, 255, 8, 8) + bounds: 384 40 8 8 + - image: solid-color(49, 5, 0, 255, 8, 8) + bounds: 392 40 8 8 + - image: solid-color(50, 5, 0, 255, 8, 8) + bounds: 400 40 8 8 + - image: solid-color(51, 5, 0, 255, 8, 8) + bounds: 408 40 8 8 + - image: solid-color(52, 5, 0, 255, 8, 8) + bounds: 416 40 8 8 + - image: solid-color(53, 5, 0, 255, 8, 8) + bounds: 424 40 8 8 + - image: solid-color(54, 5, 0, 255, 8, 8) + bounds: 432 40 8 8 + - image: solid-color(55, 5, 0, 255, 8, 8) + bounds: 440 40 8 8 + - image: solid-color(56, 5, 0, 255, 8, 8) + bounds: 448 40 8 8 + - image: solid-color(57, 5, 0, 255, 8, 8) + bounds: 456 40 8 8 + - image: solid-color(58, 5, 0, 255, 8, 8) + bounds: 464 40 8 8 + - image: solid-color(59, 5, 0, 255, 8, 8) + bounds: 472 40 8 8 + - image: solid-color(60, 5, 0, 255, 8, 8) + bounds: 480 40 8 8 + - image: solid-color(61, 5, 0, 255, 8, 8) + bounds: 488 40 8 8 + - image: solid-color(62, 5, 0, 255, 8, 8) + bounds: 496 40 8 8 + - image: solid-color(63, 5, 0, 255, 8, 8) + bounds: 504 40 8 8 + - image: solid-color(64, 5, 0, 255, 8, 8) + bounds: 512 40 8 8 + - image: solid-color(65, 5, 0, 255, 8, 8) + bounds: 520 40 8 8 + - image: solid-color(66, 5, 0, 255, 8, 8) + bounds: 528 40 8 8 + - image: solid-color(67, 5, 0, 255, 8, 8) + bounds: 536 40 8 8 + - image: solid-color(68, 5, 0, 255, 8, 8) + bounds: 544 40 8 8 + - image: solid-color(69, 5, 0, 255, 8, 8) + bounds: 552 40 8 8 + - image: solid-color(70, 5, 0, 255, 8, 8) + bounds: 560 40 8 8 + - image: solid-color(71, 5, 0, 255, 8, 8) + bounds: 568 40 8 8 + - image: solid-color(72, 5, 0, 255, 8, 8) + bounds: 576 40 8 8 + - image: solid-color(73, 5, 0, 255, 8, 8) + bounds: 584 40 8 8 + - image: solid-color(74, 5, 0, 255, 8, 8) + bounds: 592 40 8 8 + - image: solid-color(75, 5, 0, 255, 8, 8) + bounds: 600 40 8 8 + - image: solid-color(76, 5, 0, 255, 8, 8) + bounds: 608 40 8 8 + - image: solid-color(77, 5, 0, 255, 8, 8) + bounds: 616 40 8 8 + - image: solid-color(78, 5, 0, 255, 8, 8) + bounds: 624 40 8 8 + - image: solid-color(79, 5, 0, 255, 8, 8) + bounds: 632 40 8 8 + - image: solid-color(80, 5, 0, 255, 8, 8) + bounds: 640 40 8 8 + - image: solid-color(81, 5, 0, 255, 8, 8) + bounds: 648 40 8 8 + - image: solid-color(82, 5, 0, 255, 8, 8) + bounds: 656 40 8 8 + - image: solid-color(83, 5, 0, 255, 8, 8) + bounds: 664 40 8 8 + - image: solid-color(84, 5, 0, 255, 8, 8) + bounds: 672 40 8 8 + - image: solid-color(85, 5, 0, 255, 8, 8) + bounds: 680 40 8 8 + - image: solid-color(86, 5, 0, 255, 8, 8) + bounds: 688 40 8 8 + - image: solid-color(87, 5, 0, 255, 8, 8) + bounds: 696 40 8 8 + - image: solid-color(88, 5, 0, 255, 8, 8) + bounds: 704 40 8 8 + - image: solid-color(89, 5, 0, 255, 8, 8) + bounds: 712 40 8 8 + - image: solid-color(90, 5, 0, 255, 8, 8) + bounds: 720 40 8 8 + - image: solid-color(91, 5, 0, 255, 8, 8) + bounds: 728 40 8 8 + - image: solid-color(92, 5, 0, 255, 8, 8) + bounds: 736 40 8 8 + - image: solid-color(93, 5, 0, 255, 8, 8) + bounds: 744 40 8 8 + - image: solid-color(94, 5, 0, 255, 8, 8) + bounds: 752 40 8 8 + - image: solid-color(95, 5, 0, 255, 8, 8) + bounds: 760 40 8 8 + - image: solid-color(96, 5, 0, 255, 8, 8) + bounds: 768 40 8 8 + - image: solid-color(97, 5, 0, 255, 8, 8) + bounds: 776 40 8 8 + - image: solid-color(98, 5, 0, 255, 8, 8) + bounds: 784 40 8 8 + - image: solid-color(99, 5, 0, 255, 8, 8) + bounds: 792 40 8 8 + - image: solid-color(100, 5, 0, 255, 8, 8) + bounds: 800 40 8 8 + - image: solid-color(101, 5, 0, 255, 8, 8) + bounds: 808 40 8 8 + - image: solid-color(102, 5, 0, 255, 8, 8) + bounds: 816 40 8 8 + - image: solid-color(103, 5, 0, 255, 8, 8) + bounds: 824 40 8 8 + - image: solid-color(104, 5, 0, 255, 8, 8) + bounds: 832 40 8 8 + - image: solid-color(105, 5, 0, 255, 8, 8) + bounds: 840 40 8 8 + - image: solid-color(106, 5, 0, 255, 8, 8) + bounds: 848 40 8 8 + - image: solid-color(107, 5, 0, 255, 8, 8) + bounds: 856 40 8 8 + - image: solid-color(108, 5, 0, 255, 8, 8) + bounds: 864 40 8 8 + - image: solid-color(109, 5, 0, 255, 8, 8) + bounds: 872 40 8 8 + - image: solid-color(110, 5, 0, 255, 8, 8) + bounds: 880 40 8 8 + - image: solid-color(111, 5, 0, 255, 8, 8) + bounds: 888 40 8 8 + - image: solid-color(112, 5, 0, 255, 8, 8) + bounds: 896 40 8 8 + - image: solid-color(113, 5, 0, 255, 8, 8) + bounds: 904 40 8 8 + - image: solid-color(114, 5, 0, 255, 8, 8) + bounds: 912 40 8 8 + - image: solid-color(115, 5, 0, 255, 8, 8) + bounds: 920 40 8 8 + - image: solid-color(116, 5, 0, 255, 8, 8) + bounds: 928 40 8 8 + - image: solid-color(117, 5, 0, 255, 8, 8) + bounds: 936 40 8 8 + - image: solid-color(118, 5, 0, 255, 8, 8) + bounds: 944 40 8 8 + - image: solid-color(119, 5, 0, 255, 8, 8) + bounds: 952 40 8 8 + - image: solid-color(120, 5, 0, 255, 8, 8) + bounds: 960 40 8 8 + - image: solid-color(121, 5, 0, 255, 8, 8) + bounds: 968 40 8 8 + - image: solid-color(122, 5, 0, 255, 8, 8) + bounds: 976 40 8 8 + - image: solid-color(123, 5, 0, 255, 8, 8) + bounds: 984 40 8 8 + - image: solid-color(124, 5, 0, 255, 8, 8) + bounds: 992 40 8 8 + - image: solid-color(125, 5, 0, 255, 8, 8) + bounds: 1000 40 8 8 + - image: solid-color(126, 5, 0, 255, 8, 8) + bounds: 1008 40 8 8 + - image: solid-color(127, 5, 0, 255, 8, 8) + bounds: 1016 40 8 8 + - image: solid-color(0, 6, 0, 255, 8, 8) + bounds: 0 48 8 8 + - image: solid-color(1, 6, 0, 255, 8, 8) + bounds: 8 48 8 8 + - image: solid-color(2, 6, 0, 255, 8, 8) + bounds: 16 48 8 8 + - image: solid-color(3, 6, 0, 255, 8, 8) + bounds: 24 48 8 8 + - image: solid-color(4, 6, 0, 255, 8, 8) + bounds: 32 48 8 8 + - image: solid-color(5, 6, 0, 255, 8, 8) + bounds: 40 48 8 8 + - image: solid-color(6, 6, 0, 255, 8, 8) + bounds: 48 48 8 8 + - image: solid-color(7, 6, 0, 255, 8, 8) + bounds: 56 48 8 8 + - image: solid-color(8, 6, 0, 255, 8, 8) + bounds: 64 48 8 8 + - image: solid-color(9, 6, 0, 255, 8, 8) + bounds: 72 48 8 8 + - image: solid-color(10, 6, 0, 255, 8, 8) + bounds: 80 48 8 8 + - image: solid-color(11, 6, 0, 255, 8, 8) + bounds: 88 48 8 8 + - image: solid-color(12, 6, 0, 255, 8, 8) + bounds: 96 48 8 8 + - image: solid-color(13, 6, 0, 255, 8, 8) + bounds: 104 48 8 8 + - image: solid-color(14, 6, 0, 255, 8, 8) + bounds: 112 48 8 8 + - image: solid-color(15, 6, 0, 255, 8, 8) + bounds: 120 48 8 8 + - image: solid-color(16, 6, 0, 255, 8, 8) + bounds: 128 48 8 8 + - image: solid-color(17, 6, 0, 255, 8, 8) + bounds: 136 48 8 8 + - image: solid-color(18, 6, 0, 255, 8, 8) + bounds: 144 48 8 8 + - image: solid-color(19, 6, 0, 255, 8, 8) + bounds: 152 48 8 8 + - image: solid-color(20, 6, 0, 255, 8, 8) + bounds: 160 48 8 8 + - image: solid-color(21, 6, 0, 255, 8, 8) + bounds: 168 48 8 8 + - image: solid-color(22, 6, 0, 255, 8, 8) + bounds: 176 48 8 8 + - image: solid-color(23, 6, 0, 255, 8, 8) + bounds: 184 48 8 8 + - image: solid-color(24, 6, 0, 255, 8, 8) + bounds: 192 48 8 8 + - image: solid-color(25, 6, 0, 255, 8, 8) + bounds: 200 48 8 8 + - image: solid-color(26, 6, 0, 255, 8, 8) + bounds: 208 48 8 8 + - image: solid-color(27, 6, 0, 255, 8, 8) + bounds: 216 48 8 8 + - image: solid-color(28, 6, 0, 255, 8, 8) + bounds: 224 48 8 8 + - image: solid-color(29, 6, 0, 255, 8, 8) + bounds: 232 48 8 8 + - image: solid-color(30, 6, 0, 255, 8, 8) + bounds: 240 48 8 8 + - image: solid-color(31, 6, 0, 255, 8, 8) + bounds: 248 48 8 8 + - image: solid-color(32, 6, 0, 255, 8, 8) + bounds: 256 48 8 8 + - image: solid-color(33, 6, 0, 255, 8, 8) + bounds: 264 48 8 8 + - image: solid-color(34, 6, 0, 255, 8, 8) + bounds: 272 48 8 8 + - image: solid-color(35, 6, 0, 255, 8, 8) + bounds: 280 48 8 8 + - image: solid-color(36, 6, 0, 255, 8, 8) + bounds: 288 48 8 8 + - image: solid-color(37, 6, 0, 255, 8, 8) + bounds: 296 48 8 8 + - image: solid-color(38, 6, 0, 255, 8, 8) + bounds: 304 48 8 8 + - image: solid-color(39, 6, 0, 255, 8, 8) + bounds: 312 48 8 8 + - image: solid-color(40, 6, 0, 255, 8, 8) + bounds: 320 48 8 8 + - image: solid-color(41, 6, 0, 255, 8, 8) + bounds: 328 48 8 8 + - image: solid-color(42, 6, 0, 255, 8, 8) + bounds: 336 48 8 8 + - image: solid-color(43, 6, 0, 255, 8, 8) + bounds: 344 48 8 8 + - image: solid-color(44, 6, 0, 255, 8, 8) + bounds: 352 48 8 8 + - image: solid-color(45, 6, 0, 255, 8, 8) + bounds: 360 48 8 8 + - image: solid-color(46, 6, 0, 255, 8, 8) + bounds: 368 48 8 8 + - image: solid-color(47, 6, 0, 255, 8, 8) + bounds: 376 48 8 8 + - image: solid-color(48, 6, 0, 255, 8, 8) + bounds: 384 48 8 8 + - image: solid-color(49, 6, 0, 255, 8, 8) + bounds: 392 48 8 8 + - image: solid-color(50, 6, 0, 255, 8, 8) + bounds: 400 48 8 8 + - image: solid-color(51, 6, 0, 255, 8, 8) + bounds: 408 48 8 8 + - image: solid-color(52, 6, 0, 255, 8, 8) + bounds: 416 48 8 8 + - image: solid-color(53, 6, 0, 255, 8, 8) + bounds: 424 48 8 8 + - image: solid-color(54, 6, 0, 255, 8, 8) + bounds: 432 48 8 8 + - image: solid-color(55, 6, 0, 255, 8, 8) + bounds: 440 48 8 8 + - image: solid-color(56, 6, 0, 255, 8, 8) + bounds: 448 48 8 8 + - image: solid-color(57, 6, 0, 255, 8, 8) + bounds: 456 48 8 8 + - image: solid-color(58, 6, 0, 255, 8, 8) + bounds: 464 48 8 8 + - image: solid-color(59, 6, 0, 255, 8, 8) + bounds: 472 48 8 8 + - image: solid-color(60, 6, 0, 255, 8, 8) + bounds: 480 48 8 8 + - image: solid-color(61, 6, 0, 255, 8, 8) + bounds: 488 48 8 8 + - image: solid-color(62, 6, 0, 255, 8, 8) + bounds: 496 48 8 8 + - image: solid-color(63, 6, 0, 255, 8, 8) + bounds: 504 48 8 8 + - image: solid-color(64, 6, 0, 255, 8, 8) + bounds: 512 48 8 8 + - image: solid-color(65, 6, 0, 255, 8, 8) + bounds: 520 48 8 8 + - image: solid-color(66, 6, 0, 255, 8, 8) + bounds: 528 48 8 8 + - image: solid-color(67, 6, 0, 255, 8, 8) + bounds: 536 48 8 8 + - image: solid-color(68, 6, 0, 255, 8, 8) + bounds: 544 48 8 8 + - image: solid-color(69, 6, 0, 255, 8, 8) + bounds: 552 48 8 8 + - image: solid-color(70, 6, 0, 255, 8, 8) + bounds: 560 48 8 8 + - image: solid-color(71, 6, 0, 255, 8, 8) + bounds: 568 48 8 8 + - image: solid-color(72, 6, 0, 255, 8, 8) + bounds: 576 48 8 8 + - image: solid-color(73, 6, 0, 255, 8, 8) + bounds: 584 48 8 8 + - image: solid-color(74, 6, 0, 255, 8, 8) + bounds: 592 48 8 8 + - image: solid-color(75, 6, 0, 255, 8, 8) + bounds: 600 48 8 8 + - image: solid-color(76, 6, 0, 255, 8, 8) + bounds: 608 48 8 8 + - image: solid-color(77, 6, 0, 255, 8, 8) + bounds: 616 48 8 8 + - image: solid-color(78, 6, 0, 255, 8, 8) + bounds: 624 48 8 8 + - image: solid-color(79, 6, 0, 255, 8, 8) + bounds: 632 48 8 8 + - image: solid-color(80, 6, 0, 255, 8, 8) + bounds: 640 48 8 8 + - image: solid-color(81, 6, 0, 255, 8, 8) + bounds: 648 48 8 8 + - image: solid-color(82, 6, 0, 255, 8, 8) + bounds: 656 48 8 8 + - image: solid-color(83, 6, 0, 255, 8, 8) + bounds: 664 48 8 8 + - image: solid-color(84, 6, 0, 255, 8, 8) + bounds: 672 48 8 8 + - image: solid-color(85, 6, 0, 255, 8, 8) + bounds: 680 48 8 8 + - image: solid-color(86, 6, 0, 255, 8, 8) + bounds: 688 48 8 8 + - image: solid-color(87, 6, 0, 255, 8, 8) + bounds: 696 48 8 8 + - image: solid-color(88, 6, 0, 255, 8, 8) + bounds: 704 48 8 8 + - image: solid-color(89, 6, 0, 255, 8, 8) + bounds: 712 48 8 8 + - image: solid-color(90, 6, 0, 255, 8, 8) + bounds: 720 48 8 8 + - image: solid-color(91, 6, 0, 255, 8, 8) + bounds: 728 48 8 8 + - image: solid-color(92, 6, 0, 255, 8, 8) + bounds: 736 48 8 8 + - image: solid-color(93, 6, 0, 255, 8, 8) + bounds: 744 48 8 8 + - image: solid-color(94, 6, 0, 255, 8, 8) + bounds: 752 48 8 8 + - image: solid-color(95, 6, 0, 255, 8, 8) + bounds: 760 48 8 8 + - image: solid-color(96, 6, 0, 255, 8, 8) + bounds: 768 48 8 8 + - image: solid-color(97, 6, 0, 255, 8, 8) + bounds: 776 48 8 8 + - image: solid-color(98, 6, 0, 255, 8, 8) + bounds: 784 48 8 8 + - image: solid-color(99, 6, 0, 255, 8, 8) + bounds: 792 48 8 8 + - image: solid-color(100, 6, 0, 255, 8, 8) + bounds: 800 48 8 8 + - image: solid-color(101, 6, 0, 255, 8, 8) + bounds: 808 48 8 8 + - image: solid-color(102, 6, 0, 255, 8, 8) + bounds: 816 48 8 8 + - image: solid-color(103, 6, 0, 255, 8, 8) + bounds: 824 48 8 8 + - image: solid-color(104, 6, 0, 255, 8, 8) + bounds: 832 48 8 8 + - image: solid-color(105, 6, 0, 255, 8, 8) + bounds: 840 48 8 8 + - image: solid-color(106, 6, 0, 255, 8, 8) + bounds: 848 48 8 8 + - image: solid-color(107, 6, 0, 255, 8, 8) + bounds: 856 48 8 8 + - image: solid-color(108, 6, 0, 255, 8, 8) + bounds: 864 48 8 8 + - image: solid-color(109, 6, 0, 255, 8, 8) + bounds: 872 48 8 8 + - image: solid-color(110, 6, 0, 255, 8, 8) + bounds: 880 48 8 8 + - image: solid-color(111, 6, 0, 255, 8, 8) + bounds: 888 48 8 8 + - image: solid-color(112, 6, 0, 255, 8, 8) + bounds: 896 48 8 8 + - image: solid-color(113, 6, 0, 255, 8, 8) + bounds: 904 48 8 8 + - image: solid-color(114, 6, 0, 255, 8, 8) + bounds: 912 48 8 8 + - image: solid-color(115, 6, 0, 255, 8, 8) + bounds: 920 48 8 8 + - image: solid-color(116, 6, 0, 255, 8, 8) + bounds: 928 48 8 8 + - image: solid-color(117, 6, 0, 255, 8, 8) + bounds: 936 48 8 8 + - image: solid-color(118, 6, 0, 255, 8, 8) + bounds: 944 48 8 8 + - image: solid-color(119, 6, 0, 255, 8, 8) + bounds: 952 48 8 8 + - image: solid-color(120, 6, 0, 255, 8, 8) + bounds: 960 48 8 8 + - image: solid-color(121, 6, 0, 255, 8, 8) + bounds: 968 48 8 8 + - image: solid-color(122, 6, 0, 255, 8, 8) + bounds: 976 48 8 8 + - image: solid-color(123, 6, 0, 255, 8, 8) + bounds: 984 48 8 8 + - image: solid-color(124, 6, 0, 255, 8, 8) + bounds: 992 48 8 8 + - image: solid-color(125, 6, 0, 255, 8, 8) + bounds: 1000 48 8 8 + - image: solid-color(126, 6, 0, 255, 8, 8) + bounds: 1008 48 8 8 + - image: solid-color(127, 6, 0, 255, 8, 8) + bounds: 1016 48 8 8 + - image: solid-color(0, 7, 0, 255, 8, 8) + bounds: 0 56 8 8 + - image: solid-color(1, 7, 0, 255, 8, 8) + bounds: 8 56 8 8 + - image: solid-color(2, 7, 0, 255, 8, 8) + bounds: 16 56 8 8 + - image: solid-color(3, 7, 0, 255, 8, 8) + bounds: 24 56 8 8 + - image: solid-color(4, 7, 0, 255, 8, 8) + bounds: 32 56 8 8 + - image: solid-color(5, 7, 0, 255, 8, 8) + bounds: 40 56 8 8 + - image: solid-color(6, 7, 0, 255, 8, 8) + bounds: 48 56 8 8 + - image: solid-color(7, 7, 0, 255, 8, 8) + bounds: 56 56 8 8 + - image: solid-color(8, 7, 0, 255, 8, 8) + bounds: 64 56 8 8 + - image: solid-color(9, 7, 0, 255, 8, 8) + bounds: 72 56 8 8 + - image: solid-color(10, 7, 0, 255, 8, 8) + bounds: 80 56 8 8 + - image: solid-color(11, 7, 0, 255, 8, 8) + bounds: 88 56 8 8 + - image: solid-color(12, 7, 0, 255, 8, 8) + bounds: 96 56 8 8 + - image: solid-color(13, 7, 0, 255, 8, 8) + bounds: 104 56 8 8 + - image: solid-color(14, 7, 0, 255, 8, 8) + bounds: 112 56 8 8 + - image: solid-color(15, 7, 0, 255, 8, 8) + bounds: 120 56 8 8 + - image: solid-color(16, 7, 0, 255, 8, 8) + bounds: 128 56 8 8 + - image: solid-color(17, 7, 0, 255, 8, 8) + bounds: 136 56 8 8 + - image: solid-color(18, 7, 0, 255, 8, 8) + bounds: 144 56 8 8 + - image: solid-color(19, 7, 0, 255, 8, 8) + bounds: 152 56 8 8 + - image: solid-color(20, 7, 0, 255, 8, 8) + bounds: 160 56 8 8 + - image: solid-color(21, 7, 0, 255, 8, 8) + bounds: 168 56 8 8 + - image: solid-color(22, 7, 0, 255, 8, 8) + bounds: 176 56 8 8 + - image: solid-color(23, 7, 0, 255, 8, 8) + bounds: 184 56 8 8 + - image: solid-color(24, 7, 0, 255, 8, 8) + bounds: 192 56 8 8 + - image: solid-color(25, 7, 0, 255, 8, 8) + bounds: 200 56 8 8 + - image: solid-color(26, 7, 0, 255, 8, 8) + bounds: 208 56 8 8 + - image: solid-color(27, 7, 0, 255, 8, 8) + bounds: 216 56 8 8 + - image: solid-color(28, 7, 0, 255, 8, 8) + bounds: 224 56 8 8 + - image: solid-color(29, 7, 0, 255, 8, 8) + bounds: 232 56 8 8 + - image: solid-color(30, 7, 0, 255, 8, 8) + bounds: 240 56 8 8 + - image: solid-color(31, 7, 0, 255, 8, 8) + bounds: 248 56 8 8 + - image: solid-color(32, 7, 0, 255, 8, 8) + bounds: 256 56 8 8 + - image: solid-color(33, 7, 0, 255, 8, 8) + bounds: 264 56 8 8 + - image: solid-color(34, 7, 0, 255, 8, 8) + bounds: 272 56 8 8 + - image: solid-color(35, 7, 0, 255, 8, 8) + bounds: 280 56 8 8 + - image: solid-color(36, 7, 0, 255, 8, 8) + bounds: 288 56 8 8 + - image: solid-color(37, 7, 0, 255, 8, 8) + bounds: 296 56 8 8 + - image: solid-color(38, 7, 0, 255, 8, 8) + bounds: 304 56 8 8 + - image: solid-color(39, 7, 0, 255, 8, 8) + bounds: 312 56 8 8 + - image: solid-color(40, 7, 0, 255, 8, 8) + bounds: 320 56 8 8 + - image: solid-color(41, 7, 0, 255, 8, 8) + bounds: 328 56 8 8 + - image: solid-color(42, 7, 0, 255, 8, 8) + bounds: 336 56 8 8 + - image: solid-color(43, 7, 0, 255, 8, 8) + bounds: 344 56 8 8 + - image: solid-color(44, 7, 0, 255, 8, 8) + bounds: 352 56 8 8 + - image: solid-color(45, 7, 0, 255, 8, 8) + bounds: 360 56 8 8 + - image: solid-color(46, 7, 0, 255, 8, 8) + bounds: 368 56 8 8 + - image: solid-color(47, 7, 0, 255, 8, 8) + bounds: 376 56 8 8 + - image: solid-color(48, 7, 0, 255, 8, 8) + bounds: 384 56 8 8 + - image: solid-color(49, 7, 0, 255, 8, 8) + bounds: 392 56 8 8 + - image: solid-color(50, 7, 0, 255, 8, 8) + bounds: 400 56 8 8 + - image: solid-color(51, 7, 0, 255, 8, 8) + bounds: 408 56 8 8 + - image: solid-color(52, 7, 0, 255, 8, 8) + bounds: 416 56 8 8 + - image: solid-color(53, 7, 0, 255, 8, 8) + bounds: 424 56 8 8 + - image: solid-color(54, 7, 0, 255, 8, 8) + bounds: 432 56 8 8 + - image: solid-color(55, 7, 0, 255, 8, 8) + bounds: 440 56 8 8 + - image: solid-color(56, 7, 0, 255, 8, 8) + bounds: 448 56 8 8 + - image: solid-color(57, 7, 0, 255, 8, 8) + bounds: 456 56 8 8 + - image: solid-color(58, 7, 0, 255, 8, 8) + bounds: 464 56 8 8 + - image: solid-color(59, 7, 0, 255, 8, 8) + bounds: 472 56 8 8 + - image: solid-color(60, 7, 0, 255, 8, 8) + bounds: 480 56 8 8 + - image: solid-color(61, 7, 0, 255, 8, 8) + bounds: 488 56 8 8 + - image: solid-color(62, 7, 0, 255, 8, 8) + bounds: 496 56 8 8 + - image: solid-color(63, 7, 0, 255, 8, 8) + bounds: 504 56 8 8 + - image: solid-color(64, 7, 0, 255, 8, 8) + bounds: 512 56 8 8 + - image: solid-color(65, 7, 0, 255, 8, 8) + bounds: 520 56 8 8 + - image: solid-color(66, 7, 0, 255, 8, 8) + bounds: 528 56 8 8 + - image: solid-color(67, 7, 0, 255, 8, 8) + bounds: 536 56 8 8 + - image: solid-color(68, 7, 0, 255, 8, 8) + bounds: 544 56 8 8 + - image: solid-color(69, 7, 0, 255, 8, 8) + bounds: 552 56 8 8 + - image: solid-color(70, 7, 0, 255, 8, 8) + bounds: 560 56 8 8 + - image: solid-color(71, 7, 0, 255, 8, 8) + bounds: 568 56 8 8 + - image: solid-color(72, 7, 0, 255, 8, 8) + bounds: 576 56 8 8 + - image: solid-color(73, 7, 0, 255, 8, 8) + bounds: 584 56 8 8 + - image: solid-color(74, 7, 0, 255, 8, 8) + bounds: 592 56 8 8 + - image: solid-color(75, 7, 0, 255, 8, 8) + bounds: 600 56 8 8 + - image: solid-color(76, 7, 0, 255, 8, 8) + bounds: 608 56 8 8 + - image: solid-color(77, 7, 0, 255, 8, 8) + bounds: 616 56 8 8 + - image: solid-color(78, 7, 0, 255, 8, 8) + bounds: 624 56 8 8 + - image: solid-color(79, 7, 0, 255, 8, 8) + bounds: 632 56 8 8 + - image: solid-color(80, 7, 0, 255, 8, 8) + bounds: 640 56 8 8 + - image: solid-color(81, 7, 0, 255, 8, 8) + bounds: 648 56 8 8 + - image: solid-color(82, 7, 0, 255, 8, 8) + bounds: 656 56 8 8 + - image: solid-color(83, 7, 0, 255, 8, 8) + bounds: 664 56 8 8 + - image: solid-color(84, 7, 0, 255, 8, 8) + bounds: 672 56 8 8 + - image: solid-color(85, 7, 0, 255, 8, 8) + bounds: 680 56 8 8 + - image: solid-color(86, 7, 0, 255, 8, 8) + bounds: 688 56 8 8 + - image: solid-color(87, 7, 0, 255, 8, 8) + bounds: 696 56 8 8 + - image: solid-color(88, 7, 0, 255, 8, 8) + bounds: 704 56 8 8 + - image: solid-color(89, 7, 0, 255, 8, 8) + bounds: 712 56 8 8 + - image: solid-color(90, 7, 0, 255, 8, 8) + bounds: 720 56 8 8 + - image: solid-color(91, 7, 0, 255, 8, 8) + bounds: 728 56 8 8 + - image: solid-color(92, 7, 0, 255, 8, 8) + bounds: 736 56 8 8 + - image: solid-color(93, 7, 0, 255, 8, 8) + bounds: 744 56 8 8 + - image: solid-color(94, 7, 0, 255, 8, 8) + bounds: 752 56 8 8 + - image: solid-color(95, 7, 0, 255, 8, 8) + bounds: 760 56 8 8 + - image: solid-color(96, 7, 0, 255, 8, 8) + bounds: 768 56 8 8 + - image: solid-color(97, 7, 0, 255, 8, 8) + bounds: 776 56 8 8 + - image: solid-color(98, 7, 0, 255, 8, 8) + bounds: 784 56 8 8 + - image: solid-color(99, 7, 0, 255, 8, 8) + bounds: 792 56 8 8 + - image: solid-color(100, 7, 0, 255, 8, 8) + bounds: 800 56 8 8 + - image: solid-color(101, 7, 0, 255, 8, 8) + bounds: 808 56 8 8 + - image: solid-color(102, 7, 0, 255, 8, 8) + bounds: 816 56 8 8 + - image: solid-color(103, 7, 0, 255, 8, 8) + bounds: 824 56 8 8 + - image: solid-color(104, 7, 0, 255, 8, 8) + bounds: 832 56 8 8 + - image: solid-color(105, 7, 0, 255, 8, 8) + bounds: 840 56 8 8 + - image: solid-color(106, 7, 0, 255, 8, 8) + bounds: 848 56 8 8 + - image: solid-color(107, 7, 0, 255, 8, 8) + bounds: 856 56 8 8 + - image: solid-color(108, 7, 0, 255, 8, 8) + bounds: 864 56 8 8 + - image: solid-color(109, 7, 0, 255, 8, 8) + bounds: 872 56 8 8 + - image: solid-color(110, 7, 0, 255, 8, 8) + bounds: 880 56 8 8 + - image: solid-color(111, 7, 0, 255, 8, 8) + bounds: 888 56 8 8 + - image: solid-color(112, 7, 0, 255, 8, 8) + bounds: 896 56 8 8 + - image: solid-color(113, 7, 0, 255, 8, 8) + bounds: 904 56 8 8 + - image: solid-color(114, 7, 0, 255, 8, 8) + bounds: 912 56 8 8 + - image: solid-color(115, 7, 0, 255, 8, 8) + bounds: 920 56 8 8 + - image: solid-color(116, 7, 0, 255, 8, 8) + bounds: 928 56 8 8 + - image: solid-color(117, 7, 0, 255, 8, 8) + bounds: 936 56 8 8 + - image: solid-color(118, 7, 0, 255, 8, 8) + bounds: 944 56 8 8 + - image: solid-color(119, 7, 0, 255, 8, 8) + bounds: 952 56 8 8 + - image: solid-color(120, 7, 0, 255, 8, 8) + bounds: 960 56 8 8 + - image: solid-color(121, 7, 0, 255, 8, 8) + bounds: 968 56 8 8 + - image: solid-color(122, 7, 0, 255, 8, 8) + bounds: 976 56 8 8 + - image: solid-color(123, 7, 0, 255, 8, 8) + bounds: 984 56 8 8 + - image: solid-color(124, 7, 0, 255, 8, 8) + bounds: 992 56 8 8 + - image: solid-color(125, 7, 0, 255, 8, 8) + bounds: 1000 56 8 8 + - image: solid-color(126, 7, 0, 255, 8, 8) + bounds: 1008 56 8 8 + - image: solid-color(127, 7, 0, 255, 8, 8) + bounds: 1016 56 8 8 + - image: solid-color(0, 8, 0, 255, 8, 8) + bounds: 0 64 8 8 + - image: solid-color(1, 8, 0, 255, 8, 8) + bounds: 8 64 8 8 + - image: solid-color(2, 8, 0, 255, 8, 8) + bounds: 16 64 8 8 + - image: solid-color(3, 8, 0, 255, 8, 8) + bounds: 24 64 8 8 + - image: solid-color(4, 8, 0, 255, 8, 8) + bounds: 32 64 8 8 + - image: solid-color(5, 8, 0, 255, 8, 8) + bounds: 40 64 8 8 + - image: solid-color(6, 8, 0, 255, 8, 8) + bounds: 48 64 8 8 + - image: solid-color(7, 8, 0, 255, 8, 8) + bounds: 56 64 8 8 + - image: solid-color(8, 8, 0, 255, 8, 8) + bounds: 64 64 8 8 + - image: solid-color(9, 8, 0, 255, 8, 8) + bounds: 72 64 8 8 + - image: solid-color(10, 8, 0, 255, 8, 8) + bounds: 80 64 8 8 + - image: solid-color(11, 8, 0, 255, 8, 8) + bounds: 88 64 8 8 + - image: solid-color(12, 8, 0, 255, 8, 8) + bounds: 96 64 8 8 + - image: solid-color(13, 8, 0, 255, 8, 8) + bounds: 104 64 8 8 + - image: solid-color(14, 8, 0, 255, 8, 8) + bounds: 112 64 8 8 + - image: solid-color(15, 8, 0, 255, 8, 8) + bounds: 120 64 8 8 + - image: solid-color(16, 8, 0, 255, 8, 8) + bounds: 128 64 8 8 + - image: solid-color(17, 8, 0, 255, 8, 8) + bounds: 136 64 8 8 + - image: solid-color(18, 8, 0, 255, 8, 8) + bounds: 144 64 8 8 + - image: solid-color(19, 8, 0, 255, 8, 8) + bounds: 152 64 8 8 + - image: solid-color(20, 8, 0, 255, 8, 8) + bounds: 160 64 8 8 + - image: solid-color(21, 8, 0, 255, 8, 8) + bounds: 168 64 8 8 + - image: solid-color(22, 8, 0, 255, 8, 8) + bounds: 176 64 8 8 + - image: solid-color(23, 8, 0, 255, 8, 8) + bounds: 184 64 8 8 + - image: solid-color(24, 8, 0, 255, 8, 8) + bounds: 192 64 8 8 + - image: solid-color(25, 8, 0, 255, 8, 8) + bounds: 200 64 8 8 + - image: solid-color(26, 8, 0, 255, 8, 8) + bounds: 208 64 8 8 + - image: solid-color(27, 8, 0, 255, 8, 8) + bounds: 216 64 8 8 + - image: solid-color(28, 8, 0, 255, 8, 8) + bounds: 224 64 8 8 + - image: solid-color(29, 8, 0, 255, 8, 8) + bounds: 232 64 8 8 + - image: solid-color(30, 8, 0, 255, 8, 8) + bounds: 240 64 8 8 + - image: solid-color(31, 8, 0, 255, 8, 8) + bounds: 248 64 8 8 + - image: solid-color(32, 8, 0, 255, 8, 8) + bounds: 256 64 8 8 + - image: solid-color(33, 8, 0, 255, 8, 8) + bounds: 264 64 8 8 + - image: solid-color(34, 8, 0, 255, 8, 8) + bounds: 272 64 8 8 + - image: solid-color(35, 8, 0, 255, 8, 8) + bounds: 280 64 8 8 + - image: solid-color(36, 8, 0, 255, 8, 8) + bounds: 288 64 8 8 + - image: solid-color(37, 8, 0, 255, 8, 8) + bounds: 296 64 8 8 + - image: solid-color(38, 8, 0, 255, 8, 8) + bounds: 304 64 8 8 + - image: solid-color(39, 8, 0, 255, 8, 8) + bounds: 312 64 8 8 + - image: solid-color(40, 8, 0, 255, 8, 8) + bounds: 320 64 8 8 + - image: solid-color(41, 8, 0, 255, 8, 8) + bounds: 328 64 8 8 + - image: solid-color(42, 8, 0, 255, 8, 8) + bounds: 336 64 8 8 + - image: solid-color(43, 8, 0, 255, 8, 8) + bounds: 344 64 8 8 + - image: solid-color(44, 8, 0, 255, 8, 8) + bounds: 352 64 8 8 + - image: solid-color(45, 8, 0, 255, 8, 8) + bounds: 360 64 8 8 + - image: solid-color(46, 8, 0, 255, 8, 8) + bounds: 368 64 8 8 + - image: solid-color(47, 8, 0, 255, 8, 8) + bounds: 376 64 8 8 + - image: solid-color(48, 8, 0, 255, 8, 8) + bounds: 384 64 8 8 + - image: solid-color(49, 8, 0, 255, 8, 8) + bounds: 392 64 8 8 + - image: solid-color(50, 8, 0, 255, 8, 8) + bounds: 400 64 8 8 + - image: solid-color(51, 8, 0, 255, 8, 8) + bounds: 408 64 8 8 + - image: solid-color(52, 8, 0, 255, 8, 8) + bounds: 416 64 8 8 + - image: solid-color(53, 8, 0, 255, 8, 8) + bounds: 424 64 8 8 + - image: solid-color(54, 8, 0, 255, 8, 8) + bounds: 432 64 8 8 + - image: solid-color(55, 8, 0, 255, 8, 8) + bounds: 440 64 8 8 + - image: solid-color(56, 8, 0, 255, 8, 8) + bounds: 448 64 8 8 + - image: solid-color(57, 8, 0, 255, 8, 8) + bounds: 456 64 8 8 + - image: solid-color(58, 8, 0, 255, 8, 8) + bounds: 464 64 8 8 + - image: solid-color(59, 8, 0, 255, 8, 8) + bounds: 472 64 8 8 + - image: solid-color(60, 8, 0, 255, 8, 8) + bounds: 480 64 8 8 + - image: solid-color(61, 8, 0, 255, 8, 8) + bounds: 488 64 8 8 + - image: solid-color(62, 8, 0, 255, 8, 8) + bounds: 496 64 8 8 + - image: solid-color(63, 8, 0, 255, 8, 8) + bounds: 504 64 8 8 + - image: solid-color(64, 8, 0, 255, 8, 8) + bounds: 512 64 8 8 + - image: solid-color(65, 8, 0, 255, 8, 8) + bounds: 520 64 8 8 + - image: solid-color(66, 8, 0, 255, 8, 8) + bounds: 528 64 8 8 + - image: solid-color(67, 8, 0, 255, 8, 8) + bounds: 536 64 8 8 + - image: solid-color(68, 8, 0, 255, 8, 8) + bounds: 544 64 8 8 + - image: solid-color(69, 8, 0, 255, 8, 8) + bounds: 552 64 8 8 + - image: solid-color(70, 8, 0, 255, 8, 8) + bounds: 560 64 8 8 + - image: solid-color(71, 8, 0, 255, 8, 8) + bounds: 568 64 8 8 + - image: solid-color(72, 8, 0, 255, 8, 8) + bounds: 576 64 8 8 + - image: solid-color(73, 8, 0, 255, 8, 8) + bounds: 584 64 8 8 + - image: solid-color(74, 8, 0, 255, 8, 8) + bounds: 592 64 8 8 + - image: solid-color(75, 8, 0, 255, 8, 8) + bounds: 600 64 8 8 + - image: solid-color(76, 8, 0, 255, 8, 8) + bounds: 608 64 8 8 + - image: solid-color(77, 8, 0, 255, 8, 8) + bounds: 616 64 8 8 + - image: solid-color(78, 8, 0, 255, 8, 8) + bounds: 624 64 8 8 + - image: solid-color(79, 8, 0, 255, 8, 8) + bounds: 632 64 8 8 + - image: solid-color(80, 8, 0, 255, 8, 8) + bounds: 640 64 8 8 + - image: solid-color(81, 8, 0, 255, 8, 8) + bounds: 648 64 8 8 + - image: solid-color(82, 8, 0, 255, 8, 8) + bounds: 656 64 8 8 + - image: solid-color(83, 8, 0, 255, 8, 8) + bounds: 664 64 8 8 + - image: solid-color(84, 8, 0, 255, 8, 8) + bounds: 672 64 8 8 + - image: solid-color(85, 8, 0, 255, 8, 8) + bounds: 680 64 8 8 + - image: solid-color(86, 8, 0, 255, 8, 8) + bounds: 688 64 8 8 + - image: solid-color(87, 8, 0, 255, 8, 8) + bounds: 696 64 8 8 + - image: solid-color(88, 8, 0, 255, 8, 8) + bounds: 704 64 8 8 + - image: solid-color(89, 8, 0, 255, 8, 8) + bounds: 712 64 8 8 + - image: solid-color(90, 8, 0, 255, 8, 8) + bounds: 720 64 8 8 + - image: solid-color(91, 8, 0, 255, 8, 8) + bounds: 728 64 8 8 + - image: solid-color(92, 8, 0, 255, 8, 8) + bounds: 736 64 8 8 + - image: solid-color(93, 8, 0, 255, 8, 8) + bounds: 744 64 8 8 + - image: solid-color(94, 8, 0, 255, 8, 8) + bounds: 752 64 8 8 + - image: solid-color(95, 8, 0, 255, 8, 8) + bounds: 760 64 8 8 + - image: solid-color(96, 8, 0, 255, 8, 8) + bounds: 768 64 8 8 + - image: solid-color(97, 8, 0, 255, 8, 8) + bounds: 776 64 8 8 + - image: solid-color(98, 8, 0, 255, 8, 8) + bounds: 784 64 8 8 + - image: solid-color(99, 8, 0, 255, 8, 8) + bounds: 792 64 8 8 + - image: solid-color(100, 8, 0, 255, 8, 8) + bounds: 800 64 8 8 + - image: solid-color(101, 8, 0, 255, 8, 8) + bounds: 808 64 8 8 + - image: solid-color(102, 8, 0, 255, 8, 8) + bounds: 816 64 8 8 + - image: solid-color(103, 8, 0, 255, 8, 8) + bounds: 824 64 8 8 + - image: solid-color(104, 8, 0, 255, 8, 8) + bounds: 832 64 8 8 + - image: solid-color(105, 8, 0, 255, 8, 8) + bounds: 840 64 8 8 + - image: solid-color(106, 8, 0, 255, 8, 8) + bounds: 848 64 8 8 + - image: solid-color(107, 8, 0, 255, 8, 8) + bounds: 856 64 8 8 + - image: solid-color(108, 8, 0, 255, 8, 8) + bounds: 864 64 8 8 + - image: solid-color(109, 8, 0, 255, 8, 8) + bounds: 872 64 8 8 + - image: solid-color(110, 8, 0, 255, 8, 8) + bounds: 880 64 8 8 + - image: solid-color(111, 8, 0, 255, 8, 8) + bounds: 888 64 8 8 + - image: solid-color(112, 8, 0, 255, 8, 8) + bounds: 896 64 8 8 + - image: solid-color(113, 8, 0, 255, 8, 8) + bounds: 904 64 8 8 + - image: solid-color(114, 8, 0, 255, 8, 8) + bounds: 912 64 8 8 + - image: solid-color(115, 8, 0, 255, 8, 8) + bounds: 920 64 8 8 + - image: solid-color(116, 8, 0, 255, 8, 8) + bounds: 928 64 8 8 + - image: solid-color(117, 8, 0, 255, 8, 8) + bounds: 936 64 8 8 + - image: solid-color(118, 8, 0, 255, 8, 8) + bounds: 944 64 8 8 + - image: solid-color(119, 8, 0, 255, 8, 8) + bounds: 952 64 8 8 + - image: solid-color(120, 8, 0, 255, 8, 8) + bounds: 960 64 8 8 + - image: solid-color(121, 8, 0, 255, 8, 8) + bounds: 968 64 8 8 + - image: solid-color(122, 8, 0, 255, 8, 8) + bounds: 976 64 8 8 + - image: solid-color(123, 8, 0, 255, 8, 8) + bounds: 984 64 8 8 + - image: solid-color(124, 8, 0, 255, 8, 8) + bounds: 992 64 8 8 + - image: solid-color(125, 8, 0, 255, 8, 8) + bounds: 1000 64 8 8 + - image: solid-color(126, 8, 0, 255, 8, 8) + bounds: 1008 64 8 8 + - image: solid-color(127, 8, 0, 255, 8, 8) + bounds: 1016 64 8 8 + - image: solid-color(0, 9, 0, 255, 8, 8) + bounds: 0 72 8 8 + - image: solid-color(1, 9, 0, 255, 8, 8) + bounds: 8 72 8 8 + - image: solid-color(2, 9, 0, 255, 8, 8) + bounds: 16 72 8 8 + - image: solid-color(3, 9, 0, 255, 8, 8) + bounds: 24 72 8 8 + - image: solid-color(4, 9, 0, 255, 8, 8) + bounds: 32 72 8 8 + - image: solid-color(5, 9, 0, 255, 8, 8) + bounds: 40 72 8 8 + - image: solid-color(6, 9, 0, 255, 8, 8) + bounds: 48 72 8 8 + - image: solid-color(7, 9, 0, 255, 8, 8) + bounds: 56 72 8 8 + - image: solid-color(8, 9, 0, 255, 8, 8) + bounds: 64 72 8 8 + - image: solid-color(9, 9, 0, 255, 8, 8) + bounds: 72 72 8 8 + - image: solid-color(10, 9, 0, 255, 8, 8) + bounds: 80 72 8 8 + - image: solid-color(11, 9, 0, 255, 8, 8) + bounds: 88 72 8 8 + - image: solid-color(12, 9, 0, 255, 8, 8) + bounds: 96 72 8 8 + - image: solid-color(13, 9, 0, 255, 8, 8) + bounds: 104 72 8 8 + - image: solid-color(14, 9, 0, 255, 8, 8) + bounds: 112 72 8 8 + - image: solid-color(15, 9, 0, 255, 8, 8) + bounds: 120 72 8 8 + - image: solid-color(16, 9, 0, 255, 8, 8) + bounds: 128 72 8 8 + - image: solid-color(17, 9, 0, 255, 8, 8) + bounds: 136 72 8 8 + - image: solid-color(18, 9, 0, 255, 8, 8) + bounds: 144 72 8 8 + - image: solid-color(19, 9, 0, 255, 8, 8) + bounds: 152 72 8 8 + - image: solid-color(20, 9, 0, 255, 8, 8) + bounds: 160 72 8 8 + - image: solid-color(21, 9, 0, 255, 8, 8) + bounds: 168 72 8 8 + - image: solid-color(22, 9, 0, 255, 8, 8) + bounds: 176 72 8 8 + - image: solid-color(23, 9, 0, 255, 8, 8) + bounds: 184 72 8 8 + - image: solid-color(24, 9, 0, 255, 8, 8) + bounds: 192 72 8 8 + - image: solid-color(25, 9, 0, 255, 8, 8) + bounds: 200 72 8 8 + - image: solid-color(26, 9, 0, 255, 8, 8) + bounds: 208 72 8 8 + - image: solid-color(27, 9, 0, 255, 8, 8) + bounds: 216 72 8 8 + - image: solid-color(28, 9, 0, 255, 8, 8) + bounds: 224 72 8 8 + - image: solid-color(29, 9, 0, 255, 8, 8) + bounds: 232 72 8 8 + - image: solid-color(30, 9, 0, 255, 8, 8) + bounds: 240 72 8 8 + - image: solid-color(31, 9, 0, 255, 8, 8) + bounds: 248 72 8 8 + - image: solid-color(32, 9, 0, 255, 8, 8) + bounds: 256 72 8 8 + - image: solid-color(33, 9, 0, 255, 8, 8) + bounds: 264 72 8 8 + - image: solid-color(34, 9, 0, 255, 8, 8) + bounds: 272 72 8 8 + - image: solid-color(35, 9, 0, 255, 8, 8) + bounds: 280 72 8 8 + - image: solid-color(36, 9, 0, 255, 8, 8) + bounds: 288 72 8 8 + - image: solid-color(37, 9, 0, 255, 8, 8) + bounds: 296 72 8 8 + - image: solid-color(38, 9, 0, 255, 8, 8) + bounds: 304 72 8 8 + - image: solid-color(39, 9, 0, 255, 8, 8) + bounds: 312 72 8 8 + - image: solid-color(40, 9, 0, 255, 8, 8) + bounds: 320 72 8 8 + - image: solid-color(41, 9, 0, 255, 8, 8) + bounds: 328 72 8 8 + - image: solid-color(42, 9, 0, 255, 8, 8) + bounds: 336 72 8 8 + - image: solid-color(43, 9, 0, 255, 8, 8) + bounds: 344 72 8 8 + - image: solid-color(44, 9, 0, 255, 8, 8) + bounds: 352 72 8 8 + - image: solid-color(45, 9, 0, 255, 8, 8) + bounds: 360 72 8 8 + - image: solid-color(46, 9, 0, 255, 8, 8) + bounds: 368 72 8 8 + - image: solid-color(47, 9, 0, 255, 8, 8) + bounds: 376 72 8 8 + - image: solid-color(48, 9, 0, 255, 8, 8) + bounds: 384 72 8 8 + - image: solid-color(49, 9, 0, 255, 8, 8) + bounds: 392 72 8 8 + - image: solid-color(50, 9, 0, 255, 8, 8) + bounds: 400 72 8 8 + - image: solid-color(51, 9, 0, 255, 8, 8) + bounds: 408 72 8 8 + - image: solid-color(52, 9, 0, 255, 8, 8) + bounds: 416 72 8 8 + - image: solid-color(53, 9, 0, 255, 8, 8) + bounds: 424 72 8 8 + - image: solid-color(54, 9, 0, 255, 8, 8) + bounds: 432 72 8 8 + - image: solid-color(55, 9, 0, 255, 8, 8) + bounds: 440 72 8 8 + - image: solid-color(56, 9, 0, 255, 8, 8) + bounds: 448 72 8 8 + - image: solid-color(57, 9, 0, 255, 8, 8) + bounds: 456 72 8 8 + - image: solid-color(58, 9, 0, 255, 8, 8) + bounds: 464 72 8 8 + - image: solid-color(59, 9, 0, 255, 8, 8) + bounds: 472 72 8 8 + - image: solid-color(60, 9, 0, 255, 8, 8) + bounds: 480 72 8 8 + - image: solid-color(61, 9, 0, 255, 8, 8) + bounds: 488 72 8 8 + - image: solid-color(62, 9, 0, 255, 8, 8) + bounds: 496 72 8 8 + - image: solid-color(63, 9, 0, 255, 8, 8) + bounds: 504 72 8 8 + - image: solid-color(64, 9, 0, 255, 8, 8) + bounds: 512 72 8 8 + - image: solid-color(65, 9, 0, 255, 8, 8) + bounds: 520 72 8 8 + - image: solid-color(66, 9, 0, 255, 8, 8) + bounds: 528 72 8 8 + - image: solid-color(67, 9, 0, 255, 8, 8) + bounds: 536 72 8 8 + - image: solid-color(68, 9, 0, 255, 8, 8) + bounds: 544 72 8 8 + - image: solid-color(69, 9, 0, 255, 8, 8) + bounds: 552 72 8 8 + - image: solid-color(70, 9, 0, 255, 8, 8) + bounds: 560 72 8 8 + - image: solid-color(71, 9, 0, 255, 8, 8) + bounds: 568 72 8 8 + - image: solid-color(72, 9, 0, 255, 8, 8) + bounds: 576 72 8 8 + - image: solid-color(73, 9, 0, 255, 8, 8) + bounds: 584 72 8 8 + - image: solid-color(74, 9, 0, 255, 8, 8) + bounds: 592 72 8 8 + - image: solid-color(75, 9, 0, 255, 8, 8) + bounds: 600 72 8 8 + - image: solid-color(76, 9, 0, 255, 8, 8) + bounds: 608 72 8 8 + - image: solid-color(77, 9, 0, 255, 8, 8) + bounds: 616 72 8 8 + - image: solid-color(78, 9, 0, 255, 8, 8) + bounds: 624 72 8 8 + - image: solid-color(79, 9, 0, 255, 8, 8) + bounds: 632 72 8 8 + - image: solid-color(80, 9, 0, 255, 8, 8) + bounds: 640 72 8 8 + - image: solid-color(81, 9, 0, 255, 8, 8) + bounds: 648 72 8 8 + - image: solid-color(82, 9, 0, 255, 8, 8) + bounds: 656 72 8 8 + - image: solid-color(83, 9, 0, 255, 8, 8) + bounds: 664 72 8 8 + - image: solid-color(84, 9, 0, 255, 8, 8) + bounds: 672 72 8 8 + - image: solid-color(85, 9, 0, 255, 8, 8) + bounds: 680 72 8 8 + - image: solid-color(86, 9, 0, 255, 8, 8) + bounds: 688 72 8 8 + - image: solid-color(87, 9, 0, 255, 8, 8) + bounds: 696 72 8 8 + - image: solid-color(88, 9, 0, 255, 8, 8) + bounds: 704 72 8 8 + - image: solid-color(89, 9, 0, 255, 8, 8) + bounds: 712 72 8 8 + - image: solid-color(90, 9, 0, 255, 8, 8) + bounds: 720 72 8 8 + - image: solid-color(91, 9, 0, 255, 8, 8) + bounds: 728 72 8 8 + - image: solid-color(92, 9, 0, 255, 8, 8) + bounds: 736 72 8 8 + - image: solid-color(93, 9, 0, 255, 8, 8) + bounds: 744 72 8 8 + - image: solid-color(94, 9, 0, 255, 8, 8) + bounds: 752 72 8 8 + - image: solid-color(95, 9, 0, 255, 8, 8) + bounds: 760 72 8 8 + - image: solid-color(96, 9, 0, 255, 8, 8) + bounds: 768 72 8 8 + - image: solid-color(97, 9, 0, 255, 8, 8) + bounds: 776 72 8 8 + - image: solid-color(98, 9, 0, 255, 8, 8) + bounds: 784 72 8 8 + - image: solid-color(99, 9, 0, 255, 8, 8) + bounds: 792 72 8 8 + - image: solid-color(100, 9, 0, 255, 8, 8) + bounds: 800 72 8 8 + - image: solid-color(101, 9, 0, 255, 8, 8) + bounds: 808 72 8 8 + - image: solid-color(102, 9, 0, 255, 8, 8) + bounds: 816 72 8 8 + - image: solid-color(103, 9, 0, 255, 8, 8) + bounds: 824 72 8 8 + - image: solid-color(104, 9, 0, 255, 8, 8) + bounds: 832 72 8 8 + - image: solid-color(105, 9, 0, 255, 8, 8) + bounds: 840 72 8 8 + - image: solid-color(106, 9, 0, 255, 8, 8) + bounds: 848 72 8 8 + - image: solid-color(107, 9, 0, 255, 8, 8) + bounds: 856 72 8 8 + - image: solid-color(108, 9, 0, 255, 8, 8) + bounds: 864 72 8 8 + - image: solid-color(109, 9, 0, 255, 8, 8) + bounds: 872 72 8 8 + - image: solid-color(110, 9, 0, 255, 8, 8) + bounds: 880 72 8 8 + - image: solid-color(111, 9, 0, 255, 8, 8) + bounds: 888 72 8 8 + - image: solid-color(112, 9, 0, 255, 8, 8) + bounds: 896 72 8 8 + - image: solid-color(113, 9, 0, 255, 8, 8) + bounds: 904 72 8 8 + - image: solid-color(114, 9, 0, 255, 8, 8) + bounds: 912 72 8 8 + - image: solid-color(115, 9, 0, 255, 8, 8) + bounds: 920 72 8 8 + - image: solid-color(116, 9, 0, 255, 8, 8) + bounds: 928 72 8 8 + - image: solid-color(117, 9, 0, 255, 8, 8) + bounds: 936 72 8 8 + - image: solid-color(118, 9, 0, 255, 8, 8) + bounds: 944 72 8 8 + - image: solid-color(119, 9, 0, 255, 8, 8) + bounds: 952 72 8 8 + - image: solid-color(120, 9, 0, 255, 8, 8) + bounds: 960 72 8 8 + - image: solid-color(121, 9, 0, 255, 8, 8) + bounds: 968 72 8 8 + - image: solid-color(122, 9, 0, 255, 8, 8) + bounds: 976 72 8 8 + - image: solid-color(123, 9, 0, 255, 8, 8) + bounds: 984 72 8 8 + - image: solid-color(124, 9, 0, 255, 8, 8) + bounds: 992 72 8 8 + - image: solid-color(125, 9, 0, 255, 8, 8) + bounds: 1000 72 8 8 + - image: solid-color(126, 9, 0, 255, 8, 8) + bounds: 1008 72 8 8 + - image: solid-color(127, 9, 0, 255, 8, 8) + bounds: 1016 72 8 8 + - image: solid-color(0, 10, 0, 255, 8, 8) + bounds: 0 80 8 8 + - image: solid-color(1, 10, 0, 255, 8, 8) + bounds: 8 80 8 8 + - image: solid-color(2, 10, 0, 255, 8, 8) + bounds: 16 80 8 8 + - image: solid-color(3, 10, 0, 255, 8, 8) + bounds: 24 80 8 8 + - image: solid-color(4, 10, 0, 255, 8, 8) + bounds: 32 80 8 8 + - image: solid-color(5, 10, 0, 255, 8, 8) + bounds: 40 80 8 8 + - image: solid-color(6, 10, 0, 255, 8, 8) + bounds: 48 80 8 8 + - image: solid-color(7, 10, 0, 255, 8, 8) + bounds: 56 80 8 8 + - image: solid-color(8, 10, 0, 255, 8, 8) + bounds: 64 80 8 8 + - image: solid-color(9, 10, 0, 255, 8, 8) + bounds: 72 80 8 8 + - image: solid-color(10, 10, 0, 255, 8, 8) + bounds: 80 80 8 8 + - image: solid-color(11, 10, 0, 255, 8, 8) + bounds: 88 80 8 8 + - image: solid-color(12, 10, 0, 255, 8, 8) + bounds: 96 80 8 8 + - image: solid-color(13, 10, 0, 255, 8, 8) + bounds: 104 80 8 8 + - image: solid-color(14, 10, 0, 255, 8, 8) + bounds: 112 80 8 8 + - image: solid-color(15, 10, 0, 255, 8, 8) + bounds: 120 80 8 8 + - image: solid-color(16, 10, 0, 255, 8, 8) + bounds: 128 80 8 8 + - image: solid-color(17, 10, 0, 255, 8, 8) + bounds: 136 80 8 8 + - image: solid-color(18, 10, 0, 255, 8, 8) + bounds: 144 80 8 8 + - image: solid-color(19, 10, 0, 255, 8, 8) + bounds: 152 80 8 8 + - image: solid-color(20, 10, 0, 255, 8, 8) + bounds: 160 80 8 8 + - image: solid-color(21, 10, 0, 255, 8, 8) + bounds: 168 80 8 8 + - image: solid-color(22, 10, 0, 255, 8, 8) + bounds: 176 80 8 8 + - image: solid-color(23, 10, 0, 255, 8, 8) + bounds: 184 80 8 8 + - image: solid-color(24, 10, 0, 255, 8, 8) + bounds: 192 80 8 8 + - image: solid-color(25, 10, 0, 255, 8, 8) + bounds: 200 80 8 8 + - image: solid-color(26, 10, 0, 255, 8, 8) + bounds: 208 80 8 8 + - image: solid-color(27, 10, 0, 255, 8, 8) + bounds: 216 80 8 8 + - image: solid-color(28, 10, 0, 255, 8, 8) + bounds: 224 80 8 8 + - image: solid-color(29, 10, 0, 255, 8, 8) + bounds: 232 80 8 8 + - image: solid-color(30, 10, 0, 255, 8, 8) + bounds: 240 80 8 8 + - image: solid-color(31, 10, 0, 255, 8, 8) + bounds: 248 80 8 8 + - image: solid-color(32, 10, 0, 255, 8, 8) + bounds: 256 80 8 8 + - image: solid-color(33, 10, 0, 255, 8, 8) + bounds: 264 80 8 8 + - image: solid-color(34, 10, 0, 255, 8, 8) + bounds: 272 80 8 8 + - image: solid-color(35, 10, 0, 255, 8, 8) + bounds: 280 80 8 8 + - image: solid-color(36, 10, 0, 255, 8, 8) + bounds: 288 80 8 8 + - image: solid-color(37, 10, 0, 255, 8, 8) + bounds: 296 80 8 8 + - image: solid-color(38, 10, 0, 255, 8, 8) + bounds: 304 80 8 8 + - image: solid-color(39, 10, 0, 255, 8, 8) + bounds: 312 80 8 8 + - image: solid-color(40, 10, 0, 255, 8, 8) + bounds: 320 80 8 8 + - image: solid-color(41, 10, 0, 255, 8, 8) + bounds: 328 80 8 8 + - image: solid-color(42, 10, 0, 255, 8, 8) + bounds: 336 80 8 8 + - image: solid-color(43, 10, 0, 255, 8, 8) + bounds: 344 80 8 8 + - image: solid-color(44, 10, 0, 255, 8, 8) + bounds: 352 80 8 8 + - image: solid-color(45, 10, 0, 255, 8, 8) + bounds: 360 80 8 8 + - image: solid-color(46, 10, 0, 255, 8, 8) + bounds: 368 80 8 8 + - image: solid-color(47, 10, 0, 255, 8, 8) + bounds: 376 80 8 8 + - image: solid-color(48, 10, 0, 255, 8, 8) + bounds: 384 80 8 8 + - image: solid-color(49, 10, 0, 255, 8, 8) + bounds: 392 80 8 8 + - image: solid-color(50, 10, 0, 255, 8, 8) + bounds: 400 80 8 8 + - image: solid-color(51, 10, 0, 255, 8, 8) + bounds: 408 80 8 8 + - image: solid-color(52, 10, 0, 255, 8, 8) + bounds: 416 80 8 8 + - image: solid-color(53, 10, 0, 255, 8, 8) + bounds: 424 80 8 8 + - image: solid-color(54, 10, 0, 255, 8, 8) + bounds: 432 80 8 8 + - image: solid-color(55, 10, 0, 255, 8, 8) + bounds: 440 80 8 8 + - image: solid-color(56, 10, 0, 255, 8, 8) + bounds: 448 80 8 8 + - image: solid-color(57, 10, 0, 255, 8, 8) + bounds: 456 80 8 8 + - image: solid-color(58, 10, 0, 255, 8, 8) + bounds: 464 80 8 8 + - image: solid-color(59, 10, 0, 255, 8, 8) + bounds: 472 80 8 8 + - image: solid-color(60, 10, 0, 255, 8, 8) + bounds: 480 80 8 8 + - image: solid-color(61, 10, 0, 255, 8, 8) + bounds: 488 80 8 8 + - image: solid-color(62, 10, 0, 255, 8, 8) + bounds: 496 80 8 8 + - image: solid-color(63, 10, 0, 255, 8, 8) + bounds: 504 80 8 8 + - image: solid-color(64, 10, 0, 255, 8, 8) + bounds: 512 80 8 8 + - image: solid-color(65, 10, 0, 255, 8, 8) + bounds: 520 80 8 8 + - image: solid-color(66, 10, 0, 255, 8, 8) + bounds: 528 80 8 8 + - image: solid-color(67, 10, 0, 255, 8, 8) + bounds: 536 80 8 8 + - image: solid-color(68, 10, 0, 255, 8, 8) + bounds: 544 80 8 8 + - image: solid-color(69, 10, 0, 255, 8, 8) + bounds: 552 80 8 8 + - image: solid-color(70, 10, 0, 255, 8, 8) + bounds: 560 80 8 8 + - image: solid-color(71, 10, 0, 255, 8, 8) + bounds: 568 80 8 8 + - image: solid-color(72, 10, 0, 255, 8, 8) + bounds: 576 80 8 8 + - image: solid-color(73, 10, 0, 255, 8, 8) + bounds: 584 80 8 8 + - image: solid-color(74, 10, 0, 255, 8, 8) + bounds: 592 80 8 8 + - image: solid-color(75, 10, 0, 255, 8, 8) + bounds: 600 80 8 8 + - image: solid-color(76, 10, 0, 255, 8, 8) + bounds: 608 80 8 8 + - image: solid-color(77, 10, 0, 255, 8, 8) + bounds: 616 80 8 8 + - image: solid-color(78, 10, 0, 255, 8, 8) + bounds: 624 80 8 8 + - image: solid-color(79, 10, 0, 255, 8, 8) + bounds: 632 80 8 8 + - image: solid-color(80, 10, 0, 255, 8, 8) + bounds: 640 80 8 8 + - image: solid-color(81, 10, 0, 255, 8, 8) + bounds: 648 80 8 8 + - image: solid-color(82, 10, 0, 255, 8, 8) + bounds: 656 80 8 8 + - image: solid-color(83, 10, 0, 255, 8, 8) + bounds: 664 80 8 8 + - image: solid-color(84, 10, 0, 255, 8, 8) + bounds: 672 80 8 8 + - image: solid-color(85, 10, 0, 255, 8, 8) + bounds: 680 80 8 8 + - image: solid-color(86, 10, 0, 255, 8, 8) + bounds: 688 80 8 8 + - image: solid-color(87, 10, 0, 255, 8, 8) + bounds: 696 80 8 8 + - image: solid-color(88, 10, 0, 255, 8, 8) + bounds: 704 80 8 8 + - image: solid-color(89, 10, 0, 255, 8, 8) + bounds: 712 80 8 8 + - image: solid-color(90, 10, 0, 255, 8, 8) + bounds: 720 80 8 8 + - image: solid-color(91, 10, 0, 255, 8, 8) + bounds: 728 80 8 8 + - image: solid-color(92, 10, 0, 255, 8, 8) + bounds: 736 80 8 8 + - image: solid-color(93, 10, 0, 255, 8, 8) + bounds: 744 80 8 8 + - image: solid-color(94, 10, 0, 255, 8, 8) + bounds: 752 80 8 8 + - image: solid-color(95, 10, 0, 255, 8, 8) + bounds: 760 80 8 8 + - image: solid-color(96, 10, 0, 255, 8, 8) + bounds: 768 80 8 8 + - image: solid-color(97, 10, 0, 255, 8, 8) + bounds: 776 80 8 8 + - image: solid-color(98, 10, 0, 255, 8, 8) + bounds: 784 80 8 8 + - image: solid-color(99, 10, 0, 255, 8, 8) + bounds: 792 80 8 8 + - image: solid-color(100, 10, 0, 255, 8, 8) + bounds: 800 80 8 8 + - image: solid-color(101, 10, 0, 255, 8, 8) + bounds: 808 80 8 8 + - image: solid-color(102, 10, 0, 255, 8, 8) + bounds: 816 80 8 8 + - image: solid-color(103, 10, 0, 255, 8, 8) + bounds: 824 80 8 8 + - image: solid-color(104, 10, 0, 255, 8, 8) + bounds: 832 80 8 8 + - image: solid-color(105, 10, 0, 255, 8, 8) + bounds: 840 80 8 8 + - image: solid-color(106, 10, 0, 255, 8, 8) + bounds: 848 80 8 8 + - image: solid-color(107, 10, 0, 255, 8, 8) + bounds: 856 80 8 8 + - image: solid-color(108, 10, 0, 255, 8, 8) + bounds: 864 80 8 8 + - image: solid-color(109, 10, 0, 255, 8, 8) + bounds: 872 80 8 8 + - image: solid-color(110, 10, 0, 255, 8, 8) + bounds: 880 80 8 8 + - image: solid-color(111, 10, 0, 255, 8, 8) + bounds: 888 80 8 8 + - image: solid-color(112, 10, 0, 255, 8, 8) + bounds: 896 80 8 8 + - image: solid-color(113, 10, 0, 255, 8, 8) + bounds: 904 80 8 8 + - image: solid-color(114, 10, 0, 255, 8, 8) + bounds: 912 80 8 8 + - image: solid-color(115, 10, 0, 255, 8, 8) + bounds: 920 80 8 8 + - image: solid-color(116, 10, 0, 255, 8, 8) + bounds: 928 80 8 8 + - image: solid-color(117, 10, 0, 255, 8, 8) + bounds: 936 80 8 8 + - image: solid-color(118, 10, 0, 255, 8, 8) + bounds: 944 80 8 8 + - image: solid-color(119, 10, 0, 255, 8, 8) + bounds: 952 80 8 8 + - image: solid-color(120, 10, 0, 255, 8, 8) + bounds: 960 80 8 8 + - image: solid-color(121, 10, 0, 255, 8, 8) + bounds: 968 80 8 8 + - image: solid-color(122, 10, 0, 255, 8, 8) + bounds: 976 80 8 8 + - image: solid-color(123, 10, 0, 255, 8, 8) + bounds: 984 80 8 8 + - image: solid-color(124, 10, 0, 255, 8, 8) + bounds: 992 80 8 8 + - image: solid-color(125, 10, 0, 255, 8, 8) + bounds: 1000 80 8 8 + - image: solid-color(126, 10, 0, 255, 8, 8) + bounds: 1008 80 8 8 + - image: solid-color(127, 10, 0, 255, 8, 8) + bounds: 1016 80 8 8 + - image: solid-color(0, 11, 0, 255, 8, 8) + bounds: 0 88 8 8 + - image: solid-color(1, 11, 0, 255, 8, 8) + bounds: 8 88 8 8 + - image: solid-color(2, 11, 0, 255, 8, 8) + bounds: 16 88 8 8 + - image: solid-color(3, 11, 0, 255, 8, 8) + bounds: 24 88 8 8 + - image: solid-color(4, 11, 0, 255, 8, 8) + bounds: 32 88 8 8 + - image: solid-color(5, 11, 0, 255, 8, 8) + bounds: 40 88 8 8 + - image: solid-color(6, 11, 0, 255, 8, 8) + bounds: 48 88 8 8 + - image: solid-color(7, 11, 0, 255, 8, 8) + bounds: 56 88 8 8 + - image: solid-color(8, 11, 0, 255, 8, 8) + bounds: 64 88 8 8 + - image: solid-color(9, 11, 0, 255, 8, 8) + bounds: 72 88 8 8 + - image: solid-color(10, 11, 0, 255, 8, 8) + bounds: 80 88 8 8 + - image: solid-color(11, 11, 0, 255, 8, 8) + bounds: 88 88 8 8 + - image: solid-color(12, 11, 0, 255, 8, 8) + bounds: 96 88 8 8 + - image: solid-color(13, 11, 0, 255, 8, 8) + bounds: 104 88 8 8 + - image: solid-color(14, 11, 0, 255, 8, 8) + bounds: 112 88 8 8 + - image: solid-color(15, 11, 0, 255, 8, 8) + bounds: 120 88 8 8 + - image: solid-color(16, 11, 0, 255, 8, 8) + bounds: 128 88 8 8 + - image: solid-color(17, 11, 0, 255, 8, 8) + bounds: 136 88 8 8 + - image: solid-color(18, 11, 0, 255, 8, 8) + bounds: 144 88 8 8 + - image: solid-color(19, 11, 0, 255, 8, 8) + bounds: 152 88 8 8 + - image: solid-color(20, 11, 0, 255, 8, 8) + bounds: 160 88 8 8 + - image: solid-color(21, 11, 0, 255, 8, 8) + bounds: 168 88 8 8 + - image: solid-color(22, 11, 0, 255, 8, 8) + bounds: 176 88 8 8 + - image: solid-color(23, 11, 0, 255, 8, 8) + bounds: 184 88 8 8 + - image: solid-color(24, 11, 0, 255, 8, 8) + bounds: 192 88 8 8 + - image: solid-color(25, 11, 0, 255, 8, 8) + bounds: 200 88 8 8 + - image: solid-color(26, 11, 0, 255, 8, 8) + bounds: 208 88 8 8 + - image: solid-color(27, 11, 0, 255, 8, 8) + bounds: 216 88 8 8 + - image: solid-color(28, 11, 0, 255, 8, 8) + bounds: 224 88 8 8 + - image: solid-color(29, 11, 0, 255, 8, 8) + bounds: 232 88 8 8 + - image: solid-color(30, 11, 0, 255, 8, 8) + bounds: 240 88 8 8 + - image: solid-color(31, 11, 0, 255, 8, 8) + bounds: 248 88 8 8 + - image: solid-color(32, 11, 0, 255, 8, 8) + bounds: 256 88 8 8 + - image: solid-color(33, 11, 0, 255, 8, 8) + bounds: 264 88 8 8 + - image: solid-color(34, 11, 0, 255, 8, 8) + bounds: 272 88 8 8 + - image: solid-color(35, 11, 0, 255, 8, 8) + bounds: 280 88 8 8 + - image: solid-color(36, 11, 0, 255, 8, 8) + bounds: 288 88 8 8 + - image: solid-color(37, 11, 0, 255, 8, 8) + bounds: 296 88 8 8 + - image: solid-color(38, 11, 0, 255, 8, 8) + bounds: 304 88 8 8 + - image: solid-color(39, 11, 0, 255, 8, 8) + bounds: 312 88 8 8 + - image: solid-color(40, 11, 0, 255, 8, 8) + bounds: 320 88 8 8 + - image: solid-color(41, 11, 0, 255, 8, 8) + bounds: 328 88 8 8 + - image: solid-color(42, 11, 0, 255, 8, 8) + bounds: 336 88 8 8 + - image: solid-color(43, 11, 0, 255, 8, 8) + bounds: 344 88 8 8 + - image: solid-color(44, 11, 0, 255, 8, 8) + bounds: 352 88 8 8 + - image: solid-color(45, 11, 0, 255, 8, 8) + bounds: 360 88 8 8 + - image: solid-color(46, 11, 0, 255, 8, 8) + bounds: 368 88 8 8 + - image: solid-color(47, 11, 0, 255, 8, 8) + bounds: 376 88 8 8 + - image: solid-color(48, 11, 0, 255, 8, 8) + bounds: 384 88 8 8 + - image: solid-color(49, 11, 0, 255, 8, 8) + bounds: 392 88 8 8 + - image: solid-color(50, 11, 0, 255, 8, 8) + bounds: 400 88 8 8 + - image: solid-color(51, 11, 0, 255, 8, 8) + bounds: 408 88 8 8 + - image: solid-color(52, 11, 0, 255, 8, 8) + bounds: 416 88 8 8 + - image: solid-color(53, 11, 0, 255, 8, 8) + bounds: 424 88 8 8 + - image: solid-color(54, 11, 0, 255, 8, 8) + bounds: 432 88 8 8 + - image: solid-color(55, 11, 0, 255, 8, 8) + bounds: 440 88 8 8 + - image: solid-color(56, 11, 0, 255, 8, 8) + bounds: 448 88 8 8 + - image: solid-color(57, 11, 0, 255, 8, 8) + bounds: 456 88 8 8 + - image: solid-color(58, 11, 0, 255, 8, 8) + bounds: 464 88 8 8 + - image: solid-color(59, 11, 0, 255, 8, 8) + bounds: 472 88 8 8 + - image: solid-color(60, 11, 0, 255, 8, 8) + bounds: 480 88 8 8 + - image: solid-color(61, 11, 0, 255, 8, 8) + bounds: 488 88 8 8 + - image: solid-color(62, 11, 0, 255, 8, 8) + bounds: 496 88 8 8 + - image: solid-color(63, 11, 0, 255, 8, 8) + bounds: 504 88 8 8 + - image: solid-color(64, 11, 0, 255, 8, 8) + bounds: 512 88 8 8 + - image: solid-color(65, 11, 0, 255, 8, 8) + bounds: 520 88 8 8 + - image: solid-color(66, 11, 0, 255, 8, 8) + bounds: 528 88 8 8 + - image: solid-color(67, 11, 0, 255, 8, 8) + bounds: 536 88 8 8 + - image: solid-color(68, 11, 0, 255, 8, 8) + bounds: 544 88 8 8 + - image: solid-color(69, 11, 0, 255, 8, 8) + bounds: 552 88 8 8 + - image: solid-color(70, 11, 0, 255, 8, 8) + bounds: 560 88 8 8 + - image: solid-color(71, 11, 0, 255, 8, 8) + bounds: 568 88 8 8 + - image: solid-color(72, 11, 0, 255, 8, 8) + bounds: 576 88 8 8 + - image: solid-color(73, 11, 0, 255, 8, 8) + bounds: 584 88 8 8 + - image: solid-color(74, 11, 0, 255, 8, 8) + bounds: 592 88 8 8 + - image: solid-color(75, 11, 0, 255, 8, 8) + bounds: 600 88 8 8 + - image: solid-color(76, 11, 0, 255, 8, 8) + bounds: 608 88 8 8 + - image: solid-color(77, 11, 0, 255, 8, 8) + bounds: 616 88 8 8 + - image: solid-color(78, 11, 0, 255, 8, 8) + bounds: 624 88 8 8 + - image: solid-color(79, 11, 0, 255, 8, 8) + bounds: 632 88 8 8 + - image: solid-color(80, 11, 0, 255, 8, 8) + bounds: 640 88 8 8 + - image: solid-color(81, 11, 0, 255, 8, 8) + bounds: 648 88 8 8 + - image: solid-color(82, 11, 0, 255, 8, 8) + bounds: 656 88 8 8 + - image: solid-color(83, 11, 0, 255, 8, 8) + bounds: 664 88 8 8 + - image: solid-color(84, 11, 0, 255, 8, 8) + bounds: 672 88 8 8 + - image: solid-color(85, 11, 0, 255, 8, 8) + bounds: 680 88 8 8 + - image: solid-color(86, 11, 0, 255, 8, 8) + bounds: 688 88 8 8 + - image: solid-color(87, 11, 0, 255, 8, 8) + bounds: 696 88 8 8 + - image: solid-color(88, 11, 0, 255, 8, 8) + bounds: 704 88 8 8 + - image: solid-color(89, 11, 0, 255, 8, 8) + bounds: 712 88 8 8 + - image: solid-color(90, 11, 0, 255, 8, 8) + bounds: 720 88 8 8 + - image: solid-color(91, 11, 0, 255, 8, 8) + bounds: 728 88 8 8 + - image: solid-color(92, 11, 0, 255, 8, 8) + bounds: 736 88 8 8 + - image: solid-color(93, 11, 0, 255, 8, 8) + bounds: 744 88 8 8 + - image: solid-color(94, 11, 0, 255, 8, 8) + bounds: 752 88 8 8 + - image: solid-color(95, 11, 0, 255, 8, 8) + bounds: 760 88 8 8 + - image: solid-color(96, 11, 0, 255, 8, 8) + bounds: 768 88 8 8 + - image: solid-color(97, 11, 0, 255, 8, 8) + bounds: 776 88 8 8 + - image: solid-color(98, 11, 0, 255, 8, 8) + bounds: 784 88 8 8 + - image: solid-color(99, 11, 0, 255, 8, 8) + bounds: 792 88 8 8 + - image: solid-color(100, 11, 0, 255, 8, 8) + bounds: 800 88 8 8 + - image: solid-color(101, 11, 0, 255, 8, 8) + bounds: 808 88 8 8 + - image: solid-color(102, 11, 0, 255, 8, 8) + bounds: 816 88 8 8 + - image: solid-color(103, 11, 0, 255, 8, 8) + bounds: 824 88 8 8 + - image: solid-color(104, 11, 0, 255, 8, 8) + bounds: 832 88 8 8 + - image: solid-color(105, 11, 0, 255, 8, 8) + bounds: 840 88 8 8 + - image: solid-color(106, 11, 0, 255, 8, 8) + bounds: 848 88 8 8 + - image: solid-color(107, 11, 0, 255, 8, 8) + bounds: 856 88 8 8 + - image: solid-color(108, 11, 0, 255, 8, 8) + bounds: 864 88 8 8 + - image: solid-color(109, 11, 0, 255, 8, 8) + bounds: 872 88 8 8 + - image: solid-color(110, 11, 0, 255, 8, 8) + bounds: 880 88 8 8 + - image: solid-color(111, 11, 0, 255, 8, 8) + bounds: 888 88 8 8 + - image: solid-color(112, 11, 0, 255, 8, 8) + bounds: 896 88 8 8 + - image: solid-color(113, 11, 0, 255, 8, 8) + bounds: 904 88 8 8 + - image: solid-color(114, 11, 0, 255, 8, 8) + bounds: 912 88 8 8 + - image: solid-color(115, 11, 0, 255, 8, 8) + bounds: 920 88 8 8 + - image: solid-color(116, 11, 0, 255, 8, 8) + bounds: 928 88 8 8 + - image: solid-color(117, 11, 0, 255, 8, 8) + bounds: 936 88 8 8 + - image: solid-color(118, 11, 0, 255, 8, 8) + bounds: 944 88 8 8 + - image: solid-color(119, 11, 0, 255, 8, 8) + bounds: 952 88 8 8 + - image: solid-color(120, 11, 0, 255, 8, 8) + bounds: 960 88 8 8 + - image: solid-color(121, 11, 0, 255, 8, 8) + bounds: 968 88 8 8 + - image: solid-color(122, 11, 0, 255, 8, 8) + bounds: 976 88 8 8 + - image: solid-color(123, 11, 0, 255, 8, 8) + bounds: 984 88 8 8 + - image: solid-color(124, 11, 0, 255, 8, 8) + bounds: 992 88 8 8 + - image: solid-color(125, 11, 0, 255, 8, 8) + bounds: 1000 88 8 8 + - image: solid-color(126, 11, 0, 255, 8, 8) + bounds: 1008 88 8 8 + - image: solid-color(127, 11, 0, 255, 8, 8) + bounds: 1016 88 8 8 + - image: solid-color(0, 12, 0, 255, 8, 8) + bounds: 0 96 8 8 + - image: solid-color(1, 12, 0, 255, 8, 8) + bounds: 8 96 8 8 + - image: solid-color(2, 12, 0, 255, 8, 8) + bounds: 16 96 8 8 + - image: solid-color(3, 12, 0, 255, 8, 8) + bounds: 24 96 8 8 + - image: solid-color(4, 12, 0, 255, 8, 8) + bounds: 32 96 8 8 + - image: solid-color(5, 12, 0, 255, 8, 8) + bounds: 40 96 8 8 + - image: solid-color(6, 12, 0, 255, 8, 8) + bounds: 48 96 8 8 + - image: solid-color(7, 12, 0, 255, 8, 8) + bounds: 56 96 8 8 + - image: solid-color(8, 12, 0, 255, 8, 8) + bounds: 64 96 8 8 + - image: solid-color(9, 12, 0, 255, 8, 8) + bounds: 72 96 8 8 + - image: solid-color(10, 12, 0, 255, 8, 8) + bounds: 80 96 8 8 + - image: solid-color(11, 12, 0, 255, 8, 8) + bounds: 88 96 8 8 + - image: solid-color(12, 12, 0, 255, 8, 8) + bounds: 96 96 8 8 + - image: solid-color(13, 12, 0, 255, 8, 8) + bounds: 104 96 8 8 + - image: solid-color(14, 12, 0, 255, 8, 8) + bounds: 112 96 8 8 + - image: solid-color(15, 12, 0, 255, 8, 8) + bounds: 120 96 8 8 + - image: solid-color(16, 12, 0, 255, 8, 8) + bounds: 128 96 8 8 + - image: solid-color(17, 12, 0, 255, 8, 8) + bounds: 136 96 8 8 + - image: solid-color(18, 12, 0, 255, 8, 8) + bounds: 144 96 8 8 + - image: solid-color(19, 12, 0, 255, 8, 8) + bounds: 152 96 8 8 + - image: solid-color(20, 12, 0, 255, 8, 8) + bounds: 160 96 8 8 + - image: solid-color(21, 12, 0, 255, 8, 8) + bounds: 168 96 8 8 + - image: solid-color(22, 12, 0, 255, 8, 8) + bounds: 176 96 8 8 + - image: solid-color(23, 12, 0, 255, 8, 8) + bounds: 184 96 8 8 + - image: solid-color(24, 12, 0, 255, 8, 8) + bounds: 192 96 8 8 + - image: solid-color(25, 12, 0, 255, 8, 8) + bounds: 200 96 8 8 + - image: solid-color(26, 12, 0, 255, 8, 8) + bounds: 208 96 8 8 + - image: solid-color(27, 12, 0, 255, 8, 8) + bounds: 216 96 8 8 + - image: solid-color(28, 12, 0, 255, 8, 8) + bounds: 224 96 8 8 + - image: solid-color(29, 12, 0, 255, 8, 8) + bounds: 232 96 8 8 + - image: solid-color(30, 12, 0, 255, 8, 8) + bounds: 240 96 8 8 + - image: solid-color(31, 12, 0, 255, 8, 8) + bounds: 248 96 8 8 + - image: solid-color(32, 12, 0, 255, 8, 8) + bounds: 256 96 8 8 + - image: solid-color(33, 12, 0, 255, 8, 8) + bounds: 264 96 8 8 + - image: solid-color(34, 12, 0, 255, 8, 8) + bounds: 272 96 8 8 + - image: solid-color(35, 12, 0, 255, 8, 8) + bounds: 280 96 8 8 + - image: solid-color(36, 12, 0, 255, 8, 8) + bounds: 288 96 8 8 + - image: solid-color(37, 12, 0, 255, 8, 8) + bounds: 296 96 8 8 + - image: solid-color(38, 12, 0, 255, 8, 8) + bounds: 304 96 8 8 + - image: solid-color(39, 12, 0, 255, 8, 8) + bounds: 312 96 8 8 + - image: solid-color(40, 12, 0, 255, 8, 8) + bounds: 320 96 8 8 + - image: solid-color(41, 12, 0, 255, 8, 8) + bounds: 328 96 8 8 + - image: solid-color(42, 12, 0, 255, 8, 8) + bounds: 336 96 8 8 + - image: solid-color(43, 12, 0, 255, 8, 8) + bounds: 344 96 8 8 + - image: solid-color(44, 12, 0, 255, 8, 8) + bounds: 352 96 8 8 + - image: solid-color(45, 12, 0, 255, 8, 8) + bounds: 360 96 8 8 + - image: solid-color(46, 12, 0, 255, 8, 8) + bounds: 368 96 8 8 + - image: solid-color(47, 12, 0, 255, 8, 8) + bounds: 376 96 8 8 + - image: solid-color(48, 12, 0, 255, 8, 8) + bounds: 384 96 8 8 + - image: solid-color(49, 12, 0, 255, 8, 8) + bounds: 392 96 8 8 + - image: solid-color(50, 12, 0, 255, 8, 8) + bounds: 400 96 8 8 + - image: solid-color(51, 12, 0, 255, 8, 8) + bounds: 408 96 8 8 + - image: solid-color(52, 12, 0, 255, 8, 8) + bounds: 416 96 8 8 + - image: solid-color(53, 12, 0, 255, 8, 8) + bounds: 424 96 8 8 + - image: solid-color(54, 12, 0, 255, 8, 8) + bounds: 432 96 8 8 + - image: solid-color(55, 12, 0, 255, 8, 8) + bounds: 440 96 8 8 + - image: solid-color(56, 12, 0, 255, 8, 8) + bounds: 448 96 8 8 + - image: solid-color(57, 12, 0, 255, 8, 8) + bounds: 456 96 8 8 + - image: solid-color(58, 12, 0, 255, 8, 8) + bounds: 464 96 8 8 + - image: solid-color(59, 12, 0, 255, 8, 8) + bounds: 472 96 8 8 + - image: solid-color(60, 12, 0, 255, 8, 8) + bounds: 480 96 8 8 + - image: solid-color(61, 12, 0, 255, 8, 8) + bounds: 488 96 8 8 + - image: solid-color(62, 12, 0, 255, 8, 8) + bounds: 496 96 8 8 + - image: solid-color(63, 12, 0, 255, 8, 8) + bounds: 504 96 8 8 + - image: solid-color(64, 12, 0, 255, 8, 8) + bounds: 512 96 8 8 + - image: solid-color(65, 12, 0, 255, 8, 8) + bounds: 520 96 8 8 + - image: solid-color(66, 12, 0, 255, 8, 8) + bounds: 528 96 8 8 + - image: solid-color(67, 12, 0, 255, 8, 8) + bounds: 536 96 8 8 + - image: solid-color(68, 12, 0, 255, 8, 8) + bounds: 544 96 8 8 + - image: solid-color(69, 12, 0, 255, 8, 8) + bounds: 552 96 8 8 + - image: solid-color(70, 12, 0, 255, 8, 8) + bounds: 560 96 8 8 + - image: solid-color(71, 12, 0, 255, 8, 8) + bounds: 568 96 8 8 + - image: solid-color(72, 12, 0, 255, 8, 8) + bounds: 576 96 8 8 + - image: solid-color(73, 12, 0, 255, 8, 8) + bounds: 584 96 8 8 + - image: solid-color(74, 12, 0, 255, 8, 8) + bounds: 592 96 8 8 + - image: solid-color(75, 12, 0, 255, 8, 8) + bounds: 600 96 8 8 + - image: solid-color(76, 12, 0, 255, 8, 8) + bounds: 608 96 8 8 + - image: solid-color(77, 12, 0, 255, 8, 8) + bounds: 616 96 8 8 + - image: solid-color(78, 12, 0, 255, 8, 8) + bounds: 624 96 8 8 + - image: solid-color(79, 12, 0, 255, 8, 8) + bounds: 632 96 8 8 + - image: solid-color(80, 12, 0, 255, 8, 8) + bounds: 640 96 8 8 + - image: solid-color(81, 12, 0, 255, 8, 8) + bounds: 648 96 8 8 + - image: solid-color(82, 12, 0, 255, 8, 8) + bounds: 656 96 8 8 + - image: solid-color(83, 12, 0, 255, 8, 8) + bounds: 664 96 8 8 + - image: solid-color(84, 12, 0, 255, 8, 8) + bounds: 672 96 8 8 + - image: solid-color(85, 12, 0, 255, 8, 8) + bounds: 680 96 8 8 + - image: solid-color(86, 12, 0, 255, 8, 8) + bounds: 688 96 8 8 + - image: solid-color(87, 12, 0, 255, 8, 8) + bounds: 696 96 8 8 + - image: solid-color(88, 12, 0, 255, 8, 8) + bounds: 704 96 8 8 + - image: solid-color(89, 12, 0, 255, 8, 8) + bounds: 712 96 8 8 + - image: solid-color(90, 12, 0, 255, 8, 8) + bounds: 720 96 8 8 + - image: solid-color(91, 12, 0, 255, 8, 8) + bounds: 728 96 8 8 + - image: solid-color(92, 12, 0, 255, 8, 8) + bounds: 736 96 8 8 + - image: solid-color(93, 12, 0, 255, 8, 8) + bounds: 744 96 8 8 + - image: solid-color(94, 12, 0, 255, 8, 8) + bounds: 752 96 8 8 + - image: solid-color(95, 12, 0, 255, 8, 8) + bounds: 760 96 8 8 + - image: solid-color(96, 12, 0, 255, 8, 8) + bounds: 768 96 8 8 + - image: solid-color(97, 12, 0, 255, 8, 8) + bounds: 776 96 8 8 + - image: solid-color(98, 12, 0, 255, 8, 8) + bounds: 784 96 8 8 + - image: solid-color(99, 12, 0, 255, 8, 8) + bounds: 792 96 8 8 + - image: solid-color(100, 12, 0, 255, 8, 8) + bounds: 800 96 8 8 + - image: solid-color(101, 12, 0, 255, 8, 8) + bounds: 808 96 8 8 + - image: solid-color(102, 12, 0, 255, 8, 8) + bounds: 816 96 8 8 + - image: solid-color(103, 12, 0, 255, 8, 8) + bounds: 824 96 8 8 + - image: solid-color(104, 12, 0, 255, 8, 8) + bounds: 832 96 8 8 + - image: solid-color(105, 12, 0, 255, 8, 8) + bounds: 840 96 8 8 + - image: solid-color(106, 12, 0, 255, 8, 8) + bounds: 848 96 8 8 + - image: solid-color(107, 12, 0, 255, 8, 8) + bounds: 856 96 8 8 + - image: solid-color(108, 12, 0, 255, 8, 8) + bounds: 864 96 8 8 + - image: solid-color(109, 12, 0, 255, 8, 8) + bounds: 872 96 8 8 + - image: solid-color(110, 12, 0, 255, 8, 8) + bounds: 880 96 8 8 + - image: solid-color(111, 12, 0, 255, 8, 8) + bounds: 888 96 8 8 + - image: solid-color(112, 12, 0, 255, 8, 8) + bounds: 896 96 8 8 + - image: solid-color(113, 12, 0, 255, 8, 8) + bounds: 904 96 8 8 + - image: solid-color(114, 12, 0, 255, 8, 8) + bounds: 912 96 8 8 + - image: solid-color(115, 12, 0, 255, 8, 8) + bounds: 920 96 8 8 + - image: solid-color(116, 12, 0, 255, 8, 8) + bounds: 928 96 8 8 + - image: solid-color(117, 12, 0, 255, 8, 8) + bounds: 936 96 8 8 + - image: solid-color(118, 12, 0, 255, 8, 8) + bounds: 944 96 8 8 + - image: solid-color(119, 12, 0, 255, 8, 8) + bounds: 952 96 8 8 + - image: solid-color(120, 12, 0, 255, 8, 8) + bounds: 960 96 8 8 + - image: solid-color(121, 12, 0, 255, 8, 8) + bounds: 968 96 8 8 + - image: solid-color(122, 12, 0, 255, 8, 8) + bounds: 976 96 8 8 + - image: solid-color(123, 12, 0, 255, 8, 8) + bounds: 984 96 8 8 + - image: solid-color(124, 12, 0, 255, 8, 8) + bounds: 992 96 8 8 + - image: solid-color(125, 12, 0, 255, 8, 8) + bounds: 1000 96 8 8 + - image: solid-color(126, 12, 0, 255, 8, 8) + bounds: 1008 96 8 8 + - image: solid-color(127, 12, 0, 255, 8, 8) + bounds: 1016 96 8 8 + - image: solid-color(0, 13, 0, 255, 8, 8) + bounds: 0 104 8 8 + - image: solid-color(1, 13, 0, 255, 8, 8) + bounds: 8 104 8 8 + - image: solid-color(2, 13, 0, 255, 8, 8) + bounds: 16 104 8 8 + - image: solid-color(3, 13, 0, 255, 8, 8) + bounds: 24 104 8 8 + - image: solid-color(4, 13, 0, 255, 8, 8) + bounds: 32 104 8 8 + - image: solid-color(5, 13, 0, 255, 8, 8) + bounds: 40 104 8 8 + - image: solid-color(6, 13, 0, 255, 8, 8) + bounds: 48 104 8 8 + - image: solid-color(7, 13, 0, 255, 8, 8) + bounds: 56 104 8 8 + - image: solid-color(8, 13, 0, 255, 8, 8) + bounds: 64 104 8 8 + - image: solid-color(9, 13, 0, 255, 8, 8) + bounds: 72 104 8 8 + - image: solid-color(10, 13, 0, 255, 8, 8) + bounds: 80 104 8 8 + - image: solid-color(11, 13, 0, 255, 8, 8) + bounds: 88 104 8 8 + - image: solid-color(12, 13, 0, 255, 8, 8) + bounds: 96 104 8 8 + - image: solid-color(13, 13, 0, 255, 8, 8) + bounds: 104 104 8 8 + - image: solid-color(14, 13, 0, 255, 8, 8) + bounds: 112 104 8 8 + - image: solid-color(15, 13, 0, 255, 8, 8) + bounds: 120 104 8 8 + - image: solid-color(16, 13, 0, 255, 8, 8) + bounds: 128 104 8 8 + - image: solid-color(17, 13, 0, 255, 8, 8) + bounds: 136 104 8 8 + - image: solid-color(18, 13, 0, 255, 8, 8) + bounds: 144 104 8 8 + - image: solid-color(19, 13, 0, 255, 8, 8) + bounds: 152 104 8 8 + - image: solid-color(20, 13, 0, 255, 8, 8) + bounds: 160 104 8 8 + - image: solid-color(21, 13, 0, 255, 8, 8) + bounds: 168 104 8 8 + - image: solid-color(22, 13, 0, 255, 8, 8) + bounds: 176 104 8 8 + - image: solid-color(23, 13, 0, 255, 8, 8) + bounds: 184 104 8 8 + - image: solid-color(24, 13, 0, 255, 8, 8) + bounds: 192 104 8 8 + - image: solid-color(25, 13, 0, 255, 8, 8) + bounds: 200 104 8 8 + - image: solid-color(26, 13, 0, 255, 8, 8) + bounds: 208 104 8 8 + - image: solid-color(27, 13, 0, 255, 8, 8) + bounds: 216 104 8 8 + - image: solid-color(28, 13, 0, 255, 8, 8) + bounds: 224 104 8 8 + - image: solid-color(29, 13, 0, 255, 8, 8) + bounds: 232 104 8 8 + - image: solid-color(30, 13, 0, 255, 8, 8) + bounds: 240 104 8 8 + - image: solid-color(31, 13, 0, 255, 8, 8) + bounds: 248 104 8 8 + - image: solid-color(32, 13, 0, 255, 8, 8) + bounds: 256 104 8 8 + - image: solid-color(33, 13, 0, 255, 8, 8) + bounds: 264 104 8 8 + - image: solid-color(34, 13, 0, 255, 8, 8) + bounds: 272 104 8 8 + - image: solid-color(35, 13, 0, 255, 8, 8) + bounds: 280 104 8 8 + - image: solid-color(36, 13, 0, 255, 8, 8) + bounds: 288 104 8 8 + - image: solid-color(37, 13, 0, 255, 8, 8) + bounds: 296 104 8 8 + - image: solid-color(38, 13, 0, 255, 8, 8) + bounds: 304 104 8 8 + - image: solid-color(39, 13, 0, 255, 8, 8) + bounds: 312 104 8 8 + - image: solid-color(40, 13, 0, 255, 8, 8) + bounds: 320 104 8 8 + - image: solid-color(41, 13, 0, 255, 8, 8) + bounds: 328 104 8 8 + - image: solid-color(42, 13, 0, 255, 8, 8) + bounds: 336 104 8 8 + - image: solid-color(43, 13, 0, 255, 8, 8) + bounds: 344 104 8 8 + - image: solid-color(44, 13, 0, 255, 8, 8) + bounds: 352 104 8 8 + - image: solid-color(45, 13, 0, 255, 8, 8) + bounds: 360 104 8 8 + - image: solid-color(46, 13, 0, 255, 8, 8) + bounds: 368 104 8 8 + - image: solid-color(47, 13, 0, 255, 8, 8) + bounds: 376 104 8 8 + - image: solid-color(48, 13, 0, 255, 8, 8) + bounds: 384 104 8 8 + - image: solid-color(49, 13, 0, 255, 8, 8) + bounds: 392 104 8 8 + - image: solid-color(50, 13, 0, 255, 8, 8) + bounds: 400 104 8 8 + - image: solid-color(51, 13, 0, 255, 8, 8) + bounds: 408 104 8 8 + - image: solid-color(52, 13, 0, 255, 8, 8) + bounds: 416 104 8 8 + - image: solid-color(53, 13, 0, 255, 8, 8) + bounds: 424 104 8 8 + - image: solid-color(54, 13, 0, 255, 8, 8) + bounds: 432 104 8 8 + - image: solid-color(55, 13, 0, 255, 8, 8) + bounds: 440 104 8 8 + - image: solid-color(56, 13, 0, 255, 8, 8) + bounds: 448 104 8 8 + - image: solid-color(57, 13, 0, 255, 8, 8) + bounds: 456 104 8 8 + - image: solid-color(58, 13, 0, 255, 8, 8) + bounds: 464 104 8 8 + - image: solid-color(59, 13, 0, 255, 8, 8) + bounds: 472 104 8 8 + - image: solid-color(60, 13, 0, 255, 8, 8) + bounds: 480 104 8 8 + - image: solid-color(61, 13, 0, 255, 8, 8) + bounds: 488 104 8 8 + - image: solid-color(62, 13, 0, 255, 8, 8) + bounds: 496 104 8 8 + - image: solid-color(63, 13, 0, 255, 8, 8) + bounds: 504 104 8 8 + - image: solid-color(64, 13, 0, 255, 8, 8) + bounds: 512 104 8 8 + - image: solid-color(65, 13, 0, 255, 8, 8) + bounds: 520 104 8 8 + - image: solid-color(66, 13, 0, 255, 8, 8) + bounds: 528 104 8 8 + - image: solid-color(67, 13, 0, 255, 8, 8) + bounds: 536 104 8 8 + - image: solid-color(68, 13, 0, 255, 8, 8) + bounds: 544 104 8 8 + - image: solid-color(69, 13, 0, 255, 8, 8) + bounds: 552 104 8 8 + - image: solid-color(70, 13, 0, 255, 8, 8) + bounds: 560 104 8 8 + - image: solid-color(71, 13, 0, 255, 8, 8) + bounds: 568 104 8 8 + - image: solid-color(72, 13, 0, 255, 8, 8) + bounds: 576 104 8 8 + - image: solid-color(73, 13, 0, 255, 8, 8) + bounds: 584 104 8 8 + - image: solid-color(74, 13, 0, 255, 8, 8) + bounds: 592 104 8 8 + - image: solid-color(75, 13, 0, 255, 8, 8) + bounds: 600 104 8 8 + - image: solid-color(76, 13, 0, 255, 8, 8) + bounds: 608 104 8 8 + - image: solid-color(77, 13, 0, 255, 8, 8) + bounds: 616 104 8 8 + - image: solid-color(78, 13, 0, 255, 8, 8) + bounds: 624 104 8 8 + - image: solid-color(79, 13, 0, 255, 8, 8) + bounds: 632 104 8 8 + - image: solid-color(80, 13, 0, 255, 8, 8) + bounds: 640 104 8 8 + - image: solid-color(81, 13, 0, 255, 8, 8) + bounds: 648 104 8 8 + - image: solid-color(82, 13, 0, 255, 8, 8) + bounds: 656 104 8 8 + - image: solid-color(83, 13, 0, 255, 8, 8) + bounds: 664 104 8 8 + - image: solid-color(84, 13, 0, 255, 8, 8) + bounds: 672 104 8 8 + - image: solid-color(85, 13, 0, 255, 8, 8) + bounds: 680 104 8 8 + - image: solid-color(86, 13, 0, 255, 8, 8) + bounds: 688 104 8 8 + - image: solid-color(87, 13, 0, 255, 8, 8) + bounds: 696 104 8 8 + - image: solid-color(88, 13, 0, 255, 8, 8) + bounds: 704 104 8 8 + - image: solid-color(89, 13, 0, 255, 8, 8) + bounds: 712 104 8 8 + - image: solid-color(90, 13, 0, 255, 8, 8) + bounds: 720 104 8 8 + - image: solid-color(91, 13, 0, 255, 8, 8) + bounds: 728 104 8 8 + - image: solid-color(92, 13, 0, 255, 8, 8) + bounds: 736 104 8 8 + - image: solid-color(93, 13, 0, 255, 8, 8) + bounds: 744 104 8 8 + - image: solid-color(94, 13, 0, 255, 8, 8) + bounds: 752 104 8 8 + - image: solid-color(95, 13, 0, 255, 8, 8) + bounds: 760 104 8 8 + - image: solid-color(96, 13, 0, 255, 8, 8) + bounds: 768 104 8 8 + - image: solid-color(97, 13, 0, 255, 8, 8) + bounds: 776 104 8 8 + - image: solid-color(98, 13, 0, 255, 8, 8) + bounds: 784 104 8 8 + - image: solid-color(99, 13, 0, 255, 8, 8) + bounds: 792 104 8 8 + - image: solid-color(100, 13, 0, 255, 8, 8) + bounds: 800 104 8 8 + - image: solid-color(101, 13, 0, 255, 8, 8) + bounds: 808 104 8 8 + - image: solid-color(102, 13, 0, 255, 8, 8) + bounds: 816 104 8 8 + - image: solid-color(103, 13, 0, 255, 8, 8) + bounds: 824 104 8 8 + - image: solid-color(104, 13, 0, 255, 8, 8) + bounds: 832 104 8 8 + - image: solid-color(105, 13, 0, 255, 8, 8) + bounds: 840 104 8 8 + - image: solid-color(106, 13, 0, 255, 8, 8) + bounds: 848 104 8 8 + - image: solid-color(107, 13, 0, 255, 8, 8) + bounds: 856 104 8 8 + - image: solid-color(108, 13, 0, 255, 8, 8) + bounds: 864 104 8 8 + - image: solid-color(109, 13, 0, 255, 8, 8) + bounds: 872 104 8 8 + - image: solid-color(110, 13, 0, 255, 8, 8) + bounds: 880 104 8 8 + - image: solid-color(111, 13, 0, 255, 8, 8) + bounds: 888 104 8 8 + - image: solid-color(112, 13, 0, 255, 8, 8) + bounds: 896 104 8 8 + - image: solid-color(113, 13, 0, 255, 8, 8) + bounds: 904 104 8 8 + - image: solid-color(114, 13, 0, 255, 8, 8) + bounds: 912 104 8 8 + - image: solid-color(115, 13, 0, 255, 8, 8) + bounds: 920 104 8 8 + - image: solid-color(116, 13, 0, 255, 8, 8) + bounds: 928 104 8 8 + - image: solid-color(117, 13, 0, 255, 8, 8) + bounds: 936 104 8 8 + - image: solid-color(118, 13, 0, 255, 8, 8) + bounds: 944 104 8 8 + - image: solid-color(119, 13, 0, 255, 8, 8) + bounds: 952 104 8 8 + - image: solid-color(120, 13, 0, 255, 8, 8) + bounds: 960 104 8 8 + - image: solid-color(121, 13, 0, 255, 8, 8) + bounds: 968 104 8 8 + - image: solid-color(122, 13, 0, 255, 8, 8) + bounds: 976 104 8 8 + - image: solid-color(123, 13, 0, 255, 8, 8) + bounds: 984 104 8 8 + - image: solid-color(124, 13, 0, 255, 8, 8) + bounds: 992 104 8 8 + - image: solid-color(125, 13, 0, 255, 8, 8) + bounds: 1000 104 8 8 + - image: solid-color(126, 13, 0, 255, 8, 8) + bounds: 1008 104 8 8 + - image: solid-color(127, 13, 0, 255, 8, 8) + bounds: 1016 104 8 8 + - image: solid-color(0, 14, 0, 255, 8, 8) + bounds: 0 112 8 8 + - image: solid-color(1, 14, 0, 255, 8, 8) + bounds: 8 112 8 8 + - image: solid-color(2, 14, 0, 255, 8, 8) + bounds: 16 112 8 8 + - image: solid-color(3, 14, 0, 255, 8, 8) + bounds: 24 112 8 8 + - image: solid-color(4, 14, 0, 255, 8, 8) + bounds: 32 112 8 8 + - image: solid-color(5, 14, 0, 255, 8, 8) + bounds: 40 112 8 8 + - image: solid-color(6, 14, 0, 255, 8, 8) + bounds: 48 112 8 8 + - image: solid-color(7, 14, 0, 255, 8, 8) + bounds: 56 112 8 8 + - image: solid-color(8, 14, 0, 255, 8, 8) + bounds: 64 112 8 8 + - image: solid-color(9, 14, 0, 255, 8, 8) + bounds: 72 112 8 8 + - image: solid-color(10, 14, 0, 255, 8, 8) + bounds: 80 112 8 8 + - image: solid-color(11, 14, 0, 255, 8, 8) + bounds: 88 112 8 8 + - image: solid-color(12, 14, 0, 255, 8, 8) + bounds: 96 112 8 8 + - image: solid-color(13, 14, 0, 255, 8, 8) + bounds: 104 112 8 8 + - image: solid-color(14, 14, 0, 255, 8, 8) + bounds: 112 112 8 8 + - image: solid-color(15, 14, 0, 255, 8, 8) + bounds: 120 112 8 8 + - image: solid-color(16, 14, 0, 255, 8, 8) + bounds: 128 112 8 8 + - image: solid-color(17, 14, 0, 255, 8, 8) + bounds: 136 112 8 8 + - image: solid-color(18, 14, 0, 255, 8, 8) + bounds: 144 112 8 8 + - image: solid-color(19, 14, 0, 255, 8, 8) + bounds: 152 112 8 8 + - image: solid-color(20, 14, 0, 255, 8, 8) + bounds: 160 112 8 8 + - image: solid-color(21, 14, 0, 255, 8, 8) + bounds: 168 112 8 8 + - image: solid-color(22, 14, 0, 255, 8, 8) + bounds: 176 112 8 8 + - image: solid-color(23, 14, 0, 255, 8, 8) + bounds: 184 112 8 8 + - image: solid-color(24, 14, 0, 255, 8, 8) + bounds: 192 112 8 8 + - image: solid-color(25, 14, 0, 255, 8, 8) + bounds: 200 112 8 8 + - image: solid-color(26, 14, 0, 255, 8, 8) + bounds: 208 112 8 8 + - image: solid-color(27, 14, 0, 255, 8, 8) + bounds: 216 112 8 8 + - image: solid-color(28, 14, 0, 255, 8, 8) + bounds: 224 112 8 8 + - image: solid-color(29, 14, 0, 255, 8, 8) + bounds: 232 112 8 8 + - image: solid-color(30, 14, 0, 255, 8, 8) + bounds: 240 112 8 8 + - image: solid-color(31, 14, 0, 255, 8, 8) + bounds: 248 112 8 8 + - image: solid-color(32, 14, 0, 255, 8, 8) + bounds: 256 112 8 8 + - image: solid-color(33, 14, 0, 255, 8, 8) + bounds: 264 112 8 8 + - image: solid-color(34, 14, 0, 255, 8, 8) + bounds: 272 112 8 8 + - image: solid-color(35, 14, 0, 255, 8, 8) + bounds: 280 112 8 8 + - image: solid-color(36, 14, 0, 255, 8, 8) + bounds: 288 112 8 8 + - image: solid-color(37, 14, 0, 255, 8, 8) + bounds: 296 112 8 8 + - image: solid-color(38, 14, 0, 255, 8, 8) + bounds: 304 112 8 8 + - image: solid-color(39, 14, 0, 255, 8, 8) + bounds: 312 112 8 8 + - image: solid-color(40, 14, 0, 255, 8, 8) + bounds: 320 112 8 8 + - image: solid-color(41, 14, 0, 255, 8, 8) + bounds: 328 112 8 8 + - image: solid-color(42, 14, 0, 255, 8, 8) + bounds: 336 112 8 8 + - image: solid-color(43, 14, 0, 255, 8, 8) + bounds: 344 112 8 8 + - image: solid-color(44, 14, 0, 255, 8, 8) + bounds: 352 112 8 8 + - image: solid-color(45, 14, 0, 255, 8, 8) + bounds: 360 112 8 8 + - image: solid-color(46, 14, 0, 255, 8, 8) + bounds: 368 112 8 8 + - image: solid-color(47, 14, 0, 255, 8, 8) + bounds: 376 112 8 8 + - image: solid-color(48, 14, 0, 255, 8, 8) + bounds: 384 112 8 8 + - image: solid-color(49, 14, 0, 255, 8, 8) + bounds: 392 112 8 8 + - image: solid-color(50, 14, 0, 255, 8, 8) + bounds: 400 112 8 8 + - image: solid-color(51, 14, 0, 255, 8, 8) + bounds: 408 112 8 8 + - image: solid-color(52, 14, 0, 255, 8, 8) + bounds: 416 112 8 8 + - image: solid-color(53, 14, 0, 255, 8, 8) + bounds: 424 112 8 8 + - image: solid-color(54, 14, 0, 255, 8, 8) + bounds: 432 112 8 8 + - image: solid-color(55, 14, 0, 255, 8, 8) + bounds: 440 112 8 8 + - image: solid-color(56, 14, 0, 255, 8, 8) + bounds: 448 112 8 8 + - image: solid-color(57, 14, 0, 255, 8, 8) + bounds: 456 112 8 8 + - image: solid-color(58, 14, 0, 255, 8, 8) + bounds: 464 112 8 8 + - image: solid-color(59, 14, 0, 255, 8, 8) + bounds: 472 112 8 8 + - image: solid-color(60, 14, 0, 255, 8, 8) + bounds: 480 112 8 8 + - image: solid-color(61, 14, 0, 255, 8, 8) + bounds: 488 112 8 8 + - image: solid-color(62, 14, 0, 255, 8, 8) + bounds: 496 112 8 8 + - image: solid-color(63, 14, 0, 255, 8, 8) + bounds: 504 112 8 8 + - image: solid-color(64, 14, 0, 255, 8, 8) + bounds: 512 112 8 8 + - image: solid-color(65, 14, 0, 255, 8, 8) + bounds: 520 112 8 8 + - image: solid-color(66, 14, 0, 255, 8, 8) + bounds: 528 112 8 8 + - image: solid-color(67, 14, 0, 255, 8, 8) + bounds: 536 112 8 8 + - image: solid-color(68, 14, 0, 255, 8, 8) + bounds: 544 112 8 8 + - image: solid-color(69, 14, 0, 255, 8, 8) + bounds: 552 112 8 8 + - image: solid-color(70, 14, 0, 255, 8, 8) + bounds: 560 112 8 8 + - image: solid-color(71, 14, 0, 255, 8, 8) + bounds: 568 112 8 8 + - image: solid-color(72, 14, 0, 255, 8, 8) + bounds: 576 112 8 8 + - image: solid-color(73, 14, 0, 255, 8, 8) + bounds: 584 112 8 8 + - image: solid-color(74, 14, 0, 255, 8, 8) + bounds: 592 112 8 8 + - image: solid-color(75, 14, 0, 255, 8, 8) + bounds: 600 112 8 8 + - image: solid-color(76, 14, 0, 255, 8, 8) + bounds: 608 112 8 8 + - image: solid-color(77, 14, 0, 255, 8, 8) + bounds: 616 112 8 8 + - image: solid-color(78, 14, 0, 255, 8, 8) + bounds: 624 112 8 8 + - image: solid-color(79, 14, 0, 255, 8, 8) + bounds: 632 112 8 8 + - image: solid-color(80, 14, 0, 255, 8, 8) + bounds: 640 112 8 8 + - image: solid-color(81, 14, 0, 255, 8, 8) + bounds: 648 112 8 8 + - image: solid-color(82, 14, 0, 255, 8, 8) + bounds: 656 112 8 8 + - image: solid-color(83, 14, 0, 255, 8, 8) + bounds: 664 112 8 8 + - image: solid-color(84, 14, 0, 255, 8, 8) + bounds: 672 112 8 8 + - image: solid-color(85, 14, 0, 255, 8, 8) + bounds: 680 112 8 8 + - image: solid-color(86, 14, 0, 255, 8, 8) + bounds: 688 112 8 8 + - image: solid-color(87, 14, 0, 255, 8, 8) + bounds: 696 112 8 8 + - image: solid-color(88, 14, 0, 255, 8, 8) + bounds: 704 112 8 8 + - image: solid-color(89, 14, 0, 255, 8, 8) + bounds: 712 112 8 8 + - image: solid-color(90, 14, 0, 255, 8, 8) + bounds: 720 112 8 8 + - image: solid-color(91, 14, 0, 255, 8, 8) + bounds: 728 112 8 8 + - image: solid-color(92, 14, 0, 255, 8, 8) + bounds: 736 112 8 8 + - image: solid-color(93, 14, 0, 255, 8, 8) + bounds: 744 112 8 8 + - image: solid-color(94, 14, 0, 255, 8, 8) + bounds: 752 112 8 8 + - image: solid-color(95, 14, 0, 255, 8, 8) + bounds: 760 112 8 8 + - image: solid-color(96, 14, 0, 255, 8, 8) + bounds: 768 112 8 8 + - image: solid-color(97, 14, 0, 255, 8, 8) + bounds: 776 112 8 8 + - image: solid-color(98, 14, 0, 255, 8, 8) + bounds: 784 112 8 8 + - image: solid-color(99, 14, 0, 255, 8, 8) + bounds: 792 112 8 8 + - image: solid-color(100, 14, 0, 255, 8, 8) + bounds: 800 112 8 8 + - image: solid-color(101, 14, 0, 255, 8, 8) + bounds: 808 112 8 8 + - image: solid-color(102, 14, 0, 255, 8, 8) + bounds: 816 112 8 8 + - image: solid-color(103, 14, 0, 255, 8, 8) + bounds: 824 112 8 8 + - image: solid-color(104, 14, 0, 255, 8, 8) + bounds: 832 112 8 8 + - image: solid-color(105, 14, 0, 255, 8, 8) + bounds: 840 112 8 8 + - image: solid-color(106, 14, 0, 255, 8, 8) + bounds: 848 112 8 8 + - image: solid-color(107, 14, 0, 255, 8, 8) + bounds: 856 112 8 8 + - image: solid-color(108, 14, 0, 255, 8, 8) + bounds: 864 112 8 8 + - image: solid-color(109, 14, 0, 255, 8, 8) + bounds: 872 112 8 8 + - image: solid-color(110, 14, 0, 255, 8, 8) + bounds: 880 112 8 8 + - image: solid-color(111, 14, 0, 255, 8, 8) + bounds: 888 112 8 8 + - image: solid-color(112, 14, 0, 255, 8, 8) + bounds: 896 112 8 8 + - image: solid-color(113, 14, 0, 255, 8, 8) + bounds: 904 112 8 8 + - image: solid-color(114, 14, 0, 255, 8, 8) + bounds: 912 112 8 8 + - image: solid-color(115, 14, 0, 255, 8, 8) + bounds: 920 112 8 8 + - image: solid-color(116, 14, 0, 255, 8, 8) + bounds: 928 112 8 8 + - image: solid-color(117, 14, 0, 255, 8, 8) + bounds: 936 112 8 8 + - image: solid-color(118, 14, 0, 255, 8, 8) + bounds: 944 112 8 8 + - image: solid-color(119, 14, 0, 255, 8, 8) + bounds: 952 112 8 8 + - image: solid-color(120, 14, 0, 255, 8, 8) + bounds: 960 112 8 8 + - image: solid-color(121, 14, 0, 255, 8, 8) + bounds: 968 112 8 8 + - image: solid-color(122, 14, 0, 255, 8, 8) + bounds: 976 112 8 8 + - image: solid-color(123, 14, 0, 255, 8, 8) + bounds: 984 112 8 8 + - image: solid-color(124, 14, 0, 255, 8, 8) + bounds: 992 112 8 8 + - image: solid-color(125, 14, 0, 255, 8, 8) + bounds: 1000 112 8 8 + - image: solid-color(126, 14, 0, 255, 8, 8) + bounds: 1008 112 8 8 + - image: solid-color(127, 14, 0, 255, 8, 8) + bounds: 1016 112 8 8 + - image: solid-color(0, 15, 0, 255, 8, 8) + bounds: 0 120 8 8 + - image: solid-color(1, 15, 0, 255, 8, 8) + bounds: 8 120 8 8 + - image: solid-color(2, 15, 0, 255, 8, 8) + bounds: 16 120 8 8 + - image: solid-color(3, 15, 0, 255, 8, 8) + bounds: 24 120 8 8 + - image: solid-color(4, 15, 0, 255, 8, 8) + bounds: 32 120 8 8 + - image: solid-color(5, 15, 0, 255, 8, 8) + bounds: 40 120 8 8 + - image: solid-color(6, 15, 0, 255, 8, 8) + bounds: 48 120 8 8 + - image: solid-color(7, 15, 0, 255, 8, 8) + bounds: 56 120 8 8 + - image: solid-color(8, 15, 0, 255, 8, 8) + bounds: 64 120 8 8 + - image: solid-color(9, 15, 0, 255, 8, 8) + bounds: 72 120 8 8 + - image: solid-color(10, 15, 0, 255, 8, 8) + bounds: 80 120 8 8 + - image: solid-color(11, 15, 0, 255, 8, 8) + bounds: 88 120 8 8 + - image: solid-color(12, 15, 0, 255, 8, 8) + bounds: 96 120 8 8 + - image: solid-color(13, 15, 0, 255, 8, 8) + bounds: 104 120 8 8 + - image: solid-color(14, 15, 0, 255, 8, 8) + bounds: 112 120 8 8 + - image: solid-color(15, 15, 0, 255, 8, 8) + bounds: 120 120 8 8 + - image: solid-color(16, 15, 0, 255, 8, 8) + bounds: 128 120 8 8 + - image: solid-color(17, 15, 0, 255, 8, 8) + bounds: 136 120 8 8 + - image: solid-color(18, 15, 0, 255, 8, 8) + bounds: 144 120 8 8 + - image: solid-color(19, 15, 0, 255, 8, 8) + bounds: 152 120 8 8 + - image: solid-color(20, 15, 0, 255, 8, 8) + bounds: 160 120 8 8 + - image: solid-color(21, 15, 0, 255, 8, 8) + bounds: 168 120 8 8 + - image: solid-color(22, 15, 0, 255, 8, 8) + bounds: 176 120 8 8 + - image: solid-color(23, 15, 0, 255, 8, 8) + bounds: 184 120 8 8 + - image: solid-color(24, 15, 0, 255, 8, 8) + bounds: 192 120 8 8 + - image: solid-color(25, 15, 0, 255, 8, 8) + bounds: 200 120 8 8 + - image: solid-color(26, 15, 0, 255, 8, 8) + bounds: 208 120 8 8 + - image: solid-color(27, 15, 0, 255, 8, 8) + bounds: 216 120 8 8 + - image: solid-color(28, 15, 0, 255, 8, 8) + bounds: 224 120 8 8 + - image: solid-color(29, 15, 0, 255, 8, 8) + bounds: 232 120 8 8 + - image: solid-color(30, 15, 0, 255, 8, 8) + bounds: 240 120 8 8 + - image: solid-color(31, 15, 0, 255, 8, 8) + bounds: 248 120 8 8 + - image: solid-color(32, 15, 0, 255, 8, 8) + bounds: 256 120 8 8 + - image: solid-color(33, 15, 0, 255, 8, 8) + bounds: 264 120 8 8 + - image: solid-color(34, 15, 0, 255, 8, 8) + bounds: 272 120 8 8 + - image: solid-color(35, 15, 0, 255, 8, 8) + bounds: 280 120 8 8 + - image: solid-color(36, 15, 0, 255, 8, 8) + bounds: 288 120 8 8 + - image: solid-color(37, 15, 0, 255, 8, 8) + bounds: 296 120 8 8 + - image: solid-color(38, 15, 0, 255, 8, 8) + bounds: 304 120 8 8 + - image: solid-color(39, 15, 0, 255, 8, 8) + bounds: 312 120 8 8 + - image: solid-color(40, 15, 0, 255, 8, 8) + bounds: 320 120 8 8 + - image: solid-color(41, 15, 0, 255, 8, 8) + bounds: 328 120 8 8 + - image: solid-color(42, 15, 0, 255, 8, 8) + bounds: 336 120 8 8 + - image: solid-color(43, 15, 0, 255, 8, 8) + bounds: 344 120 8 8 + - image: solid-color(44, 15, 0, 255, 8, 8) + bounds: 352 120 8 8 + - image: solid-color(45, 15, 0, 255, 8, 8) + bounds: 360 120 8 8 + - image: solid-color(46, 15, 0, 255, 8, 8) + bounds: 368 120 8 8 + - image: solid-color(47, 15, 0, 255, 8, 8) + bounds: 376 120 8 8 + - image: solid-color(48, 15, 0, 255, 8, 8) + bounds: 384 120 8 8 + - image: solid-color(49, 15, 0, 255, 8, 8) + bounds: 392 120 8 8 + - image: solid-color(50, 15, 0, 255, 8, 8) + bounds: 400 120 8 8 + - image: solid-color(51, 15, 0, 255, 8, 8) + bounds: 408 120 8 8 + - image: solid-color(52, 15, 0, 255, 8, 8) + bounds: 416 120 8 8 + - image: solid-color(53, 15, 0, 255, 8, 8) + bounds: 424 120 8 8 + - image: solid-color(54, 15, 0, 255, 8, 8) + bounds: 432 120 8 8 + - image: solid-color(55, 15, 0, 255, 8, 8) + bounds: 440 120 8 8 + - image: solid-color(56, 15, 0, 255, 8, 8) + bounds: 448 120 8 8 + - image: solid-color(57, 15, 0, 255, 8, 8) + bounds: 456 120 8 8 + - image: solid-color(58, 15, 0, 255, 8, 8) + bounds: 464 120 8 8 + - image: solid-color(59, 15, 0, 255, 8, 8) + bounds: 472 120 8 8 + - image: solid-color(60, 15, 0, 255, 8, 8) + bounds: 480 120 8 8 + - image: solid-color(61, 15, 0, 255, 8, 8) + bounds: 488 120 8 8 + - image: solid-color(62, 15, 0, 255, 8, 8) + bounds: 496 120 8 8 + - image: solid-color(63, 15, 0, 255, 8, 8) + bounds: 504 120 8 8 + - image: solid-color(64, 15, 0, 255, 8, 8) + bounds: 512 120 8 8 + - image: solid-color(65, 15, 0, 255, 8, 8) + bounds: 520 120 8 8 + - image: solid-color(66, 15, 0, 255, 8, 8) + bounds: 528 120 8 8 + - image: solid-color(67, 15, 0, 255, 8, 8) + bounds: 536 120 8 8 + - image: solid-color(68, 15, 0, 255, 8, 8) + bounds: 544 120 8 8 + - image: solid-color(69, 15, 0, 255, 8, 8) + bounds: 552 120 8 8 + - image: solid-color(70, 15, 0, 255, 8, 8) + bounds: 560 120 8 8 + - image: solid-color(71, 15, 0, 255, 8, 8) + bounds: 568 120 8 8 + - image: solid-color(72, 15, 0, 255, 8, 8) + bounds: 576 120 8 8 + - image: solid-color(73, 15, 0, 255, 8, 8) + bounds: 584 120 8 8 + - image: solid-color(74, 15, 0, 255, 8, 8) + bounds: 592 120 8 8 + - image: solid-color(75, 15, 0, 255, 8, 8) + bounds: 600 120 8 8 + - image: solid-color(76, 15, 0, 255, 8, 8) + bounds: 608 120 8 8 + - image: solid-color(77, 15, 0, 255, 8, 8) + bounds: 616 120 8 8 + - image: solid-color(78, 15, 0, 255, 8, 8) + bounds: 624 120 8 8 + - image: solid-color(79, 15, 0, 255, 8, 8) + bounds: 632 120 8 8 + - image: solid-color(80, 15, 0, 255, 8, 8) + bounds: 640 120 8 8 + - image: solid-color(81, 15, 0, 255, 8, 8) + bounds: 648 120 8 8 + - image: solid-color(82, 15, 0, 255, 8, 8) + bounds: 656 120 8 8 + - image: solid-color(83, 15, 0, 255, 8, 8) + bounds: 664 120 8 8 + - image: solid-color(84, 15, 0, 255, 8, 8) + bounds: 672 120 8 8 + - image: solid-color(85, 15, 0, 255, 8, 8) + bounds: 680 120 8 8 + - image: solid-color(86, 15, 0, 255, 8, 8) + bounds: 688 120 8 8 + - image: solid-color(87, 15, 0, 255, 8, 8) + bounds: 696 120 8 8 + - image: solid-color(88, 15, 0, 255, 8, 8) + bounds: 704 120 8 8 + - image: solid-color(89, 15, 0, 255, 8, 8) + bounds: 712 120 8 8 + - image: solid-color(90, 15, 0, 255, 8, 8) + bounds: 720 120 8 8 + - image: solid-color(91, 15, 0, 255, 8, 8) + bounds: 728 120 8 8 + - image: solid-color(92, 15, 0, 255, 8, 8) + bounds: 736 120 8 8 + - image: solid-color(93, 15, 0, 255, 8, 8) + bounds: 744 120 8 8 + - image: solid-color(94, 15, 0, 255, 8, 8) + bounds: 752 120 8 8 + - image: solid-color(95, 15, 0, 255, 8, 8) + bounds: 760 120 8 8 + - image: solid-color(96, 15, 0, 255, 8, 8) + bounds: 768 120 8 8 + - image: solid-color(97, 15, 0, 255, 8, 8) + bounds: 776 120 8 8 + - image: solid-color(98, 15, 0, 255, 8, 8) + bounds: 784 120 8 8 + - image: solid-color(99, 15, 0, 255, 8, 8) + bounds: 792 120 8 8 + - image: solid-color(100, 15, 0, 255, 8, 8) + bounds: 800 120 8 8 + - image: solid-color(101, 15, 0, 255, 8, 8) + bounds: 808 120 8 8 + - image: solid-color(102, 15, 0, 255, 8, 8) + bounds: 816 120 8 8 + - image: solid-color(103, 15, 0, 255, 8, 8) + bounds: 824 120 8 8 + - image: solid-color(104, 15, 0, 255, 8, 8) + bounds: 832 120 8 8 + - image: solid-color(105, 15, 0, 255, 8, 8) + bounds: 840 120 8 8 + - image: solid-color(106, 15, 0, 255, 8, 8) + bounds: 848 120 8 8 + - image: solid-color(107, 15, 0, 255, 8, 8) + bounds: 856 120 8 8 + - image: solid-color(108, 15, 0, 255, 8, 8) + bounds: 864 120 8 8 + - image: solid-color(109, 15, 0, 255, 8, 8) + bounds: 872 120 8 8 + - image: solid-color(110, 15, 0, 255, 8, 8) + bounds: 880 120 8 8 + - image: solid-color(111, 15, 0, 255, 8, 8) + bounds: 888 120 8 8 + - image: solid-color(112, 15, 0, 255, 8, 8) + bounds: 896 120 8 8 + - image: solid-color(113, 15, 0, 255, 8, 8) + bounds: 904 120 8 8 + - image: solid-color(114, 15, 0, 255, 8, 8) + bounds: 912 120 8 8 + - image: solid-color(115, 15, 0, 255, 8, 8) + bounds: 920 120 8 8 + - image: solid-color(116, 15, 0, 255, 8, 8) + bounds: 928 120 8 8 + - image: solid-color(117, 15, 0, 255, 8, 8) + bounds: 936 120 8 8 + - image: solid-color(118, 15, 0, 255, 8, 8) + bounds: 944 120 8 8 + - image: solid-color(119, 15, 0, 255, 8, 8) + bounds: 952 120 8 8 + - image: solid-color(120, 15, 0, 255, 8, 8) + bounds: 960 120 8 8 + - image: solid-color(121, 15, 0, 255, 8, 8) + bounds: 968 120 8 8 + - image: solid-color(122, 15, 0, 255, 8, 8) + bounds: 976 120 8 8 + - image: solid-color(123, 15, 0, 255, 8, 8) + bounds: 984 120 8 8 + - image: solid-color(124, 15, 0, 255, 8, 8) + bounds: 992 120 8 8 + - image: solid-color(125, 15, 0, 255, 8, 8) + bounds: 1000 120 8 8 + - image: solid-color(126, 15, 0, 255, 8, 8) + bounds: 1008 120 8 8 + - image: solid-color(127, 15, 0, 255, 8, 8) + bounds: 1016 120 8 8 + - image: solid-color(0, 16, 0, 255, 8, 8) + bounds: 0 128 8 8 + - image: solid-color(1, 16, 0, 255, 8, 8) + bounds: 8 128 8 8 + - image: solid-color(2, 16, 0, 255, 8, 8) + bounds: 16 128 8 8 + - image: solid-color(3, 16, 0, 255, 8, 8) + bounds: 24 128 8 8 + - image: solid-color(4, 16, 0, 255, 8, 8) + bounds: 32 128 8 8 + - image: solid-color(5, 16, 0, 255, 8, 8) + bounds: 40 128 8 8 + - image: solid-color(6, 16, 0, 255, 8, 8) + bounds: 48 128 8 8 + - image: solid-color(7, 16, 0, 255, 8, 8) + bounds: 56 128 8 8 + - image: solid-color(8, 16, 0, 255, 8, 8) + bounds: 64 128 8 8 + - image: solid-color(9, 16, 0, 255, 8, 8) + bounds: 72 128 8 8 + - image: solid-color(10, 16, 0, 255, 8, 8) + bounds: 80 128 8 8 + - image: solid-color(11, 16, 0, 255, 8, 8) + bounds: 88 128 8 8 + - image: solid-color(12, 16, 0, 255, 8, 8) + bounds: 96 128 8 8 + - image: solid-color(13, 16, 0, 255, 8, 8) + bounds: 104 128 8 8 + - image: solid-color(14, 16, 0, 255, 8, 8) + bounds: 112 128 8 8 + - image: solid-color(15, 16, 0, 255, 8, 8) + bounds: 120 128 8 8 + - image: solid-color(16, 16, 0, 255, 8, 8) + bounds: 128 128 8 8 + - image: solid-color(17, 16, 0, 255, 8, 8) + bounds: 136 128 8 8 + - image: solid-color(18, 16, 0, 255, 8, 8) + bounds: 144 128 8 8 + - image: solid-color(19, 16, 0, 255, 8, 8) + bounds: 152 128 8 8 + - image: solid-color(20, 16, 0, 255, 8, 8) + bounds: 160 128 8 8 + - image: solid-color(21, 16, 0, 255, 8, 8) + bounds: 168 128 8 8 + - image: solid-color(22, 16, 0, 255, 8, 8) + bounds: 176 128 8 8 + - image: solid-color(23, 16, 0, 255, 8, 8) + bounds: 184 128 8 8 + - image: solid-color(24, 16, 0, 255, 8, 8) + bounds: 192 128 8 8 + - image: solid-color(25, 16, 0, 255, 8, 8) + bounds: 200 128 8 8 + - image: solid-color(26, 16, 0, 255, 8, 8) + bounds: 208 128 8 8 + - image: solid-color(27, 16, 0, 255, 8, 8) + bounds: 216 128 8 8 + - image: solid-color(28, 16, 0, 255, 8, 8) + bounds: 224 128 8 8 + - image: solid-color(29, 16, 0, 255, 8, 8) + bounds: 232 128 8 8 + - image: solid-color(30, 16, 0, 255, 8, 8) + bounds: 240 128 8 8 + - image: solid-color(31, 16, 0, 255, 8, 8) + bounds: 248 128 8 8 + - image: solid-color(32, 16, 0, 255, 8, 8) + bounds: 256 128 8 8 + - image: solid-color(33, 16, 0, 255, 8, 8) + bounds: 264 128 8 8 + - image: solid-color(34, 16, 0, 255, 8, 8) + bounds: 272 128 8 8 + - image: solid-color(35, 16, 0, 255, 8, 8) + bounds: 280 128 8 8 + - image: solid-color(36, 16, 0, 255, 8, 8) + bounds: 288 128 8 8 + - image: solid-color(37, 16, 0, 255, 8, 8) + bounds: 296 128 8 8 + - image: solid-color(38, 16, 0, 255, 8, 8) + bounds: 304 128 8 8 + - image: solid-color(39, 16, 0, 255, 8, 8) + bounds: 312 128 8 8 + - image: solid-color(40, 16, 0, 255, 8, 8) + bounds: 320 128 8 8 + - image: solid-color(41, 16, 0, 255, 8, 8) + bounds: 328 128 8 8 + - image: solid-color(42, 16, 0, 255, 8, 8) + bounds: 336 128 8 8 + - image: solid-color(43, 16, 0, 255, 8, 8) + bounds: 344 128 8 8 + - image: solid-color(44, 16, 0, 255, 8, 8) + bounds: 352 128 8 8 + - image: solid-color(45, 16, 0, 255, 8, 8) + bounds: 360 128 8 8 + - image: solid-color(46, 16, 0, 255, 8, 8) + bounds: 368 128 8 8 + - image: solid-color(47, 16, 0, 255, 8, 8) + bounds: 376 128 8 8 + - image: solid-color(48, 16, 0, 255, 8, 8) + bounds: 384 128 8 8 + - image: solid-color(49, 16, 0, 255, 8, 8) + bounds: 392 128 8 8 + - image: solid-color(50, 16, 0, 255, 8, 8) + bounds: 400 128 8 8 + - image: solid-color(51, 16, 0, 255, 8, 8) + bounds: 408 128 8 8 + - image: solid-color(52, 16, 0, 255, 8, 8) + bounds: 416 128 8 8 + - image: solid-color(53, 16, 0, 255, 8, 8) + bounds: 424 128 8 8 + - image: solid-color(54, 16, 0, 255, 8, 8) + bounds: 432 128 8 8 + - image: solid-color(55, 16, 0, 255, 8, 8) + bounds: 440 128 8 8 + - image: solid-color(56, 16, 0, 255, 8, 8) + bounds: 448 128 8 8 + - image: solid-color(57, 16, 0, 255, 8, 8) + bounds: 456 128 8 8 + - image: solid-color(58, 16, 0, 255, 8, 8) + bounds: 464 128 8 8 + - image: solid-color(59, 16, 0, 255, 8, 8) + bounds: 472 128 8 8 + - image: solid-color(60, 16, 0, 255, 8, 8) + bounds: 480 128 8 8 + - image: solid-color(61, 16, 0, 255, 8, 8) + bounds: 488 128 8 8 + - image: solid-color(62, 16, 0, 255, 8, 8) + bounds: 496 128 8 8 + - image: solid-color(63, 16, 0, 255, 8, 8) + bounds: 504 128 8 8 + - image: solid-color(64, 16, 0, 255, 8, 8) + bounds: 512 128 8 8 + - image: solid-color(65, 16, 0, 255, 8, 8) + bounds: 520 128 8 8 + - image: solid-color(66, 16, 0, 255, 8, 8) + bounds: 528 128 8 8 + - image: solid-color(67, 16, 0, 255, 8, 8) + bounds: 536 128 8 8 + - image: solid-color(68, 16, 0, 255, 8, 8) + bounds: 544 128 8 8 + - image: solid-color(69, 16, 0, 255, 8, 8) + bounds: 552 128 8 8 + - image: solid-color(70, 16, 0, 255, 8, 8) + bounds: 560 128 8 8 + - image: solid-color(71, 16, 0, 255, 8, 8) + bounds: 568 128 8 8 + - image: solid-color(72, 16, 0, 255, 8, 8) + bounds: 576 128 8 8 + - image: solid-color(73, 16, 0, 255, 8, 8) + bounds: 584 128 8 8 + - image: solid-color(74, 16, 0, 255, 8, 8) + bounds: 592 128 8 8 + - image: solid-color(75, 16, 0, 255, 8, 8) + bounds: 600 128 8 8 + - image: solid-color(76, 16, 0, 255, 8, 8) + bounds: 608 128 8 8 + - image: solid-color(77, 16, 0, 255, 8, 8) + bounds: 616 128 8 8 + - image: solid-color(78, 16, 0, 255, 8, 8) + bounds: 624 128 8 8 + - image: solid-color(79, 16, 0, 255, 8, 8) + bounds: 632 128 8 8 + - image: solid-color(80, 16, 0, 255, 8, 8) + bounds: 640 128 8 8 + - image: solid-color(81, 16, 0, 255, 8, 8) + bounds: 648 128 8 8 + - image: solid-color(82, 16, 0, 255, 8, 8) + bounds: 656 128 8 8 + - image: solid-color(83, 16, 0, 255, 8, 8) + bounds: 664 128 8 8 + - image: solid-color(84, 16, 0, 255, 8, 8) + bounds: 672 128 8 8 + - image: solid-color(85, 16, 0, 255, 8, 8) + bounds: 680 128 8 8 + - image: solid-color(86, 16, 0, 255, 8, 8) + bounds: 688 128 8 8 + - image: solid-color(87, 16, 0, 255, 8, 8) + bounds: 696 128 8 8 + - image: solid-color(88, 16, 0, 255, 8, 8) + bounds: 704 128 8 8 + - image: solid-color(89, 16, 0, 255, 8, 8) + bounds: 712 128 8 8 + - image: solid-color(90, 16, 0, 255, 8, 8) + bounds: 720 128 8 8 + - image: solid-color(91, 16, 0, 255, 8, 8) + bounds: 728 128 8 8 + - image: solid-color(92, 16, 0, 255, 8, 8) + bounds: 736 128 8 8 + - image: solid-color(93, 16, 0, 255, 8, 8) + bounds: 744 128 8 8 + - image: solid-color(94, 16, 0, 255, 8, 8) + bounds: 752 128 8 8 + - image: solid-color(95, 16, 0, 255, 8, 8) + bounds: 760 128 8 8 + - image: solid-color(96, 16, 0, 255, 8, 8) + bounds: 768 128 8 8 + - image: solid-color(97, 16, 0, 255, 8, 8) + bounds: 776 128 8 8 + - image: solid-color(98, 16, 0, 255, 8, 8) + bounds: 784 128 8 8 + - image: solid-color(99, 16, 0, 255, 8, 8) + bounds: 792 128 8 8 + - image: solid-color(100, 16, 0, 255, 8, 8) + bounds: 800 128 8 8 + - image: solid-color(101, 16, 0, 255, 8, 8) + bounds: 808 128 8 8 + - image: solid-color(102, 16, 0, 255, 8, 8) + bounds: 816 128 8 8 + - image: solid-color(103, 16, 0, 255, 8, 8) + bounds: 824 128 8 8 + - image: solid-color(104, 16, 0, 255, 8, 8) + bounds: 832 128 8 8 + - image: solid-color(105, 16, 0, 255, 8, 8) + bounds: 840 128 8 8 + - image: solid-color(106, 16, 0, 255, 8, 8) + bounds: 848 128 8 8 + - image: solid-color(107, 16, 0, 255, 8, 8) + bounds: 856 128 8 8 + - image: solid-color(108, 16, 0, 255, 8, 8) + bounds: 864 128 8 8 + - image: solid-color(109, 16, 0, 255, 8, 8) + bounds: 872 128 8 8 + - image: solid-color(110, 16, 0, 255, 8, 8) + bounds: 880 128 8 8 + - image: solid-color(111, 16, 0, 255, 8, 8) + bounds: 888 128 8 8 + - image: solid-color(112, 16, 0, 255, 8, 8) + bounds: 896 128 8 8 + - image: solid-color(113, 16, 0, 255, 8, 8) + bounds: 904 128 8 8 + - image: solid-color(114, 16, 0, 255, 8, 8) + bounds: 912 128 8 8 + - image: solid-color(115, 16, 0, 255, 8, 8) + bounds: 920 128 8 8 + - image: solid-color(116, 16, 0, 255, 8, 8) + bounds: 928 128 8 8 + - image: solid-color(117, 16, 0, 255, 8, 8) + bounds: 936 128 8 8 + - image: solid-color(118, 16, 0, 255, 8, 8) + bounds: 944 128 8 8 + - image: solid-color(119, 16, 0, 255, 8, 8) + bounds: 952 128 8 8 + - image: solid-color(120, 16, 0, 255, 8, 8) + bounds: 960 128 8 8 + - image: solid-color(121, 16, 0, 255, 8, 8) + bounds: 968 128 8 8 + - image: solid-color(122, 16, 0, 255, 8, 8) + bounds: 976 128 8 8 + - image: solid-color(123, 16, 0, 255, 8, 8) + bounds: 984 128 8 8 + - image: solid-color(124, 16, 0, 255, 8, 8) + bounds: 992 128 8 8 + - image: solid-color(125, 16, 0, 255, 8, 8) + bounds: 1000 128 8 8 + - image: solid-color(126, 16, 0, 255, 8, 8) + bounds: 1008 128 8 8 + - image: solid-color(127, 16, 0, 255, 8, 8) + bounds: 1016 128 8 8 + - image: solid-color(0, 17, 0, 255, 8, 8) + bounds: 0 136 8 8 + - image: solid-color(1, 17, 0, 255, 8, 8) + bounds: 8 136 8 8 + - image: solid-color(2, 17, 0, 255, 8, 8) + bounds: 16 136 8 8 + - image: solid-color(3, 17, 0, 255, 8, 8) + bounds: 24 136 8 8 + - image: solid-color(4, 17, 0, 255, 8, 8) + bounds: 32 136 8 8 + - image: solid-color(5, 17, 0, 255, 8, 8) + bounds: 40 136 8 8 + - image: solid-color(6, 17, 0, 255, 8, 8) + bounds: 48 136 8 8 + - image: solid-color(7, 17, 0, 255, 8, 8) + bounds: 56 136 8 8 + - image: solid-color(8, 17, 0, 255, 8, 8) + bounds: 64 136 8 8 + - image: solid-color(9, 17, 0, 255, 8, 8) + bounds: 72 136 8 8 + - image: solid-color(10, 17, 0, 255, 8, 8) + bounds: 80 136 8 8 + - image: solid-color(11, 17, 0, 255, 8, 8) + bounds: 88 136 8 8 + - image: solid-color(12, 17, 0, 255, 8, 8) + bounds: 96 136 8 8 + - image: solid-color(13, 17, 0, 255, 8, 8) + bounds: 104 136 8 8 + - image: solid-color(14, 17, 0, 255, 8, 8) + bounds: 112 136 8 8 + - image: solid-color(15, 17, 0, 255, 8, 8) + bounds: 120 136 8 8 + - image: solid-color(16, 17, 0, 255, 8, 8) + bounds: 128 136 8 8 + - image: solid-color(17, 17, 0, 255, 8, 8) + bounds: 136 136 8 8 + - image: solid-color(18, 17, 0, 255, 8, 8) + bounds: 144 136 8 8 + - image: solid-color(19, 17, 0, 255, 8, 8) + bounds: 152 136 8 8 + - image: solid-color(20, 17, 0, 255, 8, 8) + bounds: 160 136 8 8 + - image: solid-color(21, 17, 0, 255, 8, 8) + bounds: 168 136 8 8 + - image: solid-color(22, 17, 0, 255, 8, 8) + bounds: 176 136 8 8 + - image: solid-color(23, 17, 0, 255, 8, 8) + bounds: 184 136 8 8 + - image: solid-color(24, 17, 0, 255, 8, 8) + bounds: 192 136 8 8 + - image: solid-color(25, 17, 0, 255, 8, 8) + bounds: 200 136 8 8 + - image: solid-color(26, 17, 0, 255, 8, 8) + bounds: 208 136 8 8 + - image: solid-color(27, 17, 0, 255, 8, 8) + bounds: 216 136 8 8 + - image: solid-color(28, 17, 0, 255, 8, 8) + bounds: 224 136 8 8 + - image: solid-color(29, 17, 0, 255, 8, 8) + bounds: 232 136 8 8 + - image: solid-color(30, 17, 0, 255, 8, 8) + bounds: 240 136 8 8 + - image: solid-color(31, 17, 0, 255, 8, 8) + bounds: 248 136 8 8 + - image: solid-color(32, 17, 0, 255, 8, 8) + bounds: 256 136 8 8 + - image: solid-color(33, 17, 0, 255, 8, 8) + bounds: 264 136 8 8 + - image: solid-color(34, 17, 0, 255, 8, 8) + bounds: 272 136 8 8 + - image: solid-color(35, 17, 0, 255, 8, 8) + bounds: 280 136 8 8 + - image: solid-color(36, 17, 0, 255, 8, 8) + bounds: 288 136 8 8 + - image: solid-color(37, 17, 0, 255, 8, 8) + bounds: 296 136 8 8 + - image: solid-color(38, 17, 0, 255, 8, 8) + bounds: 304 136 8 8 + - image: solid-color(39, 17, 0, 255, 8, 8) + bounds: 312 136 8 8 + - image: solid-color(40, 17, 0, 255, 8, 8) + bounds: 320 136 8 8 + - image: solid-color(41, 17, 0, 255, 8, 8) + bounds: 328 136 8 8 + - image: solid-color(42, 17, 0, 255, 8, 8) + bounds: 336 136 8 8 + - image: solid-color(43, 17, 0, 255, 8, 8) + bounds: 344 136 8 8 + - image: solid-color(44, 17, 0, 255, 8, 8) + bounds: 352 136 8 8 + - image: solid-color(45, 17, 0, 255, 8, 8) + bounds: 360 136 8 8 + - image: solid-color(46, 17, 0, 255, 8, 8) + bounds: 368 136 8 8 + - image: solid-color(47, 17, 0, 255, 8, 8) + bounds: 376 136 8 8 + - image: solid-color(48, 17, 0, 255, 8, 8) + bounds: 384 136 8 8 + - image: solid-color(49, 17, 0, 255, 8, 8) + bounds: 392 136 8 8 + - image: solid-color(50, 17, 0, 255, 8, 8) + bounds: 400 136 8 8 + - image: solid-color(51, 17, 0, 255, 8, 8) + bounds: 408 136 8 8 + - image: solid-color(52, 17, 0, 255, 8, 8) + bounds: 416 136 8 8 + - image: solid-color(53, 17, 0, 255, 8, 8) + bounds: 424 136 8 8 + - image: solid-color(54, 17, 0, 255, 8, 8) + bounds: 432 136 8 8 + - image: solid-color(55, 17, 0, 255, 8, 8) + bounds: 440 136 8 8 + - image: solid-color(56, 17, 0, 255, 8, 8) + bounds: 448 136 8 8 + - image: solid-color(57, 17, 0, 255, 8, 8) + bounds: 456 136 8 8 + - image: solid-color(58, 17, 0, 255, 8, 8) + bounds: 464 136 8 8 + - image: solid-color(59, 17, 0, 255, 8, 8) + bounds: 472 136 8 8 + - image: solid-color(60, 17, 0, 255, 8, 8) + bounds: 480 136 8 8 + - image: solid-color(61, 17, 0, 255, 8, 8) + bounds: 488 136 8 8 + - image: solid-color(62, 17, 0, 255, 8, 8) + bounds: 496 136 8 8 + - image: solid-color(63, 17, 0, 255, 8, 8) + bounds: 504 136 8 8 + - image: solid-color(64, 17, 0, 255, 8, 8) + bounds: 512 136 8 8 + - image: solid-color(65, 17, 0, 255, 8, 8) + bounds: 520 136 8 8 + - image: solid-color(66, 17, 0, 255, 8, 8) + bounds: 528 136 8 8 + - image: solid-color(67, 17, 0, 255, 8, 8) + bounds: 536 136 8 8 + - image: solid-color(68, 17, 0, 255, 8, 8) + bounds: 544 136 8 8 + - image: solid-color(69, 17, 0, 255, 8, 8) + bounds: 552 136 8 8 + - image: solid-color(70, 17, 0, 255, 8, 8) + bounds: 560 136 8 8 + - image: solid-color(71, 17, 0, 255, 8, 8) + bounds: 568 136 8 8 + - image: solid-color(72, 17, 0, 255, 8, 8) + bounds: 576 136 8 8 + - image: solid-color(73, 17, 0, 255, 8, 8) + bounds: 584 136 8 8 + - image: solid-color(74, 17, 0, 255, 8, 8) + bounds: 592 136 8 8 + - image: solid-color(75, 17, 0, 255, 8, 8) + bounds: 600 136 8 8 + - image: solid-color(76, 17, 0, 255, 8, 8) + bounds: 608 136 8 8 + - image: solid-color(77, 17, 0, 255, 8, 8) + bounds: 616 136 8 8 + - image: solid-color(78, 17, 0, 255, 8, 8) + bounds: 624 136 8 8 + - image: solid-color(79, 17, 0, 255, 8, 8) + bounds: 632 136 8 8 + - image: solid-color(80, 17, 0, 255, 8, 8) + bounds: 640 136 8 8 + - image: solid-color(81, 17, 0, 255, 8, 8) + bounds: 648 136 8 8 + - image: solid-color(82, 17, 0, 255, 8, 8) + bounds: 656 136 8 8 + - image: solid-color(83, 17, 0, 255, 8, 8) + bounds: 664 136 8 8 + - image: solid-color(84, 17, 0, 255, 8, 8) + bounds: 672 136 8 8 + - image: solid-color(85, 17, 0, 255, 8, 8) + bounds: 680 136 8 8 + - image: solid-color(86, 17, 0, 255, 8, 8) + bounds: 688 136 8 8 + - image: solid-color(87, 17, 0, 255, 8, 8) + bounds: 696 136 8 8 + - image: solid-color(88, 17, 0, 255, 8, 8) + bounds: 704 136 8 8 + - image: solid-color(89, 17, 0, 255, 8, 8) + bounds: 712 136 8 8 + - image: solid-color(90, 17, 0, 255, 8, 8) + bounds: 720 136 8 8 + - image: solid-color(91, 17, 0, 255, 8, 8) + bounds: 728 136 8 8 + - image: solid-color(92, 17, 0, 255, 8, 8) + bounds: 736 136 8 8 + - image: solid-color(93, 17, 0, 255, 8, 8) + bounds: 744 136 8 8 + - image: solid-color(94, 17, 0, 255, 8, 8) + bounds: 752 136 8 8 + - image: solid-color(95, 17, 0, 255, 8, 8) + bounds: 760 136 8 8 + - image: solid-color(96, 17, 0, 255, 8, 8) + bounds: 768 136 8 8 + - image: solid-color(97, 17, 0, 255, 8, 8) + bounds: 776 136 8 8 + - image: solid-color(98, 17, 0, 255, 8, 8) + bounds: 784 136 8 8 + - image: solid-color(99, 17, 0, 255, 8, 8) + bounds: 792 136 8 8 + - image: solid-color(100, 17, 0, 255, 8, 8) + bounds: 800 136 8 8 + - image: solid-color(101, 17, 0, 255, 8, 8) + bounds: 808 136 8 8 + - image: solid-color(102, 17, 0, 255, 8, 8) + bounds: 816 136 8 8 + - image: solid-color(103, 17, 0, 255, 8, 8) + bounds: 824 136 8 8 + - image: solid-color(104, 17, 0, 255, 8, 8) + bounds: 832 136 8 8 + - image: solid-color(105, 17, 0, 255, 8, 8) + bounds: 840 136 8 8 + - image: solid-color(106, 17, 0, 255, 8, 8) + bounds: 848 136 8 8 + - image: solid-color(107, 17, 0, 255, 8, 8) + bounds: 856 136 8 8 + - image: solid-color(108, 17, 0, 255, 8, 8) + bounds: 864 136 8 8 + - image: solid-color(109, 17, 0, 255, 8, 8) + bounds: 872 136 8 8 + - image: solid-color(110, 17, 0, 255, 8, 8) + bounds: 880 136 8 8 + - image: solid-color(111, 17, 0, 255, 8, 8) + bounds: 888 136 8 8 + - image: solid-color(112, 17, 0, 255, 8, 8) + bounds: 896 136 8 8 + - image: solid-color(113, 17, 0, 255, 8, 8) + bounds: 904 136 8 8 + - image: solid-color(114, 17, 0, 255, 8, 8) + bounds: 912 136 8 8 + - image: solid-color(115, 17, 0, 255, 8, 8) + bounds: 920 136 8 8 + - image: solid-color(116, 17, 0, 255, 8, 8) + bounds: 928 136 8 8 + - image: solid-color(117, 17, 0, 255, 8, 8) + bounds: 936 136 8 8 + - image: solid-color(118, 17, 0, 255, 8, 8) + bounds: 944 136 8 8 + - image: solid-color(119, 17, 0, 255, 8, 8) + bounds: 952 136 8 8 + - image: solid-color(120, 17, 0, 255, 8, 8) + bounds: 960 136 8 8 + - image: solid-color(121, 17, 0, 255, 8, 8) + bounds: 968 136 8 8 + - image: solid-color(122, 17, 0, 255, 8, 8) + bounds: 976 136 8 8 + - image: solid-color(123, 17, 0, 255, 8, 8) + bounds: 984 136 8 8 + - image: solid-color(124, 17, 0, 255, 8, 8) + bounds: 992 136 8 8 + - image: solid-color(125, 17, 0, 255, 8, 8) + bounds: 1000 136 8 8 + - image: solid-color(126, 17, 0, 255, 8, 8) + bounds: 1008 136 8 8 + - image: solid-color(127, 17, 0, 255, 8, 8) + bounds: 1016 136 8 8 + - image: solid-color(0, 18, 0, 255, 8, 8) + bounds: 0 144 8 8 + - image: solid-color(1, 18, 0, 255, 8, 8) + bounds: 8 144 8 8 + - image: solid-color(2, 18, 0, 255, 8, 8) + bounds: 16 144 8 8 + - image: solid-color(3, 18, 0, 255, 8, 8) + bounds: 24 144 8 8 + - image: solid-color(4, 18, 0, 255, 8, 8) + bounds: 32 144 8 8 + - image: solid-color(5, 18, 0, 255, 8, 8) + bounds: 40 144 8 8 + - image: solid-color(6, 18, 0, 255, 8, 8) + bounds: 48 144 8 8 + - image: solid-color(7, 18, 0, 255, 8, 8) + bounds: 56 144 8 8 + - image: solid-color(8, 18, 0, 255, 8, 8) + bounds: 64 144 8 8 + - image: solid-color(9, 18, 0, 255, 8, 8) + bounds: 72 144 8 8 + - image: solid-color(10, 18, 0, 255, 8, 8) + bounds: 80 144 8 8 + - image: solid-color(11, 18, 0, 255, 8, 8) + bounds: 88 144 8 8 + - image: solid-color(12, 18, 0, 255, 8, 8) + bounds: 96 144 8 8 + - image: solid-color(13, 18, 0, 255, 8, 8) + bounds: 104 144 8 8 + - image: solid-color(14, 18, 0, 255, 8, 8) + bounds: 112 144 8 8 + - image: solid-color(15, 18, 0, 255, 8, 8) + bounds: 120 144 8 8 + - image: solid-color(16, 18, 0, 255, 8, 8) + bounds: 128 144 8 8 + - image: solid-color(17, 18, 0, 255, 8, 8) + bounds: 136 144 8 8 + - image: solid-color(18, 18, 0, 255, 8, 8) + bounds: 144 144 8 8 + - image: solid-color(19, 18, 0, 255, 8, 8) + bounds: 152 144 8 8 + - image: solid-color(20, 18, 0, 255, 8, 8) + bounds: 160 144 8 8 + - image: solid-color(21, 18, 0, 255, 8, 8) + bounds: 168 144 8 8 + - image: solid-color(22, 18, 0, 255, 8, 8) + bounds: 176 144 8 8 + - image: solid-color(23, 18, 0, 255, 8, 8) + bounds: 184 144 8 8 + - image: solid-color(24, 18, 0, 255, 8, 8) + bounds: 192 144 8 8 + - image: solid-color(25, 18, 0, 255, 8, 8) + bounds: 200 144 8 8 + - image: solid-color(26, 18, 0, 255, 8, 8) + bounds: 208 144 8 8 + - image: solid-color(27, 18, 0, 255, 8, 8) + bounds: 216 144 8 8 + - image: solid-color(28, 18, 0, 255, 8, 8) + bounds: 224 144 8 8 + - image: solid-color(29, 18, 0, 255, 8, 8) + bounds: 232 144 8 8 + - image: solid-color(30, 18, 0, 255, 8, 8) + bounds: 240 144 8 8 + - image: solid-color(31, 18, 0, 255, 8, 8) + bounds: 248 144 8 8 + - image: solid-color(32, 18, 0, 255, 8, 8) + bounds: 256 144 8 8 + - image: solid-color(33, 18, 0, 255, 8, 8) + bounds: 264 144 8 8 + - image: solid-color(34, 18, 0, 255, 8, 8) + bounds: 272 144 8 8 + - image: solid-color(35, 18, 0, 255, 8, 8) + bounds: 280 144 8 8 + - image: solid-color(36, 18, 0, 255, 8, 8) + bounds: 288 144 8 8 + - image: solid-color(37, 18, 0, 255, 8, 8) + bounds: 296 144 8 8 + - image: solid-color(38, 18, 0, 255, 8, 8) + bounds: 304 144 8 8 + - image: solid-color(39, 18, 0, 255, 8, 8) + bounds: 312 144 8 8 + - image: solid-color(40, 18, 0, 255, 8, 8) + bounds: 320 144 8 8 + - image: solid-color(41, 18, 0, 255, 8, 8) + bounds: 328 144 8 8 + - image: solid-color(42, 18, 0, 255, 8, 8) + bounds: 336 144 8 8 + - image: solid-color(43, 18, 0, 255, 8, 8) + bounds: 344 144 8 8 + - image: solid-color(44, 18, 0, 255, 8, 8) + bounds: 352 144 8 8 + - image: solid-color(45, 18, 0, 255, 8, 8) + bounds: 360 144 8 8 + - image: solid-color(46, 18, 0, 255, 8, 8) + bounds: 368 144 8 8 + - image: solid-color(47, 18, 0, 255, 8, 8) + bounds: 376 144 8 8 + - image: solid-color(48, 18, 0, 255, 8, 8) + bounds: 384 144 8 8 + - image: solid-color(49, 18, 0, 255, 8, 8) + bounds: 392 144 8 8 + - image: solid-color(50, 18, 0, 255, 8, 8) + bounds: 400 144 8 8 + - image: solid-color(51, 18, 0, 255, 8, 8) + bounds: 408 144 8 8 + - image: solid-color(52, 18, 0, 255, 8, 8) + bounds: 416 144 8 8 + - image: solid-color(53, 18, 0, 255, 8, 8) + bounds: 424 144 8 8 + - image: solid-color(54, 18, 0, 255, 8, 8) + bounds: 432 144 8 8 + - image: solid-color(55, 18, 0, 255, 8, 8) + bounds: 440 144 8 8 + - image: solid-color(56, 18, 0, 255, 8, 8) + bounds: 448 144 8 8 + - image: solid-color(57, 18, 0, 255, 8, 8) + bounds: 456 144 8 8 + - image: solid-color(58, 18, 0, 255, 8, 8) + bounds: 464 144 8 8 + - image: solid-color(59, 18, 0, 255, 8, 8) + bounds: 472 144 8 8 + - image: solid-color(60, 18, 0, 255, 8, 8) + bounds: 480 144 8 8 + - image: solid-color(61, 18, 0, 255, 8, 8) + bounds: 488 144 8 8 + - image: solid-color(62, 18, 0, 255, 8, 8) + bounds: 496 144 8 8 + - image: solid-color(63, 18, 0, 255, 8, 8) + bounds: 504 144 8 8 + - image: solid-color(64, 18, 0, 255, 8, 8) + bounds: 512 144 8 8 + - image: solid-color(65, 18, 0, 255, 8, 8) + bounds: 520 144 8 8 + - image: solid-color(66, 18, 0, 255, 8, 8) + bounds: 528 144 8 8 + - image: solid-color(67, 18, 0, 255, 8, 8) + bounds: 536 144 8 8 + - image: solid-color(68, 18, 0, 255, 8, 8) + bounds: 544 144 8 8 + - image: solid-color(69, 18, 0, 255, 8, 8) + bounds: 552 144 8 8 + - image: solid-color(70, 18, 0, 255, 8, 8) + bounds: 560 144 8 8 + - image: solid-color(71, 18, 0, 255, 8, 8) + bounds: 568 144 8 8 + - image: solid-color(72, 18, 0, 255, 8, 8) + bounds: 576 144 8 8 + - image: solid-color(73, 18, 0, 255, 8, 8) + bounds: 584 144 8 8 + - image: solid-color(74, 18, 0, 255, 8, 8) + bounds: 592 144 8 8 + - image: solid-color(75, 18, 0, 255, 8, 8) + bounds: 600 144 8 8 + - image: solid-color(76, 18, 0, 255, 8, 8) + bounds: 608 144 8 8 + - image: solid-color(77, 18, 0, 255, 8, 8) + bounds: 616 144 8 8 + - image: solid-color(78, 18, 0, 255, 8, 8) + bounds: 624 144 8 8 + - image: solid-color(79, 18, 0, 255, 8, 8) + bounds: 632 144 8 8 + - image: solid-color(80, 18, 0, 255, 8, 8) + bounds: 640 144 8 8 + - image: solid-color(81, 18, 0, 255, 8, 8) + bounds: 648 144 8 8 + - image: solid-color(82, 18, 0, 255, 8, 8) + bounds: 656 144 8 8 + - image: solid-color(83, 18, 0, 255, 8, 8) + bounds: 664 144 8 8 + - image: solid-color(84, 18, 0, 255, 8, 8) + bounds: 672 144 8 8 + - image: solid-color(85, 18, 0, 255, 8, 8) + bounds: 680 144 8 8 + - image: solid-color(86, 18, 0, 255, 8, 8) + bounds: 688 144 8 8 + - image: solid-color(87, 18, 0, 255, 8, 8) + bounds: 696 144 8 8 + - image: solid-color(88, 18, 0, 255, 8, 8) + bounds: 704 144 8 8 + - image: solid-color(89, 18, 0, 255, 8, 8) + bounds: 712 144 8 8 + - image: solid-color(90, 18, 0, 255, 8, 8) + bounds: 720 144 8 8 + - image: solid-color(91, 18, 0, 255, 8, 8) + bounds: 728 144 8 8 + - image: solid-color(92, 18, 0, 255, 8, 8) + bounds: 736 144 8 8 + - image: solid-color(93, 18, 0, 255, 8, 8) + bounds: 744 144 8 8 + - image: solid-color(94, 18, 0, 255, 8, 8) + bounds: 752 144 8 8 + - image: solid-color(95, 18, 0, 255, 8, 8) + bounds: 760 144 8 8 + - image: solid-color(96, 18, 0, 255, 8, 8) + bounds: 768 144 8 8 + - image: solid-color(97, 18, 0, 255, 8, 8) + bounds: 776 144 8 8 + - image: solid-color(98, 18, 0, 255, 8, 8) + bounds: 784 144 8 8 + - image: solid-color(99, 18, 0, 255, 8, 8) + bounds: 792 144 8 8 + - image: solid-color(100, 18, 0, 255, 8, 8) + bounds: 800 144 8 8 + - image: solid-color(101, 18, 0, 255, 8, 8) + bounds: 808 144 8 8 + - image: solid-color(102, 18, 0, 255, 8, 8) + bounds: 816 144 8 8 + - image: solid-color(103, 18, 0, 255, 8, 8) + bounds: 824 144 8 8 + - image: solid-color(104, 18, 0, 255, 8, 8) + bounds: 832 144 8 8 + - image: solid-color(105, 18, 0, 255, 8, 8) + bounds: 840 144 8 8 + - image: solid-color(106, 18, 0, 255, 8, 8) + bounds: 848 144 8 8 + - image: solid-color(107, 18, 0, 255, 8, 8) + bounds: 856 144 8 8 + - image: solid-color(108, 18, 0, 255, 8, 8) + bounds: 864 144 8 8 + - image: solid-color(109, 18, 0, 255, 8, 8) + bounds: 872 144 8 8 + - image: solid-color(110, 18, 0, 255, 8, 8) + bounds: 880 144 8 8 + - image: solid-color(111, 18, 0, 255, 8, 8) + bounds: 888 144 8 8 + - image: solid-color(112, 18, 0, 255, 8, 8) + bounds: 896 144 8 8 + - image: solid-color(113, 18, 0, 255, 8, 8) + bounds: 904 144 8 8 + - image: solid-color(114, 18, 0, 255, 8, 8) + bounds: 912 144 8 8 + - image: solid-color(115, 18, 0, 255, 8, 8) + bounds: 920 144 8 8 + - image: solid-color(116, 18, 0, 255, 8, 8) + bounds: 928 144 8 8 + - image: solid-color(117, 18, 0, 255, 8, 8) + bounds: 936 144 8 8 + - image: solid-color(118, 18, 0, 255, 8, 8) + bounds: 944 144 8 8 + - image: solid-color(119, 18, 0, 255, 8, 8) + bounds: 952 144 8 8 + - image: solid-color(120, 18, 0, 255, 8, 8) + bounds: 960 144 8 8 + - image: solid-color(121, 18, 0, 255, 8, 8) + bounds: 968 144 8 8 + - image: solid-color(122, 18, 0, 255, 8, 8) + bounds: 976 144 8 8 + - image: solid-color(123, 18, 0, 255, 8, 8) + bounds: 984 144 8 8 + - image: solid-color(124, 18, 0, 255, 8, 8) + bounds: 992 144 8 8 + - image: solid-color(125, 18, 0, 255, 8, 8) + bounds: 1000 144 8 8 + - image: solid-color(126, 18, 0, 255, 8, 8) + bounds: 1008 144 8 8 + - image: solid-color(127, 18, 0, 255, 8, 8) + bounds: 1016 144 8 8 + - image: solid-color(0, 19, 0, 255, 8, 8) + bounds: 0 152 8 8 + - image: solid-color(1, 19, 0, 255, 8, 8) + bounds: 8 152 8 8 + - image: solid-color(2, 19, 0, 255, 8, 8) + bounds: 16 152 8 8 + - image: solid-color(3, 19, 0, 255, 8, 8) + bounds: 24 152 8 8 + - image: solid-color(4, 19, 0, 255, 8, 8) + bounds: 32 152 8 8 + - image: solid-color(5, 19, 0, 255, 8, 8) + bounds: 40 152 8 8 + - image: solid-color(6, 19, 0, 255, 8, 8) + bounds: 48 152 8 8 + - image: solid-color(7, 19, 0, 255, 8, 8) + bounds: 56 152 8 8 + - image: solid-color(8, 19, 0, 255, 8, 8) + bounds: 64 152 8 8 + - image: solid-color(9, 19, 0, 255, 8, 8) + bounds: 72 152 8 8 + - image: solid-color(10, 19, 0, 255, 8, 8) + bounds: 80 152 8 8 + - image: solid-color(11, 19, 0, 255, 8, 8) + bounds: 88 152 8 8 + - image: solid-color(12, 19, 0, 255, 8, 8) + bounds: 96 152 8 8 + - image: solid-color(13, 19, 0, 255, 8, 8) + bounds: 104 152 8 8 + - image: solid-color(14, 19, 0, 255, 8, 8) + bounds: 112 152 8 8 + - image: solid-color(15, 19, 0, 255, 8, 8) + bounds: 120 152 8 8 + - image: solid-color(16, 19, 0, 255, 8, 8) + bounds: 128 152 8 8 + - image: solid-color(17, 19, 0, 255, 8, 8) + bounds: 136 152 8 8 + - image: solid-color(18, 19, 0, 255, 8, 8) + bounds: 144 152 8 8 + - image: solid-color(19, 19, 0, 255, 8, 8) + bounds: 152 152 8 8 + - image: solid-color(20, 19, 0, 255, 8, 8) + bounds: 160 152 8 8 + - image: solid-color(21, 19, 0, 255, 8, 8) + bounds: 168 152 8 8 + - image: solid-color(22, 19, 0, 255, 8, 8) + bounds: 176 152 8 8 + - image: solid-color(23, 19, 0, 255, 8, 8) + bounds: 184 152 8 8 + - image: solid-color(24, 19, 0, 255, 8, 8) + bounds: 192 152 8 8 + - image: solid-color(25, 19, 0, 255, 8, 8) + bounds: 200 152 8 8 + - image: solid-color(26, 19, 0, 255, 8, 8) + bounds: 208 152 8 8 + - image: solid-color(27, 19, 0, 255, 8, 8) + bounds: 216 152 8 8 + - image: solid-color(28, 19, 0, 255, 8, 8) + bounds: 224 152 8 8 + - image: solid-color(29, 19, 0, 255, 8, 8) + bounds: 232 152 8 8 + - image: solid-color(30, 19, 0, 255, 8, 8) + bounds: 240 152 8 8 + - image: solid-color(31, 19, 0, 255, 8, 8) + bounds: 248 152 8 8 + - image: solid-color(32, 19, 0, 255, 8, 8) + bounds: 256 152 8 8 + - image: solid-color(33, 19, 0, 255, 8, 8) + bounds: 264 152 8 8 + - image: solid-color(34, 19, 0, 255, 8, 8) + bounds: 272 152 8 8 + - image: solid-color(35, 19, 0, 255, 8, 8) + bounds: 280 152 8 8 + - image: solid-color(36, 19, 0, 255, 8, 8) + bounds: 288 152 8 8 + - image: solid-color(37, 19, 0, 255, 8, 8) + bounds: 296 152 8 8 + - image: solid-color(38, 19, 0, 255, 8, 8) + bounds: 304 152 8 8 + - image: solid-color(39, 19, 0, 255, 8, 8) + bounds: 312 152 8 8 + - image: solid-color(40, 19, 0, 255, 8, 8) + bounds: 320 152 8 8 + - image: solid-color(41, 19, 0, 255, 8, 8) + bounds: 328 152 8 8 + - image: solid-color(42, 19, 0, 255, 8, 8) + bounds: 336 152 8 8 + - image: solid-color(43, 19, 0, 255, 8, 8) + bounds: 344 152 8 8 + - image: solid-color(44, 19, 0, 255, 8, 8) + bounds: 352 152 8 8 + - image: solid-color(45, 19, 0, 255, 8, 8) + bounds: 360 152 8 8 + - image: solid-color(46, 19, 0, 255, 8, 8) + bounds: 368 152 8 8 + - image: solid-color(47, 19, 0, 255, 8, 8) + bounds: 376 152 8 8 + - image: solid-color(48, 19, 0, 255, 8, 8) + bounds: 384 152 8 8 + - image: solid-color(49, 19, 0, 255, 8, 8) + bounds: 392 152 8 8 + - image: solid-color(50, 19, 0, 255, 8, 8) + bounds: 400 152 8 8 + - image: solid-color(51, 19, 0, 255, 8, 8) + bounds: 408 152 8 8 + - image: solid-color(52, 19, 0, 255, 8, 8) + bounds: 416 152 8 8 + - image: solid-color(53, 19, 0, 255, 8, 8) + bounds: 424 152 8 8 + - image: solid-color(54, 19, 0, 255, 8, 8) + bounds: 432 152 8 8 + - image: solid-color(55, 19, 0, 255, 8, 8) + bounds: 440 152 8 8 + - image: solid-color(56, 19, 0, 255, 8, 8) + bounds: 448 152 8 8 + - image: solid-color(57, 19, 0, 255, 8, 8) + bounds: 456 152 8 8 + - image: solid-color(58, 19, 0, 255, 8, 8) + bounds: 464 152 8 8 + - image: solid-color(59, 19, 0, 255, 8, 8) + bounds: 472 152 8 8 + - image: solid-color(60, 19, 0, 255, 8, 8) + bounds: 480 152 8 8 + - image: solid-color(61, 19, 0, 255, 8, 8) + bounds: 488 152 8 8 + - image: solid-color(62, 19, 0, 255, 8, 8) + bounds: 496 152 8 8 + - image: solid-color(63, 19, 0, 255, 8, 8) + bounds: 504 152 8 8 + - image: solid-color(64, 19, 0, 255, 8, 8) + bounds: 512 152 8 8 + - image: solid-color(65, 19, 0, 255, 8, 8) + bounds: 520 152 8 8 + - image: solid-color(66, 19, 0, 255, 8, 8) + bounds: 528 152 8 8 + - image: solid-color(67, 19, 0, 255, 8, 8) + bounds: 536 152 8 8 + - image: solid-color(68, 19, 0, 255, 8, 8) + bounds: 544 152 8 8 + - image: solid-color(69, 19, 0, 255, 8, 8) + bounds: 552 152 8 8 + - image: solid-color(70, 19, 0, 255, 8, 8) + bounds: 560 152 8 8 + - image: solid-color(71, 19, 0, 255, 8, 8) + bounds: 568 152 8 8 + - image: solid-color(72, 19, 0, 255, 8, 8) + bounds: 576 152 8 8 + - image: solid-color(73, 19, 0, 255, 8, 8) + bounds: 584 152 8 8 + - image: solid-color(74, 19, 0, 255, 8, 8) + bounds: 592 152 8 8 + - image: solid-color(75, 19, 0, 255, 8, 8) + bounds: 600 152 8 8 + - image: solid-color(76, 19, 0, 255, 8, 8) + bounds: 608 152 8 8 + - image: solid-color(77, 19, 0, 255, 8, 8) + bounds: 616 152 8 8 + - image: solid-color(78, 19, 0, 255, 8, 8) + bounds: 624 152 8 8 + - image: solid-color(79, 19, 0, 255, 8, 8) + bounds: 632 152 8 8 + - image: solid-color(80, 19, 0, 255, 8, 8) + bounds: 640 152 8 8 + - image: solid-color(81, 19, 0, 255, 8, 8) + bounds: 648 152 8 8 + - image: solid-color(82, 19, 0, 255, 8, 8) + bounds: 656 152 8 8 + - image: solid-color(83, 19, 0, 255, 8, 8) + bounds: 664 152 8 8 + - image: solid-color(84, 19, 0, 255, 8, 8) + bounds: 672 152 8 8 + - image: solid-color(85, 19, 0, 255, 8, 8) + bounds: 680 152 8 8 + - image: solid-color(86, 19, 0, 255, 8, 8) + bounds: 688 152 8 8 + - image: solid-color(87, 19, 0, 255, 8, 8) + bounds: 696 152 8 8 + - image: solid-color(88, 19, 0, 255, 8, 8) + bounds: 704 152 8 8 + - image: solid-color(89, 19, 0, 255, 8, 8) + bounds: 712 152 8 8 + - image: solid-color(90, 19, 0, 255, 8, 8) + bounds: 720 152 8 8 + - image: solid-color(91, 19, 0, 255, 8, 8) + bounds: 728 152 8 8 + - image: solid-color(92, 19, 0, 255, 8, 8) + bounds: 736 152 8 8 + - image: solid-color(93, 19, 0, 255, 8, 8) + bounds: 744 152 8 8 + - image: solid-color(94, 19, 0, 255, 8, 8) + bounds: 752 152 8 8 + - image: solid-color(95, 19, 0, 255, 8, 8) + bounds: 760 152 8 8 + - image: solid-color(96, 19, 0, 255, 8, 8) + bounds: 768 152 8 8 + - image: solid-color(97, 19, 0, 255, 8, 8) + bounds: 776 152 8 8 + - image: solid-color(98, 19, 0, 255, 8, 8) + bounds: 784 152 8 8 + - image: solid-color(99, 19, 0, 255, 8, 8) + bounds: 792 152 8 8 + - image: solid-color(100, 19, 0, 255, 8, 8) + bounds: 800 152 8 8 + - image: solid-color(101, 19, 0, 255, 8, 8) + bounds: 808 152 8 8 + - image: solid-color(102, 19, 0, 255, 8, 8) + bounds: 816 152 8 8 + - image: solid-color(103, 19, 0, 255, 8, 8) + bounds: 824 152 8 8 + - image: solid-color(104, 19, 0, 255, 8, 8) + bounds: 832 152 8 8 + - image: solid-color(105, 19, 0, 255, 8, 8) + bounds: 840 152 8 8 + - image: solid-color(106, 19, 0, 255, 8, 8) + bounds: 848 152 8 8 + - image: solid-color(107, 19, 0, 255, 8, 8) + bounds: 856 152 8 8 + - image: solid-color(108, 19, 0, 255, 8, 8) + bounds: 864 152 8 8 + - image: solid-color(109, 19, 0, 255, 8, 8) + bounds: 872 152 8 8 + - image: solid-color(110, 19, 0, 255, 8, 8) + bounds: 880 152 8 8 + - image: solid-color(111, 19, 0, 255, 8, 8) + bounds: 888 152 8 8 + - image: solid-color(112, 19, 0, 255, 8, 8) + bounds: 896 152 8 8 + - image: solid-color(113, 19, 0, 255, 8, 8) + bounds: 904 152 8 8 + - image: solid-color(114, 19, 0, 255, 8, 8) + bounds: 912 152 8 8 + - image: solid-color(115, 19, 0, 255, 8, 8) + bounds: 920 152 8 8 + - image: solid-color(116, 19, 0, 255, 8, 8) + bounds: 928 152 8 8 + - image: solid-color(117, 19, 0, 255, 8, 8) + bounds: 936 152 8 8 + - image: solid-color(118, 19, 0, 255, 8, 8) + bounds: 944 152 8 8 + - image: solid-color(119, 19, 0, 255, 8, 8) + bounds: 952 152 8 8 + - image: solid-color(120, 19, 0, 255, 8, 8) + bounds: 960 152 8 8 + - image: solid-color(121, 19, 0, 255, 8, 8) + bounds: 968 152 8 8 + - image: solid-color(122, 19, 0, 255, 8, 8) + bounds: 976 152 8 8 + - image: solid-color(123, 19, 0, 255, 8, 8) + bounds: 984 152 8 8 + - image: solid-color(124, 19, 0, 255, 8, 8) + bounds: 992 152 8 8 + - image: solid-color(125, 19, 0, 255, 8, 8) + bounds: 1000 152 8 8 + - image: solid-color(126, 19, 0, 255, 8, 8) + bounds: 1008 152 8 8 + - image: solid-color(127, 19, 0, 255, 8, 8) + bounds: 1016 152 8 8 + - image: solid-color(0, 20, 0, 255, 8, 8) + bounds: 0 160 8 8 + - image: solid-color(1, 20, 0, 255, 8, 8) + bounds: 8 160 8 8 + - image: solid-color(2, 20, 0, 255, 8, 8) + bounds: 16 160 8 8 + - image: solid-color(3, 20, 0, 255, 8, 8) + bounds: 24 160 8 8 + - image: solid-color(4, 20, 0, 255, 8, 8) + bounds: 32 160 8 8 + - image: solid-color(5, 20, 0, 255, 8, 8) + bounds: 40 160 8 8 + - image: solid-color(6, 20, 0, 255, 8, 8) + bounds: 48 160 8 8 + - image: solid-color(7, 20, 0, 255, 8, 8) + bounds: 56 160 8 8 + - image: solid-color(8, 20, 0, 255, 8, 8) + bounds: 64 160 8 8 + - image: solid-color(9, 20, 0, 255, 8, 8) + bounds: 72 160 8 8 + - image: solid-color(10, 20, 0, 255, 8, 8) + bounds: 80 160 8 8 + - image: solid-color(11, 20, 0, 255, 8, 8) + bounds: 88 160 8 8 + - image: solid-color(12, 20, 0, 255, 8, 8) + bounds: 96 160 8 8 + - image: solid-color(13, 20, 0, 255, 8, 8) + bounds: 104 160 8 8 + - image: solid-color(14, 20, 0, 255, 8, 8) + bounds: 112 160 8 8 + - image: solid-color(15, 20, 0, 255, 8, 8) + bounds: 120 160 8 8 + - image: solid-color(16, 20, 0, 255, 8, 8) + bounds: 128 160 8 8 + - image: solid-color(17, 20, 0, 255, 8, 8) + bounds: 136 160 8 8 + - image: solid-color(18, 20, 0, 255, 8, 8) + bounds: 144 160 8 8 + - image: solid-color(19, 20, 0, 255, 8, 8) + bounds: 152 160 8 8 + - image: solid-color(20, 20, 0, 255, 8, 8) + bounds: 160 160 8 8 + - image: solid-color(21, 20, 0, 255, 8, 8) + bounds: 168 160 8 8 + - image: solid-color(22, 20, 0, 255, 8, 8) + bounds: 176 160 8 8 + - image: solid-color(23, 20, 0, 255, 8, 8) + bounds: 184 160 8 8 + - image: solid-color(24, 20, 0, 255, 8, 8) + bounds: 192 160 8 8 + - image: solid-color(25, 20, 0, 255, 8, 8) + bounds: 200 160 8 8 + - image: solid-color(26, 20, 0, 255, 8, 8) + bounds: 208 160 8 8 + - image: solid-color(27, 20, 0, 255, 8, 8) + bounds: 216 160 8 8 + - image: solid-color(28, 20, 0, 255, 8, 8) + bounds: 224 160 8 8 + - image: solid-color(29, 20, 0, 255, 8, 8) + bounds: 232 160 8 8 + - image: solid-color(30, 20, 0, 255, 8, 8) + bounds: 240 160 8 8 + - image: solid-color(31, 20, 0, 255, 8, 8) + bounds: 248 160 8 8 + - image: solid-color(32, 20, 0, 255, 8, 8) + bounds: 256 160 8 8 + - image: solid-color(33, 20, 0, 255, 8, 8) + bounds: 264 160 8 8 + - image: solid-color(34, 20, 0, 255, 8, 8) + bounds: 272 160 8 8 + - image: solid-color(35, 20, 0, 255, 8, 8) + bounds: 280 160 8 8 + - image: solid-color(36, 20, 0, 255, 8, 8) + bounds: 288 160 8 8 + - image: solid-color(37, 20, 0, 255, 8, 8) + bounds: 296 160 8 8 + - image: solid-color(38, 20, 0, 255, 8, 8) + bounds: 304 160 8 8 + - image: solid-color(39, 20, 0, 255, 8, 8) + bounds: 312 160 8 8 + - image: solid-color(40, 20, 0, 255, 8, 8) + bounds: 320 160 8 8 + - image: solid-color(41, 20, 0, 255, 8, 8) + bounds: 328 160 8 8 + - image: solid-color(42, 20, 0, 255, 8, 8) + bounds: 336 160 8 8 + - image: solid-color(43, 20, 0, 255, 8, 8) + bounds: 344 160 8 8 + - image: solid-color(44, 20, 0, 255, 8, 8) + bounds: 352 160 8 8 + - image: solid-color(45, 20, 0, 255, 8, 8) + bounds: 360 160 8 8 + - image: solid-color(46, 20, 0, 255, 8, 8) + bounds: 368 160 8 8 + - image: solid-color(47, 20, 0, 255, 8, 8) + bounds: 376 160 8 8 + - image: solid-color(48, 20, 0, 255, 8, 8) + bounds: 384 160 8 8 + - image: solid-color(49, 20, 0, 255, 8, 8) + bounds: 392 160 8 8 + - image: solid-color(50, 20, 0, 255, 8, 8) + bounds: 400 160 8 8 + - image: solid-color(51, 20, 0, 255, 8, 8) + bounds: 408 160 8 8 + - image: solid-color(52, 20, 0, 255, 8, 8) + bounds: 416 160 8 8 + - image: solid-color(53, 20, 0, 255, 8, 8) + bounds: 424 160 8 8 + - image: solid-color(54, 20, 0, 255, 8, 8) + bounds: 432 160 8 8 + - image: solid-color(55, 20, 0, 255, 8, 8) + bounds: 440 160 8 8 + - image: solid-color(56, 20, 0, 255, 8, 8) + bounds: 448 160 8 8 + - image: solid-color(57, 20, 0, 255, 8, 8) + bounds: 456 160 8 8 + - image: solid-color(58, 20, 0, 255, 8, 8) + bounds: 464 160 8 8 + - image: solid-color(59, 20, 0, 255, 8, 8) + bounds: 472 160 8 8 + - image: solid-color(60, 20, 0, 255, 8, 8) + bounds: 480 160 8 8 + - image: solid-color(61, 20, 0, 255, 8, 8) + bounds: 488 160 8 8 + - image: solid-color(62, 20, 0, 255, 8, 8) + bounds: 496 160 8 8 + - image: solid-color(63, 20, 0, 255, 8, 8) + bounds: 504 160 8 8 + - image: solid-color(64, 20, 0, 255, 8, 8) + bounds: 512 160 8 8 + - image: solid-color(65, 20, 0, 255, 8, 8) + bounds: 520 160 8 8 + - image: solid-color(66, 20, 0, 255, 8, 8) + bounds: 528 160 8 8 + - image: solid-color(67, 20, 0, 255, 8, 8) + bounds: 536 160 8 8 + - image: solid-color(68, 20, 0, 255, 8, 8) + bounds: 544 160 8 8 + - image: solid-color(69, 20, 0, 255, 8, 8) + bounds: 552 160 8 8 + - image: solid-color(70, 20, 0, 255, 8, 8) + bounds: 560 160 8 8 + - image: solid-color(71, 20, 0, 255, 8, 8) + bounds: 568 160 8 8 + - image: solid-color(72, 20, 0, 255, 8, 8) + bounds: 576 160 8 8 + - image: solid-color(73, 20, 0, 255, 8, 8) + bounds: 584 160 8 8 + - image: solid-color(74, 20, 0, 255, 8, 8) + bounds: 592 160 8 8 + - image: solid-color(75, 20, 0, 255, 8, 8) + bounds: 600 160 8 8 + - image: solid-color(76, 20, 0, 255, 8, 8) + bounds: 608 160 8 8 + - image: solid-color(77, 20, 0, 255, 8, 8) + bounds: 616 160 8 8 + - image: solid-color(78, 20, 0, 255, 8, 8) + bounds: 624 160 8 8 + - image: solid-color(79, 20, 0, 255, 8, 8) + bounds: 632 160 8 8 + - image: solid-color(80, 20, 0, 255, 8, 8) + bounds: 640 160 8 8 + - image: solid-color(81, 20, 0, 255, 8, 8) + bounds: 648 160 8 8 + - image: solid-color(82, 20, 0, 255, 8, 8) + bounds: 656 160 8 8 + - image: solid-color(83, 20, 0, 255, 8, 8) + bounds: 664 160 8 8 + - image: solid-color(84, 20, 0, 255, 8, 8) + bounds: 672 160 8 8 + - image: solid-color(85, 20, 0, 255, 8, 8) + bounds: 680 160 8 8 + - image: solid-color(86, 20, 0, 255, 8, 8) + bounds: 688 160 8 8 + - image: solid-color(87, 20, 0, 255, 8, 8) + bounds: 696 160 8 8 + - image: solid-color(88, 20, 0, 255, 8, 8) + bounds: 704 160 8 8 + - image: solid-color(89, 20, 0, 255, 8, 8) + bounds: 712 160 8 8 + - image: solid-color(90, 20, 0, 255, 8, 8) + bounds: 720 160 8 8 + - image: solid-color(91, 20, 0, 255, 8, 8) + bounds: 728 160 8 8 + - image: solid-color(92, 20, 0, 255, 8, 8) + bounds: 736 160 8 8 + - image: solid-color(93, 20, 0, 255, 8, 8) + bounds: 744 160 8 8 + - image: solid-color(94, 20, 0, 255, 8, 8) + bounds: 752 160 8 8 + - image: solid-color(95, 20, 0, 255, 8, 8) + bounds: 760 160 8 8 + - image: solid-color(96, 20, 0, 255, 8, 8) + bounds: 768 160 8 8 + - image: solid-color(97, 20, 0, 255, 8, 8) + bounds: 776 160 8 8 + - image: solid-color(98, 20, 0, 255, 8, 8) + bounds: 784 160 8 8 + - image: solid-color(99, 20, 0, 255, 8, 8) + bounds: 792 160 8 8 + - image: solid-color(100, 20, 0, 255, 8, 8) + bounds: 800 160 8 8 + - image: solid-color(101, 20, 0, 255, 8, 8) + bounds: 808 160 8 8 + - image: solid-color(102, 20, 0, 255, 8, 8) + bounds: 816 160 8 8 + - image: solid-color(103, 20, 0, 255, 8, 8) + bounds: 824 160 8 8 + - image: solid-color(104, 20, 0, 255, 8, 8) + bounds: 832 160 8 8 + - image: solid-color(105, 20, 0, 255, 8, 8) + bounds: 840 160 8 8 + - image: solid-color(106, 20, 0, 255, 8, 8) + bounds: 848 160 8 8 + - image: solid-color(107, 20, 0, 255, 8, 8) + bounds: 856 160 8 8 + - image: solid-color(108, 20, 0, 255, 8, 8) + bounds: 864 160 8 8 + - image: solid-color(109, 20, 0, 255, 8, 8) + bounds: 872 160 8 8 + - image: solid-color(110, 20, 0, 255, 8, 8) + bounds: 880 160 8 8 + - image: solid-color(111, 20, 0, 255, 8, 8) + bounds: 888 160 8 8 + - image: solid-color(112, 20, 0, 255, 8, 8) + bounds: 896 160 8 8 + - image: solid-color(113, 20, 0, 255, 8, 8) + bounds: 904 160 8 8 + - image: solid-color(114, 20, 0, 255, 8, 8) + bounds: 912 160 8 8 + - image: solid-color(115, 20, 0, 255, 8, 8) + bounds: 920 160 8 8 + - image: solid-color(116, 20, 0, 255, 8, 8) + bounds: 928 160 8 8 + - image: solid-color(117, 20, 0, 255, 8, 8) + bounds: 936 160 8 8 + - image: solid-color(118, 20, 0, 255, 8, 8) + bounds: 944 160 8 8 + - image: solid-color(119, 20, 0, 255, 8, 8) + bounds: 952 160 8 8 + - image: solid-color(120, 20, 0, 255, 8, 8) + bounds: 960 160 8 8 + - image: solid-color(121, 20, 0, 255, 8, 8) + bounds: 968 160 8 8 + - image: solid-color(122, 20, 0, 255, 8, 8) + bounds: 976 160 8 8 + - image: solid-color(123, 20, 0, 255, 8, 8) + bounds: 984 160 8 8 + - image: solid-color(124, 20, 0, 255, 8, 8) + bounds: 992 160 8 8 + - image: solid-color(125, 20, 0, 255, 8, 8) + bounds: 1000 160 8 8 + - image: solid-color(126, 20, 0, 255, 8, 8) + bounds: 1008 160 8 8 + - image: solid-color(127, 20, 0, 255, 8, 8) + bounds: 1016 160 8 8 + - image: solid-color(0, 21, 0, 255, 8, 8) + bounds: 0 168 8 8 + - image: solid-color(1, 21, 0, 255, 8, 8) + bounds: 8 168 8 8 + - image: solid-color(2, 21, 0, 255, 8, 8) + bounds: 16 168 8 8 + - image: solid-color(3, 21, 0, 255, 8, 8) + bounds: 24 168 8 8 + - image: solid-color(4, 21, 0, 255, 8, 8) + bounds: 32 168 8 8 + - image: solid-color(5, 21, 0, 255, 8, 8) + bounds: 40 168 8 8 + - image: solid-color(6, 21, 0, 255, 8, 8) + bounds: 48 168 8 8 + - image: solid-color(7, 21, 0, 255, 8, 8) + bounds: 56 168 8 8 + - image: solid-color(8, 21, 0, 255, 8, 8) + bounds: 64 168 8 8 + - image: solid-color(9, 21, 0, 255, 8, 8) + bounds: 72 168 8 8 + - image: solid-color(10, 21, 0, 255, 8, 8) + bounds: 80 168 8 8 + - image: solid-color(11, 21, 0, 255, 8, 8) + bounds: 88 168 8 8 + - image: solid-color(12, 21, 0, 255, 8, 8) + bounds: 96 168 8 8 + - image: solid-color(13, 21, 0, 255, 8, 8) + bounds: 104 168 8 8 + - image: solid-color(14, 21, 0, 255, 8, 8) + bounds: 112 168 8 8 + - image: solid-color(15, 21, 0, 255, 8, 8) + bounds: 120 168 8 8 + - image: solid-color(16, 21, 0, 255, 8, 8) + bounds: 128 168 8 8 + - image: solid-color(17, 21, 0, 255, 8, 8) + bounds: 136 168 8 8 + - image: solid-color(18, 21, 0, 255, 8, 8) + bounds: 144 168 8 8 + - image: solid-color(19, 21, 0, 255, 8, 8) + bounds: 152 168 8 8 + - image: solid-color(20, 21, 0, 255, 8, 8) + bounds: 160 168 8 8 + - image: solid-color(21, 21, 0, 255, 8, 8) + bounds: 168 168 8 8 + - image: solid-color(22, 21, 0, 255, 8, 8) + bounds: 176 168 8 8 + - image: solid-color(23, 21, 0, 255, 8, 8) + bounds: 184 168 8 8 + - image: solid-color(24, 21, 0, 255, 8, 8) + bounds: 192 168 8 8 + - image: solid-color(25, 21, 0, 255, 8, 8) + bounds: 200 168 8 8 + - image: solid-color(26, 21, 0, 255, 8, 8) + bounds: 208 168 8 8 + - image: solid-color(27, 21, 0, 255, 8, 8) + bounds: 216 168 8 8 + - image: solid-color(28, 21, 0, 255, 8, 8) + bounds: 224 168 8 8 + - image: solid-color(29, 21, 0, 255, 8, 8) + bounds: 232 168 8 8 + - image: solid-color(30, 21, 0, 255, 8, 8) + bounds: 240 168 8 8 + - image: solid-color(31, 21, 0, 255, 8, 8) + bounds: 248 168 8 8 + - image: solid-color(32, 21, 0, 255, 8, 8) + bounds: 256 168 8 8 + - image: solid-color(33, 21, 0, 255, 8, 8) + bounds: 264 168 8 8 + - image: solid-color(34, 21, 0, 255, 8, 8) + bounds: 272 168 8 8 + - image: solid-color(35, 21, 0, 255, 8, 8) + bounds: 280 168 8 8 + - image: solid-color(36, 21, 0, 255, 8, 8) + bounds: 288 168 8 8 + - image: solid-color(37, 21, 0, 255, 8, 8) + bounds: 296 168 8 8 + - image: solid-color(38, 21, 0, 255, 8, 8) + bounds: 304 168 8 8 + - image: solid-color(39, 21, 0, 255, 8, 8) + bounds: 312 168 8 8 + - image: solid-color(40, 21, 0, 255, 8, 8) + bounds: 320 168 8 8 + - image: solid-color(41, 21, 0, 255, 8, 8) + bounds: 328 168 8 8 + - image: solid-color(42, 21, 0, 255, 8, 8) + bounds: 336 168 8 8 + - image: solid-color(43, 21, 0, 255, 8, 8) + bounds: 344 168 8 8 + - image: solid-color(44, 21, 0, 255, 8, 8) + bounds: 352 168 8 8 + - image: solid-color(45, 21, 0, 255, 8, 8) + bounds: 360 168 8 8 + - image: solid-color(46, 21, 0, 255, 8, 8) + bounds: 368 168 8 8 + - image: solid-color(47, 21, 0, 255, 8, 8) + bounds: 376 168 8 8 + - image: solid-color(48, 21, 0, 255, 8, 8) + bounds: 384 168 8 8 + - image: solid-color(49, 21, 0, 255, 8, 8) + bounds: 392 168 8 8 + - image: solid-color(50, 21, 0, 255, 8, 8) + bounds: 400 168 8 8 + - image: solid-color(51, 21, 0, 255, 8, 8) + bounds: 408 168 8 8 + - image: solid-color(52, 21, 0, 255, 8, 8) + bounds: 416 168 8 8 + - image: solid-color(53, 21, 0, 255, 8, 8) + bounds: 424 168 8 8 + - image: solid-color(54, 21, 0, 255, 8, 8) + bounds: 432 168 8 8 + - image: solid-color(55, 21, 0, 255, 8, 8) + bounds: 440 168 8 8 + - image: solid-color(56, 21, 0, 255, 8, 8) + bounds: 448 168 8 8 + - image: solid-color(57, 21, 0, 255, 8, 8) + bounds: 456 168 8 8 + - image: solid-color(58, 21, 0, 255, 8, 8) + bounds: 464 168 8 8 + - image: solid-color(59, 21, 0, 255, 8, 8) + bounds: 472 168 8 8 + - image: solid-color(60, 21, 0, 255, 8, 8) + bounds: 480 168 8 8 + - image: solid-color(61, 21, 0, 255, 8, 8) + bounds: 488 168 8 8 + - image: solid-color(62, 21, 0, 255, 8, 8) + bounds: 496 168 8 8 + - image: solid-color(63, 21, 0, 255, 8, 8) + bounds: 504 168 8 8 + - image: solid-color(64, 21, 0, 255, 8, 8) + bounds: 512 168 8 8 + - image: solid-color(65, 21, 0, 255, 8, 8) + bounds: 520 168 8 8 + - image: solid-color(66, 21, 0, 255, 8, 8) + bounds: 528 168 8 8 + - image: solid-color(67, 21, 0, 255, 8, 8) + bounds: 536 168 8 8 + - image: solid-color(68, 21, 0, 255, 8, 8) + bounds: 544 168 8 8 + - image: solid-color(69, 21, 0, 255, 8, 8) + bounds: 552 168 8 8 + - image: solid-color(70, 21, 0, 255, 8, 8) + bounds: 560 168 8 8 + - image: solid-color(71, 21, 0, 255, 8, 8) + bounds: 568 168 8 8 + - image: solid-color(72, 21, 0, 255, 8, 8) + bounds: 576 168 8 8 + - image: solid-color(73, 21, 0, 255, 8, 8) + bounds: 584 168 8 8 + - image: solid-color(74, 21, 0, 255, 8, 8) + bounds: 592 168 8 8 + - image: solid-color(75, 21, 0, 255, 8, 8) + bounds: 600 168 8 8 + - image: solid-color(76, 21, 0, 255, 8, 8) + bounds: 608 168 8 8 + - image: solid-color(77, 21, 0, 255, 8, 8) + bounds: 616 168 8 8 + - image: solid-color(78, 21, 0, 255, 8, 8) + bounds: 624 168 8 8 + - image: solid-color(79, 21, 0, 255, 8, 8) + bounds: 632 168 8 8 + - image: solid-color(80, 21, 0, 255, 8, 8) + bounds: 640 168 8 8 + - image: solid-color(81, 21, 0, 255, 8, 8) + bounds: 648 168 8 8 + - image: solid-color(82, 21, 0, 255, 8, 8) + bounds: 656 168 8 8 + - image: solid-color(83, 21, 0, 255, 8, 8) + bounds: 664 168 8 8 + - image: solid-color(84, 21, 0, 255, 8, 8) + bounds: 672 168 8 8 + - image: solid-color(85, 21, 0, 255, 8, 8) + bounds: 680 168 8 8 + - image: solid-color(86, 21, 0, 255, 8, 8) + bounds: 688 168 8 8 + - image: solid-color(87, 21, 0, 255, 8, 8) + bounds: 696 168 8 8 + - image: solid-color(88, 21, 0, 255, 8, 8) + bounds: 704 168 8 8 + - image: solid-color(89, 21, 0, 255, 8, 8) + bounds: 712 168 8 8 + - image: solid-color(90, 21, 0, 255, 8, 8) + bounds: 720 168 8 8 + - image: solid-color(91, 21, 0, 255, 8, 8) + bounds: 728 168 8 8 + - image: solid-color(92, 21, 0, 255, 8, 8) + bounds: 736 168 8 8 + - image: solid-color(93, 21, 0, 255, 8, 8) + bounds: 744 168 8 8 + - image: solid-color(94, 21, 0, 255, 8, 8) + bounds: 752 168 8 8 + - image: solid-color(95, 21, 0, 255, 8, 8) + bounds: 760 168 8 8 + - image: solid-color(96, 21, 0, 255, 8, 8) + bounds: 768 168 8 8 + - image: solid-color(97, 21, 0, 255, 8, 8) + bounds: 776 168 8 8 + - image: solid-color(98, 21, 0, 255, 8, 8) + bounds: 784 168 8 8 + - image: solid-color(99, 21, 0, 255, 8, 8) + bounds: 792 168 8 8 + - image: solid-color(100, 21, 0, 255, 8, 8) + bounds: 800 168 8 8 + - image: solid-color(101, 21, 0, 255, 8, 8) + bounds: 808 168 8 8 + - image: solid-color(102, 21, 0, 255, 8, 8) + bounds: 816 168 8 8 + - image: solid-color(103, 21, 0, 255, 8, 8) + bounds: 824 168 8 8 + - image: solid-color(104, 21, 0, 255, 8, 8) + bounds: 832 168 8 8 + - image: solid-color(105, 21, 0, 255, 8, 8) + bounds: 840 168 8 8 + - image: solid-color(106, 21, 0, 255, 8, 8) + bounds: 848 168 8 8 + - image: solid-color(107, 21, 0, 255, 8, 8) + bounds: 856 168 8 8 + - image: solid-color(108, 21, 0, 255, 8, 8) + bounds: 864 168 8 8 + - image: solid-color(109, 21, 0, 255, 8, 8) + bounds: 872 168 8 8 + - image: solid-color(110, 21, 0, 255, 8, 8) + bounds: 880 168 8 8 + - image: solid-color(111, 21, 0, 255, 8, 8) + bounds: 888 168 8 8 + - image: solid-color(112, 21, 0, 255, 8, 8) + bounds: 896 168 8 8 + - image: solid-color(113, 21, 0, 255, 8, 8) + bounds: 904 168 8 8 + - image: solid-color(114, 21, 0, 255, 8, 8) + bounds: 912 168 8 8 + - image: solid-color(115, 21, 0, 255, 8, 8) + bounds: 920 168 8 8 + - image: solid-color(116, 21, 0, 255, 8, 8) + bounds: 928 168 8 8 + - image: solid-color(117, 21, 0, 255, 8, 8) + bounds: 936 168 8 8 + - image: solid-color(118, 21, 0, 255, 8, 8) + bounds: 944 168 8 8 + - image: solid-color(119, 21, 0, 255, 8, 8) + bounds: 952 168 8 8 + - image: solid-color(120, 21, 0, 255, 8, 8) + bounds: 960 168 8 8 + - image: solid-color(121, 21, 0, 255, 8, 8) + bounds: 968 168 8 8 + - image: solid-color(122, 21, 0, 255, 8, 8) + bounds: 976 168 8 8 + - image: solid-color(123, 21, 0, 255, 8, 8) + bounds: 984 168 8 8 + - image: solid-color(124, 21, 0, 255, 8, 8) + bounds: 992 168 8 8 + - image: solid-color(125, 21, 0, 255, 8, 8) + bounds: 1000 168 8 8 + - image: solid-color(126, 21, 0, 255, 8, 8) + bounds: 1008 168 8 8 + - image: solid-color(127, 21, 0, 255, 8, 8) + bounds: 1016 168 8 8 + - image: solid-color(0, 22, 0, 255, 8, 8) + bounds: 0 176 8 8 + - image: solid-color(1, 22, 0, 255, 8, 8) + bounds: 8 176 8 8 + - image: solid-color(2, 22, 0, 255, 8, 8) + bounds: 16 176 8 8 + - image: solid-color(3, 22, 0, 255, 8, 8) + bounds: 24 176 8 8 + - image: solid-color(4, 22, 0, 255, 8, 8) + bounds: 32 176 8 8 + - image: solid-color(5, 22, 0, 255, 8, 8) + bounds: 40 176 8 8 + - image: solid-color(6, 22, 0, 255, 8, 8) + bounds: 48 176 8 8 + - image: solid-color(7, 22, 0, 255, 8, 8) + bounds: 56 176 8 8 + - image: solid-color(8, 22, 0, 255, 8, 8) + bounds: 64 176 8 8 + - image: solid-color(9, 22, 0, 255, 8, 8) + bounds: 72 176 8 8 + - image: solid-color(10, 22, 0, 255, 8, 8) + bounds: 80 176 8 8 + - image: solid-color(11, 22, 0, 255, 8, 8) + bounds: 88 176 8 8 + - image: solid-color(12, 22, 0, 255, 8, 8) + bounds: 96 176 8 8 + - image: solid-color(13, 22, 0, 255, 8, 8) + bounds: 104 176 8 8 + - image: solid-color(14, 22, 0, 255, 8, 8) + bounds: 112 176 8 8 + - image: solid-color(15, 22, 0, 255, 8, 8) + bounds: 120 176 8 8 + - image: solid-color(16, 22, 0, 255, 8, 8) + bounds: 128 176 8 8 + - image: solid-color(17, 22, 0, 255, 8, 8) + bounds: 136 176 8 8 + - image: solid-color(18, 22, 0, 255, 8, 8) + bounds: 144 176 8 8 + - image: solid-color(19, 22, 0, 255, 8, 8) + bounds: 152 176 8 8 + - image: solid-color(20, 22, 0, 255, 8, 8) + bounds: 160 176 8 8 + - image: solid-color(21, 22, 0, 255, 8, 8) + bounds: 168 176 8 8 + - image: solid-color(22, 22, 0, 255, 8, 8) + bounds: 176 176 8 8 + - image: solid-color(23, 22, 0, 255, 8, 8) + bounds: 184 176 8 8 + - image: solid-color(24, 22, 0, 255, 8, 8) + bounds: 192 176 8 8 + - image: solid-color(25, 22, 0, 255, 8, 8) + bounds: 200 176 8 8 + - image: solid-color(26, 22, 0, 255, 8, 8) + bounds: 208 176 8 8 + - image: solid-color(27, 22, 0, 255, 8, 8) + bounds: 216 176 8 8 + - image: solid-color(28, 22, 0, 255, 8, 8) + bounds: 224 176 8 8 + - image: solid-color(29, 22, 0, 255, 8, 8) + bounds: 232 176 8 8 + - image: solid-color(30, 22, 0, 255, 8, 8) + bounds: 240 176 8 8 + - image: solid-color(31, 22, 0, 255, 8, 8) + bounds: 248 176 8 8 + - image: solid-color(32, 22, 0, 255, 8, 8) + bounds: 256 176 8 8 + - image: solid-color(33, 22, 0, 255, 8, 8) + bounds: 264 176 8 8 + - image: solid-color(34, 22, 0, 255, 8, 8) + bounds: 272 176 8 8 + - image: solid-color(35, 22, 0, 255, 8, 8) + bounds: 280 176 8 8 + - image: solid-color(36, 22, 0, 255, 8, 8) + bounds: 288 176 8 8 + - image: solid-color(37, 22, 0, 255, 8, 8) + bounds: 296 176 8 8 + - image: solid-color(38, 22, 0, 255, 8, 8) + bounds: 304 176 8 8 + - image: solid-color(39, 22, 0, 255, 8, 8) + bounds: 312 176 8 8 + - image: solid-color(40, 22, 0, 255, 8, 8) + bounds: 320 176 8 8 + - image: solid-color(41, 22, 0, 255, 8, 8) + bounds: 328 176 8 8 + - image: solid-color(42, 22, 0, 255, 8, 8) + bounds: 336 176 8 8 + - image: solid-color(43, 22, 0, 255, 8, 8) + bounds: 344 176 8 8 + - image: solid-color(44, 22, 0, 255, 8, 8) + bounds: 352 176 8 8 + - image: solid-color(45, 22, 0, 255, 8, 8) + bounds: 360 176 8 8 + - image: solid-color(46, 22, 0, 255, 8, 8) + bounds: 368 176 8 8 + - image: solid-color(47, 22, 0, 255, 8, 8) + bounds: 376 176 8 8 + - image: solid-color(48, 22, 0, 255, 8, 8) + bounds: 384 176 8 8 + - image: solid-color(49, 22, 0, 255, 8, 8) + bounds: 392 176 8 8 + - image: solid-color(50, 22, 0, 255, 8, 8) + bounds: 400 176 8 8 + - image: solid-color(51, 22, 0, 255, 8, 8) + bounds: 408 176 8 8 + - image: solid-color(52, 22, 0, 255, 8, 8) + bounds: 416 176 8 8 + - image: solid-color(53, 22, 0, 255, 8, 8) + bounds: 424 176 8 8 + - image: solid-color(54, 22, 0, 255, 8, 8) + bounds: 432 176 8 8 + - image: solid-color(55, 22, 0, 255, 8, 8) + bounds: 440 176 8 8 + - image: solid-color(56, 22, 0, 255, 8, 8) + bounds: 448 176 8 8 + - image: solid-color(57, 22, 0, 255, 8, 8) + bounds: 456 176 8 8 + - image: solid-color(58, 22, 0, 255, 8, 8) + bounds: 464 176 8 8 + - image: solid-color(59, 22, 0, 255, 8, 8) + bounds: 472 176 8 8 + - image: solid-color(60, 22, 0, 255, 8, 8) + bounds: 480 176 8 8 + - image: solid-color(61, 22, 0, 255, 8, 8) + bounds: 488 176 8 8 + - image: solid-color(62, 22, 0, 255, 8, 8) + bounds: 496 176 8 8 + - image: solid-color(63, 22, 0, 255, 8, 8) + bounds: 504 176 8 8 + - image: solid-color(64, 22, 0, 255, 8, 8) + bounds: 512 176 8 8 + - image: solid-color(65, 22, 0, 255, 8, 8) + bounds: 520 176 8 8 + - image: solid-color(66, 22, 0, 255, 8, 8) + bounds: 528 176 8 8 + - image: solid-color(67, 22, 0, 255, 8, 8) + bounds: 536 176 8 8 + - image: solid-color(68, 22, 0, 255, 8, 8) + bounds: 544 176 8 8 + - image: solid-color(69, 22, 0, 255, 8, 8) + bounds: 552 176 8 8 + - image: solid-color(70, 22, 0, 255, 8, 8) + bounds: 560 176 8 8 + - image: solid-color(71, 22, 0, 255, 8, 8) + bounds: 568 176 8 8 + - image: solid-color(72, 22, 0, 255, 8, 8) + bounds: 576 176 8 8 + - image: solid-color(73, 22, 0, 255, 8, 8) + bounds: 584 176 8 8 + - image: solid-color(74, 22, 0, 255, 8, 8) + bounds: 592 176 8 8 + - image: solid-color(75, 22, 0, 255, 8, 8) + bounds: 600 176 8 8 + - image: solid-color(76, 22, 0, 255, 8, 8) + bounds: 608 176 8 8 + - image: solid-color(77, 22, 0, 255, 8, 8) + bounds: 616 176 8 8 + - image: solid-color(78, 22, 0, 255, 8, 8) + bounds: 624 176 8 8 + - image: solid-color(79, 22, 0, 255, 8, 8) + bounds: 632 176 8 8 + - image: solid-color(80, 22, 0, 255, 8, 8) + bounds: 640 176 8 8 + - image: solid-color(81, 22, 0, 255, 8, 8) + bounds: 648 176 8 8 + - image: solid-color(82, 22, 0, 255, 8, 8) + bounds: 656 176 8 8 + - image: solid-color(83, 22, 0, 255, 8, 8) + bounds: 664 176 8 8 + - image: solid-color(84, 22, 0, 255, 8, 8) + bounds: 672 176 8 8 + - image: solid-color(85, 22, 0, 255, 8, 8) + bounds: 680 176 8 8 + - image: solid-color(86, 22, 0, 255, 8, 8) + bounds: 688 176 8 8 + - image: solid-color(87, 22, 0, 255, 8, 8) + bounds: 696 176 8 8 + - image: solid-color(88, 22, 0, 255, 8, 8) + bounds: 704 176 8 8 + - image: solid-color(89, 22, 0, 255, 8, 8) + bounds: 712 176 8 8 + - image: solid-color(90, 22, 0, 255, 8, 8) + bounds: 720 176 8 8 + - image: solid-color(91, 22, 0, 255, 8, 8) + bounds: 728 176 8 8 + - image: solid-color(92, 22, 0, 255, 8, 8) + bounds: 736 176 8 8 + - image: solid-color(93, 22, 0, 255, 8, 8) + bounds: 744 176 8 8 + - image: solid-color(94, 22, 0, 255, 8, 8) + bounds: 752 176 8 8 + - image: solid-color(95, 22, 0, 255, 8, 8) + bounds: 760 176 8 8 + - image: solid-color(96, 22, 0, 255, 8, 8) + bounds: 768 176 8 8 + - image: solid-color(97, 22, 0, 255, 8, 8) + bounds: 776 176 8 8 + - image: solid-color(98, 22, 0, 255, 8, 8) + bounds: 784 176 8 8 + - image: solid-color(99, 22, 0, 255, 8, 8) + bounds: 792 176 8 8 + - image: solid-color(100, 22, 0, 255, 8, 8) + bounds: 800 176 8 8 + - image: solid-color(101, 22, 0, 255, 8, 8) + bounds: 808 176 8 8 + - image: solid-color(102, 22, 0, 255, 8, 8) + bounds: 816 176 8 8 + - image: solid-color(103, 22, 0, 255, 8, 8) + bounds: 824 176 8 8 + - image: solid-color(104, 22, 0, 255, 8, 8) + bounds: 832 176 8 8 + - image: solid-color(105, 22, 0, 255, 8, 8) + bounds: 840 176 8 8 + - image: solid-color(106, 22, 0, 255, 8, 8) + bounds: 848 176 8 8 + - image: solid-color(107, 22, 0, 255, 8, 8) + bounds: 856 176 8 8 + - image: solid-color(108, 22, 0, 255, 8, 8) + bounds: 864 176 8 8 + - image: solid-color(109, 22, 0, 255, 8, 8) + bounds: 872 176 8 8 + - image: solid-color(110, 22, 0, 255, 8, 8) + bounds: 880 176 8 8 + - image: solid-color(111, 22, 0, 255, 8, 8) + bounds: 888 176 8 8 + - image: solid-color(112, 22, 0, 255, 8, 8) + bounds: 896 176 8 8 + - image: solid-color(113, 22, 0, 255, 8, 8) + bounds: 904 176 8 8 + - image: solid-color(114, 22, 0, 255, 8, 8) + bounds: 912 176 8 8 + - image: solid-color(115, 22, 0, 255, 8, 8) + bounds: 920 176 8 8 + - image: solid-color(116, 22, 0, 255, 8, 8) + bounds: 928 176 8 8 + - image: solid-color(117, 22, 0, 255, 8, 8) + bounds: 936 176 8 8 + - image: solid-color(118, 22, 0, 255, 8, 8) + bounds: 944 176 8 8 + - image: solid-color(119, 22, 0, 255, 8, 8) + bounds: 952 176 8 8 + - image: solid-color(120, 22, 0, 255, 8, 8) + bounds: 960 176 8 8 + - image: solid-color(121, 22, 0, 255, 8, 8) + bounds: 968 176 8 8 + - image: solid-color(122, 22, 0, 255, 8, 8) + bounds: 976 176 8 8 + - image: solid-color(123, 22, 0, 255, 8, 8) + bounds: 984 176 8 8 + - image: solid-color(124, 22, 0, 255, 8, 8) + bounds: 992 176 8 8 + - image: solid-color(125, 22, 0, 255, 8, 8) + bounds: 1000 176 8 8 + - image: solid-color(126, 22, 0, 255, 8, 8) + bounds: 1008 176 8 8 + - image: solid-color(127, 22, 0, 255, 8, 8) + bounds: 1016 176 8 8 + - image: solid-color(0, 23, 0, 255, 8, 8) + bounds: 0 184 8 8 + - image: solid-color(1, 23, 0, 255, 8, 8) + bounds: 8 184 8 8 + - image: solid-color(2, 23, 0, 255, 8, 8) + bounds: 16 184 8 8 + - image: solid-color(3, 23, 0, 255, 8, 8) + bounds: 24 184 8 8 + - image: solid-color(4, 23, 0, 255, 8, 8) + bounds: 32 184 8 8 + - image: solid-color(5, 23, 0, 255, 8, 8) + bounds: 40 184 8 8 + - image: solid-color(6, 23, 0, 255, 8, 8) + bounds: 48 184 8 8 + - image: solid-color(7, 23, 0, 255, 8, 8) + bounds: 56 184 8 8 + - image: solid-color(8, 23, 0, 255, 8, 8) + bounds: 64 184 8 8 + - image: solid-color(9, 23, 0, 255, 8, 8) + bounds: 72 184 8 8 + - image: solid-color(10, 23, 0, 255, 8, 8) + bounds: 80 184 8 8 + - image: solid-color(11, 23, 0, 255, 8, 8) + bounds: 88 184 8 8 + - image: solid-color(12, 23, 0, 255, 8, 8) + bounds: 96 184 8 8 + - image: solid-color(13, 23, 0, 255, 8, 8) + bounds: 104 184 8 8 + - image: solid-color(14, 23, 0, 255, 8, 8) + bounds: 112 184 8 8 + - image: solid-color(15, 23, 0, 255, 8, 8) + bounds: 120 184 8 8 + - image: solid-color(16, 23, 0, 255, 8, 8) + bounds: 128 184 8 8 + - image: solid-color(17, 23, 0, 255, 8, 8) + bounds: 136 184 8 8 + - image: solid-color(18, 23, 0, 255, 8, 8) + bounds: 144 184 8 8 + - image: solid-color(19, 23, 0, 255, 8, 8) + bounds: 152 184 8 8 + - image: solid-color(20, 23, 0, 255, 8, 8) + bounds: 160 184 8 8 + - image: solid-color(21, 23, 0, 255, 8, 8) + bounds: 168 184 8 8 + - image: solid-color(22, 23, 0, 255, 8, 8) + bounds: 176 184 8 8 + - image: solid-color(23, 23, 0, 255, 8, 8) + bounds: 184 184 8 8 + - image: solid-color(24, 23, 0, 255, 8, 8) + bounds: 192 184 8 8 + - image: solid-color(25, 23, 0, 255, 8, 8) + bounds: 200 184 8 8 + - image: solid-color(26, 23, 0, 255, 8, 8) + bounds: 208 184 8 8 + - image: solid-color(27, 23, 0, 255, 8, 8) + bounds: 216 184 8 8 + - image: solid-color(28, 23, 0, 255, 8, 8) + bounds: 224 184 8 8 + - image: solid-color(29, 23, 0, 255, 8, 8) + bounds: 232 184 8 8 + - image: solid-color(30, 23, 0, 255, 8, 8) + bounds: 240 184 8 8 + - image: solid-color(31, 23, 0, 255, 8, 8) + bounds: 248 184 8 8 + - image: solid-color(32, 23, 0, 255, 8, 8) + bounds: 256 184 8 8 + - image: solid-color(33, 23, 0, 255, 8, 8) + bounds: 264 184 8 8 + - image: solid-color(34, 23, 0, 255, 8, 8) + bounds: 272 184 8 8 + - image: solid-color(35, 23, 0, 255, 8, 8) + bounds: 280 184 8 8 + - image: solid-color(36, 23, 0, 255, 8, 8) + bounds: 288 184 8 8 + - image: solid-color(37, 23, 0, 255, 8, 8) + bounds: 296 184 8 8 + - image: solid-color(38, 23, 0, 255, 8, 8) + bounds: 304 184 8 8 + - image: solid-color(39, 23, 0, 255, 8, 8) + bounds: 312 184 8 8 + - image: solid-color(40, 23, 0, 255, 8, 8) + bounds: 320 184 8 8 + - image: solid-color(41, 23, 0, 255, 8, 8) + bounds: 328 184 8 8 + - image: solid-color(42, 23, 0, 255, 8, 8) + bounds: 336 184 8 8 + - image: solid-color(43, 23, 0, 255, 8, 8) + bounds: 344 184 8 8 + - image: solid-color(44, 23, 0, 255, 8, 8) + bounds: 352 184 8 8 + - image: solid-color(45, 23, 0, 255, 8, 8) + bounds: 360 184 8 8 + - image: solid-color(46, 23, 0, 255, 8, 8) + bounds: 368 184 8 8 + - image: solid-color(47, 23, 0, 255, 8, 8) + bounds: 376 184 8 8 + - image: solid-color(48, 23, 0, 255, 8, 8) + bounds: 384 184 8 8 + - image: solid-color(49, 23, 0, 255, 8, 8) + bounds: 392 184 8 8 + - image: solid-color(50, 23, 0, 255, 8, 8) + bounds: 400 184 8 8 + - image: solid-color(51, 23, 0, 255, 8, 8) + bounds: 408 184 8 8 + - image: solid-color(52, 23, 0, 255, 8, 8) + bounds: 416 184 8 8 + - image: solid-color(53, 23, 0, 255, 8, 8) + bounds: 424 184 8 8 + - image: solid-color(54, 23, 0, 255, 8, 8) + bounds: 432 184 8 8 + - image: solid-color(55, 23, 0, 255, 8, 8) + bounds: 440 184 8 8 + - image: solid-color(56, 23, 0, 255, 8, 8) + bounds: 448 184 8 8 + - image: solid-color(57, 23, 0, 255, 8, 8) + bounds: 456 184 8 8 + - image: solid-color(58, 23, 0, 255, 8, 8) + bounds: 464 184 8 8 + - image: solid-color(59, 23, 0, 255, 8, 8) + bounds: 472 184 8 8 + - image: solid-color(60, 23, 0, 255, 8, 8) + bounds: 480 184 8 8 + - image: solid-color(61, 23, 0, 255, 8, 8) + bounds: 488 184 8 8 + - image: solid-color(62, 23, 0, 255, 8, 8) + bounds: 496 184 8 8 + - image: solid-color(63, 23, 0, 255, 8, 8) + bounds: 504 184 8 8 + - image: solid-color(64, 23, 0, 255, 8, 8) + bounds: 512 184 8 8 + - image: solid-color(65, 23, 0, 255, 8, 8) + bounds: 520 184 8 8 + - image: solid-color(66, 23, 0, 255, 8, 8) + bounds: 528 184 8 8 + - image: solid-color(67, 23, 0, 255, 8, 8) + bounds: 536 184 8 8 + - image: solid-color(68, 23, 0, 255, 8, 8) + bounds: 544 184 8 8 + - image: solid-color(69, 23, 0, 255, 8, 8) + bounds: 552 184 8 8 + - image: solid-color(70, 23, 0, 255, 8, 8) + bounds: 560 184 8 8 + - image: solid-color(71, 23, 0, 255, 8, 8) + bounds: 568 184 8 8 + - image: solid-color(72, 23, 0, 255, 8, 8) + bounds: 576 184 8 8 + - image: solid-color(73, 23, 0, 255, 8, 8) + bounds: 584 184 8 8 + - image: solid-color(74, 23, 0, 255, 8, 8) + bounds: 592 184 8 8 + - image: solid-color(75, 23, 0, 255, 8, 8) + bounds: 600 184 8 8 + - image: solid-color(76, 23, 0, 255, 8, 8) + bounds: 608 184 8 8 + - image: solid-color(77, 23, 0, 255, 8, 8) + bounds: 616 184 8 8 + - image: solid-color(78, 23, 0, 255, 8, 8) + bounds: 624 184 8 8 + - image: solid-color(79, 23, 0, 255, 8, 8) + bounds: 632 184 8 8 + - image: solid-color(80, 23, 0, 255, 8, 8) + bounds: 640 184 8 8 + - image: solid-color(81, 23, 0, 255, 8, 8) + bounds: 648 184 8 8 + - image: solid-color(82, 23, 0, 255, 8, 8) + bounds: 656 184 8 8 + - image: solid-color(83, 23, 0, 255, 8, 8) + bounds: 664 184 8 8 + - image: solid-color(84, 23, 0, 255, 8, 8) + bounds: 672 184 8 8 + - image: solid-color(85, 23, 0, 255, 8, 8) + bounds: 680 184 8 8 + - image: solid-color(86, 23, 0, 255, 8, 8) + bounds: 688 184 8 8 + - image: solid-color(87, 23, 0, 255, 8, 8) + bounds: 696 184 8 8 + - image: solid-color(88, 23, 0, 255, 8, 8) + bounds: 704 184 8 8 + - image: solid-color(89, 23, 0, 255, 8, 8) + bounds: 712 184 8 8 + - image: solid-color(90, 23, 0, 255, 8, 8) + bounds: 720 184 8 8 + - image: solid-color(91, 23, 0, 255, 8, 8) + bounds: 728 184 8 8 + - image: solid-color(92, 23, 0, 255, 8, 8) + bounds: 736 184 8 8 + - image: solid-color(93, 23, 0, 255, 8, 8) + bounds: 744 184 8 8 + - image: solid-color(94, 23, 0, 255, 8, 8) + bounds: 752 184 8 8 + - image: solid-color(95, 23, 0, 255, 8, 8) + bounds: 760 184 8 8 + - image: solid-color(96, 23, 0, 255, 8, 8) + bounds: 768 184 8 8 + - image: solid-color(97, 23, 0, 255, 8, 8) + bounds: 776 184 8 8 + - image: solid-color(98, 23, 0, 255, 8, 8) + bounds: 784 184 8 8 + - image: solid-color(99, 23, 0, 255, 8, 8) + bounds: 792 184 8 8 + - image: solid-color(100, 23, 0, 255, 8, 8) + bounds: 800 184 8 8 + - image: solid-color(101, 23, 0, 255, 8, 8) + bounds: 808 184 8 8 + - image: solid-color(102, 23, 0, 255, 8, 8) + bounds: 816 184 8 8 + - image: solid-color(103, 23, 0, 255, 8, 8) + bounds: 824 184 8 8 + - image: solid-color(104, 23, 0, 255, 8, 8) + bounds: 832 184 8 8 + - image: solid-color(105, 23, 0, 255, 8, 8) + bounds: 840 184 8 8 + - image: solid-color(106, 23, 0, 255, 8, 8) + bounds: 848 184 8 8 + - image: solid-color(107, 23, 0, 255, 8, 8) + bounds: 856 184 8 8 + - image: solid-color(108, 23, 0, 255, 8, 8) + bounds: 864 184 8 8 + - image: solid-color(109, 23, 0, 255, 8, 8) + bounds: 872 184 8 8 + - image: solid-color(110, 23, 0, 255, 8, 8) + bounds: 880 184 8 8 + - image: solid-color(111, 23, 0, 255, 8, 8) + bounds: 888 184 8 8 + - image: solid-color(112, 23, 0, 255, 8, 8) + bounds: 896 184 8 8 + - image: solid-color(113, 23, 0, 255, 8, 8) + bounds: 904 184 8 8 + - image: solid-color(114, 23, 0, 255, 8, 8) + bounds: 912 184 8 8 + - image: solid-color(115, 23, 0, 255, 8, 8) + bounds: 920 184 8 8 + - image: solid-color(116, 23, 0, 255, 8, 8) + bounds: 928 184 8 8 + - image: solid-color(117, 23, 0, 255, 8, 8) + bounds: 936 184 8 8 + - image: solid-color(118, 23, 0, 255, 8, 8) + bounds: 944 184 8 8 + - image: solid-color(119, 23, 0, 255, 8, 8) + bounds: 952 184 8 8 + - image: solid-color(120, 23, 0, 255, 8, 8) + bounds: 960 184 8 8 + - image: solid-color(121, 23, 0, 255, 8, 8) + bounds: 968 184 8 8 + - image: solid-color(122, 23, 0, 255, 8, 8) + bounds: 976 184 8 8 + - image: solid-color(123, 23, 0, 255, 8, 8) + bounds: 984 184 8 8 + - image: solid-color(124, 23, 0, 255, 8, 8) + bounds: 992 184 8 8 + - image: solid-color(125, 23, 0, 255, 8, 8) + bounds: 1000 184 8 8 + - image: solid-color(126, 23, 0, 255, 8, 8) + bounds: 1008 184 8 8 + - image: solid-color(127, 23, 0, 255, 8, 8) + bounds: 1016 184 8 8 + - image: solid-color(0, 24, 0, 255, 8, 8) + bounds: 0 192 8 8 + - image: solid-color(1, 24, 0, 255, 8, 8) + bounds: 8 192 8 8 + - image: solid-color(2, 24, 0, 255, 8, 8) + bounds: 16 192 8 8 + - image: solid-color(3, 24, 0, 255, 8, 8) + bounds: 24 192 8 8 + - image: solid-color(4, 24, 0, 255, 8, 8) + bounds: 32 192 8 8 + - image: solid-color(5, 24, 0, 255, 8, 8) + bounds: 40 192 8 8 + - image: solid-color(6, 24, 0, 255, 8, 8) + bounds: 48 192 8 8 + - image: solid-color(7, 24, 0, 255, 8, 8) + bounds: 56 192 8 8 + - image: solid-color(8, 24, 0, 255, 8, 8) + bounds: 64 192 8 8 + - image: solid-color(9, 24, 0, 255, 8, 8) + bounds: 72 192 8 8 + - image: solid-color(10, 24, 0, 255, 8, 8) + bounds: 80 192 8 8 + - image: solid-color(11, 24, 0, 255, 8, 8) + bounds: 88 192 8 8 + - image: solid-color(12, 24, 0, 255, 8, 8) + bounds: 96 192 8 8 + - image: solid-color(13, 24, 0, 255, 8, 8) + bounds: 104 192 8 8 + - image: solid-color(14, 24, 0, 255, 8, 8) + bounds: 112 192 8 8 + - image: solid-color(15, 24, 0, 255, 8, 8) + bounds: 120 192 8 8 + - image: solid-color(16, 24, 0, 255, 8, 8) + bounds: 128 192 8 8 + - image: solid-color(17, 24, 0, 255, 8, 8) + bounds: 136 192 8 8 + - image: solid-color(18, 24, 0, 255, 8, 8) + bounds: 144 192 8 8 + - image: solid-color(19, 24, 0, 255, 8, 8) + bounds: 152 192 8 8 + - image: solid-color(20, 24, 0, 255, 8, 8) + bounds: 160 192 8 8 + - image: solid-color(21, 24, 0, 255, 8, 8) + bounds: 168 192 8 8 + - image: solid-color(22, 24, 0, 255, 8, 8) + bounds: 176 192 8 8 + - image: solid-color(23, 24, 0, 255, 8, 8) + bounds: 184 192 8 8 + - image: solid-color(24, 24, 0, 255, 8, 8) + bounds: 192 192 8 8 + - image: solid-color(25, 24, 0, 255, 8, 8) + bounds: 200 192 8 8 + - image: solid-color(26, 24, 0, 255, 8, 8) + bounds: 208 192 8 8 + - image: solid-color(27, 24, 0, 255, 8, 8) + bounds: 216 192 8 8 + - image: solid-color(28, 24, 0, 255, 8, 8) + bounds: 224 192 8 8 + - image: solid-color(29, 24, 0, 255, 8, 8) + bounds: 232 192 8 8 + - image: solid-color(30, 24, 0, 255, 8, 8) + bounds: 240 192 8 8 + - image: solid-color(31, 24, 0, 255, 8, 8) + bounds: 248 192 8 8 + - image: solid-color(32, 24, 0, 255, 8, 8) + bounds: 256 192 8 8 + - image: solid-color(33, 24, 0, 255, 8, 8) + bounds: 264 192 8 8 + - image: solid-color(34, 24, 0, 255, 8, 8) + bounds: 272 192 8 8 + - image: solid-color(35, 24, 0, 255, 8, 8) + bounds: 280 192 8 8 + - image: solid-color(36, 24, 0, 255, 8, 8) + bounds: 288 192 8 8 + - image: solid-color(37, 24, 0, 255, 8, 8) + bounds: 296 192 8 8 + - image: solid-color(38, 24, 0, 255, 8, 8) + bounds: 304 192 8 8 + - image: solid-color(39, 24, 0, 255, 8, 8) + bounds: 312 192 8 8 + - image: solid-color(40, 24, 0, 255, 8, 8) + bounds: 320 192 8 8 + - image: solid-color(41, 24, 0, 255, 8, 8) + bounds: 328 192 8 8 + - image: solid-color(42, 24, 0, 255, 8, 8) + bounds: 336 192 8 8 + - image: solid-color(43, 24, 0, 255, 8, 8) + bounds: 344 192 8 8 + - image: solid-color(44, 24, 0, 255, 8, 8) + bounds: 352 192 8 8 + - image: solid-color(45, 24, 0, 255, 8, 8) + bounds: 360 192 8 8 + - image: solid-color(46, 24, 0, 255, 8, 8) + bounds: 368 192 8 8 + - image: solid-color(47, 24, 0, 255, 8, 8) + bounds: 376 192 8 8 + - image: solid-color(48, 24, 0, 255, 8, 8) + bounds: 384 192 8 8 + - image: solid-color(49, 24, 0, 255, 8, 8) + bounds: 392 192 8 8 + - image: solid-color(50, 24, 0, 255, 8, 8) + bounds: 400 192 8 8 + - image: solid-color(51, 24, 0, 255, 8, 8) + bounds: 408 192 8 8 + - image: solid-color(52, 24, 0, 255, 8, 8) + bounds: 416 192 8 8 + - image: solid-color(53, 24, 0, 255, 8, 8) + bounds: 424 192 8 8 + - image: solid-color(54, 24, 0, 255, 8, 8) + bounds: 432 192 8 8 + - image: solid-color(55, 24, 0, 255, 8, 8) + bounds: 440 192 8 8 + - image: solid-color(56, 24, 0, 255, 8, 8) + bounds: 448 192 8 8 + - image: solid-color(57, 24, 0, 255, 8, 8) + bounds: 456 192 8 8 + - image: solid-color(58, 24, 0, 255, 8, 8) + bounds: 464 192 8 8 + - image: solid-color(59, 24, 0, 255, 8, 8) + bounds: 472 192 8 8 + - image: solid-color(60, 24, 0, 255, 8, 8) + bounds: 480 192 8 8 + - image: solid-color(61, 24, 0, 255, 8, 8) + bounds: 488 192 8 8 + - image: solid-color(62, 24, 0, 255, 8, 8) + bounds: 496 192 8 8 + - image: solid-color(63, 24, 0, 255, 8, 8) + bounds: 504 192 8 8 + - image: solid-color(64, 24, 0, 255, 8, 8) + bounds: 512 192 8 8 + - image: solid-color(65, 24, 0, 255, 8, 8) + bounds: 520 192 8 8 + - image: solid-color(66, 24, 0, 255, 8, 8) + bounds: 528 192 8 8 + - image: solid-color(67, 24, 0, 255, 8, 8) + bounds: 536 192 8 8 + - image: solid-color(68, 24, 0, 255, 8, 8) + bounds: 544 192 8 8 + - image: solid-color(69, 24, 0, 255, 8, 8) + bounds: 552 192 8 8 + - image: solid-color(70, 24, 0, 255, 8, 8) + bounds: 560 192 8 8 + - image: solid-color(71, 24, 0, 255, 8, 8) + bounds: 568 192 8 8 + - image: solid-color(72, 24, 0, 255, 8, 8) + bounds: 576 192 8 8 + - image: solid-color(73, 24, 0, 255, 8, 8) + bounds: 584 192 8 8 + - image: solid-color(74, 24, 0, 255, 8, 8) + bounds: 592 192 8 8 + - image: solid-color(75, 24, 0, 255, 8, 8) + bounds: 600 192 8 8 + - image: solid-color(76, 24, 0, 255, 8, 8) + bounds: 608 192 8 8 + - image: solid-color(77, 24, 0, 255, 8, 8) + bounds: 616 192 8 8 + - image: solid-color(78, 24, 0, 255, 8, 8) + bounds: 624 192 8 8 + - image: solid-color(79, 24, 0, 255, 8, 8) + bounds: 632 192 8 8 + - image: solid-color(80, 24, 0, 255, 8, 8) + bounds: 640 192 8 8 + - image: solid-color(81, 24, 0, 255, 8, 8) + bounds: 648 192 8 8 + - image: solid-color(82, 24, 0, 255, 8, 8) + bounds: 656 192 8 8 + - image: solid-color(83, 24, 0, 255, 8, 8) + bounds: 664 192 8 8 + - image: solid-color(84, 24, 0, 255, 8, 8) + bounds: 672 192 8 8 + - image: solid-color(85, 24, 0, 255, 8, 8) + bounds: 680 192 8 8 + - image: solid-color(86, 24, 0, 255, 8, 8) + bounds: 688 192 8 8 + - image: solid-color(87, 24, 0, 255, 8, 8) + bounds: 696 192 8 8 + - image: solid-color(88, 24, 0, 255, 8, 8) + bounds: 704 192 8 8 + - image: solid-color(89, 24, 0, 255, 8, 8) + bounds: 712 192 8 8 + - image: solid-color(90, 24, 0, 255, 8, 8) + bounds: 720 192 8 8 + - image: solid-color(91, 24, 0, 255, 8, 8) + bounds: 728 192 8 8 + - image: solid-color(92, 24, 0, 255, 8, 8) + bounds: 736 192 8 8 + - image: solid-color(93, 24, 0, 255, 8, 8) + bounds: 744 192 8 8 + - image: solid-color(94, 24, 0, 255, 8, 8) + bounds: 752 192 8 8 + - image: solid-color(95, 24, 0, 255, 8, 8) + bounds: 760 192 8 8 + - image: solid-color(96, 24, 0, 255, 8, 8) + bounds: 768 192 8 8 + - image: solid-color(97, 24, 0, 255, 8, 8) + bounds: 776 192 8 8 + - image: solid-color(98, 24, 0, 255, 8, 8) + bounds: 784 192 8 8 + - image: solid-color(99, 24, 0, 255, 8, 8) + bounds: 792 192 8 8 + - image: solid-color(100, 24, 0, 255, 8, 8) + bounds: 800 192 8 8 + - image: solid-color(101, 24, 0, 255, 8, 8) + bounds: 808 192 8 8 + - image: solid-color(102, 24, 0, 255, 8, 8) + bounds: 816 192 8 8 + - image: solid-color(103, 24, 0, 255, 8, 8) + bounds: 824 192 8 8 + - image: solid-color(104, 24, 0, 255, 8, 8) + bounds: 832 192 8 8 + - image: solid-color(105, 24, 0, 255, 8, 8) + bounds: 840 192 8 8 + - image: solid-color(106, 24, 0, 255, 8, 8) + bounds: 848 192 8 8 + - image: solid-color(107, 24, 0, 255, 8, 8) + bounds: 856 192 8 8 + - image: solid-color(108, 24, 0, 255, 8, 8) + bounds: 864 192 8 8 + - image: solid-color(109, 24, 0, 255, 8, 8) + bounds: 872 192 8 8 + - image: solid-color(110, 24, 0, 255, 8, 8) + bounds: 880 192 8 8 + - image: solid-color(111, 24, 0, 255, 8, 8) + bounds: 888 192 8 8 + - image: solid-color(112, 24, 0, 255, 8, 8) + bounds: 896 192 8 8 + - image: solid-color(113, 24, 0, 255, 8, 8) + bounds: 904 192 8 8 + - image: solid-color(114, 24, 0, 255, 8, 8) + bounds: 912 192 8 8 + - image: solid-color(115, 24, 0, 255, 8, 8) + bounds: 920 192 8 8 + - image: solid-color(116, 24, 0, 255, 8, 8) + bounds: 928 192 8 8 + - image: solid-color(117, 24, 0, 255, 8, 8) + bounds: 936 192 8 8 + - image: solid-color(118, 24, 0, 255, 8, 8) + bounds: 944 192 8 8 + - image: solid-color(119, 24, 0, 255, 8, 8) + bounds: 952 192 8 8 + - image: solid-color(120, 24, 0, 255, 8, 8) + bounds: 960 192 8 8 + - image: solid-color(121, 24, 0, 255, 8, 8) + bounds: 968 192 8 8 + - image: solid-color(122, 24, 0, 255, 8, 8) + bounds: 976 192 8 8 + - image: solid-color(123, 24, 0, 255, 8, 8) + bounds: 984 192 8 8 + - image: solid-color(124, 24, 0, 255, 8, 8) + bounds: 992 192 8 8 + - image: solid-color(125, 24, 0, 255, 8, 8) + bounds: 1000 192 8 8 + - image: solid-color(126, 24, 0, 255, 8, 8) + bounds: 1008 192 8 8 + - image: solid-color(127, 24, 0, 255, 8, 8) + bounds: 1016 192 8 8 + - image: solid-color(0, 25, 0, 255, 8, 8) + bounds: 0 200 8 8 + - image: solid-color(1, 25, 0, 255, 8, 8) + bounds: 8 200 8 8 + - image: solid-color(2, 25, 0, 255, 8, 8) + bounds: 16 200 8 8 + - image: solid-color(3, 25, 0, 255, 8, 8) + bounds: 24 200 8 8 + - image: solid-color(4, 25, 0, 255, 8, 8) + bounds: 32 200 8 8 + - image: solid-color(5, 25, 0, 255, 8, 8) + bounds: 40 200 8 8 + - image: solid-color(6, 25, 0, 255, 8, 8) + bounds: 48 200 8 8 + - image: solid-color(7, 25, 0, 255, 8, 8) + bounds: 56 200 8 8 + - image: solid-color(8, 25, 0, 255, 8, 8) + bounds: 64 200 8 8 + - image: solid-color(9, 25, 0, 255, 8, 8) + bounds: 72 200 8 8 + - image: solid-color(10, 25, 0, 255, 8, 8) + bounds: 80 200 8 8 + - image: solid-color(11, 25, 0, 255, 8, 8) + bounds: 88 200 8 8 + - image: solid-color(12, 25, 0, 255, 8, 8) + bounds: 96 200 8 8 + - image: solid-color(13, 25, 0, 255, 8, 8) + bounds: 104 200 8 8 + - image: solid-color(14, 25, 0, 255, 8, 8) + bounds: 112 200 8 8 + - image: solid-color(15, 25, 0, 255, 8, 8) + bounds: 120 200 8 8 + - image: solid-color(16, 25, 0, 255, 8, 8) + bounds: 128 200 8 8 + - image: solid-color(17, 25, 0, 255, 8, 8) + bounds: 136 200 8 8 + - image: solid-color(18, 25, 0, 255, 8, 8) + bounds: 144 200 8 8 + - image: solid-color(19, 25, 0, 255, 8, 8) + bounds: 152 200 8 8 + - image: solid-color(20, 25, 0, 255, 8, 8) + bounds: 160 200 8 8 + - image: solid-color(21, 25, 0, 255, 8, 8) + bounds: 168 200 8 8 + - image: solid-color(22, 25, 0, 255, 8, 8) + bounds: 176 200 8 8 + - image: solid-color(23, 25, 0, 255, 8, 8) + bounds: 184 200 8 8 + - image: solid-color(24, 25, 0, 255, 8, 8) + bounds: 192 200 8 8 + - image: solid-color(25, 25, 0, 255, 8, 8) + bounds: 200 200 8 8 + - image: solid-color(26, 25, 0, 255, 8, 8) + bounds: 208 200 8 8 + - image: solid-color(27, 25, 0, 255, 8, 8) + bounds: 216 200 8 8 + - image: solid-color(28, 25, 0, 255, 8, 8) + bounds: 224 200 8 8 + - image: solid-color(29, 25, 0, 255, 8, 8) + bounds: 232 200 8 8 + - image: solid-color(30, 25, 0, 255, 8, 8) + bounds: 240 200 8 8 + - image: solid-color(31, 25, 0, 255, 8, 8) + bounds: 248 200 8 8 + - image: solid-color(32, 25, 0, 255, 8, 8) + bounds: 256 200 8 8 + - image: solid-color(33, 25, 0, 255, 8, 8) + bounds: 264 200 8 8 + - image: solid-color(34, 25, 0, 255, 8, 8) + bounds: 272 200 8 8 + - image: solid-color(35, 25, 0, 255, 8, 8) + bounds: 280 200 8 8 + - image: solid-color(36, 25, 0, 255, 8, 8) + bounds: 288 200 8 8 + - image: solid-color(37, 25, 0, 255, 8, 8) + bounds: 296 200 8 8 + - image: solid-color(38, 25, 0, 255, 8, 8) + bounds: 304 200 8 8 + - image: solid-color(39, 25, 0, 255, 8, 8) + bounds: 312 200 8 8 + - image: solid-color(40, 25, 0, 255, 8, 8) + bounds: 320 200 8 8 + - image: solid-color(41, 25, 0, 255, 8, 8) + bounds: 328 200 8 8 + - image: solid-color(42, 25, 0, 255, 8, 8) + bounds: 336 200 8 8 + - image: solid-color(43, 25, 0, 255, 8, 8) + bounds: 344 200 8 8 + - image: solid-color(44, 25, 0, 255, 8, 8) + bounds: 352 200 8 8 + - image: solid-color(45, 25, 0, 255, 8, 8) + bounds: 360 200 8 8 + - image: solid-color(46, 25, 0, 255, 8, 8) + bounds: 368 200 8 8 + - image: solid-color(47, 25, 0, 255, 8, 8) + bounds: 376 200 8 8 + - image: solid-color(48, 25, 0, 255, 8, 8) + bounds: 384 200 8 8 + - image: solid-color(49, 25, 0, 255, 8, 8) + bounds: 392 200 8 8 + - image: solid-color(50, 25, 0, 255, 8, 8) + bounds: 400 200 8 8 + - image: solid-color(51, 25, 0, 255, 8, 8) + bounds: 408 200 8 8 + - image: solid-color(52, 25, 0, 255, 8, 8) + bounds: 416 200 8 8 + - image: solid-color(53, 25, 0, 255, 8, 8) + bounds: 424 200 8 8 + - image: solid-color(54, 25, 0, 255, 8, 8) + bounds: 432 200 8 8 + - image: solid-color(55, 25, 0, 255, 8, 8) + bounds: 440 200 8 8 + - image: solid-color(56, 25, 0, 255, 8, 8) + bounds: 448 200 8 8 + - image: solid-color(57, 25, 0, 255, 8, 8) + bounds: 456 200 8 8 + - image: solid-color(58, 25, 0, 255, 8, 8) + bounds: 464 200 8 8 + - image: solid-color(59, 25, 0, 255, 8, 8) + bounds: 472 200 8 8 + - image: solid-color(60, 25, 0, 255, 8, 8) + bounds: 480 200 8 8 + - image: solid-color(61, 25, 0, 255, 8, 8) + bounds: 488 200 8 8 + - image: solid-color(62, 25, 0, 255, 8, 8) + bounds: 496 200 8 8 + - image: solid-color(63, 25, 0, 255, 8, 8) + bounds: 504 200 8 8 + - image: solid-color(64, 25, 0, 255, 8, 8) + bounds: 512 200 8 8 + - image: solid-color(65, 25, 0, 255, 8, 8) + bounds: 520 200 8 8 + - image: solid-color(66, 25, 0, 255, 8, 8) + bounds: 528 200 8 8 + - image: solid-color(67, 25, 0, 255, 8, 8) + bounds: 536 200 8 8 + - image: solid-color(68, 25, 0, 255, 8, 8) + bounds: 544 200 8 8 + - image: solid-color(69, 25, 0, 255, 8, 8) + bounds: 552 200 8 8 + - image: solid-color(70, 25, 0, 255, 8, 8) + bounds: 560 200 8 8 + - image: solid-color(71, 25, 0, 255, 8, 8) + bounds: 568 200 8 8 + - image: solid-color(72, 25, 0, 255, 8, 8) + bounds: 576 200 8 8 + - image: solid-color(73, 25, 0, 255, 8, 8) + bounds: 584 200 8 8 + - image: solid-color(74, 25, 0, 255, 8, 8) + bounds: 592 200 8 8 + - image: solid-color(75, 25, 0, 255, 8, 8) + bounds: 600 200 8 8 + - image: solid-color(76, 25, 0, 255, 8, 8) + bounds: 608 200 8 8 + - image: solid-color(77, 25, 0, 255, 8, 8) + bounds: 616 200 8 8 + - image: solid-color(78, 25, 0, 255, 8, 8) + bounds: 624 200 8 8 + - image: solid-color(79, 25, 0, 255, 8, 8) + bounds: 632 200 8 8 + - image: solid-color(80, 25, 0, 255, 8, 8) + bounds: 640 200 8 8 + - image: solid-color(81, 25, 0, 255, 8, 8) + bounds: 648 200 8 8 + - image: solid-color(82, 25, 0, 255, 8, 8) + bounds: 656 200 8 8 + - image: solid-color(83, 25, 0, 255, 8, 8) + bounds: 664 200 8 8 + - image: solid-color(84, 25, 0, 255, 8, 8) + bounds: 672 200 8 8 + - image: solid-color(85, 25, 0, 255, 8, 8) + bounds: 680 200 8 8 + - image: solid-color(86, 25, 0, 255, 8, 8) + bounds: 688 200 8 8 + - image: solid-color(87, 25, 0, 255, 8, 8) + bounds: 696 200 8 8 + - image: solid-color(88, 25, 0, 255, 8, 8) + bounds: 704 200 8 8 + - image: solid-color(89, 25, 0, 255, 8, 8) + bounds: 712 200 8 8 + - image: solid-color(90, 25, 0, 255, 8, 8) + bounds: 720 200 8 8 + - image: solid-color(91, 25, 0, 255, 8, 8) + bounds: 728 200 8 8 + - image: solid-color(92, 25, 0, 255, 8, 8) + bounds: 736 200 8 8 + - image: solid-color(93, 25, 0, 255, 8, 8) + bounds: 744 200 8 8 + - image: solid-color(94, 25, 0, 255, 8, 8) + bounds: 752 200 8 8 + - image: solid-color(95, 25, 0, 255, 8, 8) + bounds: 760 200 8 8 + - image: solid-color(96, 25, 0, 255, 8, 8) + bounds: 768 200 8 8 + - image: solid-color(97, 25, 0, 255, 8, 8) + bounds: 776 200 8 8 + - image: solid-color(98, 25, 0, 255, 8, 8) + bounds: 784 200 8 8 + - image: solid-color(99, 25, 0, 255, 8, 8) + bounds: 792 200 8 8 + - image: solid-color(100, 25, 0, 255, 8, 8) + bounds: 800 200 8 8 + - image: solid-color(101, 25, 0, 255, 8, 8) + bounds: 808 200 8 8 + - image: solid-color(102, 25, 0, 255, 8, 8) + bounds: 816 200 8 8 + - image: solid-color(103, 25, 0, 255, 8, 8) + bounds: 824 200 8 8 + - image: solid-color(104, 25, 0, 255, 8, 8) + bounds: 832 200 8 8 + - image: solid-color(105, 25, 0, 255, 8, 8) + bounds: 840 200 8 8 + - image: solid-color(106, 25, 0, 255, 8, 8) + bounds: 848 200 8 8 + - image: solid-color(107, 25, 0, 255, 8, 8) + bounds: 856 200 8 8 + - image: solid-color(108, 25, 0, 255, 8, 8) + bounds: 864 200 8 8 + - image: solid-color(109, 25, 0, 255, 8, 8) + bounds: 872 200 8 8 + - image: solid-color(110, 25, 0, 255, 8, 8) + bounds: 880 200 8 8 + - image: solid-color(111, 25, 0, 255, 8, 8) + bounds: 888 200 8 8 + - image: solid-color(112, 25, 0, 255, 8, 8) + bounds: 896 200 8 8 + - image: solid-color(113, 25, 0, 255, 8, 8) + bounds: 904 200 8 8 + - image: solid-color(114, 25, 0, 255, 8, 8) + bounds: 912 200 8 8 + - image: solid-color(115, 25, 0, 255, 8, 8) + bounds: 920 200 8 8 + - image: solid-color(116, 25, 0, 255, 8, 8) + bounds: 928 200 8 8 + - image: solid-color(117, 25, 0, 255, 8, 8) + bounds: 936 200 8 8 + - image: solid-color(118, 25, 0, 255, 8, 8) + bounds: 944 200 8 8 + - image: solid-color(119, 25, 0, 255, 8, 8) + bounds: 952 200 8 8 + - image: solid-color(120, 25, 0, 255, 8, 8) + bounds: 960 200 8 8 + - image: solid-color(121, 25, 0, 255, 8, 8) + bounds: 968 200 8 8 + - image: solid-color(122, 25, 0, 255, 8, 8) + bounds: 976 200 8 8 + - image: solid-color(123, 25, 0, 255, 8, 8) + bounds: 984 200 8 8 + - image: solid-color(124, 25, 0, 255, 8, 8) + bounds: 992 200 8 8 + - image: solid-color(125, 25, 0, 255, 8, 8) + bounds: 1000 200 8 8 + - image: solid-color(126, 25, 0, 255, 8, 8) + bounds: 1008 200 8 8 + - image: solid-color(127, 25, 0, 255, 8, 8) + bounds: 1016 200 8 8 + - image: solid-color(0, 26, 0, 255, 8, 8) + bounds: 0 208 8 8 + - image: solid-color(1, 26, 0, 255, 8, 8) + bounds: 8 208 8 8 + - image: solid-color(2, 26, 0, 255, 8, 8) + bounds: 16 208 8 8 + - image: solid-color(3, 26, 0, 255, 8, 8) + bounds: 24 208 8 8 + - image: solid-color(4, 26, 0, 255, 8, 8) + bounds: 32 208 8 8 + - image: solid-color(5, 26, 0, 255, 8, 8) + bounds: 40 208 8 8 + - image: solid-color(6, 26, 0, 255, 8, 8) + bounds: 48 208 8 8 + - image: solid-color(7, 26, 0, 255, 8, 8) + bounds: 56 208 8 8 + - image: solid-color(8, 26, 0, 255, 8, 8) + bounds: 64 208 8 8 + - image: solid-color(9, 26, 0, 255, 8, 8) + bounds: 72 208 8 8 + - image: solid-color(10, 26, 0, 255, 8, 8) + bounds: 80 208 8 8 + - image: solid-color(11, 26, 0, 255, 8, 8) + bounds: 88 208 8 8 + - image: solid-color(12, 26, 0, 255, 8, 8) + bounds: 96 208 8 8 + - image: solid-color(13, 26, 0, 255, 8, 8) + bounds: 104 208 8 8 + - image: solid-color(14, 26, 0, 255, 8, 8) + bounds: 112 208 8 8 + - image: solid-color(15, 26, 0, 255, 8, 8) + bounds: 120 208 8 8 + - image: solid-color(16, 26, 0, 255, 8, 8) + bounds: 128 208 8 8 + - image: solid-color(17, 26, 0, 255, 8, 8) + bounds: 136 208 8 8 + - image: solid-color(18, 26, 0, 255, 8, 8) + bounds: 144 208 8 8 + - image: solid-color(19, 26, 0, 255, 8, 8) + bounds: 152 208 8 8 + - image: solid-color(20, 26, 0, 255, 8, 8) + bounds: 160 208 8 8 + - image: solid-color(21, 26, 0, 255, 8, 8) + bounds: 168 208 8 8 + - image: solid-color(22, 26, 0, 255, 8, 8) + bounds: 176 208 8 8 + - image: solid-color(23, 26, 0, 255, 8, 8) + bounds: 184 208 8 8 + - image: solid-color(24, 26, 0, 255, 8, 8) + bounds: 192 208 8 8 + - image: solid-color(25, 26, 0, 255, 8, 8) + bounds: 200 208 8 8 + - image: solid-color(26, 26, 0, 255, 8, 8) + bounds: 208 208 8 8 + - image: solid-color(27, 26, 0, 255, 8, 8) + bounds: 216 208 8 8 + - image: solid-color(28, 26, 0, 255, 8, 8) + bounds: 224 208 8 8 + - image: solid-color(29, 26, 0, 255, 8, 8) + bounds: 232 208 8 8 + - image: solid-color(30, 26, 0, 255, 8, 8) + bounds: 240 208 8 8 + - image: solid-color(31, 26, 0, 255, 8, 8) + bounds: 248 208 8 8 + - image: solid-color(32, 26, 0, 255, 8, 8) + bounds: 256 208 8 8 + - image: solid-color(33, 26, 0, 255, 8, 8) + bounds: 264 208 8 8 + - image: solid-color(34, 26, 0, 255, 8, 8) + bounds: 272 208 8 8 + - image: solid-color(35, 26, 0, 255, 8, 8) + bounds: 280 208 8 8 + - image: solid-color(36, 26, 0, 255, 8, 8) + bounds: 288 208 8 8 + - image: solid-color(37, 26, 0, 255, 8, 8) + bounds: 296 208 8 8 + - image: solid-color(38, 26, 0, 255, 8, 8) + bounds: 304 208 8 8 + - image: solid-color(39, 26, 0, 255, 8, 8) + bounds: 312 208 8 8 + - image: solid-color(40, 26, 0, 255, 8, 8) + bounds: 320 208 8 8 + - image: solid-color(41, 26, 0, 255, 8, 8) + bounds: 328 208 8 8 + - image: solid-color(42, 26, 0, 255, 8, 8) + bounds: 336 208 8 8 + - image: solid-color(43, 26, 0, 255, 8, 8) + bounds: 344 208 8 8 + - image: solid-color(44, 26, 0, 255, 8, 8) + bounds: 352 208 8 8 + - image: solid-color(45, 26, 0, 255, 8, 8) + bounds: 360 208 8 8 + - image: solid-color(46, 26, 0, 255, 8, 8) + bounds: 368 208 8 8 + - image: solid-color(47, 26, 0, 255, 8, 8) + bounds: 376 208 8 8 + - image: solid-color(48, 26, 0, 255, 8, 8) + bounds: 384 208 8 8 + - image: solid-color(49, 26, 0, 255, 8, 8) + bounds: 392 208 8 8 + - image: solid-color(50, 26, 0, 255, 8, 8) + bounds: 400 208 8 8 + - image: solid-color(51, 26, 0, 255, 8, 8) + bounds: 408 208 8 8 + - image: solid-color(52, 26, 0, 255, 8, 8) + bounds: 416 208 8 8 + - image: solid-color(53, 26, 0, 255, 8, 8) + bounds: 424 208 8 8 + - image: solid-color(54, 26, 0, 255, 8, 8) + bounds: 432 208 8 8 + - image: solid-color(55, 26, 0, 255, 8, 8) + bounds: 440 208 8 8 + - image: solid-color(56, 26, 0, 255, 8, 8) + bounds: 448 208 8 8 + - image: solid-color(57, 26, 0, 255, 8, 8) + bounds: 456 208 8 8 + - image: solid-color(58, 26, 0, 255, 8, 8) + bounds: 464 208 8 8 + - image: solid-color(59, 26, 0, 255, 8, 8) + bounds: 472 208 8 8 + - image: solid-color(60, 26, 0, 255, 8, 8) + bounds: 480 208 8 8 + - image: solid-color(61, 26, 0, 255, 8, 8) + bounds: 488 208 8 8 + - image: solid-color(62, 26, 0, 255, 8, 8) + bounds: 496 208 8 8 + - image: solid-color(63, 26, 0, 255, 8, 8) + bounds: 504 208 8 8 + - image: solid-color(64, 26, 0, 255, 8, 8) + bounds: 512 208 8 8 + - image: solid-color(65, 26, 0, 255, 8, 8) + bounds: 520 208 8 8 + - image: solid-color(66, 26, 0, 255, 8, 8) + bounds: 528 208 8 8 + - image: solid-color(67, 26, 0, 255, 8, 8) + bounds: 536 208 8 8 + - image: solid-color(68, 26, 0, 255, 8, 8) + bounds: 544 208 8 8 + - image: solid-color(69, 26, 0, 255, 8, 8) + bounds: 552 208 8 8 + - image: solid-color(70, 26, 0, 255, 8, 8) + bounds: 560 208 8 8 + - image: solid-color(71, 26, 0, 255, 8, 8) + bounds: 568 208 8 8 + - image: solid-color(72, 26, 0, 255, 8, 8) + bounds: 576 208 8 8 + - image: solid-color(73, 26, 0, 255, 8, 8) + bounds: 584 208 8 8 + - image: solid-color(74, 26, 0, 255, 8, 8) + bounds: 592 208 8 8 + - image: solid-color(75, 26, 0, 255, 8, 8) + bounds: 600 208 8 8 + - image: solid-color(76, 26, 0, 255, 8, 8) + bounds: 608 208 8 8 + - image: solid-color(77, 26, 0, 255, 8, 8) + bounds: 616 208 8 8 + - image: solid-color(78, 26, 0, 255, 8, 8) + bounds: 624 208 8 8 + - image: solid-color(79, 26, 0, 255, 8, 8) + bounds: 632 208 8 8 + - image: solid-color(80, 26, 0, 255, 8, 8) + bounds: 640 208 8 8 + - image: solid-color(81, 26, 0, 255, 8, 8) + bounds: 648 208 8 8 + - image: solid-color(82, 26, 0, 255, 8, 8) + bounds: 656 208 8 8 + - image: solid-color(83, 26, 0, 255, 8, 8) + bounds: 664 208 8 8 + - image: solid-color(84, 26, 0, 255, 8, 8) + bounds: 672 208 8 8 + - image: solid-color(85, 26, 0, 255, 8, 8) + bounds: 680 208 8 8 + - image: solid-color(86, 26, 0, 255, 8, 8) + bounds: 688 208 8 8 + - image: solid-color(87, 26, 0, 255, 8, 8) + bounds: 696 208 8 8 + - image: solid-color(88, 26, 0, 255, 8, 8) + bounds: 704 208 8 8 + - image: solid-color(89, 26, 0, 255, 8, 8) + bounds: 712 208 8 8 + - image: solid-color(90, 26, 0, 255, 8, 8) + bounds: 720 208 8 8 + - image: solid-color(91, 26, 0, 255, 8, 8) + bounds: 728 208 8 8 + - image: solid-color(92, 26, 0, 255, 8, 8) + bounds: 736 208 8 8 + - image: solid-color(93, 26, 0, 255, 8, 8) + bounds: 744 208 8 8 + - image: solid-color(94, 26, 0, 255, 8, 8) + bounds: 752 208 8 8 + - image: solid-color(95, 26, 0, 255, 8, 8) + bounds: 760 208 8 8 + - image: solid-color(96, 26, 0, 255, 8, 8) + bounds: 768 208 8 8 + - image: solid-color(97, 26, 0, 255, 8, 8) + bounds: 776 208 8 8 + - image: solid-color(98, 26, 0, 255, 8, 8) + bounds: 784 208 8 8 + - image: solid-color(99, 26, 0, 255, 8, 8) + bounds: 792 208 8 8 + - image: solid-color(100, 26, 0, 255, 8, 8) + bounds: 800 208 8 8 + - image: solid-color(101, 26, 0, 255, 8, 8) + bounds: 808 208 8 8 + - image: solid-color(102, 26, 0, 255, 8, 8) + bounds: 816 208 8 8 + - image: solid-color(103, 26, 0, 255, 8, 8) + bounds: 824 208 8 8 + - image: solid-color(104, 26, 0, 255, 8, 8) + bounds: 832 208 8 8 + - image: solid-color(105, 26, 0, 255, 8, 8) + bounds: 840 208 8 8 + - image: solid-color(106, 26, 0, 255, 8, 8) + bounds: 848 208 8 8 + - image: solid-color(107, 26, 0, 255, 8, 8) + bounds: 856 208 8 8 + - image: solid-color(108, 26, 0, 255, 8, 8) + bounds: 864 208 8 8 + - image: solid-color(109, 26, 0, 255, 8, 8) + bounds: 872 208 8 8 + - image: solid-color(110, 26, 0, 255, 8, 8) + bounds: 880 208 8 8 + - image: solid-color(111, 26, 0, 255, 8, 8) + bounds: 888 208 8 8 + - image: solid-color(112, 26, 0, 255, 8, 8) + bounds: 896 208 8 8 + - image: solid-color(113, 26, 0, 255, 8, 8) + bounds: 904 208 8 8 + - image: solid-color(114, 26, 0, 255, 8, 8) + bounds: 912 208 8 8 + - image: solid-color(115, 26, 0, 255, 8, 8) + bounds: 920 208 8 8 + - image: solid-color(116, 26, 0, 255, 8, 8) + bounds: 928 208 8 8 + - image: solid-color(117, 26, 0, 255, 8, 8) + bounds: 936 208 8 8 + - image: solid-color(118, 26, 0, 255, 8, 8) + bounds: 944 208 8 8 + - image: solid-color(119, 26, 0, 255, 8, 8) + bounds: 952 208 8 8 + - image: solid-color(120, 26, 0, 255, 8, 8) + bounds: 960 208 8 8 + - image: solid-color(121, 26, 0, 255, 8, 8) + bounds: 968 208 8 8 + - image: solid-color(122, 26, 0, 255, 8, 8) + bounds: 976 208 8 8 + - image: solid-color(123, 26, 0, 255, 8, 8) + bounds: 984 208 8 8 + - image: solid-color(124, 26, 0, 255, 8, 8) + bounds: 992 208 8 8 + - image: solid-color(125, 26, 0, 255, 8, 8) + bounds: 1000 208 8 8 + - image: solid-color(126, 26, 0, 255, 8, 8) + bounds: 1008 208 8 8 + - image: solid-color(127, 26, 0, 255, 8, 8) + bounds: 1016 208 8 8 + - image: solid-color(0, 27, 0, 255, 8, 8) + bounds: 0 216 8 8 + - image: solid-color(1, 27, 0, 255, 8, 8) + bounds: 8 216 8 8 + - image: solid-color(2, 27, 0, 255, 8, 8) + bounds: 16 216 8 8 + - image: solid-color(3, 27, 0, 255, 8, 8) + bounds: 24 216 8 8 + - image: solid-color(4, 27, 0, 255, 8, 8) + bounds: 32 216 8 8 + - image: solid-color(5, 27, 0, 255, 8, 8) + bounds: 40 216 8 8 + - image: solid-color(6, 27, 0, 255, 8, 8) + bounds: 48 216 8 8 + - image: solid-color(7, 27, 0, 255, 8, 8) + bounds: 56 216 8 8 + - image: solid-color(8, 27, 0, 255, 8, 8) + bounds: 64 216 8 8 + - image: solid-color(9, 27, 0, 255, 8, 8) + bounds: 72 216 8 8 + - image: solid-color(10, 27, 0, 255, 8, 8) + bounds: 80 216 8 8 + - image: solid-color(11, 27, 0, 255, 8, 8) + bounds: 88 216 8 8 + - image: solid-color(12, 27, 0, 255, 8, 8) + bounds: 96 216 8 8 + - image: solid-color(13, 27, 0, 255, 8, 8) + bounds: 104 216 8 8 + - image: solid-color(14, 27, 0, 255, 8, 8) + bounds: 112 216 8 8 + - image: solid-color(15, 27, 0, 255, 8, 8) + bounds: 120 216 8 8 + - image: solid-color(16, 27, 0, 255, 8, 8) + bounds: 128 216 8 8 + - image: solid-color(17, 27, 0, 255, 8, 8) + bounds: 136 216 8 8 + - image: solid-color(18, 27, 0, 255, 8, 8) + bounds: 144 216 8 8 + - image: solid-color(19, 27, 0, 255, 8, 8) + bounds: 152 216 8 8 + - image: solid-color(20, 27, 0, 255, 8, 8) + bounds: 160 216 8 8 + - image: solid-color(21, 27, 0, 255, 8, 8) + bounds: 168 216 8 8 + - image: solid-color(22, 27, 0, 255, 8, 8) + bounds: 176 216 8 8 + - image: solid-color(23, 27, 0, 255, 8, 8) + bounds: 184 216 8 8 + - image: solid-color(24, 27, 0, 255, 8, 8) + bounds: 192 216 8 8 + - image: solid-color(25, 27, 0, 255, 8, 8) + bounds: 200 216 8 8 + - image: solid-color(26, 27, 0, 255, 8, 8) + bounds: 208 216 8 8 + - image: solid-color(27, 27, 0, 255, 8, 8) + bounds: 216 216 8 8 + - image: solid-color(28, 27, 0, 255, 8, 8) + bounds: 224 216 8 8 + - image: solid-color(29, 27, 0, 255, 8, 8) + bounds: 232 216 8 8 + - image: solid-color(30, 27, 0, 255, 8, 8) + bounds: 240 216 8 8 + - image: solid-color(31, 27, 0, 255, 8, 8) + bounds: 248 216 8 8 + - image: solid-color(32, 27, 0, 255, 8, 8) + bounds: 256 216 8 8 + - image: solid-color(33, 27, 0, 255, 8, 8) + bounds: 264 216 8 8 + - image: solid-color(34, 27, 0, 255, 8, 8) + bounds: 272 216 8 8 + - image: solid-color(35, 27, 0, 255, 8, 8) + bounds: 280 216 8 8 + - image: solid-color(36, 27, 0, 255, 8, 8) + bounds: 288 216 8 8 + - image: solid-color(37, 27, 0, 255, 8, 8) + bounds: 296 216 8 8 + - image: solid-color(38, 27, 0, 255, 8, 8) + bounds: 304 216 8 8 + - image: solid-color(39, 27, 0, 255, 8, 8) + bounds: 312 216 8 8 + - image: solid-color(40, 27, 0, 255, 8, 8) + bounds: 320 216 8 8 + - image: solid-color(41, 27, 0, 255, 8, 8) + bounds: 328 216 8 8 + - image: solid-color(42, 27, 0, 255, 8, 8) + bounds: 336 216 8 8 + - image: solid-color(43, 27, 0, 255, 8, 8) + bounds: 344 216 8 8 + - image: solid-color(44, 27, 0, 255, 8, 8) + bounds: 352 216 8 8 + - image: solid-color(45, 27, 0, 255, 8, 8) + bounds: 360 216 8 8 + - image: solid-color(46, 27, 0, 255, 8, 8) + bounds: 368 216 8 8 + - image: solid-color(47, 27, 0, 255, 8, 8) + bounds: 376 216 8 8 + - image: solid-color(48, 27, 0, 255, 8, 8) + bounds: 384 216 8 8 + - image: solid-color(49, 27, 0, 255, 8, 8) + bounds: 392 216 8 8 + - image: solid-color(50, 27, 0, 255, 8, 8) + bounds: 400 216 8 8 + - image: solid-color(51, 27, 0, 255, 8, 8) + bounds: 408 216 8 8 + - image: solid-color(52, 27, 0, 255, 8, 8) + bounds: 416 216 8 8 + - image: solid-color(53, 27, 0, 255, 8, 8) + bounds: 424 216 8 8 + - image: solid-color(54, 27, 0, 255, 8, 8) + bounds: 432 216 8 8 + - image: solid-color(55, 27, 0, 255, 8, 8) + bounds: 440 216 8 8 + - image: solid-color(56, 27, 0, 255, 8, 8) + bounds: 448 216 8 8 + - image: solid-color(57, 27, 0, 255, 8, 8) + bounds: 456 216 8 8 + - image: solid-color(58, 27, 0, 255, 8, 8) + bounds: 464 216 8 8 + - image: solid-color(59, 27, 0, 255, 8, 8) + bounds: 472 216 8 8 + - image: solid-color(60, 27, 0, 255, 8, 8) + bounds: 480 216 8 8 + - image: solid-color(61, 27, 0, 255, 8, 8) + bounds: 488 216 8 8 + - image: solid-color(62, 27, 0, 255, 8, 8) + bounds: 496 216 8 8 + - image: solid-color(63, 27, 0, 255, 8, 8) + bounds: 504 216 8 8 + - image: solid-color(64, 27, 0, 255, 8, 8) + bounds: 512 216 8 8 + - image: solid-color(65, 27, 0, 255, 8, 8) + bounds: 520 216 8 8 + - image: solid-color(66, 27, 0, 255, 8, 8) + bounds: 528 216 8 8 + - image: solid-color(67, 27, 0, 255, 8, 8) + bounds: 536 216 8 8 + - image: solid-color(68, 27, 0, 255, 8, 8) + bounds: 544 216 8 8 + - image: solid-color(69, 27, 0, 255, 8, 8) + bounds: 552 216 8 8 + - image: solid-color(70, 27, 0, 255, 8, 8) + bounds: 560 216 8 8 + - image: solid-color(71, 27, 0, 255, 8, 8) + bounds: 568 216 8 8 + - image: solid-color(72, 27, 0, 255, 8, 8) + bounds: 576 216 8 8 + - image: solid-color(73, 27, 0, 255, 8, 8) + bounds: 584 216 8 8 + - image: solid-color(74, 27, 0, 255, 8, 8) + bounds: 592 216 8 8 + - image: solid-color(75, 27, 0, 255, 8, 8) + bounds: 600 216 8 8 + - image: solid-color(76, 27, 0, 255, 8, 8) + bounds: 608 216 8 8 + - image: solid-color(77, 27, 0, 255, 8, 8) + bounds: 616 216 8 8 + - image: solid-color(78, 27, 0, 255, 8, 8) + bounds: 624 216 8 8 + - image: solid-color(79, 27, 0, 255, 8, 8) + bounds: 632 216 8 8 + - image: solid-color(80, 27, 0, 255, 8, 8) + bounds: 640 216 8 8 + - image: solid-color(81, 27, 0, 255, 8, 8) + bounds: 648 216 8 8 + - image: solid-color(82, 27, 0, 255, 8, 8) + bounds: 656 216 8 8 + - image: solid-color(83, 27, 0, 255, 8, 8) + bounds: 664 216 8 8 + - image: solid-color(84, 27, 0, 255, 8, 8) + bounds: 672 216 8 8 + - image: solid-color(85, 27, 0, 255, 8, 8) + bounds: 680 216 8 8 + - image: solid-color(86, 27, 0, 255, 8, 8) + bounds: 688 216 8 8 + - image: solid-color(87, 27, 0, 255, 8, 8) + bounds: 696 216 8 8 + - image: solid-color(88, 27, 0, 255, 8, 8) + bounds: 704 216 8 8 + - image: solid-color(89, 27, 0, 255, 8, 8) + bounds: 712 216 8 8 + - image: solid-color(90, 27, 0, 255, 8, 8) + bounds: 720 216 8 8 + - image: solid-color(91, 27, 0, 255, 8, 8) + bounds: 728 216 8 8 + - image: solid-color(92, 27, 0, 255, 8, 8) + bounds: 736 216 8 8 + - image: solid-color(93, 27, 0, 255, 8, 8) + bounds: 744 216 8 8 + - image: solid-color(94, 27, 0, 255, 8, 8) + bounds: 752 216 8 8 + - image: solid-color(95, 27, 0, 255, 8, 8) + bounds: 760 216 8 8 + - image: solid-color(96, 27, 0, 255, 8, 8) + bounds: 768 216 8 8 + - image: solid-color(97, 27, 0, 255, 8, 8) + bounds: 776 216 8 8 + - image: solid-color(98, 27, 0, 255, 8, 8) + bounds: 784 216 8 8 + - image: solid-color(99, 27, 0, 255, 8, 8) + bounds: 792 216 8 8 + - image: solid-color(100, 27, 0, 255, 8, 8) + bounds: 800 216 8 8 + - image: solid-color(101, 27, 0, 255, 8, 8) + bounds: 808 216 8 8 + - image: solid-color(102, 27, 0, 255, 8, 8) + bounds: 816 216 8 8 + - image: solid-color(103, 27, 0, 255, 8, 8) + bounds: 824 216 8 8 + - image: solid-color(104, 27, 0, 255, 8, 8) + bounds: 832 216 8 8 + - image: solid-color(105, 27, 0, 255, 8, 8) + bounds: 840 216 8 8 + - image: solid-color(106, 27, 0, 255, 8, 8) + bounds: 848 216 8 8 + - image: solid-color(107, 27, 0, 255, 8, 8) + bounds: 856 216 8 8 + - image: solid-color(108, 27, 0, 255, 8, 8) + bounds: 864 216 8 8 + - image: solid-color(109, 27, 0, 255, 8, 8) + bounds: 872 216 8 8 + - image: solid-color(110, 27, 0, 255, 8, 8) + bounds: 880 216 8 8 + - image: solid-color(111, 27, 0, 255, 8, 8) + bounds: 888 216 8 8 + - image: solid-color(112, 27, 0, 255, 8, 8) + bounds: 896 216 8 8 + - image: solid-color(113, 27, 0, 255, 8, 8) + bounds: 904 216 8 8 + - image: solid-color(114, 27, 0, 255, 8, 8) + bounds: 912 216 8 8 + - image: solid-color(115, 27, 0, 255, 8, 8) + bounds: 920 216 8 8 + - image: solid-color(116, 27, 0, 255, 8, 8) + bounds: 928 216 8 8 + - image: solid-color(117, 27, 0, 255, 8, 8) + bounds: 936 216 8 8 + - image: solid-color(118, 27, 0, 255, 8, 8) + bounds: 944 216 8 8 + - image: solid-color(119, 27, 0, 255, 8, 8) + bounds: 952 216 8 8 + - image: solid-color(120, 27, 0, 255, 8, 8) + bounds: 960 216 8 8 + - image: solid-color(121, 27, 0, 255, 8, 8) + bounds: 968 216 8 8 + - image: solid-color(122, 27, 0, 255, 8, 8) + bounds: 976 216 8 8 + - image: solid-color(123, 27, 0, 255, 8, 8) + bounds: 984 216 8 8 + - image: solid-color(124, 27, 0, 255, 8, 8) + bounds: 992 216 8 8 + - image: solid-color(125, 27, 0, 255, 8, 8) + bounds: 1000 216 8 8 + - image: solid-color(126, 27, 0, 255, 8, 8) + bounds: 1008 216 8 8 + - image: solid-color(127, 27, 0, 255, 8, 8) + bounds: 1016 216 8 8 + - image: solid-color(0, 28, 0, 255, 8, 8) + bounds: 0 224 8 8 + - image: solid-color(1, 28, 0, 255, 8, 8) + bounds: 8 224 8 8 + - image: solid-color(2, 28, 0, 255, 8, 8) + bounds: 16 224 8 8 + - image: solid-color(3, 28, 0, 255, 8, 8) + bounds: 24 224 8 8 + - image: solid-color(4, 28, 0, 255, 8, 8) + bounds: 32 224 8 8 + - image: solid-color(5, 28, 0, 255, 8, 8) + bounds: 40 224 8 8 + - image: solid-color(6, 28, 0, 255, 8, 8) + bounds: 48 224 8 8 + - image: solid-color(7, 28, 0, 255, 8, 8) + bounds: 56 224 8 8 + - image: solid-color(8, 28, 0, 255, 8, 8) + bounds: 64 224 8 8 + - image: solid-color(9, 28, 0, 255, 8, 8) + bounds: 72 224 8 8 + - image: solid-color(10, 28, 0, 255, 8, 8) + bounds: 80 224 8 8 + - image: solid-color(11, 28, 0, 255, 8, 8) + bounds: 88 224 8 8 + - image: solid-color(12, 28, 0, 255, 8, 8) + bounds: 96 224 8 8 + - image: solid-color(13, 28, 0, 255, 8, 8) + bounds: 104 224 8 8 + - image: solid-color(14, 28, 0, 255, 8, 8) + bounds: 112 224 8 8 + - image: solid-color(15, 28, 0, 255, 8, 8) + bounds: 120 224 8 8 + - image: solid-color(16, 28, 0, 255, 8, 8) + bounds: 128 224 8 8 + - image: solid-color(17, 28, 0, 255, 8, 8) + bounds: 136 224 8 8 + - image: solid-color(18, 28, 0, 255, 8, 8) + bounds: 144 224 8 8 + - image: solid-color(19, 28, 0, 255, 8, 8) + bounds: 152 224 8 8 + - image: solid-color(20, 28, 0, 255, 8, 8) + bounds: 160 224 8 8 + - image: solid-color(21, 28, 0, 255, 8, 8) + bounds: 168 224 8 8 + - image: solid-color(22, 28, 0, 255, 8, 8) + bounds: 176 224 8 8 + - image: solid-color(23, 28, 0, 255, 8, 8) + bounds: 184 224 8 8 + - image: solid-color(24, 28, 0, 255, 8, 8) + bounds: 192 224 8 8 + - image: solid-color(25, 28, 0, 255, 8, 8) + bounds: 200 224 8 8 + - image: solid-color(26, 28, 0, 255, 8, 8) + bounds: 208 224 8 8 + - image: solid-color(27, 28, 0, 255, 8, 8) + bounds: 216 224 8 8 + - image: solid-color(28, 28, 0, 255, 8, 8) + bounds: 224 224 8 8 + - image: solid-color(29, 28, 0, 255, 8, 8) + bounds: 232 224 8 8 + - image: solid-color(30, 28, 0, 255, 8, 8) + bounds: 240 224 8 8 + - image: solid-color(31, 28, 0, 255, 8, 8) + bounds: 248 224 8 8 + - image: solid-color(32, 28, 0, 255, 8, 8) + bounds: 256 224 8 8 + - image: solid-color(33, 28, 0, 255, 8, 8) + bounds: 264 224 8 8 + - image: solid-color(34, 28, 0, 255, 8, 8) + bounds: 272 224 8 8 + - image: solid-color(35, 28, 0, 255, 8, 8) + bounds: 280 224 8 8 + - image: solid-color(36, 28, 0, 255, 8, 8) + bounds: 288 224 8 8 + - image: solid-color(37, 28, 0, 255, 8, 8) + bounds: 296 224 8 8 + - image: solid-color(38, 28, 0, 255, 8, 8) + bounds: 304 224 8 8 + - image: solid-color(39, 28, 0, 255, 8, 8) + bounds: 312 224 8 8 + - image: solid-color(40, 28, 0, 255, 8, 8) + bounds: 320 224 8 8 + - image: solid-color(41, 28, 0, 255, 8, 8) + bounds: 328 224 8 8 + - image: solid-color(42, 28, 0, 255, 8, 8) + bounds: 336 224 8 8 + - image: solid-color(43, 28, 0, 255, 8, 8) + bounds: 344 224 8 8 + - image: solid-color(44, 28, 0, 255, 8, 8) + bounds: 352 224 8 8 + - image: solid-color(45, 28, 0, 255, 8, 8) + bounds: 360 224 8 8 + - image: solid-color(46, 28, 0, 255, 8, 8) + bounds: 368 224 8 8 + - image: solid-color(47, 28, 0, 255, 8, 8) + bounds: 376 224 8 8 + - image: solid-color(48, 28, 0, 255, 8, 8) + bounds: 384 224 8 8 + - image: solid-color(49, 28, 0, 255, 8, 8) + bounds: 392 224 8 8 + - image: solid-color(50, 28, 0, 255, 8, 8) + bounds: 400 224 8 8 + - image: solid-color(51, 28, 0, 255, 8, 8) + bounds: 408 224 8 8 + - image: solid-color(52, 28, 0, 255, 8, 8) + bounds: 416 224 8 8 + - image: solid-color(53, 28, 0, 255, 8, 8) + bounds: 424 224 8 8 + - image: solid-color(54, 28, 0, 255, 8, 8) + bounds: 432 224 8 8 + - image: solid-color(55, 28, 0, 255, 8, 8) + bounds: 440 224 8 8 + - image: solid-color(56, 28, 0, 255, 8, 8) + bounds: 448 224 8 8 + - image: solid-color(57, 28, 0, 255, 8, 8) + bounds: 456 224 8 8 + - image: solid-color(58, 28, 0, 255, 8, 8) + bounds: 464 224 8 8 + - image: solid-color(59, 28, 0, 255, 8, 8) + bounds: 472 224 8 8 + - image: solid-color(60, 28, 0, 255, 8, 8) + bounds: 480 224 8 8 + - image: solid-color(61, 28, 0, 255, 8, 8) + bounds: 488 224 8 8 + - image: solid-color(62, 28, 0, 255, 8, 8) + bounds: 496 224 8 8 + - image: solid-color(63, 28, 0, 255, 8, 8) + bounds: 504 224 8 8 + - image: solid-color(64, 28, 0, 255, 8, 8) + bounds: 512 224 8 8 + - image: solid-color(65, 28, 0, 255, 8, 8) + bounds: 520 224 8 8 + - image: solid-color(66, 28, 0, 255, 8, 8) + bounds: 528 224 8 8 + - image: solid-color(67, 28, 0, 255, 8, 8) + bounds: 536 224 8 8 + - image: solid-color(68, 28, 0, 255, 8, 8) + bounds: 544 224 8 8 + - image: solid-color(69, 28, 0, 255, 8, 8) + bounds: 552 224 8 8 + - image: solid-color(70, 28, 0, 255, 8, 8) + bounds: 560 224 8 8 + - image: solid-color(71, 28, 0, 255, 8, 8) + bounds: 568 224 8 8 + - image: solid-color(72, 28, 0, 255, 8, 8) + bounds: 576 224 8 8 + - image: solid-color(73, 28, 0, 255, 8, 8) + bounds: 584 224 8 8 + - image: solid-color(74, 28, 0, 255, 8, 8) + bounds: 592 224 8 8 + - image: solid-color(75, 28, 0, 255, 8, 8) + bounds: 600 224 8 8 + - image: solid-color(76, 28, 0, 255, 8, 8) + bounds: 608 224 8 8 + - image: solid-color(77, 28, 0, 255, 8, 8) + bounds: 616 224 8 8 + - image: solid-color(78, 28, 0, 255, 8, 8) + bounds: 624 224 8 8 + - image: solid-color(79, 28, 0, 255, 8, 8) + bounds: 632 224 8 8 + - image: solid-color(80, 28, 0, 255, 8, 8) + bounds: 640 224 8 8 + - image: solid-color(81, 28, 0, 255, 8, 8) + bounds: 648 224 8 8 + - image: solid-color(82, 28, 0, 255, 8, 8) + bounds: 656 224 8 8 + - image: solid-color(83, 28, 0, 255, 8, 8) + bounds: 664 224 8 8 + - image: solid-color(84, 28, 0, 255, 8, 8) + bounds: 672 224 8 8 + - image: solid-color(85, 28, 0, 255, 8, 8) + bounds: 680 224 8 8 + - image: solid-color(86, 28, 0, 255, 8, 8) + bounds: 688 224 8 8 + - image: solid-color(87, 28, 0, 255, 8, 8) + bounds: 696 224 8 8 + - image: solid-color(88, 28, 0, 255, 8, 8) + bounds: 704 224 8 8 + - image: solid-color(89, 28, 0, 255, 8, 8) + bounds: 712 224 8 8 + - image: solid-color(90, 28, 0, 255, 8, 8) + bounds: 720 224 8 8 + - image: solid-color(91, 28, 0, 255, 8, 8) + bounds: 728 224 8 8 + - image: solid-color(92, 28, 0, 255, 8, 8) + bounds: 736 224 8 8 + - image: solid-color(93, 28, 0, 255, 8, 8) + bounds: 744 224 8 8 + - image: solid-color(94, 28, 0, 255, 8, 8) + bounds: 752 224 8 8 + - image: solid-color(95, 28, 0, 255, 8, 8) + bounds: 760 224 8 8 + - image: solid-color(96, 28, 0, 255, 8, 8) + bounds: 768 224 8 8 + - image: solid-color(97, 28, 0, 255, 8, 8) + bounds: 776 224 8 8 + - image: solid-color(98, 28, 0, 255, 8, 8) + bounds: 784 224 8 8 + - image: solid-color(99, 28, 0, 255, 8, 8) + bounds: 792 224 8 8 + - image: solid-color(100, 28, 0, 255, 8, 8) + bounds: 800 224 8 8 + - image: solid-color(101, 28, 0, 255, 8, 8) + bounds: 808 224 8 8 + - image: solid-color(102, 28, 0, 255, 8, 8) + bounds: 816 224 8 8 + - image: solid-color(103, 28, 0, 255, 8, 8) + bounds: 824 224 8 8 + - image: solid-color(104, 28, 0, 255, 8, 8) + bounds: 832 224 8 8 + - image: solid-color(105, 28, 0, 255, 8, 8) + bounds: 840 224 8 8 + - image: solid-color(106, 28, 0, 255, 8, 8) + bounds: 848 224 8 8 + - image: solid-color(107, 28, 0, 255, 8, 8) + bounds: 856 224 8 8 + - image: solid-color(108, 28, 0, 255, 8, 8) + bounds: 864 224 8 8 + - image: solid-color(109, 28, 0, 255, 8, 8) + bounds: 872 224 8 8 + - image: solid-color(110, 28, 0, 255, 8, 8) + bounds: 880 224 8 8 + - image: solid-color(111, 28, 0, 255, 8, 8) + bounds: 888 224 8 8 + - image: solid-color(112, 28, 0, 255, 8, 8) + bounds: 896 224 8 8 + - image: solid-color(113, 28, 0, 255, 8, 8) + bounds: 904 224 8 8 + - image: solid-color(114, 28, 0, 255, 8, 8) + bounds: 912 224 8 8 + - image: solid-color(115, 28, 0, 255, 8, 8) + bounds: 920 224 8 8 + - image: solid-color(116, 28, 0, 255, 8, 8) + bounds: 928 224 8 8 + - image: solid-color(117, 28, 0, 255, 8, 8) + bounds: 936 224 8 8 + - image: solid-color(118, 28, 0, 255, 8, 8) + bounds: 944 224 8 8 + - image: solid-color(119, 28, 0, 255, 8, 8) + bounds: 952 224 8 8 + - image: solid-color(120, 28, 0, 255, 8, 8) + bounds: 960 224 8 8 + - image: solid-color(121, 28, 0, 255, 8, 8) + bounds: 968 224 8 8 + - image: solid-color(122, 28, 0, 255, 8, 8) + bounds: 976 224 8 8 + - image: solid-color(123, 28, 0, 255, 8, 8) + bounds: 984 224 8 8 + - image: solid-color(124, 28, 0, 255, 8, 8) + bounds: 992 224 8 8 + - image: solid-color(125, 28, 0, 255, 8, 8) + bounds: 1000 224 8 8 + - image: solid-color(126, 28, 0, 255, 8, 8) + bounds: 1008 224 8 8 + - image: solid-color(127, 28, 0, 255, 8, 8) + bounds: 1016 224 8 8 + - image: solid-color(0, 29, 0, 255, 8, 8) + bounds: 0 232 8 8 + - image: solid-color(1, 29, 0, 255, 8, 8) + bounds: 8 232 8 8 + - image: solid-color(2, 29, 0, 255, 8, 8) + bounds: 16 232 8 8 + - image: solid-color(3, 29, 0, 255, 8, 8) + bounds: 24 232 8 8 + - image: solid-color(4, 29, 0, 255, 8, 8) + bounds: 32 232 8 8 + - image: solid-color(5, 29, 0, 255, 8, 8) + bounds: 40 232 8 8 + - image: solid-color(6, 29, 0, 255, 8, 8) + bounds: 48 232 8 8 + - image: solid-color(7, 29, 0, 255, 8, 8) + bounds: 56 232 8 8 + - image: solid-color(8, 29, 0, 255, 8, 8) + bounds: 64 232 8 8 + - image: solid-color(9, 29, 0, 255, 8, 8) + bounds: 72 232 8 8 + - image: solid-color(10, 29, 0, 255, 8, 8) + bounds: 80 232 8 8 + - image: solid-color(11, 29, 0, 255, 8, 8) + bounds: 88 232 8 8 + - image: solid-color(12, 29, 0, 255, 8, 8) + bounds: 96 232 8 8 + - image: solid-color(13, 29, 0, 255, 8, 8) + bounds: 104 232 8 8 + - image: solid-color(14, 29, 0, 255, 8, 8) + bounds: 112 232 8 8 + - image: solid-color(15, 29, 0, 255, 8, 8) + bounds: 120 232 8 8 + - image: solid-color(16, 29, 0, 255, 8, 8) + bounds: 128 232 8 8 + - image: solid-color(17, 29, 0, 255, 8, 8) + bounds: 136 232 8 8 + - image: solid-color(18, 29, 0, 255, 8, 8) + bounds: 144 232 8 8 + - image: solid-color(19, 29, 0, 255, 8, 8) + bounds: 152 232 8 8 + - image: solid-color(20, 29, 0, 255, 8, 8) + bounds: 160 232 8 8 + - image: solid-color(21, 29, 0, 255, 8, 8) + bounds: 168 232 8 8 + - image: solid-color(22, 29, 0, 255, 8, 8) + bounds: 176 232 8 8 + - image: solid-color(23, 29, 0, 255, 8, 8) + bounds: 184 232 8 8 + - image: solid-color(24, 29, 0, 255, 8, 8) + bounds: 192 232 8 8 + - image: solid-color(25, 29, 0, 255, 8, 8) + bounds: 200 232 8 8 + - image: solid-color(26, 29, 0, 255, 8, 8) + bounds: 208 232 8 8 + - image: solid-color(27, 29, 0, 255, 8, 8) + bounds: 216 232 8 8 + - image: solid-color(28, 29, 0, 255, 8, 8) + bounds: 224 232 8 8 + - image: solid-color(29, 29, 0, 255, 8, 8) + bounds: 232 232 8 8 + - image: solid-color(30, 29, 0, 255, 8, 8) + bounds: 240 232 8 8 + - image: solid-color(31, 29, 0, 255, 8, 8) + bounds: 248 232 8 8 + - image: solid-color(32, 29, 0, 255, 8, 8) + bounds: 256 232 8 8 + - image: solid-color(33, 29, 0, 255, 8, 8) + bounds: 264 232 8 8 + - image: solid-color(34, 29, 0, 255, 8, 8) + bounds: 272 232 8 8 + - image: solid-color(35, 29, 0, 255, 8, 8) + bounds: 280 232 8 8 + - image: solid-color(36, 29, 0, 255, 8, 8) + bounds: 288 232 8 8 + - image: solid-color(37, 29, 0, 255, 8, 8) + bounds: 296 232 8 8 + - image: solid-color(38, 29, 0, 255, 8, 8) + bounds: 304 232 8 8 + - image: solid-color(39, 29, 0, 255, 8, 8) + bounds: 312 232 8 8 + - image: solid-color(40, 29, 0, 255, 8, 8) + bounds: 320 232 8 8 + - image: solid-color(41, 29, 0, 255, 8, 8) + bounds: 328 232 8 8 + - image: solid-color(42, 29, 0, 255, 8, 8) + bounds: 336 232 8 8 + - image: solid-color(43, 29, 0, 255, 8, 8) + bounds: 344 232 8 8 + - image: solid-color(44, 29, 0, 255, 8, 8) + bounds: 352 232 8 8 + - image: solid-color(45, 29, 0, 255, 8, 8) + bounds: 360 232 8 8 + - image: solid-color(46, 29, 0, 255, 8, 8) + bounds: 368 232 8 8 + - image: solid-color(47, 29, 0, 255, 8, 8) + bounds: 376 232 8 8 + - image: solid-color(48, 29, 0, 255, 8, 8) + bounds: 384 232 8 8 + - image: solid-color(49, 29, 0, 255, 8, 8) + bounds: 392 232 8 8 + - image: solid-color(50, 29, 0, 255, 8, 8) + bounds: 400 232 8 8 + - image: solid-color(51, 29, 0, 255, 8, 8) + bounds: 408 232 8 8 + - image: solid-color(52, 29, 0, 255, 8, 8) + bounds: 416 232 8 8 + - image: solid-color(53, 29, 0, 255, 8, 8) + bounds: 424 232 8 8 + - image: solid-color(54, 29, 0, 255, 8, 8) + bounds: 432 232 8 8 + - image: solid-color(55, 29, 0, 255, 8, 8) + bounds: 440 232 8 8 + - image: solid-color(56, 29, 0, 255, 8, 8) + bounds: 448 232 8 8 + - image: solid-color(57, 29, 0, 255, 8, 8) + bounds: 456 232 8 8 + - image: solid-color(58, 29, 0, 255, 8, 8) + bounds: 464 232 8 8 + - image: solid-color(59, 29, 0, 255, 8, 8) + bounds: 472 232 8 8 + - image: solid-color(60, 29, 0, 255, 8, 8) + bounds: 480 232 8 8 + - image: solid-color(61, 29, 0, 255, 8, 8) + bounds: 488 232 8 8 + - image: solid-color(62, 29, 0, 255, 8, 8) + bounds: 496 232 8 8 + - image: solid-color(63, 29, 0, 255, 8, 8) + bounds: 504 232 8 8 + - image: solid-color(64, 29, 0, 255, 8, 8) + bounds: 512 232 8 8 + - image: solid-color(65, 29, 0, 255, 8, 8) + bounds: 520 232 8 8 + - image: solid-color(66, 29, 0, 255, 8, 8) + bounds: 528 232 8 8 + - image: solid-color(67, 29, 0, 255, 8, 8) + bounds: 536 232 8 8 + - image: solid-color(68, 29, 0, 255, 8, 8) + bounds: 544 232 8 8 + - image: solid-color(69, 29, 0, 255, 8, 8) + bounds: 552 232 8 8 + - image: solid-color(70, 29, 0, 255, 8, 8) + bounds: 560 232 8 8 + - image: solid-color(71, 29, 0, 255, 8, 8) + bounds: 568 232 8 8 + - image: solid-color(72, 29, 0, 255, 8, 8) + bounds: 576 232 8 8 + - image: solid-color(73, 29, 0, 255, 8, 8) + bounds: 584 232 8 8 + - image: solid-color(74, 29, 0, 255, 8, 8) + bounds: 592 232 8 8 + - image: solid-color(75, 29, 0, 255, 8, 8) + bounds: 600 232 8 8 + - image: solid-color(76, 29, 0, 255, 8, 8) + bounds: 608 232 8 8 + - image: solid-color(77, 29, 0, 255, 8, 8) + bounds: 616 232 8 8 + - image: solid-color(78, 29, 0, 255, 8, 8) + bounds: 624 232 8 8 + - image: solid-color(79, 29, 0, 255, 8, 8) + bounds: 632 232 8 8 + - image: solid-color(80, 29, 0, 255, 8, 8) + bounds: 640 232 8 8 + - image: solid-color(81, 29, 0, 255, 8, 8) + bounds: 648 232 8 8 + - image: solid-color(82, 29, 0, 255, 8, 8) + bounds: 656 232 8 8 + - image: solid-color(83, 29, 0, 255, 8, 8) + bounds: 664 232 8 8 + - image: solid-color(84, 29, 0, 255, 8, 8) + bounds: 672 232 8 8 + - image: solid-color(85, 29, 0, 255, 8, 8) + bounds: 680 232 8 8 + - image: solid-color(86, 29, 0, 255, 8, 8) + bounds: 688 232 8 8 + - image: solid-color(87, 29, 0, 255, 8, 8) + bounds: 696 232 8 8 + - image: solid-color(88, 29, 0, 255, 8, 8) + bounds: 704 232 8 8 + - image: solid-color(89, 29, 0, 255, 8, 8) + bounds: 712 232 8 8 + - image: solid-color(90, 29, 0, 255, 8, 8) + bounds: 720 232 8 8 + - image: solid-color(91, 29, 0, 255, 8, 8) + bounds: 728 232 8 8 + - image: solid-color(92, 29, 0, 255, 8, 8) + bounds: 736 232 8 8 + - image: solid-color(93, 29, 0, 255, 8, 8) + bounds: 744 232 8 8 + - image: solid-color(94, 29, 0, 255, 8, 8) + bounds: 752 232 8 8 + - image: solid-color(95, 29, 0, 255, 8, 8) + bounds: 760 232 8 8 + - image: solid-color(96, 29, 0, 255, 8, 8) + bounds: 768 232 8 8 + - image: solid-color(97, 29, 0, 255, 8, 8) + bounds: 776 232 8 8 + - image: solid-color(98, 29, 0, 255, 8, 8) + bounds: 784 232 8 8 + - image: solid-color(99, 29, 0, 255, 8, 8) + bounds: 792 232 8 8 + - image: solid-color(100, 29, 0, 255, 8, 8) + bounds: 800 232 8 8 + - image: solid-color(101, 29, 0, 255, 8, 8) + bounds: 808 232 8 8 + - image: solid-color(102, 29, 0, 255, 8, 8) + bounds: 816 232 8 8 + - image: solid-color(103, 29, 0, 255, 8, 8) + bounds: 824 232 8 8 + - image: solid-color(104, 29, 0, 255, 8, 8) + bounds: 832 232 8 8 + - image: solid-color(105, 29, 0, 255, 8, 8) + bounds: 840 232 8 8 + - image: solid-color(106, 29, 0, 255, 8, 8) + bounds: 848 232 8 8 + - image: solid-color(107, 29, 0, 255, 8, 8) + bounds: 856 232 8 8 + - image: solid-color(108, 29, 0, 255, 8, 8) + bounds: 864 232 8 8 + - image: solid-color(109, 29, 0, 255, 8, 8) + bounds: 872 232 8 8 + - image: solid-color(110, 29, 0, 255, 8, 8) + bounds: 880 232 8 8 + - image: solid-color(111, 29, 0, 255, 8, 8) + bounds: 888 232 8 8 + - image: solid-color(112, 29, 0, 255, 8, 8) + bounds: 896 232 8 8 + - image: solid-color(113, 29, 0, 255, 8, 8) + bounds: 904 232 8 8 + - image: solid-color(114, 29, 0, 255, 8, 8) + bounds: 912 232 8 8 + - image: solid-color(115, 29, 0, 255, 8, 8) + bounds: 920 232 8 8 + - image: solid-color(116, 29, 0, 255, 8, 8) + bounds: 928 232 8 8 + - image: solid-color(117, 29, 0, 255, 8, 8) + bounds: 936 232 8 8 + - image: solid-color(118, 29, 0, 255, 8, 8) + bounds: 944 232 8 8 + - image: solid-color(119, 29, 0, 255, 8, 8) + bounds: 952 232 8 8 + - image: solid-color(120, 29, 0, 255, 8, 8) + bounds: 960 232 8 8 + - image: solid-color(121, 29, 0, 255, 8, 8) + bounds: 968 232 8 8 + - image: solid-color(122, 29, 0, 255, 8, 8) + bounds: 976 232 8 8 + - image: solid-color(123, 29, 0, 255, 8, 8) + bounds: 984 232 8 8 + - image: solid-color(124, 29, 0, 255, 8, 8) + bounds: 992 232 8 8 + - image: solid-color(125, 29, 0, 255, 8, 8) + bounds: 1000 232 8 8 + - image: solid-color(126, 29, 0, 255, 8, 8) + bounds: 1008 232 8 8 + - image: solid-color(127, 29, 0, 255, 8, 8) + bounds: 1016 232 8 8 + - image: solid-color(0, 30, 0, 255, 8, 8) + bounds: 0 240 8 8 + - image: solid-color(1, 30, 0, 255, 8, 8) + bounds: 8 240 8 8 + - image: solid-color(2, 30, 0, 255, 8, 8) + bounds: 16 240 8 8 + - image: solid-color(3, 30, 0, 255, 8, 8) + bounds: 24 240 8 8 + - image: solid-color(4, 30, 0, 255, 8, 8) + bounds: 32 240 8 8 + - image: solid-color(5, 30, 0, 255, 8, 8) + bounds: 40 240 8 8 + - image: solid-color(6, 30, 0, 255, 8, 8) + bounds: 48 240 8 8 + - image: solid-color(7, 30, 0, 255, 8, 8) + bounds: 56 240 8 8 + - image: solid-color(8, 30, 0, 255, 8, 8) + bounds: 64 240 8 8 + - image: solid-color(9, 30, 0, 255, 8, 8) + bounds: 72 240 8 8 + - image: solid-color(10, 30, 0, 255, 8, 8) + bounds: 80 240 8 8 + - image: solid-color(11, 30, 0, 255, 8, 8) + bounds: 88 240 8 8 + - image: solid-color(12, 30, 0, 255, 8, 8) + bounds: 96 240 8 8 + - image: solid-color(13, 30, 0, 255, 8, 8) + bounds: 104 240 8 8 + - image: solid-color(14, 30, 0, 255, 8, 8) + bounds: 112 240 8 8 + - image: solid-color(15, 30, 0, 255, 8, 8) + bounds: 120 240 8 8 + - image: solid-color(16, 30, 0, 255, 8, 8) + bounds: 128 240 8 8 + - image: solid-color(17, 30, 0, 255, 8, 8) + bounds: 136 240 8 8 + - image: solid-color(18, 30, 0, 255, 8, 8) + bounds: 144 240 8 8 + - image: solid-color(19, 30, 0, 255, 8, 8) + bounds: 152 240 8 8 + - image: solid-color(20, 30, 0, 255, 8, 8) + bounds: 160 240 8 8 + - image: solid-color(21, 30, 0, 255, 8, 8) + bounds: 168 240 8 8 + - image: solid-color(22, 30, 0, 255, 8, 8) + bounds: 176 240 8 8 + - image: solid-color(23, 30, 0, 255, 8, 8) + bounds: 184 240 8 8 + - image: solid-color(24, 30, 0, 255, 8, 8) + bounds: 192 240 8 8 + - image: solid-color(25, 30, 0, 255, 8, 8) + bounds: 200 240 8 8 + - image: solid-color(26, 30, 0, 255, 8, 8) + bounds: 208 240 8 8 + - image: solid-color(27, 30, 0, 255, 8, 8) + bounds: 216 240 8 8 + - image: solid-color(28, 30, 0, 255, 8, 8) + bounds: 224 240 8 8 + - image: solid-color(29, 30, 0, 255, 8, 8) + bounds: 232 240 8 8 + - image: solid-color(30, 30, 0, 255, 8, 8) + bounds: 240 240 8 8 + - image: solid-color(31, 30, 0, 255, 8, 8) + bounds: 248 240 8 8 + - image: solid-color(32, 30, 0, 255, 8, 8) + bounds: 256 240 8 8 + - image: solid-color(33, 30, 0, 255, 8, 8) + bounds: 264 240 8 8 + - image: solid-color(34, 30, 0, 255, 8, 8) + bounds: 272 240 8 8 + - image: solid-color(35, 30, 0, 255, 8, 8) + bounds: 280 240 8 8 + - image: solid-color(36, 30, 0, 255, 8, 8) + bounds: 288 240 8 8 + - image: solid-color(37, 30, 0, 255, 8, 8) + bounds: 296 240 8 8 + - image: solid-color(38, 30, 0, 255, 8, 8) + bounds: 304 240 8 8 + - image: solid-color(39, 30, 0, 255, 8, 8) + bounds: 312 240 8 8 + - image: solid-color(40, 30, 0, 255, 8, 8) + bounds: 320 240 8 8 + - image: solid-color(41, 30, 0, 255, 8, 8) + bounds: 328 240 8 8 + - image: solid-color(42, 30, 0, 255, 8, 8) + bounds: 336 240 8 8 + - image: solid-color(43, 30, 0, 255, 8, 8) + bounds: 344 240 8 8 + - image: solid-color(44, 30, 0, 255, 8, 8) + bounds: 352 240 8 8 + - image: solid-color(45, 30, 0, 255, 8, 8) + bounds: 360 240 8 8 + - image: solid-color(46, 30, 0, 255, 8, 8) + bounds: 368 240 8 8 + - image: solid-color(47, 30, 0, 255, 8, 8) + bounds: 376 240 8 8 + - image: solid-color(48, 30, 0, 255, 8, 8) + bounds: 384 240 8 8 + - image: solid-color(49, 30, 0, 255, 8, 8) + bounds: 392 240 8 8 + - image: solid-color(50, 30, 0, 255, 8, 8) + bounds: 400 240 8 8 + - image: solid-color(51, 30, 0, 255, 8, 8) + bounds: 408 240 8 8 + - image: solid-color(52, 30, 0, 255, 8, 8) + bounds: 416 240 8 8 + - image: solid-color(53, 30, 0, 255, 8, 8) + bounds: 424 240 8 8 + - image: solid-color(54, 30, 0, 255, 8, 8) + bounds: 432 240 8 8 + - image: solid-color(55, 30, 0, 255, 8, 8) + bounds: 440 240 8 8 + - image: solid-color(56, 30, 0, 255, 8, 8) + bounds: 448 240 8 8 + - image: solid-color(57, 30, 0, 255, 8, 8) + bounds: 456 240 8 8 + - image: solid-color(58, 30, 0, 255, 8, 8) + bounds: 464 240 8 8 + - image: solid-color(59, 30, 0, 255, 8, 8) + bounds: 472 240 8 8 + - image: solid-color(60, 30, 0, 255, 8, 8) + bounds: 480 240 8 8 + - image: solid-color(61, 30, 0, 255, 8, 8) + bounds: 488 240 8 8 + - image: solid-color(62, 30, 0, 255, 8, 8) + bounds: 496 240 8 8 + - image: solid-color(63, 30, 0, 255, 8, 8) + bounds: 504 240 8 8 + - image: solid-color(64, 30, 0, 255, 8, 8) + bounds: 512 240 8 8 + - image: solid-color(65, 30, 0, 255, 8, 8) + bounds: 520 240 8 8 + - image: solid-color(66, 30, 0, 255, 8, 8) + bounds: 528 240 8 8 + - image: solid-color(67, 30, 0, 255, 8, 8) + bounds: 536 240 8 8 + - image: solid-color(68, 30, 0, 255, 8, 8) + bounds: 544 240 8 8 + - image: solid-color(69, 30, 0, 255, 8, 8) + bounds: 552 240 8 8 + - image: solid-color(70, 30, 0, 255, 8, 8) + bounds: 560 240 8 8 + - image: solid-color(71, 30, 0, 255, 8, 8) + bounds: 568 240 8 8 + - image: solid-color(72, 30, 0, 255, 8, 8) + bounds: 576 240 8 8 + - image: solid-color(73, 30, 0, 255, 8, 8) + bounds: 584 240 8 8 + - image: solid-color(74, 30, 0, 255, 8, 8) + bounds: 592 240 8 8 + - image: solid-color(75, 30, 0, 255, 8, 8) + bounds: 600 240 8 8 + - image: solid-color(76, 30, 0, 255, 8, 8) + bounds: 608 240 8 8 + - image: solid-color(77, 30, 0, 255, 8, 8) + bounds: 616 240 8 8 + - image: solid-color(78, 30, 0, 255, 8, 8) + bounds: 624 240 8 8 + - image: solid-color(79, 30, 0, 255, 8, 8) + bounds: 632 240 8 8 + - image: solid-color(80, 30, 0, 255, 8, 8) + bounds: 640 240 8 8 + - image: solid-color(81, 30, 0, 255, 8, 8) + bounds: 648 240 8 8 + - image: solid-color(82, 30, 0, 255, 8, 8) + bounds: 656 240 8 8 + - image: solid-color(83, 30, 0, 255, 8, 8) + bounds: 664 240 8 8 + - image: solid-color(84, 30, 0, 255, 8, 8) + bounds: 672 240 8 8 + - image: solid-color(85, 30, 0, 255, 8, 8) + bounds: 680 240 8 8 + - image: solid-color(86, 30, 0, 255, 8, 8) + bounds: 688 240 8 8 + - image: solid-color(87, 30, 0, 255, 8, 8) + bounds: 696 240 8 8 + - image: solid-color(88, 30, 0, 255, 8, 8) + bounds: 704 240 8 8 + - image: solid-color(89, 30, 0, 255, 8, 8) + bounds: 712 240 8 8 + - image: solid-color(90, 30, 0, 255, 8, 8) + bounds: 720 240 8 8 + - image: solid-color(91, 30, 0, 255, 8, 8) + bounds: 728 240 8 8 + - image: solid-color(92, 30, 0, 255, 8, 8) + bounds: 736 240 8 8 + - image: solid-color(93, 30, 0, 255, 8, 8) + bounds: 744 240 8 8 + - image: solid-color(94, 30, 0, 255, 8, 8) + bounds: 752 240 8 8 + - image: solid-color(95, 30, 0, 255, 8, 8) + bounds: 760 240 8 8 + - image: solid-color(96, 30, 0, 255, 8, 8) + bounds: 768 240 8 8 + - image: solid-color(97, 30, 0, 255, 8, 8) + bounds: 776 240 8 8 + - image: solid-color(98, 30, 0, 255, 8, 8) + bounds: 784 240 8 8 + - image: solid-color(99, 30, 0, 255, 8, 8) + bounds: 792 240 8 8 + - image: solid-color(100, 30, 0, 255, 8, 8) + bounds: 800 240 8 8 + - image: solid-color(101, 30, 0, 255, 8, 8) + bounds: 808 240 8 8 + - image: solid-color(102, 30, 0, 255, 8, 8) + bounds: 816 240 8 8 + - image: solid-color(103, 30, 0, 255, 8, 8) + bounds: 824 240 8 8 + - image: solid-color(104, 30, 0, 255, 8, 8) + bounds: 832 240 8 8 + - image: solid-color(105, 30, 0, 255, 8, 8) + bounds: 840 240 8 8 + - image: solid-color(106, 30, 0, 255, 8, 8) + bounds: 848 240 8 8 + - image: solid-color(107, 30, 0, 255, 8, 8) + bounds: 856 240 8 8 + - image: solid-color(108, 30, 0, 255, 8, 8) + bounds: 864 240 8 8 + - image: solid-color(109, 30, 0, 255, 8, 8) + bounds: 872 240 8 8 + - image: solid-color(110, 30, 0, 255, 8, 8) + bounds: 880 240 8 8 + - image: solid-color(111, 30, 0, 255, 8, 8) + bounds: 888 240 8 8 + - image: solid-color(112, 30, 0, 255, 8, 8) + bounds: 896 240 8 8 + - image: solid-color(113, 30, 0, 255, 8, 8) + bounds: 904 240 8 8 + - image: solid-color(114, 30, 0, 255, 8, 8) + bounds: 912 240 8 8 + - image: solid-color(115, 30, 0, 255, 8, 8) + bounds: 920 240 8 8 + - image: solid-color(116, 30, 0, 255, 8, 8) + bounds: 928 240 8 8 + - image: solid-color(117, 30, 0, 255, 8, 8) + bounds: 936 240 8 8 + - image: solid-color(118, 30, 0, 255, 8, 8) + bounds: 944 240 8 8 + - image: solid-color(119, 30, 0, 255, 8, 8) + bounds: 952 240 8 8 + - image: solid-color(120, 30, 0, 255, 8, 8) + bounds: 960 240 8 8 + - image: solid-color(121, 30, 0, 255, 8, 8) + bounds: 968 240 8 8 + - image: solid-color(122, 30, 0, 255, 8, 8) + bounds: 976 240 8 8 + - image: solid-color(123, 30, 0, 255, 8, 8) + bounds: 984 240 8 8 + - image: solid-color(124, 30, 0, 255, 8, 8) + bounds: 992 240 8 8 + - image: solid-color(125, 30, 0, 255, 8, 8) + bounds: 1000 240 8 8 + - image: solid-color(126, 30, 0, 255, 8, 8) + bounds: 1008 240 8 8 + - image: solid-color(127, 30, 0, 255, 8, 8) + bounds: 1016 240 8 8 + - image: solid-color(0, 31, 0, 255, 8, 8) + bounds: 0 248 8 8 + - image: solid-color(1, 31, 0, 255, 8, 8) + bounds: 8 248 8 8 + - image: solid-color(2, 31, 0, 255, 8, 8) + bounds: 16 248 8 8 + - image: solid-color(3, 31, 0, 255, 8, 8) + bounds: 24 248 8 8 + - image: solid-color(4, 31, 0, 255, 8, 8) + bounds: 32 248 8 8 + - image: solid-color(5, 31, 0, 255, 8, 8) + bounds: 40 248 8 8 + - image: solid-color(6, 31, 0, 255, 8, 8) + bounds: 48 248 8 8 + - image: solid-color(7, 31, 0, 255, 8, 8) + bounds: 56 248 8 8 + - image: solid-color(8, 31, 0, 255, 8, 8) + bounds: 64 248 8 8 + - image: solid-color(9, 31, 0, 255, 8, 8) + bounds: 72 248 8 8 + - image: solid-color(10, 31, 0, 255, 8, 8) + bounds: 80 248 8 8 + - image: solid-color(11, 31, 0, 255, 8, 8) + bounds: 88 248 8 8 + - image: solid-color(12, 31, 0, 255, 8, 8) + bounds: 96 248 8 8 + - image: solid-color(13, 31, 0, 255, 8, 8) + bounds: 104 248 8 8 + - image: solid-color(14, 31, 0, 255, 8, 8) + bounds: 112 248 8 8 + - image: solid-color(15, 31, 0, 255, 8, 8) + bounds: 120 248 8 8 + - image: solid-color(16, 31, 0, 255, 8, 8) + bounds: 128 248 8 8 + - image: solid-color(17, 31, 0, 255, 8, 8) + bounds: 136 248 8 8 + - image: solid-color(18, 31, 0, 255, 8, 8) + bounds: 144 248 8 8 + - image: solid-color(19, 31, 0, 255, 8, 8) + bounds: 152 248 8 8 + - image: solid-color(20, 31, 0, 255, 8, 8) + bounds: 160 248 8 8 + - image: solid-color(21, 31, 0, 255, 8, 8) + bounds: 168 248 8 8 + - image: solid-color(22, 31, 0, 255, 8, 8) + bounds: 176 248 8 8 + - image: solid-color(23, 31, 0, 255, 8, 8) + bounds: 184 248 8 8 + - image: solid-color(24, 31, 0, 255, 8, 8) + bounds: 192 248 8 8 + - image: solid-color(25, 31, 0, 255, 8, 8) + bounds: 200 248 8 8 + - image: solid-color(26, 31, 0, 255, 8, 8) + bounds: 208 248 8 8 + - image: solid-color(27, 31, 0, 255, 8, 8) + bounds: 216 248 8 8 + - image: solid-color(28, 31, 0, 255, 8, 8) + bounds: 224 248 8 8 + - image: solid-color(29, 31, 0, 255, 8, 8) + bounds: 232 248 8 8 + - image: solid-color(30, 31, 0, 255, 8, 8) + bounds: 240 248 8 8 + - image: solid-color(31, 31, 0, 255, 8, 8) + bounds: 248 248 8 8 + - image: solid-color(32, 31, 0, 255, 8, 8) + bounds: 256 248 8 8 + - image: solid-color(33, 31, 0, 255, 8, 8) + bounds: 264 248 8 8 + - image: solid-color(34, 31, 0, 255, 8, 8) + bounds: 272 248 8 8 + - image: solid-color(35, 31, 0, 255, 8, 8) + bounds: 280 248 8 8 + - image: solid-color(36, 31, 0, 255, 8, 8) + bounds: 288 248 8 8 + - image: solid-color(37, 31, 0, 255, 8, 8) + bounds: 296 248 8 8 + - image: solid-color(38, 31, 0, 255, 8, 8) + bounds: 304 248 8 8 + - image: solid-color(39, 31, 0, 255, 8, 8) + bounds: 312 248 8 8 + - image: solid-color(40, 31, 0, 255, 8, 8) + bounds: 320 248 8 8 + - image: solid-color(41, 31, 0, 255, 8, 8) + bounds: 328 248 8 8 + - image: solid-color(42, 31, 0, 255, 8, 8) + bounds: 336 248 8 8 + - image: solid-color(43, 31, 0, 255, 8, 8) + bounds: 344 248 8 8 + - image: solid-color(44, 31, 0, 255, 8, 8) + bounds: 352 248 8 8 + - image: solid-color(45, 31, 0, 255, 8, 8) + bounds: 360 248 8 8 + - image: solid-color(46, 31, 0, 255, 8, 8) + bounds: 368 248 8 8 + - image: solid-color(47, 31, 0, 255, 8, 8) + bounds: 376 248 8 8 + - image: solid-color(48, 31, 0, 255, 8, 8) + bounds: 384 248 8 8 + - image: solid-color(49, 31, 0, 255, 8, 8) + bounds: 392 248 8 8 + - image: solid-color(50, 31, 0, 255, 8, 8) + bounds: 400 248 8 8 + - image: solid-color(51, 31, 0, 255, 8, 8) + bounds: 408 248 8 8 + - image: solid-color(52, 31, 0, 255, 8, 8) + bounds: 416 248 8 8 + - image: solid-color(53, 31, 0, 255, 8, 8) + bounds: 424 248 8 8 + - image: solid-color(54, 31, 0, 255, 8, 8) + bounds: 432 248 8 8 + - image: solid-color(55, 31, 0, 255, 8, 8) + bounds: 440 248 8 8 + - image: solid-color(56, 31, 0, 255, 8, 8) + bounds: 448 248 8 8 + - image: solid-color(57, 31, 0, 255, 8, 8) + bounds: 456 248 8 8 + - image: solid-color(58, 31, 0, 255, 8, 8) + bounds: 464 248 8 8 + - image: solid-color(59, 31, 0, 255, 8, 8) + bounds: 472 248 8 8 + - image: solid-color(60, 31, 0, 255, 8, 8) + bounds: 480 248 8 8 + - image: solid-color(61, 31, 0, 255, 8, 8) + bounds: 488 248 8 8 + - image: solid-color(62, 31, 0, 255, 8, 8) + bounds: 496 248 8 8 + - image: solid-color(63, 31, 0, 255, 8, 8) + bounds: 504 248 8 8 + - image: solid-color(64, 31, 0, 255, 8, 8) + bounds: 512 248 8 8 + - image: solid-color(65, 31, 0, 255, 8, 8) + bounds: 520 248 8 8 + - image: solid-color(66, 31, 0, 255, 8, 8) + bounds: 528 248 8 8 + - image: solid-color(67, 31, 0, 255, 8, 8) + bounds: 536 248 8 8 + - image: solid-color(68, 31, 0, 255, 8, 8) + bounds: 544 248 8 8 + - image: solid-color(69, 31, 0, 255, 8, 8) + bounds: 552 248 8 8 + - image: solid-color(70, 31, 0, 255, 8, 8) + bounds: 560 248 8 8 + - image: solid-color(71, 31, 0, 255, 8, 8) + bounds: 568 248 8 8 + - image: solid-color(72, 31, 0, 255, 8, 8) + bounds: 576 248 8 8 + - image: solid-color(73, 31, 0, 255, 8, 8) + bounds: 584 248 8 8 + - image: solid-color(74, 31, 0, 255, 8, 8) + bounds: 592 248 8 8 + - image: solid-color(75, 31, 0, 255, 8, 8) + bounds: 600 248 8 8 + - image: solid-color(76, 31, 0, 255, 8, 8) + bounds: 608 248 8 8 + - image: solid-color(77, 31, 0, 255, 8, 8) + bounds: 616 248 8 8 + - image: solid-color(78, 31, 0, 255, 8, 8) + bounds: 624 248 8 8 + - image: solid-color(79, 31, 0, 255, 8, 8) + bounds: 632 248 8 8 + - image: solid-color(80, 31, 0, 255, 8, 8) + bounds: 640 248 8 8 + - image: solid-color(81, 31, 0, 255, 8, 8) + bounds: 648 248 8 8 + - image: solid-color(82, 31, 0, 255, 8, 8) + bounds: 656 248 8 8 + - image: solid-color(83, 31, 0, 255, 8, 8) + bounds: 664 248 8 8 + - image: solid-color(84, 31, 0, 255, 8, 8) + bounds: 672 248 8 8 + - image: solid-color(85, 31, 0, 255, 8, 8) + bounds: 680 248 8 8 + - image: solid-color(86, 31, 0, 255, 8, 8) + bounds: 688 248 8 8 + - image: solid-color(87, 31, 0, 255, 8, 8) + bounds: 696 248 8 8 + - image: solid-color(88, 31, 0, 255, 8, 8) + bounds: 704 248 8 8 + - image: solid-color(89, 31, 0, 255, 8, 8) + bounds: 712 248 8 8 + - image: solid-color(90, 31, 0, 255, 8, 8) + bounds: 720 248 8 8 + - image: solid-color(91, 31, 0, 255, 8, 8) + bounds: 728 248 8 8 + - image: solid-color(92, 31, 0, 255, 8, 8) + bounds: 736 248 8 8 + - image: solid-color(93, 31, 0, 255, 8, 8) + bounds: 744 248 8 8 + - image: solid-color(94, 31, 0, 255, 8, 8) + bounds: 752 248 8 8 + - image: solid-color(95, 31, 0, 255, 8, 8) + bounds: 760 248 8 8 + - image: solid-color(96, 31, 0, 255, 8, 8) + bounds: 768 248 8 8 + - image: solid-color(97, 31, 0, 255, 8, 8) + bounds: 776 248 8 8 + - image: solid-color(98, 31, 0, 255, 8, 8) + bounds: 784 248 8 8 + - image: solid-color(99, 31, 0, 255, 8, 8) + bounds: 792 248 8 8 + - image: solid-color(100, 31, 0, 255, 8, 8) + bounds: 800 248 8 8 + - image: solid-color(101, 31, 0, 255, 8, 8) + bounds: 808 248 8 8 + - image: solid-color(102, 31, 0, 255, 8, 8) + bounds: 816 248 8 8 + - image: solid-color(103, 31, 0, 255, 8, 8) + bounds: 824 248 8 8 + - image: solid-color(104, 31, 0, 255, 8, 8) + bounds: 832 248 8 8 + - image: solid-color(105, 31, 0, 255, 8, 8) + bounds: 840 248 8 8 + - image: solid-color(106, 31, 0, 255, 8, 8) + bounds: 848 248 8 8 + - image: solid-color(107, 31, 0, 255, 8, 8) + bounds: 856 248 8 8 + - image: solid-color(108, 31, 0, 255, 8, 8) + bounds: 864 248 8 8 + - image: solid-color(109, 31, 0, 255, 8, 8) + bounds: 872 248 8 8 + - image: solid-color(110, 31, 0, 255, 8, 8) + bounds: 880 248 8 8 + - image: solid-color(111, 31, 0, 255, 8, 8) + bounds: 888 248 8 8 + - image: solid-color(112, 31, 0, 255, 8, 8) + bounds: 896 248 8 8 + - image: solid-color(113, 31, 0, 255, 8, 8) + bounds: 904 248 8 8 + - image: solid-color(114, 31, 0, 255, 8, 8) + bounds: 912 248 8 8 + - image: solid-color(115, 31, 0, 255, 8, 8) + bounds: 920 248 8 8 + - image: solid-color(116, 31, 0, 255, 8, 8) + bounds: 928 248 8 8 + - image: solid-color(117, 31, 0, 255, 8, 8) + bounds: 936 248 8 8 + - image: solid-color(118, 31, 0, 255, 8, 8) + bounds: 944 248 8 8 + - image: solid-color(119, 31, 0, 255, 8, 8) + bounds: 952 248 8 8 + - image: solid-color(120, 31, 0, 255, 8, 8) + bounds: 960 248 8 8 + - image: solid-color(121, 31, 0, 255, 8, 8) + bounds: 968 248 8 8 + - image: solid-color(122, 31, 0, 255, 8, 8) + bounds: 976 248 8 8 + - image: solid-color(123, 31, 0, 255, 8, 8) + bounds: 984 248 8 8 + - image: solid-color(124, 31, 0, 255, 8, 8) + bounds: 992 248 8 8 + - image: solid-color(125, 31, 0, 255, 8, 8) + bounds: 1000 248 8 8 + - image: solid-color(126, 31, 0, 255, 8, 8) + bounds: 1008 248 8 8 + - image: solid-color(127, 31, 0, 255, 8, 8) + bounds: 1016 248 8 8 + - image: solid-color(0, 32, 0, 255, 8, 8) + bounds: 0 256 8 8 + - image: solid-color(1, 32, 0, 255, 8, 8) + bounds: 8 256 8 8 + - image: solid-color(2, 32, 0, 255, 8, 8) + bounds: 16 256 8 8 + - image: solid-color(3, 32, 0, 255, 8, 8) + bounds: 24 256 8 8 + - image: solid-color(4, 32, 0, 255, 8, 8) + bounds: 32 256 8 8 + - image: solid-color(5, 32, 0, 255, 8, 8) + bounds: 40 256 8 8 + - image: solid-color(6, 32, 0, 255, 8, 8) + bounds: 48 256 8 8 + - image: solid-color(7, 32, 0, 255, 8, 8) + bounds: 56 256 8 8 + - image: solid-color(8, 32, 0, 255, 8, 8) + bounds: 64 256 8 8 + - image: solid-color(9, 32, 0, 255, 8, 8) + bounds: 72 256 8 8 + - image: solid-color(10, 32, 0, 255, 8, 8) + bounds: 80 256 8 8 + - image: solid-color(11, 32, 0, 255, 8, 8) + bounds: 88 256 8 8 + - image: solid-color(12, 32, 0, 255, 8, 8) + bounds: 96 256 8 8 + - image: solid-color(13, 32, 0, 255, 8, 8) + bounds: 104 256 8 8 + - image: solid-color(14, 32, 0, 255, 8, 8) + bounds: 112 256 8 8 + - image: solid-color(15, 32, 0, 255, 8, 8) + bounds: 120 256 8 8 + - image: solid-color(16, 32, 0, 255, 8, 8) + bounds: 128 256 8 8 + - image: solid-color(17, 32, 0, 255, 8, 8) + bounds: 136 256 8 8 + - image: solid-color(18, 32, 0, 255, 8, 8) + bounds: 144 256 8 8 + - image: solid-color(19, 32, 0, 255, 8, 8) + bounds: 152 256 8 8 + - image: solid-color(20, 32, 0, 255, 8, 8) + bounds: 160 256 8 8 + - image: solid-color(21, 32, 0, 255, 8, 8) + bounds: 168 256 8 8 + - image: solid-color(22, 32, 0, 255, 8, 8) + bounds: 176 256 8 8 + - image: solid-color(23, 32, 0, 255, 8, 8) + bounds: 184 256 8 8 + - image: solid-color(24, 32, 0, 255, 8, 8) + bounds: 192 256 8 8 + - image: solid-color(25, 32, 0, 255, 8, 8) + bounds: 200 256 8 8 + - image: solid-color(26, 32, 0, 255, 8, 8) + bounds: 208 256 8 8 + - image: solid-color(27, 32, 0, 255, 8, 8) + bounds: 216 256 8 8 + - image: solid-color(28, 32, 0, 255, 8, 8) + bounds: 224 256 8 8 + - image: solid-color(29, 32, 0, 255, 8, 8) + bounds: 232 256 8 8 + - image: solid-color(30, 32, 0, 255, 8, 8) + bounds: 240 256 8 8 + - image: solid-color(31, 32, 0, 255, 8, 8) + bounds: 248 256 8 8 + - image: solid-color(32, 32, 0, 255, 8, 8) + bounds: 256 256 8 8 + - image: solid-color(33, 32, 0, 255, 8, 8) + bounds: 264 256 8 8 + - image: solid-color(34, 32, 0, 255, 8, 8) + bounds: 272 256 8 8 + - image: solid-color(35, 32, 0, 255, 8, 8) + bounds: 280 256 8 8 + - image: solid-color(36, 32, 0, 255, 8, 8) + bounds: 288 256 8 8 + - image: solid-color(37, 32, 0, 255, 8, 8) + bounds: 296 256 8 8 + - image: solid-color(38, 32, 0, 255, 8, 8) + bounds: 304 256 8 8 + - image: solid-color(39, 32, 0, 255, 8, 8) + bounds: 312 256 8 8 + - image: solid-color(40, 32, 0, 255, 8, 8) + bounds: 320 256 8 8 + - image: solid-color(41, 32, 0, 255, 8, 8) + bounds: 328 256 8 8 + - image: solid-color(42, 32, 0, 255, 8, 8) + bounds: 336 256 8 8 + - image: solid-color(43, 32, 0, 255, 8, 8) + bounds: 344 256 8 8 + - image: solid-color(44, 32, 0, 255, 8, 8) + bounds: 352 256 8 8 + - image: solid-color(45, 32, 0, 255, 8, 8) + bounds: 360 256 8 8 + - image: solid-color(46, 32, 0, 255, 8, 8) + bounds: 368 256 8 8 + - image: solid-color(47, 32, 0, 255, 8, 8) + bounds: 376 256 8 8 + - image: solid-color(48, 32, 0, 255, 8, 8) + bounds: 384 256 8 8 + - image: solid-color(49, 32, 0, 255, 8, 8) + bounds: 392 256 8 8 + - image: solid-color(50, 32, 0, 255, 8, 8) + bounds: 400 256 8 8 + - image: solid-color(51, 32, 0, 255, 8, 8) + bounds: 408 256 8 8 + - image: solid-color(52, 32, 0, 255, 8, 8) + bounds: 416 256 8 8 + - image: solid-color(53, 32, 0, 255, 8, 8) + bounds: 424 256 8 8 + - image: solid-color(54, 32, 0, 255, 8, 8) + bounds: 432 256 8 8 + - image: solid-color(55, 32, 0, 255, 8, 8) + bounds: 440 256 8 8 + - image: solid-color(56, 32, 0, 255, 8, 8) + bounds: 448 256 8 8 + - image: solid-color(57, 32, 0, 255, 8, 8) + bounds: 456 256 8 8 + - image: solid-color(58, 32, 0, 255, 8, 8) + bounds: 464 256 8 8 + - image: solid-color(59, 32, 0, 255, 8, 8) + bounds: 472 256 8 8 + - image: solid-color(60, 32, 0, 255, 8, 8) + bounds: 480 256 8 8 + - image: solid-color(61, 32, 0, 255, 8, 8) + bounds: 488 256 8 8 + - image: solid-color(62, 32, 0, 255, 8, 8) + bounds: 496 256 8 8 + - image: solid-color(63, 32, 0, 255, 8, 8) + bounds: 504 256 8 8 + - image: solid-color(64, 32, 0, 255, 8, 8) + bounds: 512 256 8 8 + - image: solid-color(65, 32, 0, 255, 8, 8) + bounds: 520 256 8 8 + - image: solid-color(66, 32, 0, 255, 8, 8) + bounds: 528 256 8 8 + - image: solid-color(67, 32, 0, 255, 8, 8) + bounds: 536 256 8 8 + - image: solid-color(68, 32, 0, 255, 8, 8) + bounds: 544 256 8 8 + - image: solid-color(69, 32, 0, 255, 8, 8) + bounds: 552 256 8 8 + - image: solid-color(70, 32, 0, 255, 8, 8) + bounds: 560 256 8 8 + - image: solid-color(71, 32, 0, 255, 8, 8) + bounds: 568 256 8 8 + - image: solid-color(72, 32, 0, 255, 8, 8) + bounds: 576 256 8 8 + - image: solid-color(73, 32, 0, 255, 8, 8) + bounds: 584 256 8 8 + - image: solid-color(74, 32, 0, 255, 8, 8) + bounds: 592 256 8 8 + - image: solid-color(75, 32, 0, 255, 8, 8) + bounds: 600 256 8 8 + - image: solid-color(76, 32, 0, 255, 8, 8) + bounds: 608 256 8 8 + - image: solid-color(77, 32, 0, 255, 8, 8) + bounds: 616 256 8 8 + - image: solid-color(78, 32, 0, 255, 8, 8) + bounds: 624 256 8 8 + - image: solid-color(79, 32, 0, 255, 8, 8) + bounds: 632 256 8 8 + - image: solid-color(80, 32, 0, 255, 8, 8) + bounds: 640 256 8 8 + - image: solid-color(81, 32, 0, 255, 8, 8) + bounds: 648 256 8 8 + - image: solid-color(82, 32, 0, 255, 8, 8) + bounds: 656 256 8 8 + - image: solid-color(83, 32, 0, 255, 8, 8) + bounds: 664 256 8 8 + - image: solid-color(84, 32, 0, 255, 8, 8) + bounds: 672 256 8 8 + - image: solid-color(85, 32, 0, 255, 8, 8) + bounds: 680 256 8 8 + - image: solid-color(86, 32, 0, 255, 8, 8) + bounds: 688 256 8 8 + - image: solid-color(87, 32, 0, 255, 8, 8) + bounds: 696 256 8 8 + - image: solid-color(88, 32, 0, 255, 8, 8) + bounds: 704 256 8 8 + - image: solid-color(89, 32, 0, 255, 8, 8) + bounds: 712 256 8 8 + - image: solid-color(90, 32, 0, 255, 8, 8) + bounds: 720 256 8 8 + - image: solid-color(91, 32, 0, 255, 8, 8) + bounds: 728 256 8 8 + - image: solid-color(92, 32, 0, 255, 8, 8) + bounds: 736 256 8 8 + - image: solid-color(93, 32, 0, 255, 8, 8) + bounds: 744 256 8 8 + - image: solid-color(94, 32, 0, 255, 8, 8) + bounds: 752 256 8 8 + - image: solid-color(95, 32, 0, 255, 8, 8) + bounds: 760 256 8 8 + - image: solid-color(96, 32, 0, 255, 8, 8) + bounds: 768 256 8 8 + - image: solid-color(97, 32, 0, 255, 8, 8) + bounds: 776 256 8 8 + - image: solid-color(98, 32, 0, 255, 8, 8) + bounds: 784 256 8 8 + - image: solid-color(99, 32, 0, 255, 8, 8) + bounds: 792 256 8 8 + - image: solid-color(100, 32, 0, 255, 8, 8) + bounds: 800 256 8 8 + - image: solid-color(101, 32, 0, 255, 8, 8) + bounds: 808 256 8 8 + - image: solid-color(102, 32, 0, 255, 8, 8) + bounds: 816 256 8 8 + - image: solid-color(103, 32, 0, 255, 8, 8) + bounds: 824 256 8 8 + - image: solid-color(104, 32, 0, 255, 8, 8) + bounds: 832 256 8 8 + - image: solid-color(105, 32, 0, 255, 8, 8) + bounds: 840 256 8 8 + - image: solid-color(106, 32, 0, 255, 8, 8) + bounds: 848 256 8 8 + - image: solid-color(107, 32, 0, 255, 8, 8) + bounds: 856 256 8 8 + - image: solid-color(108, 32, 0, 255, 8, 8) + bounds: 864 256 8 8 + - image: solid-color(109, 32, 0, 255, 8, 8) + bounds: 872 256 8 8 + - image: solid-color(110, 32, 0, 255, 8, 8) + bounds: 880 256 8 8 + - image: solid-color(111, 32, 0, 255, 8, 8) + bounds: 888 256 8 8 + - image: solid-color(112, 32, 0, 255, 8, 8) + bounds: 896 256 8 8 + - image: solid-color(113, 32, 0, 255, 8, 8) + bounds: 904 256 8 8 + - image: solid-color(114, 32, 0, 255, 8, 8) + bounds: 912 256 8 8 + - image: solid-color(115, 32, 0, 255, 8, 8) + bounds: 920 256 8 8 + - image: solid-color(116, 32, 0, 255, 8, 8) + bounds: 928 256 8 8 + - image: solid-color(117, 32, 0, 255, 8, 8) + bounds: 936 256 8 8 + - image: solid-color(118, 32, 0, 255, 8, 8) + bounds: 944 256 8 8 + - image: solid-color(119, 32, 0, 255, 8, 8) + bounds: 952 256 8 8 + - image: solid-color(120, 32, 0, 255, 8, 8) + bounds: 960 256 8 8 + - image: solid-color(121, 32, 0, 255, 8, 8) + bounds: 968 256 8 8 + - image: solid-color(122, 32, 0, 255, 8, 8) + bounds: 976 256 8 8 + - image: solid-color(123, 32, 0, 255, 8, 8) + bounds: 984 256 8 8 + - image: solid-color(124, 32, 0, 255, 8, 8) + bounds: 992 256 8 8 + - image: solid-color(125, 32, 0, 255, 8, 8) + bounds: 1000 256 8 8 + - image: solid-color(126, 32, 0, 255, 8, 8) + bounds: 1008 256 8 8 + - image: solid-color(127, 32, 0, 255, 8, 8) + bounds: 1016 256 8 8 + - image: solid-color(0, 33, 0, 255, 8, 8) + bounds: 0 264 8 8 + - image: solid-color(1, 33, 0, 255, 8, 8) + bounds: 8 264 8 8 + - image: solid-color(2, 33, 0, 255, 8, 8) + bounds: 16 264 8 8 + - image: solid-color(3, 33, 0, 255, 8, 8) + bounds: 24 264 8 8 + - image: solid-color(4, 33, 0, 255, 8, 8) + bounds: 32 264 8 8 + - image: solid-color(5, 33, 0, 255, 8, 8) + bounds: 40 264 8 8 + - image: solid-color(6, 33, 0, 255, 8, 8) + bounds: 48 264 8 8 + - image: solid-color(7, 33, 0, 255, 8, 8) + bounds: 56 264 8 8 + - image: solid-color(8, 33, 0, 255, 8, 8) + bounds: 64 264 8 8 + - image: solid-color(9, 33, 0, 255, 8, 8) + bounds: 72 264 8 8 + - image: solid-color(10, 33, 0, 255, 8, 8) + bounds: 80 264 8 8 + - image: solid-color(11, 33, 0, 255, 8, 8) + bounds: 88 264 8 8 + - image: solid-color(12, 33, 0, 255, 8, 8) + bounds: 96 264 8 8 + - image: solid-color(13, 33, 0, 255, 8, 8) + bounds: 104 264 8 8 + - image: solid-color(14, 33, 0, 255, 8, 8) + bounds: 112 264 8 8 + - image: solid-color(15, 33, 0, 255, 8, 8) + bounds: 120 264 8 8 + - image: solid-color(16, 33, 0, 255, 8, 8) + bounds: 128 264 8 8 + - image: solid-color(17, 33, 0, 255, 8, 8) + bounds: 136 264 8 8 + - image: solid-color(18, 33, 0, 255, 8, 8) + bounds: 144 264 8 8 + - image: solid-color(19, 33, 0, 255, 8, 8) + bounds: 152 264 8 8 + - image: solid-color(20, 33, 0, 255, 8, 8) + bounds: 160 264 8 8 + - image: solid-color(21, 33, 0, 255, 8, 8) + bounds: 168 264 8 8 + - image: solid-color(22, 33, 0, 255, 8, 8) + bounds: 176 264 8 8 + - image: solid-color(23, 33, 0, 255, 8, 8) + bounds: 184 264 8 8 + - image: solid-color(24, 33, 0, 255, 8, 8) + bounds: 192 264 8 8 + - image: solid-color(25, 33, 0, 255, 8, 8) + bounds: 200 264 8 8 + - image: solid-color(26, 33, 0, 255, 8, 8) + bounds: 208 264 8 8 + - image: solid-color(27, 33, 0, 255, 8, 8) + bounds: 216 264 8 8 + - image: solid-color(28, 33, 0, 255, 8, 8) + bounds: 224 264 8 8 + - image: solid-color(29, 33, 0, 255, 8, 8) + bounds: 232 264 8 8 + - image: solid-color(30, 33, 0, 255, 8, 8) + bounds: 240 264 8 8 + - image: solid-color(31, 33, 0, 255, 8, 8) + bounds: 248 264 8 8 + - image: solid-color(32, 33, 0, 255, 8, 8) + bounds: 256 264 8 8 + - image: solid-color(33, 33, 0, 255, 8, 8) + bounds: 264 264 8 8 + - image: solid-color(34, 33, 0, 255, 8, 8) + bounds: 272 264 8 8 + - image: solid-color(35, 33, 0, 255, 8, 8) + bounds: 280 264 8 8 + - image: solid-color(36, 33, 0, 255, 8, 8) + bounds: 288 264 8 8 + - image: solid-color(37, 33, 0, 255, 8, 8) + bounds: 296 264 8 8 + - image: solid-color(38, 33, 0, 255, 8, 8) + bounds: 304 264 8 8 + - image: solid-color(39, 33, 0, 255, 8, 8) + bounds: 312 264 8 8 + - image: solid-color(40, 33, 0, 255, 8, 8) + bounds: 320 264 8 8 + - image: solid-color(41, 33, 0, 255, 8, 8) + bounds: 328 264 8 8 + - image: solid-color(42, 33, 0, 255, 8, 8) + bounds: 336 264 8 8 + - image: solid-color(43, 33, 0, 255, 8, 8) + bounds: 344 264 8 8 + - image: solid-color(44, 33, 0, 255, 8, 8) + bounds: 352 264 8 8 + - image: solid-color(45, 33, 0, 255, 8, 8) + bounds: 360 264 8 8 + - image: solid-color(46, 33, 0, 255, 8, 8) + bounds: 368 264 8 8 + - image: solid-color(47, 33, 0, 255, 8, 8) + bounds: 376 264 8 8 + - image: solid-color(48, 33, 0, 255, 8, 8) + bounds: 384 264 8 8 + - image: solid-color(49, 33, 0, 255, 8, 8) + bounds: 392 264 8 8 + - image: solid-color(50, 33, 0, 255, 8, 8) + bounds: 400 264 8 8 + - image: solid-color(51, 33, 0, 255, 8, 8) + bounds: 408 264 8 8 + - image: solid-color(52, 33, 0, 255, 8, 8) + bounds: 416 264 8 8 + - image: solid-color(53, 33, 0, 255, 8, 8) + bounds: 424 264 8 8 + - image: solid-color(54, 33, 0, 255, 8, 8) + bounds: 432 264 8 8 + - image: solid-color(55, 33, 0, 255, 8, 8) + bounds: 440 264 8 8 + - image: solid-color(56, 33, 0, 255, 8, 8) + bounds: 448 264 8 8 + - image: solid-color(57, 33, 0, 255, 8, 8) + bounds: 456 264 8 8 + - image: solid-color(58, 33, 0, 255, 8, 8) + bounds: 464 264 8 8 + - image: solid-color(59, 33, 0, 255, 8, 8) + bounds: 472 264 8 8 + - image: solid-color(60, 33, 0, 255, 8, 8) + bounds: 480 264 8 8 + - image: solid-color(61, 33, 0, 255, 8, 8) + bounds: 488 264 8 8 + - image: solid-color(62, 33, 0, 255, 8, 8) + bounds: 496 264 8 8 + - image: solid-color(63, 33, 0, 255, 8, 8) + bounds: 504 264 8 8 + - image: solid-color(64, 33, 0, 255, 8, 8) + bounds: 512 264 8 8 + - image: solid-color(65, 33, 0, 255, 8, 8) + bounds: 520 264 8 8 + - image: solid-color(66, 33, 0, 255, 8, 8) + bounds: 528 264 8 8 + - image: solid-color(67, 33, 0, 255, 8, 8) + bounds: 536 264 8 8 + - image: solid-color(68, 33, 0, 255, 8, 8) + bounds: 544 264 8 8 + - image: solid-color(69, 33, 0, 255, 8, 8) + bounds: 552 264 8 8 + - image: solid-color(70, 33, 0, 255, 8, 8) + bounds: 560 264 8 8 + - image: solid-color(71, 33, 0, 255, 8, 8) + bounds: 568 264 8 8 + - image: solid-color(72, 33, 0, 255, 8, 8) + bounds: 576 264 8 8 + - image: solid-color(73, 33, 0, 255, 8, 8) + bounds: 584 264 8 8 + - image: solid-color(74, 33, 0, 255, 8, 8) + bounds: 592 264 8 8 + - image: solid-color(75, 33, 0, 255, 8, 8) + bounds: 600 264 8 8 + - image: solid-color(76, 33, 0, 255, 8, 8) + bounds: 608 264 8 8 + - image: solid-color(77, 33, 0, 255, 8, 8) + bounds: 616 264 8 8 + - image: solid-color(78, 33, 0, 255, 8, 8) + bounds: 624 264 8 8 + - image: solid-color(79, 33, 0, 255, 8, 8) + bounds: 632 264 8 8 + - image: solid-color(80, 33, 0, 255, 8, 8) + bounds: 640 264 8 8 + - image: solid-color(81, 33, 0, 255, 8, 8) + bounds: 648 264 8 8 + - image: solid-color(82, 33, 0, 255, 8, 8) + bounds: 656 264 8 8 + - image: solid-color(83, 33, 0, 255, 8, 8) + bounds: 664 264 8 8 + - image: solid-color(84, 33, 0, 255, 8, 8) + bounds: 672 264 8 8 + - image: solid-color(85, 33, 0, 255, 8, 8) + bounds: 680 264 8 8 + - image: solid-color(86, 33, 0, 255, 8, 8) + bounds: 688 264 8 8 + - image: solid-color(87, 33, 0, 255, 8, 8) + bounds: 696 264 8 8 + - image: solid-color(88, 33, 0, 255, 8, 8) + bounds: 704 264 8 8 + - image: solid-color(89, 33, 0, 255, 8, 8) + bounds: 712 264 8 8 + - image: solid-color(90, 33, 0, 255, 8, 8) + bounds: 720 264 8 8 + - image: solid-color(91, 33, 0, 255, 8, 8) + bounds: 728 264 8 8 + - image: solid-color(92, 33, 0, 255, 8, 8) + bounds: 736 264 8 8 + - image: solid-color(93, 33, 0, 255, 8, 8) + bounds: 744 264 8 8 + - image: solid-color(94, 33, 0, 255, 8, 8) + bounds: 752 264 8 8 + - image: solid-color(95, 33, 0, 255, 8, 8) + bounds: 760 264 8 8 + - image: solid-color(96, 33, 0, 255, 8, 8) + bounds: 768 264 8 8 + - image: solid-color(97, 33, 0, 255, 8, 8) + bounds: 776 264 8 8 + - image: solid-color(98, 33, 0, 255, 8, 8) + bounds: 784 264 8 8 + - image: solid-color(99, 33, 0, 255, 8, 8) + bounds: 792 264 8 8 + - image: solid-color(100, 33, 0, 255, 8, 8) + bounds: 800 264 8 8 + - image: solid-color(101, 33, 0, 255, 8, 8) + bounds: 808 264 8 8 + - image: solid-color(102, 33, 0, 255, 8, 8) + bounds: 816 264 8 8 + - image: solid-color(103, 33, 0, 255, 8, 8) + bounds: 824 264 8 8 + - image: solid-color(104, 33, 0, 255, 8, 8) + bounds: 832 264 8 8 + - image: solid-color(105, 33, 0, 255, 8, 8) + bounds: 840 264 8 8 + - image: solid-color(106, 33, 0, 255, 8, 8) + bounds: 848 264 8 8 + - image: solid-color(107, 33, 0, 255, 8, 8) + bounds: 856 264 8 8 + - image: solid-color(108, 33, 0, 255, 8, 8) + bounds: 864 264 8 8 + - image: solid-color(109, 33, 0, 255, 8, 8) + bounds: 872 264 8 8 + - image: solid-color(110, 33, 0, 255, 8, 8) + bounds: 880 264 8 8 + - image: solid-color(111, 33, 0, 255, 8, 8) + bounds: 888 264 8 8 + - image: solid-color(112, 33, 0, 255, 8, 8) + bounds: 896 264 8 8 + - image: solid-color(113, 33, 0, 255, 8, 8) + bounds: 904 264 8 8 + - image: solid-color(114, 33, 0, 255, 8, 8) + bounds: 912 264 8 8 + - image: solid-color(115, 33, 0, 255, 8, 8) + bounds: 920 264 8 8 + - image: solid-color(116, 33, 0, 255, 8, 8) + bounds: 928 264 8 8 + - image: solid-color(117, 33, 0, 255, 8, 8) + bounds: 936 264 8 8 + - image: solid-color(118, 33, 0, 255, 8, 8) + bounds: 944 264 8 8 + - image: solid-color(119, 33, 0, 255, 8, 8) + bounds: 952 264 8 8 + - image: solid-color(120, 33, 0, 255, 8, 8) + bounds: 960 264 8 8 + - image: solid-color(121, 33, 0, 255, 8, 8) + bounds: 968 264 8 8 + - image: solid-color(122, 33, 0, 255, 8, 8) + bounds: 976 264 8 8 + - image: solid-color(123, 33, 0, 255, 8, 8) + bounds: 984 264 8 8 + - image: solid-color(124, 33, 0, 255, 8, 8) + bounds: 992 264 8 8 + - image: solid-color(125, 33, 0, 255, 8, 8) + bounds: 1000 264 8 8 + - image: solid-color(126, 33, 0, 255, 8, 8) + bounds: 1008 264 8 8 + - image: solid-color(127, 33, 0, 255, 8, 8) + bounds: 1016 264 8 8 + - image: solid-color(0, 34, 0, 255, 8, 8) + bounds: 0 272 8 8 + - image: solid-color(1, 34, 0, 255, 8, 8) + bounds: 8 272 8 8 + - image: solid-color(2, 34, 0, 255, 8, 8) + bounds: 16 272 8 8 + - image: solid-color(3, 34, 0, 255, 8, 8) + bounds: 24 272 8 8 + - image: solid-color(4, 34, 0, 255, 8, 8) + bounds: 32 272 8 8 + - image: solid-color(5, 34, 0, 255, 8, 8) + bounds: 40 272 8 8 + - image: solid-color(6, 34, 0, 255, 8, 8) + bounds: 48 272 8 8 + - image: solid-color(7, 34, 0, 255, 8, 8) + bounds: 56 272 8 8 + - image: solid-color(8, 34, 0, 255, 8, 8) + bounds: 64 272 8 8 + - image: solid-color(9, 34, 0, 255, 8, 8) + bounds: 72 272 8 8 + - image: solid-color(10, 34, 0, 255, 8, 8) + bounds: 80 272 8 8 + - image: solid-color(11, 34, 0, 255, 8, 8) + bounds: 88 272 8 8 + - image: solid-color(12, 34, 0, 255, 8, 8) + bounds: 96 272 8 8 + - image: solid-color(13, 34, 0, 255, 8, 8) + bounds: 104 272 8 8 + - image: solid-color(14, 34, 0, 255, 8, 8) + bounds: 112 272 8 8 + - image: solid-color(15, 34, 0, 255, 8, 8) + bounds: 120 272 8 8 + - image: solid-color(16, 34, 0, 255, 8, 8) + bounds: 128 272 8 8 + - image: solid-color(17, 34, 0, 255, 8, 8) + bounds: 136 272 8 8 + - image: solid-color(18, 34, 0, 255, 8, 8) + bounds: 144 272 8 8 + - image: solid-color(19, 34, 0, 255, 8, 8) + bounds: 152 272 8 8 + - image: solid-color(20, 34, 0, 255, 8, 8) + bounds: 160 272 8 8 + - image: solid-color(21, 34, 0, 255, 8, 8) + bounds: 168 272 8 8 + - image: solid-color(22, 34, 0, 255, 8, 8) + bounds: 176 272 8 8 + - image: solid-color(23, 34, 0, 255, 8, 8) + bounds: 184 272 8 8 + - image: solid-color(24, 34, 0, 255, 8, 8) + bounds: 192 272 8 8 + - image: solid-color(25, 34, 0, 255, 8, 8) + bounds: 200 272 8 8 + - image: solid-color(26, 34, 0, 255, 8, 8) + bounds: 208 272 8 8 + - image: solid-color(27, 34, 0, 255, 8, 8) + bounds: 216 272 8 8 + - image: solid-color(28, 34, 0, 255, 8, 8) + bounds: 224 272 8 8 + - image: solid-color(29, 34, 0, 255, 8, 8) + bounds: 232 272 8 8 + - image: solid-color(30, 34, 0, 255, 8, 8) + bounds: 240 272 8 8 + - image: solid-color(31, 34, 0, 255, 8, 8) + bounds: 248 272 8 8 + - image: solid-color(32, 34, 0, 255, 8, 8) + bounds: 256 272 8 8 + - image: solid-color(33, 34, 0, 255, 8, 8) + bounds: 264 272 8 8 + - image: solid-color(34, 34, 0, 255, 8, 8) + bounds: 272 272 8 8 + - image: solid-color(35, 34, 0, 255, 8, 8) + bounds: 280 272 8 8 + - image: solid-color(36, 34, 0, 255, 8, 8) + bounds: 288 272 8 8 + - image: solid-color(37, 34, 0, 255, 8, 8) + bounds: 296 272 8 8 + - image: solid-color(38, 34, 0, 255, 8, 8) + bounds: 304 272 8 8 + - image: solid-color(39, 34, 0, 255, 8, 8) + bounds: 312 272 8 8 + - image: solid-color(40, 34, 0, 255, 8, 8) + bounds: 320 272 8 8 + - image: solid-color(41, 34, 0, 255, 8, 8) + bounds: 328 272 8 8 + - image: solid-color(42, 34, 0, 255, 8, 8) + bounds: 336 272 8 8 + - image: solid-color(43, 34, 0, 255, 8, 8) + bounds: 344 272 8 8 + - image: solid-color(44, 34, 0, 255, 8, 8) + bounds: 352 272 8 8 + - image: solid-color(45, 34, 0, 255, 8, 8) + bounds: 360 272 8 8 + - image: solid-color(46, 34, 0, 255, 8, 8) + bounds: 368 272 8 8 + - image: solid-color(47, 34, 0, 255, 8, 8) + bounds: 376 272 8 8 + - image: solid-color(48, 34, 0, 255, 8, 8) + bounds: 384 272 8 8 + - image: solid-color(49, 34, 0, 255, 8, 8) + bounds: 392 272 8 8 + - image: solid-color(50, 34, 0, 255, 8, 8) + bounds: 400 272 8 8 + - image: solid-color(51, 34, 0, 255, 8, 8) + bounds: 408 272 8 8 + - image: solid-color(52, 34, 0, 255, 8, 8) + bounds: 416 272 8 8 + - image: solid-color(53, 34, 0, 255, 8, 8) + bounds: 424 272 8 8 + - image: solid-color(54, 34, 0, 255, 8, 8) + bounds: 432 272 8 8 + - image: solid-color(55, 34, 0, 255, 8, 8) + bounds: 440 272 8 8 + - image: solid-color(56, 34, 0, 255, 8, 8) + bounds: 448 272 8 8 + - image: solid-color(57, 34, 0, 255, 8, 8) + bounds: 456 272 8 8 + - image: solid-color(58, 34, 0, 255, 8, 8) + bounds: 464 272 8 8 + - image: solid-color(59, 34, 0, 255, 8, 8) + bounds: 472 272 8 8 + - image: solid-color(60, 34, 0, 255, 8, 8) + bounds: 480 272 8 8 + - image: solid-color(61, 34, 0, 255, 8, 8) + bounds: 488 272 8 8 + - image: solid-color(62, 34, 0, 255, 8, 8) + bounds: 496 272 8 8 + - image: solid-color(63, 34, 0, 255, 8, 8) + bounds: 504 272 8 8 + - image: solid-color(64, 34, 0, 255, 8, 8) + bounds: 512 272 8 8 + - image: solid-color(65, 34, 0, 255, 8, 8) + bounds: 520 272 8 8 + - image: solid-color(66, 34, 0, 255, 8, 8) + bounds: 528 272 8 8 + - image: solid-color(67, 34, 0, 255, 8, 8) + bounds: 536 272 8 8 + - image: solid-color(68, 34, 0, 255, 8, 8) + bounds: 544 272 8 8 + - image: solid-color(69, 34, 0, 255, 8, 8) + bounds: 552 272 8 8 + - image: solid-color(70, 34, 0, 255, 8, 8) + bounds: 560 272 8 8 + - image: solid-color(71, 34, 0, 255, 8, 8) + bounds: 568 272 8 8 + - image: solid-color(72, 34, 0, 255, 8, 8) + bounds: 576 272 8 8 + - image: solid-color(73, 34, 0, 255, 8, 8) + bounds: 584 272 8 8 + - image: solid-color(74, 34, 0, 255, 8, 8) + bounds: 592 272 8 8 + - image: solid-color(75, 34, 0, 255, 8, 8) + bounds: 600 272 8 8 + - image: solid-color(76, 34, 0, 255, 8, 8) + bounds: 608 272 8 8 + - image: solid-color(77, 34, 0, 255, 8, 8) + bounds: 616 272 8 8 + - image: solid-color(78, 34, 0, 255, 8, 8) + bounds: 624 272 8 8 + - image: solid-color(79, 34, 0, 255, 8, 8) + bounds: 632 272 8 8 + - image: solid-color(80, 34, 0, 255, 8, 8) + bounds: 640 272 8 8 + - image: solid-color(81, 34, 0, 255, 8, 8) + bounds: 648 272 8 8 + - image: solid-color(82, 34, 0, 255, 8, 8) + bounds: 656 272 8 8 + - image: solid-color(83, 34, 0, 255, 8, 8) + bounds: 664 272 8 8 + - image: solid-color(84, 34, 0, 255, 8, 8) + bounds: 672 272 8 8 + - image: solid-color(85, 34, 0, 255, 8, 8) + bounds: 680 272 8 8 + - image: solid-color(86, 34, 0, 255, 8, 8) + bounds: 688 272 8 8 + - image: solid-color(87, 34, 0, 255, 8, 8) + bounds: 696 272 8 8 + - image: solid-color(88, 34, 0, 255, 8, 8) + bounds: 704 272 8 8 + - image: solid-color(89, 34, 0, 255, 8, 8) + bounds: 712 272 8 8 + - image: solid-color(90, 34, 0, 255, 8, 8) + bounds: 720 272 8 8 + - image: solid-color(91, 34, 0, 255, 8, 8) + bounds: 728 272 8 8 + - image: solid-color(92, 34, 0, 255, 8, 8) + bounds: 736 272 8 8 + - image: solid-color(93, 34, 0, 255, 8, 8) + bounds: 744 272 8 8 + - image: solid-color(94, 34, 0, 255, 8, 8) + bounds: 752 272 8 8 + - image: solid-color(95, 34, 0, 255, 8, 8) + bounds: 760 272 8 8 + - image: solid-color(96, 34, 0, 255, 8, 8) + bounds: 768 272 8 8 + - image: solid-color(97, 34, 0, 255, 8, 8) + bounds: 776 272 8 8 + - image: solid-color(98, 34, 0, 255, 8, 8) + bounds: 784 272 8 8 + - image: solid-color(99, 34, 0, 255, 8, 8) + bounds: 792 272 8 8 + - image: solid-color(100, 34, 0, 255, 8, 8) + bounds: 800 272 8 8 + - image: solid-color(101, 34, 0, 255, 8, 8) + bounds: 808 272 8 8 + - image: solid-color(102, 34, 0, 255, 8, 8) + bounds: 816 272 8 8 + - image: solid-color(103, 34, 0, 255, 8, 8) + bounds: 824 272 8 8 + - image: solid-color(104, 34, 0, 255, 8, 8) + bounds: 832 272 8 8 + - image: solid-color(105, 34, 0, 255, 8, 8) + bounds: 840 272 8 8 + - image: solid-color(106, 34, 0, 255, 8, 8) + bounds: 848 272 8 8 + - image: solid-color(107, 34, 0, 255, 8, 8) + bounds: 856 272 8 8 + - image: solid-color(108, 34, 0, 255, 8, 8) + bounds: 864 272 8 8 + - image: solid-color(109, 34, 0, 255, 8, 8) + bounds: 872 272 8 8 + - image: solid-color(110, 34, 0, 255, 8, 8) + bounds: 880 272 8 8 + - image: solid-color(111, 34, 0, 255, 8, 8) + bounds: 888 272 8 8 + - image: solid-color(112, 34, 0, 255, 8, 8) + bounds: 896 272 8 8 + - image: solid-color(113, 34, 0, 255, 8, 8) + bounds: 904 272 8 8 + - image: solid-color(114, 34, 0, 255, 8, 8) + bounds: 912 272 8 8 + - image: solid-color(115, 34, 0, 255, 8, 8) + bounds: 920 272 8 8 + - image: solid-color(116, 34, 0, 255, 8, 8) + bounds: 928 272 8 8 + - image: solid-color(117, 34, 0, 255, 8, 8) + bounds: 936 272 8 8 + - image: solid-color(118, 34, 0, 255, 8, 8) + bounds: 944 272 8 8 + - image: solid-color(119, 34, 0, 255, 8, 8) + bounds: 952 272 8 8 + - image: solid-color(120, 34, 0, 255, 8, 8) + bounds: 960 272 8 8 + - image: solid-color(121, 34, 0, 255, 8, 8) + bounds: 968 272 8 8 + - image: solid-color(122, 34, 0, 255, 8, 8) + bounds: 976 272 8 8 + - image: solid-color(123, 34, 0, 255, 8, 8) + bounds: 984 272 8 8 + - image: solid-color(124, 34, 0, 255, 8, 8) + bounds: 992 272 8 8 + - image: solid-color(125, 34, 0, 255, 8, 8) + bounds: 1000 272 8 8 + - image: solid-color(126, 34, 0, 255, 8, 8) + bounds: 1008 272 8 8 + - image: solid-color(127, 34, 0, 255, 8, 8) + bounds: 1016 272 8 8 + - image: solid-color(0, 35, 0, 255, 8, 8) + bounds: 0 280 8 8 + - image: solid-color(1, 35, 0, 255, 8, 8) + bounds: 8 280 8 8 + - image: solid-color(2, 35, 0, 255, 8, 8) + bounds: 16 280 8 8 + - image: solid-color(3, 35, 0, 255, 8, 8) + bounds: 24 280 8 8 + - image: solid-color(4, 35, 0, 255, 8, 8) + bounds: 32 280 8 8 + - image: solid-color(5, 35, 0, 255, 8, 8) + bounds: 40 280 8 8 + - image: solid-color(6, 35, 0, 255, 8, 8) + bounds: 48 280 8 8 + - image: solid-color(7, 35, 0, 255, 8, 8) + bounds: 56 280 8 8 + - image: solid-color(8, 35, 0, 255, 8, 8) + bounds: 64 280 8 8 + - image: solid-color(9, 35, 0, 255, 8, 8) + bounds: 72 280 8 8 + - image: solid-color(10, 35, 0, 255, 8, 8) + bounds: 80 280 8 8 + - image: solid-color(11, 35, 0, 255, 8, 8) + bounds: 88 280 8 8 + - image: solid-color(12, 35, 0, 255, 8, 8) + bounds: 96 280 8 8 + - image: solid-color(13, 35, 0, 255, 8, 8) + bounds: 104 280 8 8 + - image: solid-color(14, 35, 0, 255, 8, 8) + bounds: 112 280 8 8 + - image: solid-color(15, 35, 0, 255, 8, 8) + bounds: 120 280 8 8 + - image: solid-color(16, 35, 0, 255, 8, 8) + bounds: 128 280 8 8 + - image: solid-color(17, 35, 0, 255, 8, 8) + bounds: 136 280 8 8 + - image: solid-color(18, 35, 0, 255, 8, 8) + bounds: 144 280 8 8 + - image: solid-color(19, 35, 0, 255, 8, 8) + bounds: 152 280 8 8 + - image: solid-color(20, 35, 0, 255, 8, 8) + bounds: 160 280 8 8 + - image: solid-color(21, 35, 0, 255, 8, 8) + bounds: 168 280 8 8 + - image: solid-color(22, 35, 0, 255, 8, 8) + bounds: 176 280 8 8 + - image: solid-color(23, 35, 0, 255, 8, 8) + bounds: 184 280 8 8 + - image: solid-color(24, 35, 0, 255, 8, 8) + bounds: 192 280 8 8 + - image: solid-color(25, 35, 0, 255, 8, 8) + bounds: 200 280 8 8 + - image: solid-color(26, 35, 0, 255, 8, 8) + bounds: 208 280 8 8 + - image: solid-color(27, 35, 0, 255, 8, 8) + bounds: 216 280 8 8 + - image: solid-color(28, 35, 0, 255, 8, 8) + bounds: 224 280 8 8 + - image: solid-color(29, 35, 0, 255, 8, 8) + bounds: 232 280 8 8 + - image: solid-color(30, 35, 0, 255, 8, 8) + bounds: 240 280 8 8 + - image: solid-color(31, 35, 0, 255, 8, 8) + bounds: 248 280 8 8 + - image: solid-color(32, 35, 0, 255, 8, 8) + bounds: 256 280 8 8 + - image: solid-color(33, 35, 0, 255, 8, 8) + bounds: 264 280 8 8 + - image: solid-color(34, 35, 0, 255, 8, 8) + bounds: 272 280 8 8 + - image: solid-color(35, 35, 0, 255, 8, 8) + bounds: 280 280 8 8 + - image: solid-color(36, 35, 0, 255, 8, 8) + bounds: 288 280 8 8 + - image: solid-color(37, 35, 0, 255, 8, 8) + bounds: 296 280 8 8 + - image: solid-color(38, 35, 0, 255, 8, 8) + bounds: 304 280 8 8 + - image: solid-color(39, 35, 0, 255, 8, 8) + bounds: 312 280 8 8 + - image: solid-color(40, 35, 0, 255, 8, 8) + bounds: 320 280 8 8 + - image: solid-color(41, 35, 0, 255, 8, 8) + bounds: 328 280 8 8 + - image: solid-color(42, 35, 0, 255, 8, 8) + bounds: 336 280 8 8 + - image: solid-color(43, 35, 0, 255, 8, 8) + bounds: 344 280 8 8 + - image: solid-color(44, 35, 0, 255, 8, 8) + bounds: 352 280 8 8 + - image: solid-color(45, 35, 0, 255, 8, 8) + bounds: 360 280 8 8 + - image: solid-color(46, 35, 0, 255, 8, 8) + bounds: 368 280 8 8 + - image: solid-color(47, 35, 0, 255, 8, 8) + bounds: 376 280 8 8 + - image: solid-color(48, 35, 0, 255, 8, 8) + bounds: 384 280 8 8 + - image: solid-color(49, 35, 0, 255, 8, 8) + bounds: 392 280 8 8 + - image: solid-color(50, 35, 0, 255, 8, 8) + bounds: 400 280 8 8 + - image: solid-color(51, 35, 0, 255, 8, 8) + bounds: 408 280 8 8 + - image: solid-color(52, 35, 0, 255, 8, 8) + bounds: 416 280 8 8 + - image: solid-color(53, 35, 0, 255, 8, 8) + bounds: 424 280 8 8 + - image: solid-color(54, 35, 0, 255, 8, 8) + bounds: 432 280 8 8 + - image: solid-color(55, 35, 0, 255, 8, 8) + bounds: 440 280 8 8 + - image: solid-color(56, 35, 0, 255, 8, 8) + bounds: 448 280 8 8 + - image: solid-color(57, 35, 0, 255, 8, 8) + bounds: 456 280 8 8 + - image: solid-color(58, 35, 0, 255, 8, 8) + bounds: 464 280 8 8 + - image: solid-color(59, 35, 0, 255, 8, 8) + bounds: 472 280 8 8 + - image: solid-color(60, 35, 0, 255, 8, 8) + bounds: 480 280 8 8 + - image: solid-color(61, 35, 0, 255, 8, 8) + bounds: 488 280 8 8 + - image: solid-color(62, 35, 0, 255, 8, 8) + bounds: 496 280 8 8 + - image: solid-color(63, 35, 0, 255, 8, 8) + bounds: 504 280 8 8 + - image: solid-color(64, 35, 0, 255, 8, 8) + bounds: 512 280 8 8 + - image: solid-color(65, 35, 0, 255, 8, 8) + bounds: 520 280 8 8 + - image: solid-color(66, 35, 0, 255, 8, 8) + bounds: 528 280 8 8 + - image: solid-color(67, 35, 0, 255, 8, 8) + bounds: 536 280 8 8 + - image: solid-color(68, 35, 0, 255, 8, 8) + bounds: 544 280 8 8 + - image: solid-color(69, 35, 0, 255, 8, 8) + bounds: 552 280 8 8 + - image: solid-color(70, 35, 0, 255, 8, 8) + bounds: 560 280 8 8 + - image: solid-color(71, 35, 0, 255, 8, 8) + bounds: 568 280 8 8 + - image: solid-color(72, 35, 0, 255, 8, 8) + bounds: 576 280 8 8 + - image: solid-color(73, 35, 0, 255, 8, 8) + bounds: 584 280 8 8 + - image: solid-color(74, 35, 0, 255, 8, 8) + bounds: 592 280 8 8 + - image: solid-color(75, 35, 0, 255, 8, 8) + bounds: 600 280 8 8 + - image: solid-color(76, 35, 0, 255, 8, 8) + bounds: 608 280 8 8 + - image: solid-color(77, 35, 0, 255, 8, 8) + bounds: 616 280 8 8 + - image: solid-color(78, 35, 0, 255, 8, 8) + bounds: 624 280 8 8 + - image: solid-color(79, 35, 0, 255, 8, 8) + bounds: 632 280 8 8 + - image: solid-color(80, 35, 0, 255, 8, 8) + bounds: 640 280 8 8 + - image: solid-color(81, 35, 0, 255, 8, 8) + bounds: 648 280 8 8 + - image: solid-color(82, 35, 0, 255, 8, 8) + bounds: 656 280 8 8 + - image: solid-color(83, 35, 0, 255, 8, 8) + bounds: 664 280 8 8 + - image: solid-color(84, 35, 0, 255, 8, 8) + bounds: 672 280 8 8 + - image: solid-color(85, 35, 0, 255, 8, 8) + bounds: 680 280 8 8 + - image: solid-color(86, 35, 0, 255, 8, 8) + bounds: 688 280 8 8 + - image: solid-color(87, 35, 0, 255, 8, 8) + bounds: 696 280 8 8 + - image: solid-color(88, 35, 0, 255, 8, 8) + bounds: 704 280 8 8 + - image: solid-color(89, 35, 0, 255, 8, 8) + bounds: 712 280 8 8 + - image: solid-color(90, 35, 0, 255, 8, 8) + bounds: 720 280 8 8 + - image: solid-color(91, 35, 0, 255, 8, 8) + bounds: 728 280 8 8 + - image: solid-color(92, 35, 0, 255, 8, 8) + bounds: 736 280 8 8 + - image: solid-color(93, 35, 0, 255, 8, 8) + bounds: 744 280 8 8 + - image: solid-color(94, 35, 0, 255, 8, 8) + bounds: 752 280 8 8 + - image: solid-color(95, 35, 0, 255, 8, 8) + bounds: 760 280 8 8 + - image: solid-color(96, 35, 0, 255, 8, 8) + bounds: 768 280 8 8 + - image: solid-color(97, 35, 0, 255, 8, 8) + bounds: 776 280 8 8 + - image: solid-color(98, 35, 0, 255, 8, 8) + bounds: 784 280 8 8 + - image: solid-color(99, 35, 0, 255, 8, 8) + bounds: 792 280 8 8 + - image: solid-color(100, 35, 0, 255, 8, 8) + bounds: 800 280 8 8 + - image: solid-color(101, 35, 0, 255, 8, 8) + bounds: 808 280 8 8 + - image: solid-color(102, 35, 0, 255, 8, 8) + bounds: 816 280 8 8 + - image: solid-color(103, 35, 0, 255, 8, 8) + bounds: 824 280 8 8 + - image: solid-color(104, 35, 0, 255, 8, 8) + bounds: 832 280 8 8 + - image: solid-color(105, 35, 0, 255, 8, 8) + bounds: 840 280 8 8 + - image: solid-color(106, 35, 0, 255, 8, 8) + bounds: 848 280 8 8 + - image: solid-color(107, 35, 0, 255, 8, 8) + bounds: 856 280 8 8 + - image: solid-color(108, 35, 0, 255, 8, 8) + bounds: 864 280 8 8 + - image: solid-color(109, 35, 0, 255, 8, 8) + bounds: 872 280 8 8 + - image: solid-color(110, 35, 0, 255, 8, 8) + bounds: 880 280 8 8 + - image: solid-color(111, 35, 0, 255, 8, 8) + bounds: 888 280 8 8 + - image: solid-color(112, 35, 0, 255, 8, 8) + bounds: 896 280 8 8 + - image: solid-color(113, 35, 0, 255, 8, 8) + bounds: 904 280 8 8 + - image: solid-color(114, 35, 0, 255, 8, 8) + bounds: 912 280 8 8 + - image: solid-color(115, 35, 0, 255, 8, 8) + bounds: 920 280 8 8 + - image: solid-color(116, 35, 0, 255, 8, 8) + bounds: 928 280 8 8 + - image: solid-color(117, 35, 0, 255, 8, 8) + bounds: 936 280 8 8 + - image: solid-color(118, 35, 0, 255, 8, 8) + bounds: 944 280 8 8 + - image: solid-color(119, 35, 0, 255, 8, 8) + bounds: 952 280 8 8 + - image: solid-color(120, 35, 0, 255, 8, 8) + bounds: 960 280 8 8 + - image: solid-color(121, 35, 0, 255, 8, 8) + bounds: 968 280 8 8 + - image: solid-color(122, 35, 0, 255, 8, 8) + bounds: 976 280 8 8 + - image: solid-color(123, 35, 0, 255, 8, 8) + bounds: 984 280 8 8 + - image: solid-color(124, 35, 0, 255, 8, 8) + bounds: 992 280 8 8 + - image: solid-color(125, 35, 0, 255, 8, 8) + bounds: 1000 280 8 8 + - image: solid-color(126, 35, 0, 255, 8, 8) + bounds: 1008 280 8 8 + - image: solid-color(127, 35, 0, 255, 8, 8) + bounds: 1016 280 8 8 + - image: solid-color(0, 36, 0, 255, 8, 8) + bounds: 0 288 8 8 + - image: solid-color(1, 36, 0, 255, 8, 8) + bounds: 8 288 8 8 + - image: solid-color(2, 36, 0, 255, 8, 8) + bounds: 16 288 8 8 + - image: solid-color(3, 36, 0, 255, 8, 8) + bounds: 24 288 8 8 + - image: solid-color(4, 36, 0, 255, 8, 8) + bounds: 32 288 8 8 + - image: solid-color(5, 36, 0, 255, 8, 8) + bounds: 40 288 8 8 + - image: solid-color(6, 36, 0, 255, 8, 8) + bounds: 48 288 8 8 + - image: solid-color(7, 36, 0, 255, 8, 8) + bounds: 56 288 8 8 + - image: solid-color(8, 36, 0, 255, 8, 8) + bounds: 64 288 8 8 + - image: solid-color(9, 36, 0, 255, 8, 8) + bounds: 72 288 8 8 + - image: solid-color(10, 36, 0, 255, 8, 8) + bounds: 80 288 8 8 + - image: solid-color(11, 36, 0, 255, 8, 8) + bounds: 88 288 8 8 + - image: solid-color(12, 36, 0, 255, 8, 8) + bounds: 96 288 8 8 + - image: solid-color(13, 36, 0, 255, 8, 8) + bounds: 104 288 8 8 + - image: solid-color(14, 36, 0, 255, 8, 8) + bounds: 112 288 8 8 + - image: solid-color(15, 36, 0, 255, 8, 8) + bounds: 120 288 8 8 + - image: solid-color(16, 36, 0, 255, 8, 8) + bounds: 128 288 8 8 + - image: solid-color(17, 36, 0, 255, 8, 8) + bounds: 136 288 8 8 + - image: solid-color(18, 36, 0, 255, 8, 8) + bounds: 144 288 8 8 + - image: solid-color(19, 36, 0, 255, 8, 8) + bounds: 152 288 8 8 + - image: solid-color(20, 36, 0, 255, 8, 8) + bounds: 160 288 8 8 + - image: solid-color(21, 36, 0, 255, 8, 8) + bounds: 168 288 8 8 + - image: solid-color(22, 36, 0, 255, 8, 8) + bounds: 176 288 8 8 + - image: solid-color(23, 36, 0, 255, 8, 8) + bounds: 184 288 8 8 + - image: solid-color(24, 36, 0, 255, 8, 8) + bounds: 192 288 8 8 + - image: solid-color(25, 36, 0, 255, 8, 8) + bounds: 200 288 8 8 + - image: solid-color(26, 36, 0, 255, 8, 8) + bounds: 208 288 8 8 + - image: solid-color(27, 36, 0, 255, 8, 8) + bounds: 216 288 8 8 + - image: solid-color(28, 36, 0, 255, 8, 8) + bounds: 224 288 8 8 + - image: solid-color(29, 36, 0, 255, 8, 8) + bounds: 232 288 8 8 + - image: solid-color(30, 36, 0, 255, 8, 8) + bounds: 240 288 8 8 + - image: solid-color(31, 36, 0, 255, 8, 8) + bounds: 248 288 8 8 + - image: solid-color(32, 36, 0, 255, 8, 8) + bounds: 256 288 8 8 + - image: solid-color(33, 36, 0, 255, 8, 8) + bounds: 264 288 8 8 + - image: solid-color(34, 36, 0, 255, 8, 8) + bounds: 272 288 8 8 + - image: solid-color(35, 36, 0, 255, 8, 8) + bounds: 280 288 8 8 + - image: solid-color(36, 36, 0, 255, 8, 8) + bounds: 288 288 8 8 + - image: solid-color(37, 36, 0, 255, 8, 8) + bounds: 296 288 8 8 + - image: solid-color(38, 36, 0, 255, 8, 8) + bounds: 304 288 8 8 + - image: solid-color(39, 36, 0, 255, 8, 8) + bounds: 312 288 8 8 + - image: solid-color(40, 36, 0, 255, 8, 8) + bounds: 320 288 8 8 + - image: solid-color(41, 36, 0, 255, 8, 8) + bounds: 328 288 8 8 + - image: solid-color(42, 36, 0, 255, 8, 8) + bounds: 336 288 8 8 + - image: solid-color(43, 36, 0, 255, 8, 8) + bounds: 344 288 8 8 + - image: solid-color(44, 36, 0, 255, 8, 8) + bounds: 352 288 8 8 + - image: solid-color(45, 36, 0, 255, 8, 8) + bounds: 360 288 8 8 + - image: solid-color(46, 36, 0, 255, 8, 8) + bounds: 368 288 8 8 + - image: solid-color(47, 36, 0, 255, 8, 8) + bounds: 376 288 8 8 + - image: solid-color(48, 36, 0, 255, 8, 8) + bounds: 384 288 8 8 + - image: solid-color(49, 36, 0, 255, 8, 8) + bounds: 392 288 8 8 + - image: solid-color(50, 36, 0, 255, 8, 8) + bounds: 400 288 8 8 + - image: solid-color(51, 36, 0, 255, 8, 8) + bounds: 408 288 8 8 + - image: solid-color(52, 36, 0, 255, 8, 8) + bounds: 416 288 8 8 + - image: solid-color(53, 36, 0, 255, 8, 8) + bounds: 424 288 8 8 + - image: solid-color(54, 36, 0, 255, 8, 8) + bounds: 432 288 8 8 + - image: solid-color(55, 36, 0, 255, 8, 8) + bounds: 440 288 8 8 + - image: solid-color(56, 36, 0, 255, 8, 8) + bounds: 448 288 8 8 + - image: solid-color(57, 36, 0, 255, 8, 8) + bounds: 456 288 8 8 + - image: solid-color(58, 36, 0, 255, 8, 8) + bounds: 464 288 8 8 + - image: solid-color(59, 36, 0, 255, 8, 8) + bounds: 472 288 8 8 + - image: solid-color(60, 36, 0, 255, 8, 8) + bounds: 480 288 8 8 + - image: solid-color(61, 36, 0, 255, 8, 8) + bounds: 488 288 8 8 + - image: solid-color(62, 36, 0, 255, 8, 8) + bounds: 496 288 8 8 + - image: solid-color(63, 36, 0, 255, 8, 8) + bounds: 504 288 8 8 + - image: solid-color(64, 36, 0, 255, 8, 8) + bounds: 512 288 8 8 + - image: solid-color(65, 36, 0, 255, 8, 8) + bounds: 520 288 8 8 + - image: solid-color(66, 36, 0, 255, 8, 8) + bounds: 528 288 8 8 + - image: solid-color(67, 36, 0, 255, 8, 8) + bounds: 536 288 8 8 + - image: solid-color(68, 36, 0, 255, 8, 8) + bounds: 544 288 8 8 + - image: solid-color(69, 36, 0, 255, 8, 8) + bounds: 552 288 8 8 + - image: solid-color(70, 36, 0, 255, 8, 8) + bounds: 560 288 8 8 + - image: solid-color(71, 36, 0, 255, 8, 8) + bounds: 568 288 8 8 + - image: solid-color(72, 36, 0, 255, 8, 8) + bounds: 576 288 8 8 + - image: solid-color(73, 36, 0, 255, 8, 8) + bounds: 584 288 8 8 + - image: solid-color(74, 36, 0, 255, 8, 8) + bounds: 592 288 8 8 + - image: solid-color(75, 36, 0, 255, 8, 8) + bounds: 600 288 8 8 + - image: solid-color(76, 36, 0, 255, 8, 8) + bounds: 608 288 8 8 + - image: solid-color(77, 36, 0, 255, 8, 8) + bounds: 616 288 8 8 + - image: solid-color(78, 36, 0, 255, 8, 8) + bounds: 624 288 8 8 + - image: solid-color(79, 36, 0, 255, 8, 8) + bounds: 632 288 8 8 + - image: solid-color(80, 36, 0, 255, 8, 8) + bounds: 640 288 8 8 + - image: solid-color(81, 36, 0, 255, 8, 8) + bounds: 648 288 8 8 + - image: solid-color(82, 36, 0, 255, 8, 8) + bounds: 656 288 8 8 + - image: solid-color(83, 36, 0, 255, 8, 8) + bounds: 664 288 8 8 + - image: solid-color(84, 36, 0, 255, 8, 8) + bounds: 672 288 8 8 + - image: solid-color(85, 36, 0, 255, 8, 8) + bounds: 680 288 8 8 + - image: solid-color(86, 36, 0, 255, 8, 8) + bounds: 688 288 8 8 + - image: solid-color(87, 36, 0, 255, 8, 8) + bounds: 696 288 8 8 + - image: solid-color(88, 36, 0, 255, 8, 8) + bounds: 704 288 8 8 + - image: solid-color(89, 36, 0, 255, 8, 8) + bounds: 712 288 8 8 + - image: solid-color(90, 36, 0, 255, 8, 8) + bounds: 720 288 8 8 + - image: solid-color(91, 36, 0, 255, 8, 8) + bounds: 728 288 8 8 + - image: solid-color(92, 36, 0, 255, 8, 8) + bounds: 736 288 8 8 + - image: solid-color(93, 36, 0, 255, 8, 8) + bounds: 744 288 8 8 + - image: solid-color(94, 36, 0, 255, 8, 8) + bounds: 752 288 8 8 + - image: solid-color(95, 36, 0, 255, 8, 8) + bounds: 760 288 8 8 + - image: solid-color(96, 36, 0, 255, 8, 8) + bounds: 768 288 8 8 + - image: solid-color(97, 36, 0, 255, 8, 8) + bounds: 776 288 8 8 + - image: solid-color(98, 36, 0, 255, 8, 8) + bounds: 784 288 8 8 + - image: solid-color(99, 36, 0, 255, 8, 8) + bounds: 792 288 8 8 + - image: solid-color(100, 36, 0, 255, 8, 8) + bounds: 800 288 8 8 + - image: solid-color(101, 36, 0, 255, 8, 8) + bounds: 808 288 8 8 + - image: solid-color(102, 36, 0, 255, 8, 8) + bounds: 816 288 8 8 + - image: solid-color(103, 36, 0, 255, 8, 8) + bounds: 824 288 8 8 + - image: solid-color(104, 36, 0, 255, 8, 8) + bounds: 832 288 8 8 + - image: solid-color(105, 36, 0, 255, 8, 8) + bounds: 840 288 8 8 + - image: solid-color(106, 36, 0, 255, 8, 8) + bounds: 848 288 8 8 + - image: solid-color(107, 36, 0, 255, 8, 8) + bounds: 856 288 8 8 + - image: solid-color(108, 36, 0, 255, 8, 8) + bounds: 864 288 8 8 + - image: solid-color(109, 36, 0, 255, 8, 8) + bounds: 872 288 8 8 + - image: solid-color(110, 36, 0, 255, 8, 8) + bounds: 880 288 8 8 + - image: solid-color(111, 36, 0, 255, 8, 8) + bounds: 888 288 8 8 + - image: solid-color(112, 36, 0, 255, 8, 8) + bounds: 896 288 8 8 + - image: solid-color(113, 36, 0, 255, 8, 8) + bounds: 904 288 8 8 + - image: solid-color(114, 36, 0, 255, 8, 8) + bounds: 912 288 8 8 + - image: solid-color(115, 36, 0, 255, 8, 8) + bounds: 920 288 8 8 + - image: solid-color(116, 36, 0, 255, 8, 8) + bounds: 928 288 8 8 + - image: solid-color(117, 36, 0, 255, 8, 8) + bounds: 936 288 8 8 + - image: solid-color(118, 36, 0, 255, 8, 8) + bounds: 944 288 8 8 + - image: solid-color(119, 36, 0, 255, 8, 8) + bounds: 952 288 8 8 + - image: solid-color(120, 36, 0, 255, 8, 8) + bounds: 960 288 8 8 + - image: solid-color(121, 36, 0, 255, 8, 8) + bounds: 968 288 8 8 + - image: solid-color(122, 36, 0, 255, 8, 8) + bounds: 976 288 8 8 + - image: solid-color(123, 36, 0, 255, 8, 8) + bounds: 984 288 8 8 + - image: solid-color(124, 36, 0, 255, 8, 8) + bounds: 992 288 8 8 + - image: solid-color(125, 36, 0, 255, 8, 8) + bounds: 1000 288 8 8 + - image: solid-color(126, 36, 0, 255, 8, 8) + bounds: 1008 288 8 8 + - image: solid-color(127, 36, 0, 255, 8, 8) + bounds: 1016 288 8 8 + - image: solid-color(0, 37, 0, 255, 8, 8) + bounds: 0 296 8 8 + - image: solid-color(1, 37, 0, 255, 8, 8) + bounds: 8 296 8 8 + - image: solid-color(2, 37, 0, 255, 8, 8) + bounds: 16 296 8 8 + - image: solid-color(3, 37, 0, 255, 8, 8) + bounds: 24 296 8 8 + - image: solid-color(4, 37, 0, 255, 8, 8) + bounds: 32 296 8 8 + - image: solid-color(5, 37, 0, 255, 8, 8) + bounds: 40 296 8 8 + - image: solid-color(6, 37, 0, 255, 8, 8) + bounds: 48 296 8 8 + - image: solid-color(7, 37, 0, 255, 8, 8) + bounds: 56 296 8 8 + - image: solid-color(8, 37, 0, 255, 8, 8) + bounds: 64 296 8 8 + - image: solid-color(9, 37, 0, 255, 8, 8) + bounds: 72 296 8 8 + - image: solid-color(10, 37, 0, 255, 8, 8) + bounds: 80 296 8 8 + - image: solid-color(11, 37, 0, 255, 8, 8) + bounds: 88 296 8 8 + - image: solid-color(12, 37, 0, 255, 8, 8) + bounds: 96 296 8 8 + - image: solid-color(13, 37, 0, 255, 8, 8) + bounds: 104 296 8 8 + - image: solid-color(14, 37, 0, 255, 8, 8) + bounds: 112 296 8 8 + - image: solid-color(15, 37, 0, 255, 8, 8) + bounds: 120 296 8 8 + - image: solid-color(16, 37, 0, 255, 8, 8) + bounds: 128 296 8 8 + - image: solid-color(17, 37, 0, 255, 8, 8) + bounds: 136 296 8 8 + - image: solid-color(18, 37, 0, 255, 8, 8) + bounds: 144 296 8 8 + - image: solid-color(19, 37, 0, 255, 8, 8) + bounds: 152 296 8 8 + - image: solid-color(20, 37, 0, 255, 8, 8) + bounds: 160 296 8 8 + - image: solid-color(21, 37, 0, 255, 8, 8) + bounds: 168 296 8 8 + - image: solid-color(22, 37, 0, 255, 8, 8) + bounds: 176 296 8 8 + - image: solid-color(23, 37, 0, 255, 8, 8) + bounds: 184 296 8 8 + - image: solid-color(24, 37, 0, 255, 8, 8) + bounds: 192 296 8 8 + - image: solid-color(25, 37, 0, 255, 8, 8) + bounds: 200 296 8 8 + - image: solid-color(26, 37, 0, 255, 8, 8) + bounds: 208 296 8 8 + - image: solid-color(27, 37, 0, 255, 8, 8) + bounds: 216 296 8 8 + - image: solid-color(28, 37, 0, 255, 8, 8) + bounds: 224 296 8 8 + - image: solid-color(29, 37, 0, 255, 8, 8) + bounds: 232 296 8 8 + - image: solid-color(30, 37, 0, 255, 8, 8) + bounds: 240 296 8 8 + - image: solid-color(31, 37, 0, 255, 8, 8) + bounds: 248 296 8 8 + - image: solid-color(32, 37, 0, 255, 8, 8) + bounds: 256 296 8 8 + - image: solid-color(33, 37, 0, 255, 8, 8) + bounds: 264 296 8 8 + - image: solid-color(34, 37, 0, 255, 8, 8) + bounds: 272 296 8 8 + - image: solid-color(35, 37, 0, 255, 8, 8) + bounds: 280 296 8 8 + - image: solid-color(36, 37, 0, 255, 8, 8) + bounds: 288 296 8 8 + - image: solid-color(37, 37, 0, 255, 8, 8) + bounds: 296 296 8 8 + - image: solid-color(38, 37, 0, 255, 8, 8) + bounds: 304 296 8 8 + - image: solid-color(39, 37, 0, 255, 8, 8) + bounds: 312 296 8 8 + - image: solid-color(40, 37, 0, 255, 8, 8) + bounds: 320 296 8 8 + - image: solid-color(41, 37, 0, 255, 8, 8) + bounds: 328 296 8 8 + - image: solid-color(42, 37, 0, 255, 8, 8) + bounds: 336 296 8 8 + - image: solid-color(43, 37, 0, 255, 8, 8) + bounds: 344 296 8 8 + - image: solid-color(44, 37, 0, 255, 8, 8) + bounds: 352 296 8 8 + - image: solid-color(45, 37, 0, 255, 8, 8) + bounds: 360 296 8 8 + - image: solid-color(46, 37, 0, 255, 8, 8) + bounds: 368 296 8 8 + - image: solid-color(47, 37, 0, 255, 8, 8) + bounds: 376 296 8 8 + - image: solid-color(48, 37, 0, 255, 8, 8) + bounds: 384 296 8 8 + - image: solid-color(49, 37, 0, 255, 8, 8) + bounds: 392 296 8 8 + - image: solid-color(50, 37, 0, 255, 8, 8) + bounds: 400 296 8 8 + - image: solid-color(51, 37, 0, 255, 8, 8) + bounds: 408 296 8 8 + - image: solid-color(52, 37, 0, 255, 8, 8) + bounds: 416 296 8 8 + - image: solid-color(53, 37, 0, 255, 8, 8) + bounds: 424 296 8 8 + - image: solid-color(54, 37, 0, 255, 8, 8) + bounds: 432 296 8 8 + - image: solid-color(55, 37, 0, 255, 8, 8) + bounds: 440 296 8 8 + - image: solid-color(56, 37, 0, 255, 8, 8) + bounds: 448 296 8 8 + - image: solid-color(57, 37, 0, 255, 8, 8) + bounds: 456 296 8 8 + - image: solid-color(58, 37, 0, 255, 8, 8) + bounds: 464 296 8 8 + - image: solid-color(59, 37, 0, 255, 8, 8) + bounds: 472 296 8 8 + - image: solid-color(60, 37, 0, 255, 8, 8) + bounds: 480 296 8 8 + - image: solid-color(61, 37, 0, 255, 8, 8) + bounds: 488 296 8 8 + - image: solid-color(62, 37, 0, 255, 8, 8) + bounds: 496 296 8 8 + - image: solid-color(63, 37, 0, 255, 8, 8) + bounds: 504 296 8 8 + - image: solid-color(64, 37, 0, 255, 8, 8) + bounds: 512 296 8 8 + - image: solid-color(65, 37, 0, 255, 8, 8) + bounds: 520 296 8 8 + - image: solid-color(66, 37, 0, 255, 8, 8) + bounds: 528 296 8 8 + - image: solid-color(67, 37, 0, 255, 8, 8) + bounds: 536 296 8 8 + - image: solid-color(68, 37, 0, 255, 8, 8) + bounds: 544 296 8 8 + - image: solid-color(69, 37, 0, 255, 8, 8) + bounds: 552 296 8 8 + - image: solid-color(70, 37, 0, 255, 8, 8) + bounds: 560 296 8 8 + - image: solid-color(71, 37, 0, 255, 8, 8) + bounds: 568 296 8 8 + - image: solid-color(72, 37, 0, 255, 8, 8) + bounds: 576 296 8 8 + - image: solid-color(73, 37, 0, 255, 8, 8) + bounds: 584 296 8 8 + - image: solid-color(74, 37, 0, 255, 8, 8) + bounds: 592 296 8 8 + - image: solid-color(75, 37, 0, 255, 8, 8) + bounds: 600 296 8 8 + - image: solid-color(76, 37, 0, 255, 8, 8) + bounds: 608 296 8 8 + - image: solid-color(77, 37, 0, 255, 8, 8) + bounds: 616 296 8 8 + - image: solid-color(78, 37, 0, 255, 8, 8) + bounds: 624 296 8 8 + - image: solid-color(79, 37, 0, 255, 8, 8) + bounds: 632 296 8 8 + - image: solid-color(80, 37, 0, 255, 8, 8) + bounds: 640 296 8 8 + - image: solid-color(81, 37, 0, 255, 8, 8) + bounds: 648 296 8 8 + - image: solid-color(82, 37, 0, 255, 8, 8) + bounds: 656 296 8 8 + - image: solid-color(83, 37, 0, 255, 8, 8) + bounds: 664 296 8 8 + - image: solid-color(84, 37, 0, 255, 8, 8) + bounds: 672 296 8 8 + - image: solid-color(85, 37, 0, 255, 8, 8) + bounds: 680 296 8 8 + - image: solid-color(86, 37, 0, 255, 8, 8) + bounds: 688 296 8 8 + - image: solid-color(87, 37, 0, 255, 8, 8) + bounds: 696 296 8 8 + - image: solid-color(88, 37, 0, 255, 8, 8) + bounds: 704 296 8 8 + - image: solid-color(89, 37, 0, 255, 8, 8) + bounds: 712 296 8 8 + - image: solid-color(90, 37, 0, 255, 8, 8) + bounds: 720 296 8 8 + - image: solid-color(91, 37, 0, 255, 8, 8) + bounds: 728 296 8 8 + - image: solid-color(92, 37, 0, 255, 8, 8) + bounds: 736 296 8 8 + - image: solid-color(93, 37, 0, 255, 8, 8) + bounds: 744 296 8 8 + - image: solid-color(94, 37, 0, 255, 8, 8) + bounds: 752 296 8 8 + - image: solid-color(95, 37, 0, 255, 8, 8) + bounds: 760 296 8 8 + - image: solid-color(96, 37, 0, 255, 8, 8) + bounds: 768 296 8 8 + - image: solid-color(97, 37, 0, 255, 8, 8) + bounds: 776 296 8 8 + - image: solid-color(98, 37, 0, 255, 8, 8) + bounds: 784 296 8 8 + - image: solid-color(99, 37, 0, 255, 8, 8) + bounds: 792 296 8 8 + - image: solid-color(100, 37, 0, 255, 8, 8) + bounds: 800 296 8 8 + - image: solid-color(101, 37, 0, 255, 8, 8) + bounds: 808 296 8 8 + - image: solid-color(102, 37, 0, 255, 8, 8) + bounds: 816 296 8 8 + - image: solid-color(103, 37, 0, 255, 8, 8) + bounds: 824 296 8 8 + - image: solid-color(104, 37, 0, 255, 8, 8) + bounds: 832 296 8 8 + - image: solid-color(105, 37, 0, 255, 8, 8) + bounds: 840 296 8 8 + - image: solid-color(106, 37, 0, 255, 8, 8) + bounds: 848 296 8 8 + - image: solid-color(107, 37, 0, 255, 8, 8) + bounds: 856 296 8 8 + - image: solid-color(108, 37, 0, 255, 8, 8) + bounds: 864 296 8 8 + - image: solid-color(109, 37, 0, 255, 8, 8) + bounds: 872 296 8 8 + - image: solid-color(110, 37, 0, 255, 8, 8) + bounds: 880 296 8 8 + - image: solid-color(111, 37, 0, 255, 8, 8) + bounds: 888 296 8 8 + - image: solid-color(112, 37, 0, 255, 8, 8) + bounds: 896 296 8 8 + - image: solid-color(113, 37, 0, 255, 8, 8) + bounds: 904 296 8 8 + - image: solid-color(114, 37, 0, 255, 8, 8) + bounds: 912 296 8 8 + - image: solid-color(115, 37, 0, 255, 8, 8) + bounds: 920 296 8 8 + - image: solid-color(116, 37, 0, 255, 8, 8) + bounds: 928 296 8 8 + - image: solid-color(117, 37, 0, 255, 8, 8) + bounds: 936 296 8 8 + - image: solid-color(118, 37, 0, 255, 8, 8) + bounds: 944 296 8 8 + - image: solid-color(119, 37, 0, 255, 8, 8) + bounds: 952 296 8 8 + - image: solid-color(120, 37, 0, 255, 8, 8) + bounds: 960 296 8 8 + - image: solid-color(121, 37, 0, 255, 8, 8) + bounds: 968 296 8 8 + - image: solid-color(122, 37, 0, 255, 8, 8) + bounds: 976 296 8 8 + - image: solid-color(123, 37, 0, 255, 8, 8) + bounds: 984 296 8 8 + - image: solid-color(124, 37, 0, 255, 8, 8) + bounds: 992 296 8 8 + - image: solid-color(125, 37, 0, 255, 8, 8) + bounds: 1000 296 8 8 + - image: solid-color(126, 37, 0, 255, 8, 8) + bounds: 1008 296 8 8 + - image: solid-color(127, 37, 0, 255, 8, 8) + bounds: 1016 296 8 8 + - image: solid-color(0, 38, 0, 255, 8, 8) + bounds: 0 304 8 8 + - image: solid-color(1, 38, 0, 255, 8, 8) + bounds: 8 304 8 8 + - image: solid-color(2, 38, 0, 255, 8, 8) + bounds: 16 304 8 8 + - image: solid-color(3, 38, 0, 255, 8, 8) + bounds: 24 304 8 8 + - image: solid-color(4, 38, 0, 255, 8, 8) + bounds: 32 304 8 8 + - image: solid-color(5, 38, 0, 255, 8, 8) + bounds: 40 304 8 8 + - image: solid-color(6, 38, 0, 255, 8, 8) + bounds: 48 304 8 8 + - image: solid-color(7, 38, 0, 255, 8, 8) + bounds: 56 304 8 8 + - image: solid-color(8, 38, 0, 255, 8, 8) + bounds: 64 304 8 8 + - image: solid-color(9, 38, 0, 255, 8, 8) + bounds: 72 304 8 8 + - image: solid-color(10, 38, 0, 255, 8, 8) + bounds: 80 304 8 8 + - image: solid-color(11, 38, 0, 255, 8, 8) + bounds: 88 304 8 8 + - image: solid-color(12, 38, 0, 255, 8, 8) + bounds: 96 304 8 8 + - image: solid-color(13, 38, 0, 255, 8, 8) + bounds: 104 304 8 8 + - image: solid-color(14, 38, 0, 255, 8, 8) + bounds: 112 304 8 8 + - image: solid-color(15, 38, 0, 255, 8, 8) + bounds: 120 304 8 8 + - image: solid-color(16, 38, 0, 255, 8, 8) + bounds: 128 304 8 8 + - image: solid-color(17, 38, 0, 255, 8, 8) + bounds: 136 304 8 8 + - image: solid-color(18, 38, 0, 255, 8, 8) + bounds: 144 304 8 8 + - image: solid-color(19, 38, 0, 255, 8, 8) + bounds: 152 304 8 8 + - image: solid-color(20, 38, 0, 255, 8, 8) + bounds: 160 304 8 8 + - image: solid-color(21, 38, 0, 255, 8, 8) + bounds: 168 304 8 8 + - image: solid-color(22, 38, 0, 255, 8, 8) + bounds: 176 304 8 8 + - image: solid-color(23, 38, 0, 255, 8, 8) + bounds: 184 304 8 8 + - image: solid-color(24, 38, 0, 255, 8, 8) + bounds: 192 304 8 8 + - image: solid-color(25, 38, 0, 255, 8, 8) + bounds: 200 304 8 8 + - image: solid-color(26, 38, 0, 255, 8, 8) + bounds: 208 304 8 8 + - image: solid-color(27, 38, 0, 255, 8, 8) + bounds: 216 304 8 8 + - image: solid-color(28, 38, 0, 255, 8, 8) + bounds: 224 304 8 8 + - image: solid-color(29, 38, 0, 255, 8, 8) + bounds: 232 304 8 8 + - image: solid-color(30, 38, 0, 255, 8, 8) + bounds: 240 304 8 8 + - image: solid-color(31, 38, 0, 255, 8, 8) + bounds: 248 304 8 8 + - image: solid-color(32, 38, 0, 255, 8, 8) + bounds: 256 304 8 8 + - image: solid-color(33, 38, 0, 255, 8, 8) + bounds: 264 304 8 8 + - image: solid-color(34, 38, 0, 255, 8, 8) + bounds: 272 304 8 8 + - image: solid-color(35, 38, 0, 255, 8, 8) + bounds: 280 304 8 8 + - image: solid-color(36, 38, 0, 255, 8, 8) + bounds: 288 304 8 8 + - image: solid-color(37, 38, 0, 255, 8, 8) + bounds: 296 304 8 8 + - image: solid-color(38, 38, 0, 255, 8, 8) + bounds: 304 304 8 8 + - image: solid-color(39, 38, 0, 255, 8, 8) + bounds: 312 304 8 8 + - image: solid-color(40, 38, 0, 255, 8, 8) + bounds: 320 304 8 8 + - image: solid-color(41, 38, 0, 255, 8, 8) + bounds: 328 304 8 8 + - image: solid-color(42, 38, 0, 255, 8, 8) + bounds: 336 304 8 8 + - image: solid-color(43, 38, 0, 255, 8, 8) + bounds: 344 304 8 8 + - image: solid-color(44, 38, 0, 255, 8, 8) + bounds: 352 304 8 8 + - image: solid-color(45, 38, 0, 255, 8, 8) + bounds: 360 304 8 8 + - image: solid-color(46, 38, 0, 255, 8, 8) + bounds: 368 304 8 8 + - image: solid-color(47, 38, 0, 255, 8, 8) + bounds: 376 304 8 8 + - image: solid-color(48, 38, 0, 255, 8, 8) + bounds: 384 304 8 8 + - image: solid-color(49, 38, 0, 255, 8, 8) + bounds: 392 304 8 8 + - image: solid-color(50, 38, 0, 255, 8, 8) + bounds: 400 304 8 8 + - image: solid-color(51, 38, 0, 255, 8, 8) + bounds: 408 304 8 8 + - image: solid-color(52, 38, 0, 255, 8, 8) + bounds: 416 304 8 8 + - image: solid-color(53, 38, 0, 255, 8, 8) + bounds: 424 304 8 8 + - image: solid-color(54, 38, 0, 255, 8, 8) + bounds: 432 304 8 8 + - image: solid-color(55, 38, 0, 255, 8, 8) + bounds: 440 304 8 8 + - image: solid-color(56, 38, 0, 255, 8, 8) + bounds: 448 304 8 8 + - image: solid-color(57, 38, 0, 255, 8, 8) + bounds: 456 304 8 8 + - image: solid-color(58, 38, 0, 255, 8, 8) + bounds: 464 304 8 8 + - image: solid-color(59, 38, 0, 255, 8, 8) + bounds: 472 304 8 8 + - image: solid-color(60, 38, 0, 255, 8, 8) + bounds: 480 304 8 8 + - image: solid-color(61, 38, 0, 255, 8, 8) + bounds: 488 304 8 8 + - image: solid-color(62, 38, 0, 255, 8, 8) + bounds: 496 304 8 8 + - image: solid-color(63, 38, 0, 255, 8, 8) + bounds: 504 304 8 8 + - image: solid-color(64, 38, 0, 255, 8, 8) + bounds: 512 304 8 8 + - image: solid-color(65, 38, 0, 255, 8, 8) + bounds: 520 304 8 8 + - image: solid-color(66, 38, 0, 255, 8, 8) + bounds: 528 304 8 8 + - image: solid-color(67, 38, 0, 255, 8, 8) + bounds: 536 304 8 8 + - image: solid-color(68, 38, 0, 255, 8, 8) + bounds: 544 304 8 8 + - image: solid-color(69, 38, 0, 255, 8, 8) + bounds: 552 304 8 8 + - image: solid-color(70, 38, 0, 255, 8, 8) + bounds: 560 304 8 8 + - image: solid-color(71, 38, 0, 255, 8, 8) + bounds: 568 304 8 8 + - image: solid-color(72, 38, 0, 255, 8, 8) + bounds: 576 304 8 8 + - image: solid-color(73, 38, 0, 255, 8, 8) + bounds: 584 304 8 8 + - image: solid-color(74, 38, 0, 255, 8, 8) + bounds: 592 304 8 8 + - image: solid-color(75, 38, 0, 255, 8, 8) + bounds: 600 304 8 8 + - image: solid-color(76, 38, 0, 255, 8, 8) + bounds: 608 304 8 8 + - image: solid-color(77, 38, 0, 255, 8, 8) + bounds: 616 304 8 8 + - image: solid-color(78, 38, 0, 255, 8, 8) + bounds: 624 304 8 8 + - image: solid-color(79, 38, 0, 255, 8, 8) + bounds: 632 304 8 8 + - image: solid-color(80, 38, 0, 255, 8, 8) + bounds: 640 304 8 8 + - image: solid-color(81, 38, 0, 255, 8, 8) + bounds: 648 304 8 8 + - image: solid-color(82, 38, 0, 255, 8, 8) + bounds: 656 304 8 8 + - image: solid-color(83, 38, 0, 255, 8, 8) + bounds: 664 304 8 8 + - image: solid-color(84, 38, 0, 255, 8, 8) + bounds: 672 304 8 8 + - image: solid-color(85, 38, 0, 255, 8, 8) + bounds: 680 304 8 8 + - image: solid-color(86, 38, 0, 255, 8, 8) + bounds: 688 304 8 8 + - image: solid-color(87, 38, 0, 255, 8, 8) + bounds: 696 304 8 8 + - image: solid-color(88, 38, 0, 255, 8, 8) + bounds: 704 304 8 8 + - image: solid-color(89, 38, 0, 255, 8, 8) + bounds: 712 304 8 8 + - image: solid-color(90, 38, 0, 255, 8, 8) + bounds: 720 304 8 8 + - image: solid-color(91, 38, 0, 255, 8, 8) + bounds: 728 304 8 8 + - image: solid-color(92, 38, 0, 255, 8, 8) + bounds: 736 304 8 8 + - image: solid-color(93, 38, 0, 255, 8, 8) + bounds: 744 304 8 8 + - image: solid-color(94, 38, 0, 255, 8, 8) + bounds: 752 304 8 8 + - image: solid-color(95, 38, 0, 255, 8, 8) + bounds: 760 304 8 8 + - image: solid-color(96, 38, 0, 255, 8, 8) + bounds: 768 304 8 8 + - image: solid-color(97, 38, 0, 255, 8, 8) + bounds: 776 304 8 8 + - image: solid-color(98, 38, 0, 255, 8, 8) + bounds: 784 304 8 8 + - image: solid-color(99, 38, 0, 255, 8, 8) + bounds: 792 304 8 8 + - image: solid-color(100, 38, 0, 255, 8, 8) + bounds: 800 304 8 8 + - image: solid-color(101, 38, 0, 255, 8, 8) + bounds: 808 304 8 8 + - image: solid-color(102, 38, 0, 255, 8, 8) + bounds: 816 304 8 8 + - image: solid-color(103, 38, 0, 255, 8, 8) + bounds: 824 304 8 8 + - image: solid-color(104, 38, 0, 255, 8, 8) + bounds: 832 304 8 8 + - image: solid-color(105, 38, 0, 255, 8, 8) + bounds: 840 304 8 8 + - image: solid-color(106, 38, 0, 255, 8, 8) + bounds: 848 304 8 8 + - image: solid-color(107, 38, 0, 255, 8, 8) + bounds: 856 304 8 8 + - image: solid-color(108, 38, 0, 255, 8, 8) + bounds: 864 304 8 8 + - image: solid-color(109, 38, 0, 255, 8, 8) + bounds: 872 304 8 8 + - image: solid-color(110, 38, 0, 255, 8, 8) + bounds: 880 304 8 8 + - image: solid-color(111, 38, 0, 255, 8, 8) + bounds: 888 304 8 8 + - image: solid-color(112, 38, 0, 255, 8, 8) + bounds: 896 304 8 8 + - image: solid-color(113, 38, 0, 255, 8, 8) + bounds: 904 304 8 8 + - image: solid-color(114, 38, 0, 255, 8, 8) + bounds: 912 304 8 8 + - image: solid-color(115, 38, 0, 255, 8, 8) + bounds: 920 304 8 8 + - image: solid-color(116, 38, 0, 255, 8, 8) + bounds: 928 304 8 8 + - image: solid-color(117, 38, 0, 255, 8, 8) + bounds: 936 304 8 8 + - image: solid-color(118, 38, 0, 255, 8, 8) + bounds: 944 304 8 8 + - image: solid-color(119, 38, 0, 255, 8, 8) + bounds: 952 304 8 8 + - image: solid-color(120, 38, 0, 255, 8, 8) + bounds: 960 304 8 8 + - image: solid-color(121, 38, 0, 255, 8, 8) + bounds: 968 304 8 8 + - image: solid-color(122, 38, 0, 255, 8, 8) + bounds: 976 304 8 8 + - image: solid-color(123, 38, 0, 255, 8, 8) + bounds: 984 304 8 8 + - image: solid-color(124, 38, 0, 255, 8, 8) + bounds: 992 304 8 8 + - image: solid-color(125, 38, 0, 255, 8, 8) + bounds: 1000 304 8 8 + - image: solid-color(126, 38, 0, 255, 8, 8) + bounds: 1008 304 8 8 + - image: solid-color(127, 38, 0, 255, 8, 8) + bounds: 1016 304 8 8 + - image: solid-color(0, 39, 0, 255, 8, 8) + bounds: 0 312 8 8 + - image: solid-color(1, 39, 0, 255, 8, 8) + bounds: 8 312 8 8 + - image: solid-color(2, 39, 0, 255, 8, 8) + bounds: 16 312 8 8 + - image: solid-color(3, 39, 0, 255, 8, 8) + bounds: 24 312 8 8 + - image: solid-color(4, 39, 0, 255, 8, 8) + bounds: 32 312 8 8 + - image: solid-color(5, 39, 0, 255, 8, 8) + bounds: 40 312 8 8 + - image: solid-color(6, 39, 0, 255, 8, 8) + bounds: 48 312 8 8 + - image: solid-color(7, 39, 0, 255, 8, 8) + bounds: 56 312 8 8 + - image: solid-color(8, 39, 0, 255, 8, 8) + bounds: 64 312 8 8 + - image: solid-color(9, 39, 0, 255, 8, 8) + bounds: 72 312 8 8 + - image: solid-color(10, 39, 0, 255, 8, 8) + bounds: 80 312 8 8 + - image: solid-color(11, 39, 0, 255, 8, 8) + bounds: 88 312 8 8 + - image: solid-color(12, 39, 0, 255, 8, 8) + bounds: 96 312 8 8 + - image: solid-color(13, 39, 0, 255, 8, 8) + bounds: 104 312 8 8 + - image: solid-color(14, 39, 0, 255, 8, 8) + bounds: 112 312 8 8 + - image: solid-color(15, 39, 0, 255, 8, 8) + bounds: 120 312 8 8 + - image: solid-color(16, 39, 0, 255, 8, 8) + bounds: 128 312 8 8 + - image: solid-color(17, 39, 0, 255, 8, 8) + bounds: 136 312 8 8 + - image: solid-color(18, 39, 0, 255, 8, 8) + bounds: 144 312 8 8 + - image: solid-color(19, 39, 0, 255, 8, 8) + bounds: 152 312 8 8 + - image: solid-color(20, 39, 0, 255, 8, 8) + bounds: 160 312 8 8 + - image: solid-color(21, 39, 0, 255, 8, 8) + bounds: 168 312 8 8 + - image: solid-color(22, 39, 0, 255, 8, 8) + bounds: 176 312 8 8 + - image: solid-color(23, 39, 0, 255, 8, 8) + bounds: 184 312 8 8 + - image: solid-color(24, 39, 0, 255, 8, 8) + bounds: 192 312 8 8 + - image: solid-color(25, 39, 0, 255, 8, 8) + bounds: 200 312 8 8 + - image: solid-color(26, 39, 0, 255, 8, 8) + bounds: 208 312 8 8 + - image: solid-color(27, 39, 0, 255, 8, 8) + bounds: 216 312 8 8 + - image: solid-color(28, 39, 0, 255, 8, 8) + bounds: 224 312 8 8 + - image: solid-color(29, 39, 0, 255, 8, 8) + bounds: 232 312 8 8 + - image: solid-color(30, 39, 0, 255, 8, 8) + bounds: 240 312 8 8 + - image: solid-color(31, 39, 0, 255, 8, 8) + bounds: 248 312 8 8 + - image: solid-color(32, 39, 0, 255, 8, 8) + bounds: 256 312 8 8 + - image: solid-color(33, 39, 0, 255, 8, 8) + bounds: 264 312 8 8 + - image: solid-color(34, 39, 0, 255, 8, 8) + bounds: 272 312 8 8 + - image: solid-color(35, 39, 0, 255, 8, 8) + bounds: 280 312 8 8 + - image: solid-color(36, 39, 0, 255, 8, 8) + bounds: 288 312 8 8 + - image: solid-color(37, 39, 0, 255, 8, 8) + bounds: 296 312 8 8 + - image: solid-color(38, 39, 0, 255, 8, 8) + bounds: 304 312 8 8 + - image: solid-color(39, 39, 0, 255, 8, 8) + bounds: 312 312 8 8 + - image: solid-color(40, 39, 0, 255, 8, 8) + bounds: 320 312 8 8 + - image: solid-color(41, 39, 0, 255, 8, 8) + bounds: 328 312 8 8 + - image: solid-color(42, 39, 0, 255, 8, 8) + bounds: 336 312 8 8 + - image: solid-color(43, 39, 0, 255, 8, 8) + bounds: 344 312 8 8 + - image: solid-color(44, 39, 0, 255, 8, 8) + bounds: 352 312 8 8 + - image: solid-color(45, 39, 0, 255, 8, 8) + bounds: 360 312 8 8 + - image: solid-color(46, 39, 0, 255, 8, 8) + bounds: 368 312 8 8 + - image: solid-color(47, 39, 0, 255, 8, 8) + bounds: 376 312 8 8 + - image: solid-color(48, 39, 0, 255, 8, 8) + bounds: 384 312 8 8 + - image: solid-color(49, 39, 0, 255, 8, 8) + bounds: 392 312 8 8 + - image: solid-color(50, 39, 0, 255, 8, 8) + bounds: 400 312 8 8 + - image: solid-color(51, 39, 0, 255, 8, 8) + bounds: 408 312 8 8 + - image: solid-color(52, 39, 0, 255, 8, 8) + bounds: 416 312 8 8 + - image: solid-color(53, 39, 0, 255, 8, 8) + bounds: 424 312 8 8 + - image: solid-color(54, 39, 0, 255, 8, 8) + bounds: 432 312 8 8 + - image: solid-color(55, 39, 0, 255, 8, 8) + bounds: 440 312 8 8 + - image: solid-color(56, 39, 0, 255, 8, 8) + bounds: 448 312 8 8 + - image: solid-color(57, 39, 0, 255, 8, 8) + bounds: 456 312 8 8 + - image: solid-color(58, 39, 0, 255, 8, 8) + bounds: 464 312 8 8 + - image: solid-color(59, 39, 0, 255, 8, 8) + bounds: 472 312 8 8 + - image: solid-color(60, 39, 0, 255, 8, 8) + bounds: 480 312 8 8 + - image: solid-color(61, 39, 0, 255, 8, 8) + bounds: 488 312 8 8 + - image: solid-color(62, 39, 0, 255, 8, 8) + bounds: 496 312 8 8 + - image: solid-color(63, 39, 0, 255, 8, 8) + bounds: 504 312 8 8 + - image: solid-color(64, 39, 0, 255, 8, 8) + bounds: 512 312 8 8 + - image: solid-color(65, 39, 0, 255, 8, 8) + bounds: 520 312 8 8 + - image: solid-color(66, 39, 0, 255, 8, 8) + bounds: 528 312 8 8 + - image: solid-color(67, 39, 0, 255, 8, 8) + bounds: 536 312 8 8 + - image: solid-color(68, 39, 0, 255, 8, 8) + bounds: 544 312 8 8 + - image: solid-color(69, 39, 0, 255, 8, 8) + bounds: 552 312 8 8 + - image: solid-color(70, 39, 0, 255, 8, 8) + bounds: 560 312 8 8 + - image: solid-color(71, 39, 0, 255, 8, 8) + bounds: 568 312 8 8 + - image: solid-color(72, 39, 0, 255, 8, 8) + bounds: 576 312 8 8 + - image: solid-color(73, 39, 0, 255, 8, 8) + bounds: 584 312 8 8 + - image: solid-color(74, 39, 0, 255, 8, 8) + bounds: 592 312 8 8 + - image: solid-color(75, 39, 0, 255, 8, 8) + bounds: 600 312 8 8 + - image: solid-color(76, 39, 0, 255, 8, 8) + bounds: 608 312 8 8 + - image: solid-color(77, 39, 0, 255, 8, 8) + bounds: 616 312 8 8 + - image: solid-color(78, 39, 0, 255, 8, 8) + bounds: 624 312 8 8 + - image: solid-color(79, 39, 0, 255, 8, 8) + bounds: 632 312 8 8 + - image: solid-color(80, 39, 0, 255, 8, 8) + bounds: 640 312 8 8 + - image: solid-color(81, 39, 0, 255, 8, 8) + bounds: 648 312 8 8 + - image: solid-color(82, 39, 0, 255, 8, 8) + bounds: 656 312 8 8 + - image: solid-color(83, 39, 0, 255, 8, 8) + bounds: 664 312 8 8 + - image: solid-color(84, 39, 0, 255, 8, 8) + bounds: 672 312 8 8 + - image: solid-color(85, 39, 0, 255, 8, 8) + bounds: 680 312 8 8 + - image: solid-color(86, 39, 0, 255, 8, 8) + bounds: 688 312 8 8 + - image: solid-color(87, 39, 0, 255, 8, 8) + bounds: 696 312 8 8 + - image: solid-color(88, 39, 0, 255, 8, 8) + bounds: 704 312 8 8 + - image: solid-color(89, 39, 0, 255, 8, 8) + bounds: 712 312 8 8 + - image: solid-color(90, 39, 0, 255, 8, 8) + bounds: 720 312 8 8 + - image: solid-color(91, 39, 0, 255, 8, 8) + bounds: 728 312 8 8 + - image: solid-color(92, 39, 0, 255, 8, 8) + bounds: 736 312 8 8 + - image: solid-color(93, 39, 0, 255, 8, 8) + bounds: 744 312 8 8 + - image: solid-color(94, 39, 0, 255, 8, 8) + bounds: 752 312 8 8 + - image: solid-color(95, 39, 0, 255, 8, 8) + bounds: 760 312 8 8 + - image: solid-color(96, 39, 0, 255, 8, 8) + bounds: 768 312 8 8 + - image: solid-color(97, 39, 0, 255, 8, 8) + bounds: 776 312 8 8 + - image: solid-color(98, 39, 0, 255, 8, 8) + bounds: 784 312 8 8 + - image: solid-color(99, 39, 0, 255, 8, 8) + bounds: 792 312 8 8 + - image: solid-color(100, 39, 0, 255, 8, 8) + bounds: 800 312 8 8 + - image: solid-color(101, 39, 0, 255, 8, 8) + bounds: 808 312 8 8 + - image: solid-color(102, 39, 0, 255, 8, 8) + bounds: 816 312 8 8 + - image: solid-color(103, 39, 0, 255, 8, 8) + bounds: 824 312 8 8 + - image: solid-color(104, 39, 0, 255, 8, 8) + bounds: 832 312 8 8 + - image: solid-color(105, 39, 0, 255, 8, 8) + bounds: 840 312 8 8 + - image: solid-color(106, 39, 0, 255, 8, 8) + bounds: 848 312 8 8 + - image: solid-color(107, 39, 0, 255, 8, 8) + bounds: 856 312 8 8 + - image: solid-color(108, 39, 0, 255, 8, 8) + bounds: 864 312 8 8 + - image: solid-color(109, 39, 0, 255, 8, 8) + bounds: 872 312 8 8 + - image: solid-color(110, 39, 0, 255, 8, 8) + bounds: 880 312 8 8 + - image: solid-color(111, 39, 0, 255, 8, 8) + bounds: 888 312 8 8 + - image: solid-color(112, 39, 0, 255, 8, 8) + bounds: 896 312 8 8 + - image: solid-color(113, 39, 0, 255, 8, 8) + bounds: 904 312 8 8 + - image: solid-color(114, 39, 0, 255, 8, 8) + bounds: 912 312 8 8 + - image: solid-color(115, 39, 0, 255, 8, 8) + bounds: 920 312 8 8 + - image: solid-color(116, 39, 0, 255, 8, 8) + bounds: 928 312 8 8 + - image: solid-color(117, 39, 0, 255, 8, 8) + bounds: 936 312 8 8 + - image: solid-color(118, 39, 0, 255, 8, 8) + bounds: 944 312 8 8 + - image: solid-color(119, 39, 0, 255, 8, 8) + bounds: 952 312 8 8 + - image: solid-color(120, 39, 0, 255, 8, 8) + bounds: 960 312 8 8 + - image: solid-color(121, 39, 0, 255, 8, 8) + bounds: 968 312 8 8 + - image: solid-color(122, 39, 0, 255, 8, 8) + bounds: 976 312 8 8 + - image: solid-color(123, 39, 0, 255, 8, 8) + bounds: 984 312 8 8 + - image: solid-color(124, 39, 0, 255, 8, 8) + bounds: 992 312 8 8 + - image: solid-color(125, 39, 0, 255, 8, 8) + bounds: 1000 312 8 8 + - image: solid-color(126, 39, 0, 255, 8, 8) + bounds: 1008 312 8 8 + - image: solid-color(127, 39, 0, 255, 8, 8) + bounds: 1016 312 8 8 + - image: solid-color(0, 40, 0, 255, 8, 8) + bounds: 0 320 8 8 + - image: solid-color(1, 40, 0, 255, 8, 8) + bounds: 8 320 8 8 + - image: solid-color(2, 40, 0, 255, 8, 8) + bounds: 16 320 8 8 + - image: solid-color(3, 40, 0, 255, 8, 8) + bounds: 24 320 8 8 + - image: solid-color(4, 40, 0, 255, 8, 8) + bounds: 32 320 8 8 + - image: solid-color(5, 40, 0, 255, 8, 8) + bounds: 40 320 8 8 + - image: solid-color(6, 40, 0, 255, 8, 8) + bounds: 48 320 8 8 + - image: solid-color(7, 40, 0, 255, 8, 8) + bounds: 56 320 8 8 + - image: solid-color(8, 40, 0, 255, 8, 8) + bounds: 64 320 8 8 + - image: solid-color(9, 40, 0, 255, 8, 8) + bounds: 72 320 8 8 + - image: solid-color(10, 40, 0, 255, 8, 8) + bounds: 80 320 8 8 + - image: solid-color(11, 40, 0, 255, 8, 8) + bounds: 88 320 8 8 + - image: solid-color(12, 40, 0, 255, 8, 8) + bounds: 96 320 8 8 + - image: solid-color(13, 40, 0, 255, 8, 8) + bounds: 104 320 8 8 + - image: solid-color(14, 40, 0, 255, 8, 8) + bounds: 112 320 8 8 + - image: solid-color(15, 40, 0, 255, 8, 8) + bounds: 120 320 8 8 + - image: solid-color(16, 40, 0, 255, 8, 8) + bounds: 128 320 8 8 + - image: solid-color(17, 40, 0, 255, 8, 8) + bounds: 136 320 8 8 + - image: solid-color(18, 40, 0, 255, 8, 8) + bounds: 144 320 8 8 + - image: solid-color(19, 40, 0, 255, 8, 8) + bounds: 152 320 8 8 + - image: solid-color(20, 40, 0, 255, 8, 8) + bounds: 160 320 8 8 + - image: solid-color(21, 40, 0, 255, 8, 8) + bounds: 168 320 8 8 + - image: solid-color(22, 40, 0, 255, 8, 8) + bounds: 176 320 8 8 + - image: solid-color(23, 40, 0, 255, 8, 8) + bounds: 184 320 8 8 + - image: solid-color(24, 40, 0, 255, 8, 8) + bounds: 192 320 8 8 + - image: solid-color(25, 40, 0, 255, 8, 8) + bounds: 200 320 8 8 + - image: solid-color(26, 40, 0, 255, 8, 8) + bounds: 208 320 8 8 + - image: solid-color(27, 40, 0, 255, 8, 8) + bounds: 216 320 8 8 + - image: solid-color(28, 40, 0, 255, 8, 8) + bounds: 224 320 8 8 + - image: solid-color(29, 40, 0, 255, 8, 8) + bounds: 232 320 8 8 + - image: solid-color(30, 40, 0, 255, 8, 8) + bounds: 240 320 8 8 + - image: solid-color(31, 40, 0, 255, 8, 8) + bounds: 248 320 8 8 + - image: solid-color(32, 40, 0, 255, 8, 8) + bounds: 256 320 8 8 + - image: solid-color(33, 40, 0, 255, 8, 8) + bounds: 264 320 8 8 + - image: solid-color(34, 40, 0, 255, 8, 8) + bounds: 272 320 8 8 + - image: solid-color(35, 40, 0, 255, 8, 8) + bounds: 280 320 8 8 + - image: solid-color(36, 40, 0, 255, 8, 8) + bounds: 288 320 8 8 + - image: solid-color(37, 40, 0, 255, 8, 8) + bounds: 296 320 8 8 + - image: solid-color(38, 40, 0, 255, 8, 8) + bounds: 304 320 8 8 + - image: solid-color(39, 40, 0, 255, 8, 8) + bounds: 312 320 8 8 + - image: solid-color(40, 40, 0, 255, 8, 8) + bounds: 320 320 8 8 + - image: solid-color(41, 40, 0, 255, 8, 8) + bounds: 328 320 8 8 + - image: solid-color(42, 40, 0, 255, 8, 8) + bounds: 336 320 8 8 + - image: solid-color(43, 40, 0, 255, 8, 8) + bounds: 344 320 8 8 + - image: solid-color(44, 40, 0, 255, 8, 8) + bounds: 352 320 8 8 + - image: solid-color(45, 40, 0, 255, 8, 8) + bounds: 360 320 8 8 + - image: solid-color(46, 40, 0, 255, 8, 8) + bounds: 368 320 8 8 + - image: solid-color(47, 40, 0, 255, 8, 8) + bounds: 376 320 8 8 + - image: solid-color(48, 40, 0, 255, 8, 8) + bounds: 384 320 8 8 + - image: solid-color(49, 40, 0, 255, 8, 8) + bounds: 392 320 8 8 + - image: solid-color(50, 40, 0, 255, 8, 8) + bounds: 400 320 8 8 + - image: solid-color(51, 40, 0, 255, 8, 8) + bounds: 408 320 8 8 + - image: solid-color(52, 40, 0, 255, 8, 8) + bounds: 416 320 8 8 + - image: solid-color(53, 40, 0, 255, 8, 8) + bounds: 424 320 8 8 + - image: solid-color(54, 40, 0, 255, 8, 8) + bounds: 432 320 8 8 + - image: solid-color(55, 40, 0, 255, 8, 8) + bounds: 440 320 8 8 + - image: solid-color(56, 40, 0, 255, 8, 8) + bounds: 448 320 8 8 + - image: solid-color(57, 40, 0, 255, 8, 8) + bounds: 456 320 8 8 + - image: solid-color(58, 40, 0, 255, 8, 8) + bounds: 464 320 8 8 + - image: solid-color(59, 40, 0, 255, 8, 8) + bounds: 472 320 8 8 + - image: solid-color(60, 40, 0, 255, 8, 8) + bounds: 480 320 8 8 + - image: solid-color(61, 40, 0, 255, 8, 8) + bounds: 488 320 8 8 + - image: solid-color(62, 40, 0, 255, 8, 8) + bounds: 496 320 8 8 + - image: solid-color(63, 40, 0, 255, 8, 8) + bounds: 504 320 8 8 + - image: solid-color(64, 40, 0, 255, 8, 8) + bounds: 512 320 8 8 + - image: solid-color(65, 40, 0, 255, 8, 8) + bounds: 520 320 8 8 + - image: solid-color(66, 40, 0, 255, 8, 8) + bounds: 528 320 8 8 + - image: solid-color(67, 40, 0, 255, 8, 8) + bounds: 536 320 8 8 + - image: solid-color(68, 40, 0, 255, 8, 8) + bounds: 544 320 8 8 + - image: solid-color(69, 40, 0, 255, 8, 8) + bounds: 552 320 8 8 + - image: solid-color(70, 40, 0, 255, 8, 8) + bounds: 560 320 8 8 + - image: solid-color(71, 40, 0, 255, 8, 8) + bounds: 568 320 8 8 + - image: solid-color(72, 40, 0, 255, 8, 8) + bounds: 576 320 8 8 + - image: solid-color(73, 40, 0, 255, 8, 8) + bounds: 584 320 8 8 + - image: solid-color(74, 40, 0, 255, 8, 8) + bounds: 592 320 8 8 + - image: solid-color(75, 40, 0, 255, 8, 8) + bounds: 600 320 8 8 + - image: solid-color(76, 40, 0, 255, 8, 8) + bounds: 608 320 8 8 + - image: solid-color(77, 40, 0, 255, 8, 8) + bounds: 616 320 8 8 + - image: solid-color(78, 40, 0, 255, 8, 8) + bounds: 624 320 8 8 + - image: solid-color(79, 40, 0, 255, 8, 8) + bounds: 632 320 8 8 + - image: solid-color(80, 40, 0, 255, 8, 8) + bounds: 640 320 8 8 + - image: solid-color(81, 40, 0, 255, 8, 8) + bounds: 648 320 8 8 + - image: solid-color(82, 40, 0, 255, 8, 8) + bounds: 656 320 8 8 + - image: solid-color(83, 40, 0, 255, 8, 8) + bounds: 664 320 8 8 + - image: solid-color(84, 40, 0, 255, 8, 8) + bounds: 672 320 8 8 + - image: solid-color(85, 40, 0, 255, 8, 8) + bounds: 680 320 8 8 + - image: solid-color(86, 40, 0, 255, 8, 8) + bounds: 688 320 8 8 + - image: solid-color(87, 40, 0, 255, 8, 8) + bounds: 696 320 8 8 + - image: solid-color(88, 40, 0, 255, 8, 8) + bounds: 704 320 8 8 + - image: solid-color(89, 40, 0, 255, 8, 8) + bounds: 712 320 8 8 + - image: solid-color(90, 40, 0, 255, 8, 8) + bounds: 720 320 8 8 + - image: solid-color(91, 40, 0, 255, 8, 8) + bounds: 728 320 8 8 + - image: solid-color(92, 40, 0, 255, 8, 8) + bounds: 736 320 8 8 + - image: solid-color(93, 40, 0, 255, 8, 8) + bounds: 744 320 8 8 + - image: solid-color(94, 40, 0, 255, 8, 8) + bounds: 752 320 8 8 + - image: solid-color(95, 40, 0, 255, 8, 8) + bounds: 760 320 8 8 + - image: solid-color(96, 40, 0, 255, 8, 8) + bounds: 768 320 8 8 + - image: solid-color(97, 40, 0, 255, 8, 8) + bounds: 776 320 8 8 + - image: solid-color(98, 40, 0, 255, 8, 8) + bounds: 784 320 8 8 + - image: solid-color(99, 40, 0, 255, 8, 8) + bounds: 792 320 8 8 + - image: solid-color(100, 40, 0, 255, 8, 8) + bounds: 800 320 8 8 + - image: solid-color(101, 40, 0, 255, 8, 8) + bounds: 808 320 8 8 + - image: solid-color(102, 40, 0, 255, 8, 8) + bounds: 816 320 8 8 + - image: solid-color(103, 40, 0, 255, 8, 8) + bounds: 824 320 8 8 + - image: solid-color(104, 40, 0, 255, 8, 8) + bounds: 832 320 8 8 + - image: solid-color(105, 40, 0, 255, 8, 8) + bounds: 840 320 8 8 + - image: solid-color(106, 40, 0, 255, 8, 8) + bounds: 848 320 8 8 + - image: solid-color(107, 40, 0, 255, 8, 8) + bounds: 856 320 8 8 + - image: solid-color(108, 40, 0, 255, 8, 8) + bounds: 864 320 8 8 + - image: solid-color(109, 40, 0, 255, 8, 8) + bounds: 872 320 8 8 + - image: solid-color(110, 40, 0, 255, 8, 8) + bounds: 880 320 8 8 + - image: solid-color(111, 40, 0, 255, 8, 8) + bounds: 888 320 8 8 + - image: solid-color(112, 40, 0, 255, 8, 8) + bounds: 896 320 8 8 + - image: solid-color(113, 40, 0, 255, 8, 8) + bounds: 904 320 8 8 + - image: solid-color(114, 40, 0, 255, 8, 8) + bounds: 912 320 8 8 + - image: solid-color(115, 40, 0, 255, 8, 8) + bounds: 920 320 8 8 + - image: solid-color(116, 40, 0, 255, 8, 8) + bounds: 928 320 8 8 + - image: solid-color(117, 40, 0, 255, 8, 8) + bounds: 936 320 8 8 + - image: solid-color(118, 40, 0, 255, 8, 8) + bounds: 944 320 8 8 + - image: solid-color(119, 40, 0, 255, 8, 8) + bounds: 952 320 8 8 + - image: solid-color(120, 40, 0, 255, 8, 8) + bounds: 960 320 8 8 + - image: solid-color(121, 40, 0, 255, 8, 8) + bounds: 968 320 8 8 + - image: solid-color(122, 40, 0, 255, 8, 8) + bounds: 976 320 8 8 + - image: solid-color(123, 40, 0, 255, 8, 8) + bounds: 984 320 8 8 + - image: solid-color(124, 40, 0, 255, 8, 8) + bounds: 992 320 8 8 + - image: solid-color(125, 40, 0, 255, 8, 8) + bounds: 1000 320 8 8 + - image: solid-color(126, 40, 0, 255, 8, 8) + bounds: 1008 320 8 8 + - image: solid-color(127, 40, 0, 255, 8, 8) + bounds: 1016 320 8 8 + - image: solid-color(0, 41, 0, 255, 8, 8) + bounds: 0 328 8 8 + - image: solid-color(1, 41, 0, 255, 8, 8) + bounds: 8 328 8 8 + - image: solid-color(2, 41, 0, 255, 8, 8) + bounds: 16 328 8 8 + - image: solid-color(3, 41, 0, 255, 8, 8) + bounds: 24 328 8 8 + - image: solid-color(4, 41, 0, 255, 8, 8) + bounds: 32 328 8 8 + - image: solid-color(5, 41, 0, 255, 8, 8) + bounds: 40 328 8 8 + - image: solid-color(6, 41, 0, 255, 8, 8) + bounds: 48 328 8 8 + - image: solid-color(7, 41, 0, 255, 8, 8) + bounds: 56 328 8 8 + - image: solid-color(8, 41, 0, 255, 8, 8) + bounds: 64 328 8 8 + - image: solid-color(9, 41, 0, 255, 8, 8) + bounds: 72 328 8 8 + - image: solid-color(10, 41, 0, 255, 8, 8) + bounds: 80 328 8 8 + - image: solid-color(11, 41, 0, 255, 8, 8) + bounds: 88 328 8 8 + - image: solid-color(12, 41, 0, 255, 8, 8) + bounds: 96 328 8 8 + - image: solid-color(13, 41, 0, 255, 8, 8) + bounds: 104 328 8 8 + - image: solid-color(14, 41, 0, 255, 8, 8) + bounds: 112 328 8 8 + - image: solid-color(15, 41, 0, 255, 8, 8) + bounds: 120 328 8 8 + - image: solid-color(16, 41, 0, 255, 8, 8) + bounds: 128 328 8 8 + - image: solid-color(17, 41, 0, 255, 8, 8) + bounds: 136 328 8 8 + - image: solid-color(18, 41, 0, 255, 8, 8) + bounds: 144 328 8 8 + - image: solid-color(19, 41, 0, 255, 8, 8) + bounds: 152 328 8 8 + - image: solid-color(20, 41, 0, 255, 8, 8) + bounds: 160 328 8 8 + - image: solid-color(21, 41, 0, 255, 8, 8) + bounds: 168 328 8 8 + - image: solid-color(22, 41, 0, 255, 8, 8) + bounds: 176 328 8 8 + - image: solid-color(23, 41, 0, 255, 8, 8) + bounds: 184 328 8 8 + - image: solid-color(24, 41, 0, 255, 8, 8) + bounds: 192 328 8 8 + - image: solid-color(25, 41, 0, 255, 8, 8) + bounds: 200 328 8 8 + - image: solid-color(26, 41, 0, 255, 8, 8) + bounds: 208 328 8 8 + - image: solid-color(27, 41, 0, 255, 8, 8) + bounds: 216 328 8 8 + - image: solid-color(28, 41, 0, 255, 8, 8) + bounds: 224 328 8 8 + - image: solid-color(29, 41, 0, 255, 8, 8) + bounds: 232 328 8 8 + - image: solid-color(30, 41, 0, 255, 8, 8) + bounds: 240 328 8 8 + - image: solid-color(31, 41, 0, 255, 8, 8) + bounds: 248 328 8 8 + - image: solid-color(32, 41, 0, 255, 8, 8) + bounds: 256 328 8 8 + - image: solid-color(33, 41, 0, 255, 8, 8) + bounds: 264 328 8 8 + - image: solid-color(34, 41, 0, 255, 8, 8) + bounds: 272 328 8 8 + - image: solid-color(35, 41, 0, 255, 8, 8) + bounds: 280 328 8 8 + - image: solid-color(36, 41, 0, 255, 8, 8) + bounds: 288 328 8 8 + - image: solid-color(37, 41, 0, 255, 8, 8) + bounds: 296 328 8 8 + - image: solid-color(38, 41, 0, 255, 8, 8) + bounds: 304 328 8 8 + - image: solid-color(39, 41, 0, 255, 8, 8) + bounds: 312 328 8 8 + - image: solid-color(40, 41, 0, 255, 8, 8) + bounds: 320 328 8 8 + - image: solid-color(41, 41, 0, 255, 8, 8) + bounds: 328 328 8 8 + - image: solid-color(42, 41, 0, 255, 8, 8) + bounds: 336 328 8 8 + - image: solid-color(43, 41, 0, 255, 8, 8) + bounds: 344 328 8 8 + - image: solid-color(44, 41, 0, 255, 8, 8) + bounds: 352 328 8 8 + - image: solid-color(45, 41, 0, 255, 8, 8) + bounds: 360 328 8 8 + - image: solid-color(46, 41, 0, 255, 8, 8) + bounds: 368 328 8 8 + - image: solid-color(47, 41, 0, 255, 8, 8) + bounds: 376 328 8 8 + - image: solid-color(48, 41, 0, 255, 8, 8) + bounds: 384 328 8 8 + - image: solid-color(49, 41, 0, 255, 8, 8) + bounds: 392 328 8 8 + - image: solid-color(50, 41, 0, 255, 8, 8) + bounds: 400 328 8 8 + - image: solid-color(51, 41, 0, 255, 8, 8) + bounds: 408 328 8 8 + - image: solid-color(52, 41, 0, 255, 8, 8) + bounds: 416 328 8 8 + - image: solid-color(53, 41, 0, 255, 8, 8) + bounds: 424 328 8 8 + - image: solid-color(54, 41, 0, 255, 8, 8) + bounds: 432 328 8 8 + - image: solid-color(55, 41, 0, 255, 8, 8) + bounds: 440 328 8 8 + - image: solid-color(56, 41, 0, 255, 8, 8) + bounds: 448 328 8 8 + - image: solid-color(57, 41, 0, 255, 8, 8) + bounds: 456 328 8 8 + - image: solid-color(58, 41, 0, 255, 8, 8) + bounds: 464 328 8 8 + - image: solid-color(59, 41, 0, 255, 8, 8) + bounds: 472 328 8 8 + - image: solid-color(60, 41, 0, 255, 8, 8) + bounds: 480 328 8 8 + - image: solid-color(61, 41, 0, 255, 8, 8) + bounds: 488 328 8 8 + - image: solid-color(62, 41, 0, 255, 8, 8) + bounds: 496 328 8 8 + - image: solid-color(63, 41, 0, 255, 8, 8) + bounds: 504 328 8 8 + - image: solid-color(64, 41, 0, 255, 8, 8) + bounds: 512 328 8 8 + - image: solid-color(65, 41, 0, 255, 8, 8) + bounds: 520 328 8 8 + - image: solid-color(66, 41, 0, 255, 8, 8) + bounds: 528 328 8 8 + - image: solid-color(67, 41, 0, 255, 8, 8) + bounds: 536 328 8 8 + - image: solid-color(68, 41, 0, 255, 8, 8) + bounds: 544 328 8 8 + - image: solid-color(69, 41, 0, 255, 8, 8) + bounds: 552 328 8 8 + - image: solid-color(70, 41, 0, 255, 8, 8) + bounds: 560 328 8 8 + - image: solid-color(71, 41, 0, 255, 8, 8) + bounds: 568 328 8 8 + - image: solid-color(72, 41, 0, 255, 8, 8) + bounds: 576 328 8 8 + - image: solid-color(73, 41, 0, 255, 8, 8) + bounds: 584 328 8 8 + - image: solid-color(74, 41, 0, 255, 8, 8) + bounds: 592 328 8 8 + - image: solid-color(75, 41, 0, 255, 8, 8) + bounds: 600 328 8 8 + - image: solid-color(76, 41, 0, 255, 8, 8) + bounds: 608 328 8 8 + - image: solid-color(77, 41, 0, 255, 8, 8) + bounds: 616 328 8 8 + - image: solid-color(78, 41, 0, 255, 8, 8) + bounds: 624 328 8 8 + - image: solid-color(79, 41, 0, 255, 8, 8) + bounds: 632 328 8 8 + - image: solid-color(80, 41, 0, 255, 8, 8) + bounds: 640 328 8 8 + - image: solid-color(81, 41, 0, 255, 8, 8) + bounds: 648 328 8 8 + - image: solid-color(82, 41, 0, 255, 8, 8) + bounds: 656 328 8 8 + - image: solid-color(83, 41, 0, 255, 8, 8) + bounds: 664 328 8 8 + - image: solid-color(84, 41, 0, 255, 8, 8) + bounds: 672 328 8 8 + - image: solid-color(85, 41, 0, 255, 8, 8) + bounds: 680 328 8 8 + - image: solid-color(86, 41, 0, 255, 8, 8) + bounds: 688 328 8 8 + - image: solid-color(87, 41, 0, 255, 8, 8) + bounds: 696 328 8 8 + - image: solid-color(88, 41, 0, 255, 8, 8) + bounds: 704 328 8 8 + - image: solid-color(89, 41, 0, 255, 8, 8) + bounds: 712 328 8 8 + - image: solid-color(90, 41, 0, 255, 8, 8) + bounds: 720 328 8 8 + - image: solid-color(91, 41, 0, 255, 8, 8) + bounds: 728 328 8 8 + - image: solid-color(92, 41, 0, 255, 8, 8) + bounds: 736 328 8 8 + - image: solid-color(93, 41, 0, 255, 8, 8) + bounds: 744 328 8 8 + - image: solid-color(94, 41, 0, 255, 8, 8) + bounds: 752 328 8 8 + - image: solid-color(95, 41, 0, 255, 8, 8) + bounds: 760 328 8 8 + - image: solid-color(96, 41, 0, 255, 8, 8) + bounds: 768 328 8 8 + - image: solid-color(97, 41, 0, 255, 8, 8) + bounds: 776 328 8 8 + - image: solid-color(98, 41, 0, 255, 8, 8) + bounds: 784 328 8 8 + - image: solid-color(99, 41, 0, 255, 8, 8) + bounds: 792 328 8 8 + - image: solid-color(100, 41, 0, 255, 8, 8) + bounds: 800 328 8 8 + - image: solid-color(101, 41, 0, 255, 8, 8) + bounds: 808 328 8 8 + - image: solid-color(102, 41, 0, 255, 8, 8) + bounds: 816 328 8 8 + - image: solid-color(103, 41, 0, 255, 8, 8) + bounds: 824 328 8 8 + - image: solid-color(104, 41, 0, 255, 8, 8) + bounds: 832 328 8 8 + - image: solid-color(105, 41, 0, 255, 8, 8) + bounds: 840 328 8 8 + - image: solid-color(106, 41, 0, 255, 8, 8) + bounds: 848 328 8 8 + - image: solid-color(107, 41, 0, 255, 8, 8) + bounds: 856 328 8 8 + - image: solid-color(108, 41, 0, 255, 8, 8) + bounds: 864 328 8 8 + - image: solid-color(109, 41, 0, 255, 8, 8) + bounds: 872 328 8 8 + - image: solid-color(110, 41, 0, 255, 8, 8) + bounds: 880 328 8 8 + - image: solid-color(111, 41, 0, 255, 8, 8) + bounds: 888 328 8 8 + - image: solid-color(112, 41, 0, 255, 8, 8) + bounds: 896 328 8 8 + - image: solid-color(113, 41, 0, 255, 8, 8) + bounds: 904 328 8 8 + - image: solid-color(114, 41, 0, 255, 8, 8) + bounds: 912 328 8 8 + - image: solid-color(115, 41, 0, 255, 8, 8) + bounds: 920 328 8 8 + - image: solid-color(116, 41, 0, 255, 8, 8) + bounds: 928 328 8 8 + - image: solid-color(117, 41, 0, 255, 8, 8) + bounds: 936 328 8 8 + - image: solid-color(118, 41, 0, 255, 8, 8) + bounds: 944 328 8 8 + - image: solid-color(119, 41, 0, 255, 8, 8) + bounds: 952 328 8 8 + - image: solid-color(120, 41, 0, 255, 8, 8) + bounds: 960 328 8 8 + - image: solid-color(121, 41, 0, 255, 8, 8) + bounds: 968 328 8 8 + - image: solid-color(122, 41, 0, 255, 8, 8) + bounds: 976 328 8 8 + - image: solid-color(123, 41, 0, 255, 8, 8) + bounds: 984 328 8 8 + - image: solid-color(124, 41, 0, 255, 8, 8) + bounds: 992 328 8 8 + - image: solid-color(125, 41, 0, 255, 8, 8) + bounds: 1000 328 8 8 + - image: solid-color(126, 41, 0, 255, 8, 8) + bounds: 1008 328 8 8 + - image: solid-color(127, 41, 0, 255, 8, 8) + bounds: 1016 328 8 8 + - image: solid-color(0, 42, 0, 255, 8, 8) + bounds: 0 336 8 8 + - image: solid-color(1, 42, 0, 255, 8, 8) + bounds: 8 336 8 8 + - image: solid-color(2, 42, 0, 255, 8, 8) + bounds: 16 336 8 8 + - image: solid-color(3, 42, 0, 255, 8, 8) + bounds: 24 336 8 8 + - image: solid-color(4, 42, 0, 255, 8, 8) + bounds: 32 336 8 8 + - image: solid-color(5, 42, 0, 255, 8, 8) + bounds: 40 336 8 8 + - image: solid-color(6, 42, 0, 255, 8, 8) + bounds: 48 336 8 8 + - image: solid-color(7, 42, 0, 255, 8, 8) + bounds: 56 336 8 8 + - image: solid-color(8, 42, 0, 255, 8, 8) + bounds: 64 336 8 8 + - image: solid-color(9, 42, 0, 255, 8, 8) + bounds: 72 336 8 8 + - image: solid-color(10, 42, 0, 255, 8, 8) + bounds: 80 336 8 8 + - image: solid-color(11, 42, 0, 255, 8, 8) + bounds: 88 336 8 8 + - image: solid-color(12, 42, 0, 255, 8, 8) + bounds: 96 336 8 8 + - image: solid-color(13, 42, 0, 255, 8, 8) + bounds: 104 336 8 8 + - image: solid-color(14, 42, 0, 255, 8, 8) + bounds: 112 336 8 8 + - image: solid-color(15, 42, 0, 255, 8, 8) + bounds: 120 336 8 8 + - image: solid-color(16, 42, 0, 255, 8, 8) + bounds: 128 336 8 8 + - image: solid-color(17, 42, 0, 255, 8, 8) + bounds: 136 336 8 8 + - image: solid-color(18, 42, 0, 255, 8, 8) + bounds: 144 336 8 8 + - image: solid-color(19, 42, 0, 255, 8, 8) + bounds: 152 336 8 8 + - image: solid-color(20, 42, 0, 255, 8, 8) + bounds: 160 336 8 8 + - image: solid-color(21, 42, 0, 255, 8, 8) + bounds: 168 336 8 8 + - image: solid-color(22, 42, 0, 255, 8, 8) + bounds: 176 336 8 8 + - image: solid-color(23, 42, 0, 255, 8, 8) + bounds: 184 336 8 8 + - image: solid-color(24, 42, 0, 255, 8, 8) + bounds: 192 336 8 8 + - image: solid-color(25, 42, 0, 255, 8, 8) + bounds: 200 336 8 8 + - image: solid-color(26, 42, 0, 255, 8, 8) + bounds: 208 336 8 8 + - image: solid-color(27, 42, 0, 255, 8, 8) + bounds: 216 336 8 8 + - image: solid-color(28, 42, 0, 255, 8, 8) + bounds: 224 336 8 8 + - image: solid-color(29, 42, 0, 255, 8, 8) + bounds: 232 336 8 8 + - image: solid-color(30, 42, 0, 255, 8, 8) + bounds: 240 336 8 8 + - image: solid-color(31, 42, 0, 255, 8, 8) + bounds: 248 336 8 8 + - image: solid-color(32, 42, 0, 255, 8, 8) + bounds: 256 336 8 8 + - image: solid-color(33, 42, 0, 255, 8, 8) + bounds: 264 336 8 8 + - image: solid-color(34, 42, 0, 255, 8, 8) + bounds: 272 336 8 8 + - image: solid-color(35, 42, 0, 255, 8, 8) + bounds: 280 336 8 8 + - image: solid-color(36, 42, 0, 255, 8, 8) + bounds: 288 336 8 8 + - image: solid-color(37, 42, 0, 255, 8, 8) + bounds: 296 336 8 8 + - image: solid-color(38, 42, 0, 255, 8, 8) + bounds: 304 336 8 8 + - image: solid-color(39, 42, 0, 255, 8, 8) + bounds: 312 336 8 8 + - image: solid-color(40, 42, 0, 255, 8, 8) + bounds: 320 336 8 8 + - image: solid-color(41, 42, 0, 255, 8, 8) + bounds: 328 336 8 8 + - image: solid-color(42, 42, 0, 255, 8, 8) + bounds: 336 336 8 8 + - image: solid-color(43, 42, 0, 255, 8, 8) + bounds: 344 336 8 8 + - image: solid-color(44, 42, 0, 255, 8, 8) + bounds: 352 336 8 8 + - image: solid-color(45, 42, 0, 255, 8, 8) + bounds: 360 336 8 8 + - image: solid-color(46, 42, 0, 255, 8, 8) + bounds: 368 336 8 8 + - image: solid-color(47, 42, 0, 255, 8, 8) + bounds: 376 336 8 8 + - image: solid-color(48, 42, 0, 255, 8, 8) + bounds: 384 336 8 8 + - image: solid-color(49, 42, 0, 255, 8, 8) + bounds: 392 336 8 8 + - image: solid-color(50, 42, 0, 255, 8, 8) + bounds: 400 336 8 8 + - image: solid-color(51, 42, 0, 255, 8, 8) + bounds: 408 336 8 8 + - image: solid-color(52, 42, 0, 255, 8, 8) + bounds: 416 336 8 8 + - image: solid-color(53, 42, 0, 255, 8, 8) + bounds: 424 336 8 8 + - image: solid-color(54, 42, 0, 255, 8, 8) + bounds: 432 336 8 8 + - image: solid-color(55, 42, 0, 255, 8, 8) + bounds: 440 336 8 8 + - image: solid-color(56, 42, 0, 255, 8, 8) + bounds: 448 336 8 8 + - image: solid-color(57, 42, 0, 255, 8, 8) + bounds: 456 336 8 8 + - image: solid-color(58, 42, 0, 255, 8, 8) + bounds: 464 336 8 8 + - image: solid-color(59, 42, 0, 255, 8, 8) + bounds: 472 336 8 8 + - image: solid-color(60, 42, 0, 255, 8, 8) + bounds: 480 336 8 8 + - image: solid-color(61, 42, 0, 255, 8, 8) + bounds: 488 336 8 8 + - image: solid-color(62, 42, 0, 255, 8, 8) + bounds: 496 336 8 8 + - image: solid-color(63, 42, 0, 255, 8, 8) + bounds: 504 336 8 8 + - image: solid-color(64, 42, 0, 255, 8, 8) + bounds: 512 336 8 8 + - image: solid-color(65, 42, 0, 255, 8, 8) + bounds: 520 336 8 8 + - image: solid-color(66, 42, 0, 255, 8, 8) + bounds: 528 336 8 8 + - image: solid-color(67, 42, 0, 255, 8, 8) + bounds: 536 336 8 8 + - image: solid-color(68, 42, 0, 255, 8, 8) + bounds: 544 336 8 8 + - image: solid-color(69, 42, 0, 255, 8, 8) + bounds: 552 336 8 8 + - image: solid-color(70, 42, 0, 255, 8, 8) + bounds: 560 336 8 8 + - image: solid-color(71, 42, 0, 255, 8, 8) + bounds: 568 336 8 8 + - image: solid-color(72, 42, 0, 255, 8, 8) + bounds: 576 336 8 8 + - image: solid-color(73, 42, 0, 255, 8, 8) + bounds: 584 336 8 8 + - image: solid-color(74, 42, 0, 255, 8, 8) + bounds: 592 336 8 8 + - image: solid-color(75, 42, 0, 255, 8, 8) + bounds: 600 336 8 8 + - image: solid-color(76, 42, 0, 255, 8, 8) + bounds: 608 336 8 8 + - image: solid-color(77, 42, 0, 255, 8, 8) + bounds: 616 336 8 8 + - image: solid-color(78, 42, 0, 255, 8, 8) + bounds: 624 336 8 8 + - image: solid-color(79, 42, 0, 255, 8, 8) + bounds: 632 336 8 8 + - image: solid-color(80, 42, 0, 255, 8, 8) + bounds: 640 336 8 8 + - image: solid-color(81, 42, 0, 255, 8, 8) + bounds: 648 336 8 8 + - image: solid-color(82, 42, 0, 255, 8, 8) + bounds: 656 336 8 8 + - image: solid-color(83, 42, 0, 255, 8, 8) + bounds: 664 336 8 8 + - image: solid-color(84, 42, 0, 255, 8, 8) + bounds: 672 336 8 8 + - image: solid-color(85, 42, 0, 255, 8, 8) + bounds: 680 336 8 8 + - image: solid-color(86, 42, 0, 255, 8, 8) + bounds: 688 336 8 8 + - image: solid-color(87, 42, 0, 255, 8, 8) + bounds: 696 336 8 8 + - image: solid-color(88, 42, 0, 255, 8, 8) + bounds: 704 336 8 8 + - image: solid-color(89, 42, 0, 255, 8, 8) + bounds: 712 336 8 8 + - image: solid-color(90, 42, 0, 255, 8, 8) + bounds: 720 336 8 8 + - image: solid-color(91, 42, 0, 255, 8, 8) + bounds: 728 336 8 8 + - image: solid-color(92, 42, 0, 255, 8, 8) + bounds: 736 336 8 8 + - image: solid-color(93, 42, 0, 255, 8, 8) + bounds: 744 336 8 8 + - image: solid-color(94, 42, 0, 255, 8, 8) + bounds: 752 336 8 8 + - image: solid-color(95, 42, 0, 255, 8, 8) + bounds: 760 336 8 8 + - image: solid-color(96, 42, 0, 255, 8, 8) + bounds: 768 336 8 8 + - image: solid-color(97, 42, 0, 255, 8, 8) + bounds: 776 336 8 8 + - image: solid-color(98, 42, 0, 255, 8, 8) + bounds: 784 336 8 8 + - image: solid-color(99, 42, 0, 255, 8, 8) + bounds: 792 336 8 8 + - image: solid-color(100, 42, 0, 255, 8, 8) + bounds: 800 336 8 8 + - image: solid-color(101, 42, 0, 255, 8, 8) + bounds: 808 336 8 8 + - image: solid-color(102, 42, 0, 255, 8, 8) + bounds: 816 336 8 8 + - image: solid-color(103, 42, 0, 255, 8, 8) + bounds: 824 336 8 8 + - image: solid-color(104, 42, 0, 255, 8, 8) + bounds: 832 336 8 8 + - image: solid-color(105, 42, 0, 255, 8, 8) + bounds: 840 336 8 8 + - image: solid-color(106, 42, 0, 255, 8, 8) + bounds: 848 336 8 8 + - image: solid-color(107, 42, 0, 255, 8, 8) + bounds: 856 336 8 8 + - image: solid-color(108, 42, 0, 255, 8, 8) + bounds: 864 336 8 8 + - image: solid-color(109, 42, 0, 255, 8, 8) + bounds: 872 336 8 8 + - image: solid-color(110, 42, 0, 255, 8, 8) + bounds: 880 336 8 8 + - image: solid-color(111, 42, 0, 255, 8, 8) + bounds: 888 336 8 8 + - image: solid-color(112, 42, 0, 255, 8, 8) + bounds: 896 336 8 8 + - image: solid-color(113, 42, 0, 255, 8, 8) + bounds: 904 336 8 8 + - image: solid-color(114, 42, 0, 255, 8, 8) + bounds: 912 336 8 8 + - image: solid-color(115, 42, 0, 255, 8, 8) + bounds: 920 336 8 8 + - image: solid-color(116, 42, 0, 255, 8, 8) + bounds: 928 336 8 8 + - image: solid-color(117, 42, 0, 255, 8, 8) + bounds: 936 336 8 8 + - image: solid-color(118, 42, 0, 255, 8, 8) + bounds: 944 336 8 8 + - image: solid-color(119, 42, 0, 255, 8, 8) + bounds: 952 336 8 8 + - image: solid-color(120, 42, 0, 255, 8, 8) + bounds: 960 336 8 8 + - image: solid-color(121, 42, 0, 255, 8, 8) + bounds: 968 336 8 8 + - image: solid-color(122, 42, 0, 255, 8, 8) + bounds: 976 336 8 8 + - image: solid-color(123, 42, 0, 255, 8, 8) + bounds: 984 336 8 8 + - image: solid-color(124, 42, 0, 255, 8, 8) + bounds: 992 336 8 8 + - image: solid-color(125, 42, 0, 255, 8, 8) + bounds: 1000 336 8 8 + - image: solid-color(126, 42, 0, 255, 8, 8) + bounds: 1008 336 8 8 + - image: solid-color(127, 42, 0, 255, 8, 8) + bounds: 1016 336 8 8 + - image: solid-color(0, 43, 0, 255, 8, 8) + bounds: 0 344 8 8 + - image: solid-color(1, 43, 0, 255, 8, 8) + bounds: 8 344 8 8 + - image: solid-color(2, 43, 0, 255, 8, 8) + bounds: 16 344 8 8 + - image: solid-color(3, 43, 0, 255, 8, 8) + bounds: 24 344 8 8 + - image: solid-color(4, 43, 0, 255, 8, 8) + bounds: 32 344 8 8 + - image: solid-color(5, 43, 0, 255, 8, 8) + bounds: 40 344 8 8 + - image: solid-color(6, 43, 0, 255, 8, 8) + bounds: 48 344 8 8 + - image: solid-color(7, 43, 0, 255, 8, 8) + bounds: 56 344 8 8 + - image: solid-color(8, 43, 0, 255, 8, 8) + bounds: 64 344 8 8 + - image: solid-color(9, 43, 0, 255, 8, 8) + bounds: 72 344 8 8 + - image: solid-color(10, 43, 0, 255, 8, 8) + bounds: 80 344 8 8 + - image: solid-color(11, 43, 0, 255, 8, 8) + bounds: 88 344 8 8 + - image: solid-color(12, 43, 0, 255, 8, 8) + bounds: 96 344 8 8 + - image: solid-color(13, 43, 0, 255, 8, 8) + bounds: 104 344 8 8 + - image: solid-color(14, 43, 0, 255, 8, 8) + bounds: 112 344 8 8 + - image: solid-color(15, 43, 0, 255, 8, 8) + bounds: 120 344 8 8 + - image: solid-color(16, 43, 0, 255, 8, 8) + bounds: 128 344 8 8 + - image: solid-color(17, 43, 0, 255, 8, 8) + bounds: 136 344 8 8 + - image: solid-color(18, 43, 0, 255, 8, 8) + bounds: 144 344 8 8 + - image: solid-color(19, 43, 0, 255, 8, 8) + bounds: 152 344 8 8 + - image: solid-color(20, 43, 0, 255, 8, 8) + bounds: 160 344 8 8 + - image: solid-color(21, 43, 0, 255, 8, 8) + bounds: 168 344 8 8 + - image: solid-color(22, 43, 0, 255, 8, 8) + bounds: 176 344 8 8 + - image: solid-color(23, 43, 0, 255, 8, 8) + bounds: 184 344 8 8 + - image: solid-color(24, 43, 0, 255, 8, 8) + bounds: 192 344 8 8 + - image: solid-color(25, 43, 0, 255, 8, 8) + bounds: 200 344 8 8 + - image: solid-color(26, 43, 0, 255, 8, 8) + bounds: 208 344 8 8 + - image: solid-color(27, 43, 0, 255, 8, 8) + bounds: 216 344 8 8 + - image: solid-color(28, 43, 0, 255, 8, 8) + bounds: 224 344 8 8 + - image: solid-color(29, 43, 0, 255, 8, 8) + bounds: 232 344 8 8 + - image: solid-color(30, 43, 0, 255, 8, 8) + bounds: 240 344 8 8 + - image: solid-color(31, 43, 0, 255, 8, 8) + bounds: 248 344 8 8 + - image: solid-color(32, 43, 0, 255, 8, 8) + bounds: 256 344 8 8 + - image: solid-color(33, 43, 0, 255, 8, 8) + bounds: 264 344 8 8 + - image: solid-color(34, 43, 0, 255, 8, 8) + bounds: 272 344 8 8 + - image: solid-color(35, 43, 0, 255, 8, 8) + bounds: 280 344 8 8 + - image: solid-color(36, 43, 0, 255, 8, 8) + bounds: 288 344 8 8 + - image: solid-color(37, 43, 0, 255, 8, 8) + bounds: 296 344 8 8 + - image: solid-color(38, 43, 0, 255, 8, 8) + bounds: 304 344 8 8 + - image: solid-color(39, 43, 0, 255, 8, 8) + bounds: 312 344 8 8 + - image: solid-color(40, 43, 0, 255, 8, 8) + bounds: 320 344 8 8 + - image: solid-color(41, 43, 0, 255, 8, 8) + bounds: 328 344 8 8 + - image: solid-color(42, 43, 0, 255, 8, 8) + bounds: 336 344 8 8 + - image: solid-color(43, 43, 0, 255, 8, 8) + bounds: 344 344 8 8 + - image: solid-color(44, 43, 0, 255, 8, 8) + bounds: 352 344 8 8 + - image: solid-color(45, 43, 0, 255, 8, 8) + bounds: 360 344 8 8 + - image: solid-color(46, 43, 0, 255, 8, 8) + bounds: 368 344 8 8 + - image: solid-color(47, 43, 0, 255, 8, 8) + bounds: 376 344 8 8 + - image: solid-color(48, 43, 0, 255, 8, 8) + bounds: 384 344 8 8 + - image: solid-color(49, 43, 0, 255, 8, 8) + bounds: 392 344 8 8 + - image: solid-color(50, 43, 0, 255, 8, 8) + bounds: 400 344 8 8 + - image: solid-color(51, 43, 0, 255, 8, 8) + bounds: 408 344 8 8 + - image: solid-color(52, 43, 0, 255, 8, 8) + bounds: 416 344 8 8 + - image: solid-color(53, 43, 0, 255, 8, 8) + bounds: 424 344 8 8 + - image: solid-color(54, 43, 0, 255, 8, 8) + bounds: 432 344 8 8 + - image: solid-color(55, 43, 0, 255, 8, 8) + bounds: 440 344 8 8 + - image: solid-color(56, 43, 0, 255, 8, 8) + bounds: 448 344 8 8 + - image: solid-color(57, 43, 0, 255, 8, 8) + bounds: 456 344 8 8 + - image: solid-color(58, 43, 0, 255, 8, 8) + bounds: 464 344 8 8 + - image: solid-color(59, 43, 0, 255, 8, 8) + bounds: 472 344 8 8 + - image: solid-color(60, 43, 0, 255, 8, 8) + bounds: 480 344 8 8 + - image: solid-color(61, 43, 0, 255, 8, 8) + bounds: 488 344 8 8 + - image: solid-color(62, 43, 0, 255, 8, 8) + bounds: 496 344 8 8 + - image: solid-color(63, 43, 0, 255, 8, 8) + bounds: 504 344 8 8 + - image: solid-color(64, 43, 0, 255, 8, 8) + bounds: 512 344 8 8 + - image: solid-color(65, 43, 0, 255, 8, 8) + bounds: 520 344 8 8 + - image: solid-color(66, 43, 0, 255, 8, 8) + bounds: 528 344 8 8 + - image: solid-color(67, 43, 0, 255, 8, 8) + bounds: 536 344 8 8 + - image: solid-color(68, 43, 0, 255, 8, 8) + bounds: 544 344 8 8 + - image: solid-color(69, 43, 0, 255, 8, 8) + bounds: 552 344 8 8 + - image: solid-color(70, 43, 0, 255, 8, 8) + bounds: 560 344 8 8 + - image: solid-color(71, 43, 0, 255, 8, 8) + bounds: 568 344 8 8 + - image: solid-color(72, 43, 0, 255, 8, 8) + bounds: 576 344 8 8 + - image: solid-color(73, 43, 0, 255, 8, 8) + bounds: 584 344 8 8 + - image: solid-color(74, 43, 0, 255, 8, 8) + bounds: 592 344 8 8 + - image: solid-color(75, 43, 0, 255, 8, 8) + bounds: 600 344 8 8 + - image: solid-color(76, 43, 0, 255, 8, 8) + bounds: 608 344 8 8 + - image: solid-color(77, 43, 0, 255, 8, 8) + bounds: 616 344 8 8 + - image: solid-color(78, 43, 0, 255, 8, 8) + bounds: 624 344 8 8 + - image: solid-color(79, 43, 0, 255, 8, 8) + bounds: 632 344 8 8 + - image: solid-color(80, 43, 0, 255, 8, 8) + bounds: 640 344 8 8 + - image: solid-color(81, 43, 0, 255, 8, 8) + bounds: 648 344 8 8 + - image: solid-color(82, 43, 0, 255, 8, 8) + bounds: 656 344 8 8 + - image: solid-color(83, 43, 0, 255, 8, 8) + bounds: 664 344 8 8 + - image: solid-color(84, 43, 0, 255, 8, 8) + bounds: 672 344 8 8 + - image: solid-color(85, 43, 0, 255, 8, 8) + bounds: 680 344 8 8 + - image: solid-color(86, 43, 0, 255, 8, 8) + bounds: 688 344 8 8 + - image: solid-color(87, 43, 0, 255, 8, 8) + bounds: 696 344 8 8 + - image: solid-color(88, 43, 0, 255, 8, 8) + bounds: 704 344 8 8 + - image: solid-color(89, 43, 0, 255, 8, 8) + bounds: 712 344 8 8 + - image: solid-color(90, 43, 0, 255, 8, 8) + bounds: 720 344 8 8 + - image: solid-color(91, 43, 0, 255, 8, 8) + bounds: 728 344 8 8 + - image: solid-color(92, 43, 0, 255, 8, 8) + bounds: 736 344 8 8 + - image: solid-color(93, 43, 0, 255, 8, 8) + bounds: 744 344 8 8 + - image: solid-color(94, 43, 0, 255, 8, 8) + bounds: 752 344 8 8 + - image: solid-color(95, 43, 0, 255, 8, 8) + bounds: 760 344 8 8 + - image: solid-color(96, 43, 0, 255, 8, 8) + bounds: 768 344 8 8 + - image: solid-color(97, 43, 0, 255, 8, 8) + bounds: 776 344 8 8 + - image: solid-color(98, 43, 0, 255, 8, 8) + bounds: 784 344 8 8 + - image: solid-color(99, 43, 0, 255, 8, 8) + bounds: 792 344 8 8 + - image: solid-color(100, 43, 0, 255, 8, 8) + bounds: 800 344 8 8 + - image: solid-color(101, 43, 0, 255, 8, 8) + bounds: 808 344 8 8 + - image: solid-color(102, 43, 0, 255, 8, 8) + bounds: 816 344 8 8 + - image: solid-color(103, 43, 0, 255, 8, 8) + bounds: 824 344 8 8 + - image: solid-color(104, 43, 0, 255, 8, 8) + bounds: 832 344 8 8 + - image: solid-color(105, 43, 0, 255, 8, 8) + bounds: 840 344 8 8 + - image: solid-color(106, 43, 0, 255, 8, 8) + bounds: 848 344 8 8 + - image: solid-color(107, 43, 0, 255, 8, 8) + bounds: 856 344 8 8 + - image: solid-color(108, 43, 0, 255, 8, 8) + bounds: 864 344 8 8 + - image: solid-color(109, 43, 0, 255, 8, 8) + bounds: 872 344 8 8 + - image: solid-color(110, 43, 0, 255, 8, 8) + bounds: 880 344 8 8 + - image: solid-color(111, 43, 0, 255, 8, 8) + bounds: 888 344 8 8 + - image: solid-color(112, 43, 0, 255, 8, 8) + bounds: 896 344 8 8 + - image: solid-color(113, 43, 0, 255, 8, 8) + bounds: 904 344 8 8 + - image: solid-color(114, 43, 0, 255, 8, 8) + bounds: 912 344 8 8 + - image: solid-color(115, 43, 0, 255, 8, 8) + bounds: 920 344 8 8 + - image: solid-color(116, 43, 0, 255, 8, 8) + bounds: 928 344 8 8 + - image: solid-color(117, 43, 0, 255, 8, 8) + bounds: 936 344 8 8 + - image: solid-color(118, 43, 0, 255, 8, 8) + bounds: 944 344 8 8 + - image: solid-color(119, 43, 0, 255, 8, 8) + bounds: 952 344 8 8 + - image: solid-color(120, 43, 0, 255, 8, 8) + bounds: 960 344 8 8 + - image: solid-color(121, 43, 0, 255, 8, 8) + bounds: 968 344 8 8 + - image: solid-color(122, 43, 0, 255, 8, 8) + bounds: 976 344 8 8 + - image: solid-color(123, 43, 0, 255, 8, 8) + bounds: 984 344 8 8 + - image: solid-color(124, 43, 0, 255, 8, 8) + bounds: 992 344 8 8 + - image: solid-color(125, 43, 0, 255, 8, 8) + bounds: 1000 344 8 8 + - image: solid-color(126, 43, 0, 255, 8, 8) + bounds: 1008 344 8 8 + - image: solid-color(127, 43, 0, 255, 8, 8) + bounds: 1016 344 8 8 + - image: solid-color(0, 44, 0, 255, 8, 8) + bounds: 0 352 8 8 + - image: solid-color(1, 44, 0, 255, 8, 8) + bounds: 8 352 8 8 + - image: solid-color(2, 44, 0, 255, 8, 8) + bounds: 16 352 8 8 + - image: solid-color(3, 44, 0, 255, 8, 8) + bounds: 24 352 8 8 + - image: solid-color(4, 44, 0, 255, 8, 8) + bounds: 32 352 8 8 + - image: solid-color(5, 44, 0, 255, 8, 8) + bounds: 40 352 8 8 + - image: solid-color(6, 44, 0, 255, 8, 8) + bounds: 48 352 8 8 + - image: solid-color(7, 44, 0, 255, 8, 8) + bounds: 56 352 8 8 + - image: solid-color(8, 44, 0, 255, 8, 8) + bounds: 64 352 8 8 + - image: solid-color(9, 44, 0, 255, 8, 8) + bounds: 72 352 8 8 + - image: solid-color(10, 44, 0, 255, 8, 8) + bounds: 80 352 8 8 + - image: solid-color(11, 44, 0, 255, 8, 8) + bounds: 88 352 8 8 + - image: solid-color(12, 44, 0, 255, 8, 8) + bounds: 96 352 8 8 + - image: solid-color(13, 44, 0, 255, 8, 8) + bounds: 104 352 8 8 + - image: solid-color(14, 44, 0, 255, 8, 8) + bounds: 112 352 8 8 + - image: solid-color(15, 44, 0, 255, 8, 8) + bounds: 120 352 8 8 + - image: solid-color(16, 44, 0, 255, 8, 8) + bounds: 128 352 8 8 + - image: solid-color(17, 44, 0, 255, 8, 8) + bounds: 136 352 8 8 + - image: solid-color(18, 44, 0, 255, 8, 8) + bounds: 144 352 8 8 + - image: solid-color(19, 44, 0, 255, 8, 8) + bounds: 152 352 8 8 + - image: solid-color(20, 44, 0, 255, 8, 8) + bounds: 160 352 8 8 + - image: solid-color(21, 44, 0, 255, 8, 8) + bounds: 168 352 8 8 + - image: solid-color(22, 44, 0, 255, 8, 8) + bounds: 176 352 8 8 + - image: solid-color(23, 44, 0, 255, 8, 8) + bounds: 184 352 8 8 + - image: solid-color(24, 44, 0, 255, 8, 8) + bounds: 192 352 8 8 + - image: solid-color(25, 44, 0, 255, 8, 8) + bounds: 200 352 8 8 + - image: solid-color(26, 44, 0, 255, 8, 8) + bounds: 208 352 8 8 + - image: solid-color(27, 44, 0, 255, 8, 8) + bounds: 216 352 8 8 + - image: solid-color(28, 44, 0, 255, 8, 8) + bounds: 224 352 8 8 + - image: solid-color(29, 44, 0, 255, 8, 8) + bounds: 232 352 8 8 + - image: solid-color(30, 44, 0, 255, 8, 8) + bounds: 240 352 8 8 + - image: solid-color(31, 44, 0, 255, 8, 8) + bounds: 248 352 8 8 + - image: solid-color(32, 44, 0, 255, 8, 8) + bounds: 256 352 8 8 + - image: solid-color(33, 44, 0, 255, 8, 8) + bounds: 264 352 8 8 + - image: solid-color(34, 44, 0, 255, 8, 8) + bounds: 272 352 8 8 + - image: solid-color(35, 44, 0, 255, 8, 8) + bounds: 280 352 8 8 + - image: solid-color(36, 44, 0, 255, 8, 8) + bounds: 288 352 8 8 + - image: solid-color(37, 44, 0, 255, 8, 8) + bounds: 296 352 8 8 + - image: solid-color(38, 44, 0, 255, 8, 8) + bounds: 304 352 8 8 + - image: solid-color(39, 44, 0, 255, 8, 8) + bounds: 312 352 8 8 + - image: solid-color(40, 44, 0, 255, 8, 8) + bounds: 320 352 8 8 + - image: solid-color(41, 44, 0, 255, 8, 8) + bounds: 328 352 8 8 + - image: solid-color(42, 44, 0, 255, 8, 8) + bounds: 336 352 8 8 + - image: solid-color(43, 44, 0, 255, 8, 8) + bounds: 344 352 8 8 + - image: solid-color(44, 44, 0, 255, 8, 8) + bounds: 352 352 8 8 + - image: solid-color(45, 44, 0, 255, 8, 8) + bounds: 360 352 8 8 + - image: solid-color(46, 44, 0, 255, 8, 8) + bounds: 368 352 8 8 + - image: solid-color(47, 44, 0, 255, 8, 8) + bounds: 376 352 8 8 + - image: solid-color(48, 44, 0, 255, 8, 8) + bounds: 384 352 8 8 + - image: solid-color(49, 44, 0, 255, 8, 8) + bounds: 392 352 8 8 + - image: solid-color(50, 44, 0, 255, 8, 8) + bounds: 400 352 8 8 + - image: solid-color(51, 44, 0, 255, 8, 8) + bounds: 408 352 8 8 + - image: solid-color(52, 44, 0, 255, 8, 8) + bounds: 416 352 8 8 + - image: solid-color(53, 44, 0, 255, 8, 8) + bounds: 424 352 8 8 + - image: solid-color(54, 44, 0, 255, 8, 8) + bounds: 432 352 8 8 + - image: solid-color(55, 44, 0, 255, 8, 8) + bounds: 440 352 8 8 + - image: solid-color(56, 44, 0, 255, 8, 8) + bounds: 448 352 8 8 + - image: solid-color(57, 44, 0, 255, 8, 8) + bounds: 456 352 8 8 + - image: solid-color(58, 44, 0, 255, 8, 8) + bounds: 464 352 8 8 + - image: solid-color(59, 44, 0, 255, 8, 8) + bounds: 472 352 8 8 + - image: solid-color(60, 44, 0, 255, 8, 8) + bounds: 480 352 8 8 + - image: solid-color(61, 44, 0, 255, 8, 8) + bounds: 488 352 8 8 + - image: solid-color(62, 44, 0, 255, 8, 8) + bounds: 496 352 8 8 + - image: solid-color(63, 44, 0, 255, 8, 8) + bounds: 504 352 8 8 + - image: solid-color(64, 44, 0, 255, 8, 8) + bounds: 512 352 8 8 + - image: solid-color(65, 44, 0, 255, 8, 8) + bounds: 520 352 8 8 + - image: solid-color(66, 44, 0, 255, 8, 8) + bounds: 528 352 8 8 + - image: solid-color(67, 44, 0, 255, 8, 8) + bounds: 536 352 8 8 + - image: solid-color(68, 44, 0, 255, 8, 8) + bounds: 544 352 8 8 + - image: solid-color(69, 44, 0, 255, 8, 8) + bounds: 552 352 8 8 + - image: solid-color(70, 44, 0, 255, 8, 8) + bounds: 560 352 8 8 + - image: solid-color(71, 44, 0, 255, 8, 8) + bounds: 568 352 8 8 + - image: solid-color(72, 44, 0, 255, 8, 8) + bounds: 576 352 8 8 + - image: solid-color(73, 44, 0, 255, 8, 8) + bounds: 584 352 8 8 + - image: solid-color(74, 44, 0, 255, 8, 8) + bounds: 592 352 8 8 + - image: solid-color(75, 44, 0, 255, 8, 8) + bounds: 600 352 8 8 + - image: solid-color(76, 44, 0, 255, 8, 8) + bounds: 608 352 8 8 + - image: solid-color(77, 44, 0, 255, 8, 8) + bounds: 616 352 8 8 + - image: solid-color(78, 44, 0, 255, 8, 8) + bounds: 624 352 8 8 + - image: solid-color(79, 44, 0, 255, 8, 8) + bounds: 632 352 8 8 + - image: solid-color(80, 44, 0, 255, 8, 8) + bounds: 640 352 8 8 + - image: solid-color(81, 44, 0, 255, 8, 8) + bounds: 648 352 8 8 + - image: solid-color(82, 44, 0, 255, 8, 8) + bounds: 656 352 8 8 + - image: solid-color(83, 44, 0, 255, 8, 8) + bounds: 664 352 8 8 + - image: solid-color(84, 44, 0, 255, 8, 8) + bounds: 672 352 8 8 + - image: solid-color(85, 44, 0, 255, 8, 8) + bounds: 680 352 8 8 + - image: solid-color(86, 44, 0, 255, 8, 8) + bounds: 688 352 8 8 + - image: solid-color(87, 44, 0, 255, 8, 8) + bounds: 696 352 8 8 + - image: solid-color(88, 44, 0, 255, 8, 8) + bounds: 704 352 8 8 + - image: solid-color(89, 44, 0, 255, 8, 8) + bounds: 712 352 8 8 + - image: solid-color(90, 44, 0, 255, 8, 8) + bounds: 720 352 8 8 + - image: solid-color(91, 44, 0, 255, 8, 8) + bounds: 728 352 8 8 + - image: solid-color(92, 44, 0, 255, 8, 8) + bounds: 736 352 8 8 + - image: solid-color(93, 44, 0, 255, 8, 8) + bounds: 744 352 8 8 + - image: solid-color(94, 44, 0, 255, 8, 8) + bounds: 752 352 8 8 + - image: solid-color(95, 44, 0, 255, 8, 8) + bounds: 760 352 8 8 + - image: solid-color(96, 44, 0, 255, 8, 8) + bounds: 768 352 8 8 + - image: solid-color(97, 44, 0, 255, 8, 8) + bounds: 776 352 8 8 + - image: solid-color(98, 44, 0, 255, 8, 8) + bounds: 784 352 8 8 + - image: solid-color(99, 44, 0, 255, 8, 8) + bounds: 792 352 8 8 + - image: solid-color(100, 44, 0, 255, 8, 8) + bounds: 800 352 8 8 + - image: solid-color(101, 44, 0, 255, 8, 8) + bounds: 808 352 8 8 + - image: solid-color(102, 44, 0, 255, 8, 8) + bounds: 816 352 8 8 + - image: solid-color(103, 44, 0, 255, 8, 8) + bounds: 824 352 8 8 + - image: solid-color(104, 44, 0, 255, 8, 8) + bounds: 832 352 8 8 + - image: solid-color(105, 44, 0, 255, 8, 8) + bounds: 840 352 8 8 + - image: solid-color(106, 44, 0, 255, 8, 8) + bounds: 848 352 8 8 + - image: solid-color(107, 44, 0, 255, 8, 8) + bounds: 856 352 8 8 + - image: solid-color(108, 44, 0, 255, 8, 8) + bounds: 864 352 8 8 + - image: solid-color(109, 44, 0, 255, 8, 8) + bounds: 872 352 8 8 + - image: solid-color(110, 44, 0, 255, 8, 8) + bounds: 880 352 8 8 + - image: solid-color(111, 44, 0, 255, 8, 8) + bounds: 888 352 8 8 + - image: solid-color(112, 44, 0, 255, 8, 8) + bounds: 896 352 8 8 + - image: solid-color(113, 44, 0, 255, 8, 8) + bounds: 904 352 8 8 + - image: solid-color(114, 44, 0, 255, 8, 8) + bounds: 912 352 8 8 + - image: solid-color(115, 44, 0, 255, 8, 8) + bounds: 920 352 8 8 + - image: solid-color(116, 44, 0, 255, 8, 8) + bounds: 928 352 8 8 + - image: solid-color(117, 44, 0, 255, 8, 8) + bounds: 936 352 8 8 + - image: solid-color(118, 44, 0, 255, 8, 8) + bounds: 944 352 8 8 + - image: solid-color(119, 44, 0, 255, 8, 8) + bounds: 952 352 8 8 + - image: solid-color(120, 44, 0, 255, 8, 8) + bounds: 960 352 8 8 + - image: solid-color(121, 44, 0, 255, 8, 8) + bounds: 968 352 8 8 + - image: solid-color(122, 44, 0, 255, 8, 8) + bounds: 976 352 8 8 + - image: solid-color(123, 44, 0, 255, 8, 8) + bounds: 984 352 8 8 + - image: solid-color(124, 44, 0, 255, 8, 8) + bounds: 992 352 8 8 + - image: solid-color(125, 44, 0, 255, 8, 8) + bounds: 1000 352 8 8 + - image: solid-color(126, 44, 0, 255, 8, 8) + bounds: 1008 352 8 8 + - image: solid-color(127, 44, 0, 255, 8, 8) + bounds: 1016 352 8 8 + - image: solid-color(0, 45, 0, 255, 8, 8) + bounds: 0 360 8 8 + - image: solid-color(1, 45, 0, 255, 8, 8) + bounds: 8 360 8 8 + - image: solid-color(2, 45, 0, 255, 8, 8) + bounds: 16 360 8 8 + - image: solid-color(3, 45, 0, 255, 8, 8) + bounds: 24 360 8 8 + - image: solid-color(4, 45, 0, 255, 8, 8) + bounds: 32 360 8 8 + - image: solid-color(5, 45, 0, 255, 8, 8) + bounds: 40 360 8 8 + - image: solid-color(6, 45, 0, 255, 8, 8) + bounds: 48 360 8 8 + - image: solid-color(7, 45, 0, 255, 8, 8) + bounds: 56 360 8 8 + - image: solid-color(8, 45, 0, 255, 8, 8) + bounds: 64 360 8 8 + - image: solid-color(9, 45, 0, 255, 8, 8) + bounds: 72 360 8 8 + - image: solid-color(10, 45, 0, 255, 8, 8) + bounds: 80 360 8 8 + - image: solid-color(11, 45, 0, 255, 8, 8) + bounds: 88 360 8 8 + - image: solid-color(12, 45, 0, 255, 8, 8) + bounds: 96 360 8 8 + - image: solid-color(13, 45, 0, 255, 8, 8) + bounds: 104 360 8 8 + - image: solid-color(14, 45, 0, 255, 8, 8) + bounds: 112 360 8 8 + - image: solid-color(15, 45, 0, 255, 8, 8) + bounds: 120 360 8 8 + - image: solid-color(16, 45, 0, 255, 8, 8) + bounds: 128 360 8 8 + - image: solid-color(17, 45, 0, 255, 8, 8) + bounds: 136 360 8 8 + - image: solid-color(18, 45, 0, 255, 8, 8) + bounds: 144 360 8 8 + - image: solid-color(19, 45, 0, 255, 8, 8) + bounds: 152 360 8 8 + - image: solid-color(20, 45, 0, 255, 8, 8) + bounds: 160 360 8 8 + - image: solid-color(21, 45, 0, 255, 8, 8) + bounds: 168 360 8 8 + - image: solid-color(22, 45, 0, 255, 8, 8) + bounds: 176 360 8 8 + - image: solid-color(23, 45, 0, 255, 8, 8) + bounds: 184 360 8 8 + - image: solid-color(24, 45, 0, 255, 8, 8) + bounds: 192 360 8 8 + - image: solid-color(25, 45, 0, 255, 8, 8) + bounds: 200 360 8 8 + - image: solid-color(26, 45, 0, 255, 8, 8) + bounds: 208 360 8 8 + - image: solid-color(27, 45, 0, 255, 8, 8) + bounds: 216 360 8 8 + - image: solid-color(28, 45, 0, 255, 8, 8) + bounds: 224 360 8 8 + - image: solid-color(29, 45, 0, 255, 8, 8) + bounds: 232 360 8 8 + - image: solid-color(30, 45, 0, 255, 8, 8) + bounds: 240 360 8 8 + - image: solid-color(31, 45, 0, 255, 8, 8) + bounds: 248 360 8 8 + - image: solid-color(32, 45, 0, 255, 8, 8) + bounds: 256 360 8 8 + - image: solid-color(33, 45, 0, 255, 8, 8) + bounds: 264 360 8 8 + - image: solid-color(34, 45, 0, 255, 8, 8) + bounds: 272 360 8 8 + - image: solid-color(35, 45, 0, 255, 8, 8) + bounds: 280 360 8 8 + - image: solid-color(36, 45, 0, 255, 8, 8) + bounds: 288 360 8 8 + - image: solid-color(37, 45, 0, 255, 8, 8) + bounds: 296 360 8 8 + - image: solid-color(38, 45, 0, 255, 8, 8) + bounds: 304 360 8 8 + - image: solid-color(39, 45, 0, 255, 8, 8) + bounds: 312 360 8 8 + - image: solid-color(40, 45, 0, 255, 8, 8) + bounds: 320 360 8 8 + - image: solid-color(41, 45, 0, 255, 8, 8) + bounds: 328 360 8 8 + - image: solid-color(42, 45, 0, 255, 8, 8) + bounds: 336 360 8 8 + - image: solid-color(43, 45, 0, 255, 8, 8) + bounds: 344 360 8 8 + - image: solid-color(44, 45, 0, 255, 8, 8) + bounds: 352 360 8 8 + - image: solid-color(45, 45, 0, 255, 8, 8) + bounds: 360 360 8 8 + - image: solid-color(46, 45, 0, 255, 8, 8) + bounds: 368 360 8 8 + - image: solid-color(47, 45, 0, 255, 8, 8) + bounds: 376 360 8 8 + - image: solid-color(48, 45, 0, 255, 8, 8) + bounds: 384 360 8 8 + - image: solid-color(49, 45, 0, 255, 8, 8) + bounds: 392 360 8 8 + - image: solid-color(50, 45, 0, 255, 8, 8) + bounds: 400 360 8 8 + - image: solid-color(51, 45, 0, 255, 8, 8) + bounds: 408 360 8 8 + - image: solid-color(52, 45, 0, 255, 8, 8) + bounds: 416 360 8 8 + - image: solid-color(53, 45, 0, 255, 8, 8) + bounds: 424 360 8 8 + - image: solid-color(54, 45, 0, 255, 8, 8) + bounds: 432 360 8 8 + - image: solid-color(55, 45, 0, 255, 8, 8) + bounds: 440 360 8 8 + - image: solid-color(56, 45, 0, 255, 8, 8) + bounds: 448 360 8 8 + - image: solid-color(57, 45, 0, 255, 8, 8) + bounds: 456 360 8 8 + - image: solid-color(58, 45, 0, 255, 8, 8) + bounds: 464 360 8 8 + - image: solid-color(59, 45, 0, 255, 8, 8) + bounds: 472 360 8 8 + - image: solid-color(60, 45, 0, 255, 8, 8) + bounds: 480 360 8 8 + - image: solid-color(61, 45, 0, 255, 8, 8) + bounds: 488 360 8 8 + - image: solid-color(62, 45, 0, 255, 8, 8) + bounds: 496 360 8 8 + - image: solid-color(63, 45, 0, 255, 8, 8) + bounds: 504 360 8 8 + - image: solid-color(64, 45, 0, 255, 8, 8) + bounds: 512 360 8 8 + - image: solid-color(65, 45, 0, 255, 8, 8) + bounds: 520 360 8 8 + - image: solid-color(66, 45, 0, 255, 8, 8) + bounds: 528 360 8 8 + - image: solid-color(67, 45, 0, 255, 8, 8) + bounds: 536 360 8 8 + - image: solid-color(68, 45, 0, 255, 8, 8) + bounds: 544 360 8 8 + - image: solid-color(69, 45, 0, 255, 8, 8) + bounds: 552 360 8 8 + - image: solid-color(70, 45, 0, 255, 8, 8) + bounds: 560 360 8 8 + - image: solid-color(71, 45, 0, 255, 8, 8) + bounds: 568 360 8 8 + - image: solid-color(72, 45, 0, 255, 8, 8) + bounds: 576 360 8 8 + - image: solid-color(73, 45, 0, 255, 8, 8) + bounds: 584 360 8 8 + - image: solid-color(74, 45, 0, 255, 8, 8) + bounds: 592 360 8 8 + - image: solid-color(75, 45, 0, 255, 8, 8) + bounds: 600 360 8 8 + - image: solid-color(76, 45, 0, 255, 8, 8) + bounds: 608 360 8 8 + - image: solid-color(77, 45, 0, 255, 8, 8) + bounds: 616 360 8 8 + - image: solid-color(78, 45, 0, 255, 8, 8) + bounds: 624 360 8 8 + - image: solid-color(79, 45, 0, 255, 8, 8) + bounds: 632 360 8 8 + - image: solid-color(80, 45, 0, 255, 8, 8) + bounds: 640 360 8 8 + - image: solid-color(81, 45, 0, 255, 8, 8) + bounds: 648 360 8 8 + - image: solid-color(82, 45, 0, 255, 8, 8) + bounds: 656 360 8 8 + - image: solid-color(83, 45, 0, 255, 8, 8) + bounds: 664 360 8 8 + - image: solid-color(84, 45, 0, 255, 8, 8) + bounds: 672 360 8 8 + - image: solid-color(85, 45, 0, 255, 8, 8) + bounds: 680 360 8 8 + - image: solid-color(86, 45, 0, 255, 8, 8) + bounds: 688 360 8 8 + - image: solid-color(87, 45, 0, 255, 8, 8) + bounds: 696 360 8 8 + - image: solid-color(88, 45, 0, 255, 8, 8) + bounds: 704 360 8 8 + - image: solid-color(89, 45, 0, 255, 8, 8) + bounds: 712 360 8 8 + - image: solid-color(90, 45, 0, 255, 8, 8) + bounds: 720 360 8 8 + - image: solid-color(91, 45, 0, 255, 8, 8) + bounds: 728 360 8 8 + - image: solid-color(92, 45, 0, 255, 8, 8) + bounds: 736 360 8 8 + - image: solid-color(93, 45, 0, 255, 8, 8) + bounds: 744 360 8 8 + - image: solid-color(94, 45, 0, 255, 8, 8) + bounds: 752 360 8 8 + - image: solid-color(95, 45, 0, 255, 8, 8) + bounds: 760 360 8 8 + - image: solid-color(96, 45, 0, 255, 8, 8) + bounds: 768 360 8 8 + - image: solid-color(97, 45, 0, 255, 8, 8) + bounds: 776 360 8 8 + - image: solid-color(98, 45, 0, 255, 8, 8) + bounds: 784 360 8 8 + - image: solid-color(99, 45, 0, 255, 8, 8) + bounds: 792 360 8 8 + - image: solid-color(100, 45, 0, 255, 8, 8) + bounds: 800 360 8 8 + - image: solid-color(101, 45, 0, 255, 8, 8) + bounds: 808 360 8 8 + - image: solid-color(102, 45, 0, 255, 8, 8) + bounds: 816 360 8 8 + - image: solid-color(103, 45, 0, 255, 8, 8) + bounds: 824 360 8 8 + - image: solid-color(104, 45, 0, 255, 8, 8) + bounds: 832 360 8 8 + - image: solid-color(105, 45, 0, 255, 8, 8) + bounds: 840 360 8 8 + - image: solid-color(106, 45, 0, 255, 8, 8) + bounds: 848 360 8 8 + - image: solid-color(107, 45, 0, 255, 8, 8) + bounds: 856 360 8 8 + - image: solid-color(108, 45, 0, 255, 8, 8) + bounds: 864 360 8 8 + - image: solid-color(109, 45, 0, 255, 8, 8) + bounds: 872 360 8 8 + - image: solid-color(110, 45, 0, 255, 8, 8) + bounds: 880 360 8 8 + - image: solid-color(111, 45, 0, 255, 8, 8) + bounds: 888 360 8 8 + - image: solid-color(112, 45, 0, 255, 8, 8) + bounds: 896 360 8 8 + - image: solid-color(113, 45, 0, 255, 8, 8) + bounds: 904 360 8 8 + - image: solid-color(114, 45, 0, 255, 8, 8) + bounds: 912 360 8 8 + - image: solid-color(115, 45, 0, 255, 8, 8) + bounds: 920 360 8 8 + - image: solid-color(116, 45, 0, 255, 8, 8) + bounds: 928 360 8 8 + - image: solid-color(117, 45, 0, 255, 8, 8) + bounds: 936 360 8 8 + - image: solid-color(118, 45, 0, 255, 8, 8) + bounds: 944 360 8 8 + - image: solid-color(119, 45, 0, 255, 8, 8) + bounds: 952 360 8 8 + - image: solid-color(120, 45, 0, 255, 8, 8) + bounds: 960 360 8 8 + - image: solid-color(121, 45, 0, 255, 8, 8) + bounds: 968 360 8 8 + - image: solid-color(122, 45, 0, 255, 8, 8) + bounds: 976 360 8 8 + - image: solid-color(123, 45, 0, 255, 8, 8) + bounds: 984 360 8 8 + - image: solid-color(124, 45, 0, 255, 8, 8) + bounds: 992 360 8 8 + - image: solid-color(125, 45, 0, 255, 8, 8) + bounds: 1000 360 8 8 + - image: solid-color(126, 45, 0, 255, 8, 8) + bounds: 1008 360 8 8 + - image: solid-color(127, 45, 0, 255, 8, 8) + bounds: 1016 360 8 8 + - image: solid-color(0, 46, 0, 255, 8, 8) + bounds: 0 368 8 8 + - image: solid-color(1, 46, 0, 255, 8, 8) + bounds: 8 368 8 8 + - image: solid-color(2, 46, 0, 255, 8, 8) + bounds: 16 368 8 8 + - image: solid-color(3, 46, 0, 255, 8, 8) + bounds: 24 368 8 8 + - image: solid-color(4, 46, 0, 255, 8, 8) + bounds: 32 368 8 8 + - image: solid-color(5, 46, 0, 255, 8, 8) + bounds: 40 368 8 8 + - image: solid-color(6, 46, 0, 255, 8, 8) + bounds: 48 368 8 8 + - image: solid-color(7, 46, 0, 255, 8, 8) + bounds: 56 368 8 8 + - image: solid-color(8, 46, 0, 255, 8, 8) + bounds: 64 368 8 8 + - image: solid-color(9, 46, 0, 255, 8, 8) + bounds: 72 368 8 8 + - image: solid-color(10, 46, 0, 255, 8, 8) + bounds: 80 368 8 8 + - image: solid-color(11, 46, 0, 255, 8, 8) + bounds: 88 368 8 8 + - image: solid-color(12, 46, 0, 255, 8, 8) + bounds: 96 368 8 8 + - image: solid-color(13, 46, 0, 255, 8, 8) + bounds: 104 368 8 8 + - image: solid-color(14, 46, 0, 255, 8, 8) + bounds: 112 368 8 8 + - image: solid-color(15, 46, 0, 255, 8, 8) + bounds: 120 368 8 8 + - image: solid-color(16, 46, 0, 255, 8, 8) + bounds: 128 368 8 8 + - image: solid-color(17, 46, 0, 255, 8, 8) + bounds: 136 368 8 8 + - image: solid-color(18, 46, 0, 255, 8, 8) + bounds: 144 368 8 8 + - image: solid-color(19, 46, 0, 255, 8, 8) + bounds: 152 368 8 8 + - image: solid-color(20, 46, 0, 255, 8, 8) + bounds: 160 368 8 8 + - image: solid-color(21, 46, 0, 255, 8, 8) + bounds: 168 368 8 8 + - image: solid-color(22, 46, 0, 255, 8, 8) + bounds: 176 368 8 8 + - image: solid-color(23, 46, 0, 255, 8, 8) + bounds: 184 368 8 8 + - image: solid-color(24, 46, 0, 255, 8, 8) + bounds: 192 368 8 8 + - image: solid-color(25, 46, 0, 255, 8, 8) + bounds: 200 368 8 8 + - image: solid-color(26, 46, 0, 255, 8, 8) + bounds: 208 368 8 8 + - image: solid-color(27, 46, 0, 255, 8, 8) + bounds: 216 368 8 8 + - image: solid-color(28, 46, 0, 255, 8, 8) + bounds: 224 368 8 8 + - image: solid-color(29, 46, 0, 255, 8, 8) + bounds: 232 368 8 8 + - image: solid-color(30, 46, 0, 255, 8, 8) + bounds: 240 368 8 8 + - image: solid-color(31, 46, 0, 255, 8, 8) + bounds: 248 368 8 8 + - image: solid-color(32, 46, 0, 255, 8, 8) + bounds: 256 368 8 8 + - image: solid-color(33, 46, 0, 255, 8, 8) + bounds: 264 368 8 8 + - image: solid-color(34, 46, 0, 255, 8, 8) + bounds: 272 368 8 8 + - image: solid-color(35, 46, 0, 255, 8, 8) + bounds: 280 368 8 8 + - image: solid-color(36, 46, 0, 255, 8, 8) + bounds: 288 368 8 8 + - image: solid-color(37, 46, 0, 255, 8, 8) + bounds: 296 368 8 8 + - image: solid-color(38, 46, 0, 255, 8, 8) + bounds: 304 368 8 8 + - image: solid-color(39, 46, 0, 255, 8, 8) + bounds: 312 368 8 8 + - image: solid-color(40, 46, 0, 255, 8, 8) + bounds: 320 368 8 8 + - image: solid-color(41, 46, 0, 255, 8, 8) + bounds: 328 368 8 8 + - image: solid-color(42, 46, 0, 255, 8, 8) + bounds: 336 368 8 8 + - image: solid-color(43, 46, 0, 255, 8, 8) + bounds: 344 368 8 8 + - image: solid-color(44, 46, 0, 255, 8, 8) + bounds: 352 368 8 8 + - image: solid-color(45, 46, 0, 255, 8, 8) + bounds: 360 368 8 8 + - image: solid-color(46, 46, 0, 255, 8, 8) + bounds: 368 368 8 8 + - image: solid-color(47, 46, 0, 255, 8, 8) + bounds: 376 368 8 8 + - image: solid-color(48, 46, 0, 255, 8, 8) + bounds: 384 368 8 8 + - image: solid-color(49, 46, 0, 255, 8, 8) + bounds: 392 368 8 8 + - image: solid-color(50, 46, 0, 255, 8, 8) + bounds: 400 368 8 8 + - image: solid-color(51, 46, 0, 255, 8, 8) + bounds: 408 368 8 8 + - image: solid-color(52, 46, 0, 255, 8, 8) + bounds: 416 368 8 8 + - image: solid-color(53, 46, 0, 255, 8, 8) + bounds: 424 368 8 8 + - image: solid-color(54, 46, 0, 255, 8, 8) + bounds: 432 368 8 8 + - image: solid-color(55, 46, 0, 255, 8, 8) + bounds: 440 368 8 8 + - image: solid-color(56, 46, 0, 255, 8, 8) + bounds: 448 368 8 8 + - image: solid-color(57, 46, 0, 255, 8, 8) + bounds: 456 368 8 8 + - image: solid-color(58, 46, 0, 255, 8, 8) + bounds: 464 368 8 8 + - image: solid-color(59, 46, 0, 255, 8, 8) + bounds: 472 368 8 8 + - image: solid-color(60, 46, 0, 255, 8, 8) + bounds: 480 368 8 8 + - image: solid-color(61, 46, 0, 255, 8, 8) + bounds: 488 368 8 8 + - image: solid-color(62, 46, 0, 255, 8, 8) + bounds: 496 368 8 8 + - image: solid-color(63, 46, 0, 255, 8, 8) + bounds: 504 368 8 8 + - image: solid-color(64, 46, 0, 255, 8, 8) + bounds: 512 368 8 8 + - image: solid-color(65, 46, 0, 255, 8, 8) + bounds: 520 368 8 8 + - image: solid-color(66, 46, 0, 255, 8, 8) + bounds: 528 368 8 8 + - image: solid-color(67, 46, 0, 255, 8, 8) + bounds: 536 368 8 8 + - image: solid-color(68, 46, 0, 255, 8, 8) + bounds: 544 368 8 8 + - image: solid-color(69, 46, 0, 255, 8, 8) + bounds: 552 368 8 8 + - image: solid-color(70, 46, 0, 255, 8, 8) + bounds: 560 368 8 8 + - image: solid-color(71, 46, 0, 255, 8, 8) + bounds: 568 368 8 8 + - image: solid-color(72, 46, 0, 255, 8, 8) + bounds: 576 368 8 8 + - image: solid-color(73, 46, 0, 255, 8, 8) + bounds: 584 368 8 8 + - image: solid-color(74, 46, 0, 255, 8, 8) + bounds: 592 368 8 8 + - image: solid-color(75, 46, 0, 255, 8, 8) + bounds: 600 368 8 8 + - image: solid-color(76, 46, 0, 255, 8, 8) + bounds: 608 368 8 8 + - image: solid-color(77, 46, 0, 255, 8, 8) + bounds: 616 368 8 8 + - image: solid-color(78, 46, 0, 255, 8, 8) + bounds: 624 368 8 8 + - image: solid-color(79, 46, 0, 255, 8, 8) + bounds: 632 368 8 8 + - image: solid-color(80, 46, 0, 255, 8, 8) + bounds: 640 368 8 8 + - image: solid-color(81, 46, 0, 255, 8, 8) + bounds: 648 368 8 8 + - image: solid-color(82, 46, 0, 255, 8, 8) + bounds: 656 368 8 8 + - image: solid-color(83, 46, 0, 255, 8, 8) + bounds: 664 368 8 8 + - image: solid-color(84, 46, 0, 255, 8, 8) + bounds: 672 368 8 8 + - image: solid-color(85, 46, 0, 255, 8, 8) + bounds: 680 368 8 8 + - image: solid-color(86, 46, 0, 255, 8, 8) + bounds: 688 368 8 8 + - image: solid-color(87, 46, 0, 255, 8, 8) + bounds: 696 368 8 8 + - image: solid-color(88, 46, 0, 255, 8, 8) + bounds: 704 368 8 8 + - image: solid-color(89, 46, 0, 255, 8, 8) + bounds: 712 368 8 8 + - image: solid-color(90, 46, 0, 255, 8, 8) + bounds: 720 368 8 8 + - image: solid-color(91, 46, 0, 255, 8, 8) + bounds: 728 368 8 8 + - image: solid-color(92, 46, 0, 255, 8, 8) + bounds: 736 368 8 8 + - image: solid-color(93, 46, 0, 255, 8, 8) + bounds: 744 368 8 8 + - image: solid-color(94, 46, 0, 255, 8, 8) + bounds: 752 368 8 8 + - image: solid-color(95, 46, 0, 255, 8, 8) + bounds: 760 368 8 8 + - image: solid-color(96, 46, 0, 255, 8, 8) + bounds: 768 368 8 8 + - image: solid-color(97, 46, 0, 255, 8, 8) + bounds: 776 368 8 8 + - image: solid-color(98, 46, 0, 255, 8, 8) + bounds: 784 368 8 8 + - image: solid-color(99, 46, 0, 255, 8, 8) + bounds: 792 368 8 8 + - image: solid-color(100, 46, 0, 255, 8, 8) + bounds: 800 368 8 8 + - image: solid-color(101, 46, 0, 255, 8, 8) + bounds: 808 368 8 8 + - image: solid-color(102, 46, 0, 255, 8, 8) + bounds: 816 368 8 8 + - image: solid-color(103, 46, 0, 255, 8, 8) + bounds: 824 368 8 8 + - image: solid-color(104, 46, 0, 255, 8, 8) + bounds: 832 368 8 8 + - image: solid-color(105, 46, 0, 255, 8, 8) + bounds: 840 368 8 8 + - image: solid-color(106, 46, 0, 255, 8, 8) + bounds: 848 368 8 8 + - image: solid-color(107, 46, 0, 255, 8, 8) + bounds: 856 368 8 8 + - image: solid-color(108, 46, 0, 255, 8, 8) + bounds: 864 368 8 8 + - image: solid-color(109, 46, 0, 255, 8, 8) + bounds: 872 368 8 8 + - image: solid-color(110, 46, 0, 255, 8, 8) + bounds: 880 368 8 8 + - image: solid-color(111, 46, 0, 255, 8, 8) + bounds: 888 368 8 8 + - image: solid-color(112, 46, 0, 255, 8, 8) + bounds: 896 368 8 8 + - image: solid-color(113, 46, 0, 255, 8, 8) + bounds: 904 368 8 8 + - image: solid-color(114, 46, 0, 255, 8, 8) + bounds: 912 368 8 8 + - image: solid-color(115, 46, 0, 255, 8, 8) + bounds: 920 368 8 8 + - image: solid-color(116, 46, 0, 255, 8, 8) + bounds: 928 368 8 8 + - image: solid-color(117, 46, 0, 255, 8, 8) + bounds: 936 368 8 8 + - image: solid-color(118, 46, 0, 255, 8, 8) + bounds: 944 368 8 8 + - image: solid-color(119, 46, 0, 255, 8, 8) + bounds: 952 368 8 8 + - image: solid-color(120, 46, 0, 255, 8, 8) + bounds: 960 368 8 8 + - image: solid-color(121, 46, 0, 255, 8, 8) + bounds: 968 368 8 8 + - image: solid-color(122, 46, 0, 255, 8, 8) + bounds: 976 368 8 8 + - image: solid-color(123, 46, 0, 255, 8, 8) + bounds: 984 368 8 8 + - image: solid-color(124, 46, 0, 255, 8, 8) + bounds: 992 368 8 8 + - image: solid-color(125, 46, 0, 255, 8, 8) + bounds: 1000 368 8 8 + - image: solid-color(126, 46, 0, 255, 8, 8) + bounds: 1008 368 8 8 + - image: solid-color(127, 46, 0, 255, 8, 8) + bounds: 1016 368 8 8 + - image: solid-color(0, 47, 0, 255, 8, 8) + bounds: 0 376 8 8 + - image: solid-color(1, 47, 0, 255, 8, 8) + bounds: 8 376 8 8 + - image: solid-color(2, 47, 0, 255, 8, 8) + bounds: 16 376 8 8 + - image: solid-color(3, 47, 0, 255, 8, 8) + bounds: 24 376 8 8 + - image: solid-color(4, 47, 0, 255, 8, 8) + bounds: 32 376 8 8 + - image: solid-color(5, 47, 0, 255, 8, 8) + bounds: 40 376 8 8 + - image: solid-color(6, 47, 0, 255, 8, 8) + bounds: 48 376 8 8 + - image: solid-color(7, 47, 0, 255, 8, 8) + bounds: 56 376 8 8 + - image: solid-color(8, 47, 0, 255, 8, 8) + bounds: 64 376 8 8 + - image: solid-color(9, 47, 0, 255, 8, 8) + bounds: 72 376 8 8 + - image: solid-color(10, 47, 0, 255, 8, 8) + bounds: 80 376 8 8 + - image: solid-color(11, 47, 0, 255, 8, 8) + bounds: 88 376 8 8 + - image: solid-color(12, 47, 0, 255, 8, 8) + bounds: 96 376 8 8 + - image: solid-color(13, 47, 0, 255, 8, 8) + bounds: 104 376 8 8 + - image: solid-color(14, 47, 0, 255, 8, 8) + bounds: 112 376 8 8 + - image: solid-color(15, 47, 0, 255, 8, 8) + bounds: 120 376 8 8 + - image: solid-color(16, 47, 0, 255, 8, 8) + bounds: 128 376 8 8 + - image: solid-color(17, 47, 0, 255, 8, 8) + bounds: 136 376 8 8 + - image: solid-color(18, 47, 0, 255, 8, 8) + bounds: 144 376 8 8 + - image: solid-color(19, 47, 0, 255, 8, 8) + bounds: 152 376 8 8 + - image: solid-color(20, 47, 0, 255, 8, 8) + bounds: 160 376 8 8 + - image: solid-color(21, 47, 0, 255, 8, 8) + bounds: 168 376 8 8 + - image: solid-color(22, 47, 0, 255, 8, 8) + bounds: 176 376 8 8 + - image: solid-color(23, 47, 0, 255, 8, 8) + bounds: 184 376 8 8 + - image: solid-color(24, 47, 0, 255, 8, 8) + bounds: 192 376 8 8 + - image: solid-color(25, 47, 0, 255, 8, 8) + bounds: 200 376 8 8 + - image: solid-color(26, 47, 0, 255, 8, 8) + bounds: 208 376 8 8 + - image: solid-color(27, 47, 0, 255, 8, 8) + bounds: 216 376 8 8 + - image: solid-color(28, 47, 0, 255, 8, 8) + bounds: 224 376 8 8 + - image: solid-color(29, 47, 0, 255, 8, 8) + bounds: 232 376 8 8 + - image: solid-color(30, 47, 0, 255, 8, 8) + bounds: 240 376 8 8 + - image: solid-color(31, 47, 0, 255, 8, 8) + bounds: 248 376 8 8 + - image: solid-color(32, 47, 0, 255, 8, 8) + bounds: 256 376 8 8 + - image: solid-color(33, 47, 0, 255, 8, 8) + bounds: 264 376 8 8 + - image: solid-color(34, 47, 0, 255, 8, 8) + bounds: 272 376 8 8 + - image: solid-color(35, 47, 0, 255, 8, 8) + bounds: 280 376 8 8 + - image: solid-color(36, 47, 0, 255, 8, 8) + bounds: 288 376 8 8 + - image: solid-color(37, 47, 0, 255, 8, 8) + bounds: 296 376 8 8 + - image: solid-color(38, 47, 0, 255, 8, 8) + bounds: 304 376 8 8 + - image: solid-color(39, 47, 0, 255, 8, 8) + bounds: 312 376 8 8 + - image: solid-color(40, 47, 0, 255, 8, 8) + bounds: 320 376 8 8 + - image: solid-color(41, 47, 0, 255, 8, 8) + bounds: 328 376 8 8 + - image: solid-color(42, 47, 0, 255, 8, 8) + bounds: 336 376 8 8 + - image: solid-color(43, 47, 0, 255, 8, 8) + bounds: 344 376 8 8 + - image: solid-color(44, 47, 0, 255, 8, 8) + bounds: 352 376 8 8 + - image: solid-color(45, 47, 0, 255, 8, 8) + bounds: 360 376 8 8 + - image: solid-color(46, 47, 0, 255, 8, 8) + bounds: 368 376 8 8 + - image: solid-color(47, 47, 0, 255, 8, 8) + bounds: 376 376 8 8 + - image: solid-color(48, 47, 0, 255, 8, 8) + bounds: 384 376 8 8 + - image: solid-color(49, 47, 0, 255, 8, 8) + bounds: 392 376 8 8 + - image: solid-color(50, 47, 0, 255, 8, 8) + bounds: 400 376 8 8 + - image: solid-color(51, 47, 0, 255, 8, 8) + bounds: 408 376 8 8 + - image: solid-color(52, 47, 0, 255, 8, 8) + bounds: 416 376 8 8 + - image: solid-color(53, 47, 0, 255, 8, 8) + bounds: 424 376 8 8 + - image: solid-color(54, 47, 0, 255, 8, 8) + bounds: 432 376 8 8 + - image: solid-color(55, 47, 0, 255, 8, 8) + bounds: 440 376 8 8 + - image: solid-color(56, 47, 0, 255, 8, 8) + bounds: 448 376 8 8 + - image: solid-color(57, 47, 0, 255, 8, 8) + bounds: 456 376 8 8 + - image: solid-color(58, 47, 0, 255, 8, 8) + bounds: 464 376 8 8 + - image: solid-color(59, 47, 0, 255, 8, 8) + bounds: 472 376 8 8 + - image: solid-color(60, 47, 0, 255, 8, 8) + bounds: 480 376 8 8 + - image: solid-color(61, 47, 0, 255, 8, 8) + bounds: 488 376 8 8 + - image: solid-color(62, 47, 0, 255, 8, 8) + bounds: 496 376 8 8 + - image: solid-color(63, 47, 0, 255, 8, 8) + bounds: 504 376 8 8 + - image: solid-color(64, 47, 0, 255, 8, 8) + bounds: 512 376 8 8 + - image: solid-color(65, 47, 0, 255, 8, 8) + bounds: 520 376 8 8 + - image: solid-color(66, 47, 0, 255, 8, 8) + bounds: 528 376 8 8 + - image: solid-color(67, 47, 0, 255, 8, 8) + bounds: 536 376 8 8 + - image: solid-color(68, 47, 0, 255, 8, 8) + bounds: 544 376 8 8 + - image: solid-color(69, 47, 0, 255, 8, 8) + bounds: 552 376 8 8 + - image: solid-color(70, 47, 0, 255, 8, 8) + bounds: 560 376 8 8 + - image: solid-color(71, 47, 0, 255, 8, 8) + bounds: 568 376 8 8 + - image: solid-color(72, 47, 0, 255, 8, 8) + bounds: 576 376 8 8 + - image: solid-color(73, 47, 0, 255, 8, 8) + bounds: 584 376 8 8 + - image: solid-color(74, 47, 0, 255, 8, 8) + bounds: 592 376 8 8 + - image: solid-color(75, 47, 0, 255, 8, 8) + bounds: 600 376 8 8 + - image: solid-color(76, 47, 0, 255, 8, 8) + bounds: 608 376 8 8 + - image: solid-color(77, 47, 0, 255, 8, 8) + bounds: 616 376 8 8 + - image: solid-color(78, 47, 0, 255, 8, 8) + bounds: 624 376 8 8 + - image: solid-color(79, 47, 0, 255, 8, 8) + bounds: 632 376 8 8 + - image: solid-color(80, 47, 0, 255, 8, 8) + bounds: 640 376 8 8 + - image: solid-color(81, 47, 0, 255, 8, 8) + bounds: 648 376 8 8 + - image: solid-color(82, 47, 0, 255, 8, 8) + bounds: 656 376 8 8 + - image: solid-color(83, 47, 0, 255, 8, 8) + bounds: 664 376 8 8 + - image: solid-color(84, 47, 0, 255, 8, 8) + bounds: 672 376 8 8 + - image: solid-color(85, 47, 0, 255, 8, 8) + bounds: 680 376 8 8 + - image: solid-color(86, 47, 0, 255, 8, 8) + bounds: 688 376 8 8 + - image: solid-color(87, 47, 0, 255, 8, 8) + bounds: 696 376 8 8 + - image: solid-color(88, 47, 0, 255, 8, 8) + bounds: 704 376 8 8 + - image: solid-color(89, 47, 0, 255, 8, 8) + bounds: 712 376 8 8 + - image: solid-color(90, 47, 0, 255, 8, 8) + bounds: 720 376 8 8 + - image: solid-color(91, 47, 0, 255, 8, 8) + bounds: 728 376 8 8 + - image: solid-color(92, 47, 0, 255, 8, 8) + bounds: 736 376 8 8 + - image: solid-color(93, 47, 0, 255, 8, 8) + bounds: 744 376 8 8 + - image: solid-color(94, 47, 0, 255, 8, 8) + bounds: 752 376 8 8 + - image: solid-color(95, 47, 0, 255, 8, 8) + bounds: 760 376 8 8 + - image: solid-color(96, 47, 0, 255, 8, 8) + bounds: 768 376 8 8 + - image: solid-color(97, 47, 0, 255, 8, 8) + bounds: 776 376 8 8 + - image: solid-color(98, 47, 0, 255, 8, 8) + bounds: 784 376 8 8 + - image: solid-color(99, 47, 0, 255, 8, 8) + bounds: 792 376 8 8 + - image: solid-color(100, 47, 0, 255, 8, 8) + bounds: 800 376 8 8 + - image: solid-color(101, 47, 0, 255, 8, 8) + bounds: 808 376 8 8 + - image: solid-color(102, 47, 0, 255, 8, 8) + bounds: 816 376 8 8 + - image: solid-color(103, 47, 0, 255, 8, 8) + bounds: 824 376 8 8 + - image: solid-color(104, 47, 0, 255, 8, 8) + bounds: 832 376 8 8 + - image: solid-color(105, 47, 0, 255, 8, 8) + bounds: 840 376 8 8 + - image: solid-color(106, 47, 0, 255, 8, 8) + bounds: 848 376 8 8 + - image: solid-color(107, 47, 0, 255, 8, 8) + bounds: 856 376 8 8 + - image: solid-color(108, 47, 0, 255, 8, 8) + bounds: 864 376 8 8 + - image: solid-color(109, 47, 0, 255, 8, 8) + bounds: 872 376 8 8 + - image: solid-color(110, 47, 0, 255, 8, 8) + bounds: 880 376 8 8 + - image: solid-color(111, 47, 0, 255, 8, 8) + bounds: 888 376 8 8 + - image: solid-color(112, 47, 0, 255, 8, 8) + bounds: 896 376 8 8 + - image: solid-color(113, 47, 0, 255, 8, 8) + bounds: 904 376 8 8 + - image: solid-color(114, 47, 0, 255, 8, 8) + bounds: 912 376 8 8 + - image: solid-color(115, 47, 0, 255, 8, 8) + bounds: 920 376 8 8 + - image: solid-color(116, 47, 0, 255, 8, 8) + bounds: 928 376 8 8 + - image: solid-color(117, 47, 0, 255, 8, 8) + bounds: 936 376 8 8 + - image: solid-color(118, 47, 0, 255, 8, 8) + bounds: 944 376 8 8 + - image: solid-color(119, 47, 0, 255, 8, 8) + bounds: 952 376 8 8 + - image: solid-color(120, 47, 0, 255, 8, 8) + bounds: 960 376 8 8 + - image: solid-color(121, 47, 0, 255, 8, 8) + bounds: 968 376 8 8 + - image: solid-color(122, 47, 0, 255, 8, 8) + bounds: 976 376 8 8 + - image: solid-color(123, 47, 0, 255, 8, 8) + bounds: 984 376 8 8 + - image: solid-color(124, 47, 0, 255, 8, 8) + bounds: 992 376 8 8 + - image: solid-color(125, 47, 0, 255, 8, 8) + bounds: 1000 376 8 8 + - image: solid-color(126, 47, 0, 255, 8, 8) + bounds: 1008 376 8 8 + - image: solid-color(127, 47, 0, 255, 8, 8) + bounds: 1016 376 8 8 + - image: solid-color(0, 48, 0, 255, 8, 8) + bounds: 0 384 8 8 + - image: solid-color(1, 48, 0, 255, 8, 8) + bounds: 8 384 8 8 + - image: solid-color(2, 48, 0, 255, 8, 8) + bounds: 16 384 8 8 + - image: solid-color(3, 48, 0, 255, 8, 8) + bounds: 24 384 8 8 + - image: solid-color(4, 48, 0, 255, 8, 8) + bounds: 32 384 8 8 + - image: solid-color(5, 48, 0, 255, 8, 8) + bounds: 40 384 8 8 + - image: solid-color(6, 48, 0, 255, 8, 8) + bounds: 48 384 8 8 + - image: solid-color(7, 48, 0, 255, 8, 8) + bounds: 56 384 8 8 + - image: solid-color(8, 48, 0, 255, 8, 8) + bounds: 64 384 8 8 + - image: solid-color(9, 48, 0, 255, 8, 8) + bounds: 72 384 8 8 + - image: solid-color(10, 48, 0, 255, 8, 8) + bounds: 80 384 8 8 + - image: solid-color(11, 48, 0, 255, 8, 8) + bounds: 88 384 8 8 + - image: solid-color(12, 48, 0, 255, 8, 8) + bounds: 96 384 8 8 + - image: solid-color(13, 48, 0, 255, 8, 8) + bounds: 104 384 8 8 + - image: solid-color(14, 48, 0, 255, 8, 8) + bounds: 112 384 8 8 + - image: solid-color(15, 48, 0, 255, 8, 8) + bounds: 120 384 8 8 + - image: solid-color(16, 48, 0, 255, 8, 8) + bounds: 128 384 8 8 + - image: solid-color(17, 48, 0, 255, 8, 8) + bounds: 136 384 8 8 + - image: solid-color(18, 48, 0, 255, 8, 8) + bounds: 144 384 8 8 + - image: solid-color(19, 48, 0, 255, 8, 8) + bounds: 152 384 8 8 + - image: solid-color(20, 48, 0, 255, 8, 8) + bounds: 160 384 8 8 + - image: solid-color(21, 48, 0, 255, 8, 8) + bounds: 168 384 8 8 + - image: solid-color(22, 48, 0, 255, 8, 8) + bounds: 176 384 8 8 + - image: solid-color(23, 48, 0, 255, 8, 8) + bounds: 184 384 8 8 + - image: solid-color(24, 48, 0, 255, 8, 8) + bounds: 192 384 8 8 + - image: solid-color(25, 48, 0, 255, 8, 8) + bounds: 200 384 8 8 + - image: solid-color(26, 48, 0, 255, 8, 8) + bounds: 208 384 8 8 + - image: solid-color(27, 48, 0, 255, 8, 8) + bounds: 216 384 8 8 + - image: solid-color(28, 48, 0, 255, 8, 8) + bounds: 224 384 8 8 + - image: solid-color(29, 48, 0, 255, 8, 8) + bounds: 232 384 8 8 + - image: solid-color(30, 48, 0, 255, 8, 8) + bounds: 240 384 8 8 + - image: solid-color(31, 48, 0, 255, 8, 8) + bounds: 248 384 8 8 + - image: solid-color(32, 48, 0, 255, 8, 8) + bounds: 256 384 8 8 + - image: solid-color(33, 48, 0, 255, 8, 8) + bounds: 264 384 8 8 + - image: solid-color(34, 48, 0, 255, 8, 8) + bounds: 272 384 8 8 + - image: solid-color(35, 48, 0, 255, 8, 8) + bounds: 280 384 8 8 + - image: solid-color(36, 48, 0, 255, 8, 8) + bounds: 288 384 8 8 + - image: solid-color(37, 48, 0, 255, 8, 8) + bounds: 296 384 8 8 + - image: solid-color(38, 48, 0, 255, 8, 8) + bounds: 304 384 8 8 + - image: solid-color(39, 48, 0, 255, 8, 8) + bounds: 312 384 8 8 + - image: solid-color(40, 48, 0, 255, 8, 8) + bounds: 320 384 8 8 + - image: solid-color(41, 48, 0, 255, 8, 8) + bounds: 328 384 8 8 + - image: solid-color(42, 48, 0, 255, 8, 8) + bounds: 336 384 8 8 + - image: solid-color(43, 48, 0, 255, 8, 8) + bounds: 344 384 8 8 + - image: solid-color(44, 48, 0, 255, 8, 8) + bounds: 352 384 8 8 + - image: solid-color(45, 48, 0, 255, 8, 8) + bounds: 360 384 8 8 + - image: solid-color(46, 48, 0, 255, 8, 8) + bounds: 368 384 8 8 + - image: solid-color(47, 48, 0, 255, 8, 8) + bounds: 376 384 8 8 + - image: solid-color(48, 48, 0, 255, 8, 8) + bounds: 384 384 8 8 + - image: solid-color(49, 48, 0, 255, 8, 8) + bounds: 392 384 8 8 + - image: solid-color(50, 48, 0, 255, 8, 8) + bounds: 400 384 8 8 + - image: solid-color(51, 48, 0, 255, 8, 8) + bounds: 408 384 8 8 + - image: solid-color(52, 48, 0, 255, 8, 8) + bounds: 416 384 8 8 + - image: solid-color(53, 48, 0, 255, 8, 8) + bounds: 424 384 8 8 + - image: solid-color(54, 48, 0, 255, 8, 8) + bounds: 432 384 8 8 + - image: solid-color(55, 48, 0, 255, 8, 8) + bounds: 440 384 8 8 + - image: solid-color(56, 48, 0, 255, 8, 8) + bounds: 448 384 8 8 + - image: solid-color(57, 48, 0, 255, 8, 8) + bounds: 456 384 8 8 + - image: solid-color(58, 48, 0, 255, 8, 8) + bounds: 464 384 8 8 + - image: solid-color(59, 48, 0, 255, 8, 8) + bounds: 472 384 8 8 + - image: solid-color(60, 48, 0, 255, 8, 8) + bounds: 480 384 8 8 + - image: solid-color(61, 48, 0, 255, 8, 8) + bounds: 488 384 8 8 + - image: solid-color(62, 48, 0, 255, 8, 8) + bounds: 496 384 8 8 + - image: solid-color(63, 48, 0, 255, 8, 8) + bounds: 504 384 8 8 + - image: solid-color(64, 48, 0, 255, 8, 8) + bounds: 512 384 8 8 + - image: solid-color(65, 48, 0, 255, 8, 8) + bounds: 520 384 8 8 + - image: solid-color(66, 48, 0, 255, 8, 8) + bounds: 528 384 8 8 + - image: solid-color(67, 48, 0, 255, 8, 8) + bounds: 536 384 8 8 + - image: solid-color(68, 48, 0, 255, 8, 8) + bounds: 544 384 8 8 + - image: solid-color(69, 48, 0, 255, 8, 8) + bounds: 552 384 8 8 + - image: solid-color(70, 48, 0, 255, 8, 8) + bounds: 560 384 8 8 + - image: solid-color(71, 48, 0, 255, 8, 8) + bounds: 568 384 8 8 + - image: solid-color(72, 48, 0, 255, 8, 8) + bounds: 576 384 8 8 + - image: solid-color(73, 48, 0, 255, 8, 8) + bounds: 584 384 8 8 + - image: solid-color(74, 48, 0, 255, 8, 8) + bounds: 592 384 8 8 + - image: solid-color(75, 48, 0, 255, 8, 8) + bounds: 600 384 8 8 + - image: solid-color(76, 48, 0, 255, 8, 8) + bounds: 608 384 8 8 + - image: solid-color(77, 48, 0, 255, 8, 8) + bounds: 616 384 8 8 + - image: solid-color(78, 48, 0, 255, 8, 8) + bounds: 624 384 8 8 + - image: solid-color(79, 48, 0, 255, 8, 8) + bounds: 632 384 8 8 + - image: solid-color(80, 48, 0, 255, 8, 8) + bounds: 640 384 8 8 + - image: solid-color(81, 48, 0, 255, 8, 8) + bounds: 648 384 8 8 + - image: solid-color(82, 48, 0, 255, 8, 8) + bounds: 656 384 8 8 + - image: solid-color(83, 48, 0, 255, 8, 8) + bounds: 664 384 8 8 + - image: solid-color(84, 48, 0, 255, 8, 8) + bounds: 672 384 8 8 + - image: solid-color(85, 48, 0, 255, 8, 8) + bounds: 680 384 8 8 + - image: solid-color(86, 48, 0, 255, 8, 8) + bounds: 688 384 8 8 + - image: solid-color(87, 48, 0, 255, 8, 8) + bounds: 696 384 8 8 + - image: solid-color(88, 48, 0, 255, 8, 8) + bounds: 704 384 8 8 + - image: solid-color(89, 48, 0, 255, 8, 8) + bounds: 712 384 8 8 + - image: solid-color(90, 48, 0, 255, 8, 8) + bounds: 720 384 8 8 + - image: solid-color(91, 48, 0, 255, 8, 8) + bounds: 728 384 8 8 + - image: solid-color(92, 48, 0, 255, 8, 8) + bounds: 736 384 8 8 + - image: solid-color(93, 48, 0, 255, 8, 8) + bounds: 744 384 8 8 + - image: solid-color(94, 48, 0, 255, 8, 8) + bounds: 752 384 8 8 + - image: solid-color(95, 48, 0, 255, 8, 8) + bounds: 760 384 8 8 + - image: solid-color(96, 48, 0, 255, 8, 8) + bounds: 768 384 8 8 + - image: solid-color(97, 48, 0, 255, 8, 8) + bounds: 776 384 8 8 + - image: solid-color(98, 48, 0, 255, 8, 8) + bounds: 784 384 8 8 + - image: solid-color(99, 48, 0, 255, 8, 8) + bounds: 792 384 8 8 + - image: solid-color(100, 48, 0, 255, 8, 8) + bounds: 800 384 8 8 + - image: solid-color(101, 48, 0, 255, 8, 8) + bounds: 808 384 8 8 + - image: solid-color(102, 48, 0, 255, 8, 8) + bounds: 816 384 8 8 + - image: solid-color(103, 48, 0, 255, 8, 8) + bounds: 824 384 8 8 + - image: solid-color(104, 48, 0, 255, 8, 8) + bounds: 832 384 8 8 + - image: solid-color(105, 48, 0, 255, 8, 8) + bounds: 840 384 8 8 + - image: solid-color(106, 48, 0, 255, 8, 8) + bounds: 848 384 8 8 + - image: solid-color(107, 48, 0, 255, 8, 8) + bounds: 856 384 8 8 + - image: solid-color(108, 48, 0, 255, 8, 8) + bounds: 864 384 8 8 + - image: solid-color(109, 48, 0, 255, 8, 8) + bounds: 872 384 8 8 + - image: solid-color(110, 48, 0, 255, 8, 8) + bounds: 880 384 8 8 + - image: solid-color(111, 48, 0, 255, 8, 8) + bounds: 888 384 8 8 + - image: solid-color(112, 48, 0, 255, 8, 8) + bounds: 896 384 8 8 + - image: solid-color(113, 48, 0, 255, 8, 8) + bounds: 904 384 8 8 + - image: solid-color(114, 48, 0, 255, 8, 8) + bounds: 912 384 8 8 + - image: solid-color(115, 48, 0, 255, 8, 8) + bounds: 920 384 8 8 + - image: solid-color(116, 48, 0, 255, 8, 8) + bounds: 928 384 8 8 + - image: solid-color(117, 48, 0, 255, 8, 8) + bounds: 936 384 8 8 + - image: solid-color(118, 48, 0, 255, 8, 8) + bounds: 944 384 8 8 + - image: solid-color(119, 48, 0, 255, 8, 8) + bounds: 952 384 8 8 + - image: solid-color(120, 48, 0, 255, 8, 8) + bounds: 960 384 8 8 + - image: solid-color(121, 48, 0, 255, 8, 8) + bounds: 968 384 8 8 + - image: solid-color(122, 48, 0, 255, 8, 8) + bounds: 976 384 8 8 + - image: solid-color(123, 48, 0, 255, 8, 8) + bounds: 984 384 8 8 + - image: solid-color(124, 48, 0, 255, 8, 8) + bounds: 992 384 8 8 + - image: solid-color(125, 48, 0, 255, 8, 8) + bounds: 1000 384 8 8 + - image: solid-color(126, 48, 0, 255, 8, 8) + bounds: 1008 384 8 8 + - image: solid-color(127, 48, 0, 255, 8, 8) + bounds: 1016 384 8 8 + - image: solid-color(0, 49, 0, 255, 8, 8) + bounds: 0 392 8 8 + - image: solid-color(1, 49, 0, 255, 8, 8) + bounds: 8 392 8 8 + - image: solid-color(2, 49, 0, 255, 8, 8) + bounds: 16 392 8 8 + - image: solid-color(3, 49, 0, 255, 8, 8) + bounds: 24 392 8 8 + - image: solid-color(4, 49, 0, 255, 8, 8) + bounds: 32 392 8 8 + - image: solid-color(5, 49, 0, 255, 8, 8) + bounds: 40 392 8 8 + - image: solid-color(6, 49, 0, 255, 8, 8) + bounds: 48 392 8 8 + - image: solid-color(7, 49, 0, 255, 8, 8) + bounds: 56 392 8 8 + - image: solid-color(8, 49, 0, 255, 8, 8) + bounds: 64 392 8 8 + - image: solid-color(9, 49, 0, 255, 8, 8) + bounds: 72 392 8 8 + - image: solid-color(10, 49, 0, 255, 8, 8) + bounds: 80 392 8 8 + - image: solid-color(11, 49, 0, 255, 8, 8) + bounds: 88 392 8 8 + - image: solid-color(12, 49, 0, 255, 8, 8) + bounds: 96 392 8 8 + - image: solid-color(13, 49, 0, 255, 8, 8) + bounds: 104 392 8 8 + - image: solid-color(14, 49, 0, 255, 8, 8) + bounds: 112 392 8 8 + - image: solid-color(15, 49, 0, 255, 8, 8) + bounds: 120 392 8 8 + - image: solid-color(16, 49, 0, 255, 8, 8) + bounds: 128 392 8 8 + - image: solid-color(17, 49, 0, 255, 8, 8) + bounds: 136 392 8 8 + - image: solid-color(18, 49, 0, 255, 8, 8) + bounds: 144 392 8 8 + - image: solid-color(19, 49, 0, 255, 8, 8) + bounds: 152 392 8 8 + - image: solid-color(20, 49, 0, 255, 8, 8) + bounds: 160 392 8 8 + - image: solid-color(21, 49, 0, 255, 8, 8) + bounds: 168 392 8 8 + - image: solid-color(22, 49, 0, 255, 8, 8) + bounds: 176 392 8 8 + - image: solid-color(23, 49, 0, 255, 8, 8) + bounds: 184 392 8 8 + - image: solid-color(24, 49, 0, 255, 8, 8) + bounds: 192 392 8 8 + - image: solid-color(25, 49, 0, 255, 8, 8) + bounds: 200 392 8 8 + - image: solid-color(26, 49, 0, 255, 8, 8) + bounds: 208 392 8 8 + - image: solid-color(27, 49, 0, 255, 8, 8) + bounds: 216 392 8 8 + - image: solid-color(28, 49, 0, 255, 8, 8) + bounds: 224 392 8 8 + - image: solid-color(29, 49, 0, 255, 8, 8) + bounds: 232 392 8 8 + - image: solid-color(30, 49, 0, 255, 8, 8) + bounds: 240 392 8 8 + - image: solid-color(31, 49, 0, 255, 8, 8) + bounds: 248 392 8 8 + - image: solid-color(32, 49, 0, 255, 8, 8) + bounds: 256 392 8 8 + - image: solid-color(33, 49, 0, 255, 8, 8) + bounds: 264 392 8 8 + - image: solid-color(34, 49, 0, 255, 8, 8) + bounds: 272 392 8 8 + - image: solid-color(35, 49, 0, 255, 8, 8) + bounds: 280 392 8 8 + - image: solid-color(36, 49, 0, 255, 8, 8) + bounds: 288 392 8 8 + - image: solid-color(37, 49, 0, 255, 8, 8) + bounds: 296 392 8 8 + - image: solid-color(38, 49, 0, 255, 8, 8) + bounds: 304 392 8 8 + - image: solid-color(39, 49, 0, 255, 8, 8) + bounds: 312 392 8 8 + - image: solid-color(40, 49, 0, 255, 8, 8) + bounds: 320 392 8 8 + - image: solid-color(41, 49, 0, 255, 8, 8) + bounds: 328 392 8 8 + - image: solid-color(42, 49, 0, 255, 8, 8) + bounds: 336 392 8 8 + - image: solid-color(43, 49, 0, 255, 8, 8) + bounds: 344 392 8 8 + - image: solid-color(44, 49, 0, 255, 8, 8) + bounds: 352 392 8 8 + - image: solid-color(45, 49, 0, 255, 8, 8) + bounds: 360 392 8 8 + - image: solid-color(46, 49, 0, 255, 8, 8) + bounds: 368 392 8 8 + - image: solid-color(47, 49, 0, 255, 8, 8) + bounds: 376 392 8 8 + - image: solid-color(48, 49, 0, 255, 8, 8) + bounds: 384 392 8 8 + - image: solid-color(49, 49, 0, 255, 8, 8) + bounds: 392 392 8 8 + - image: solid-color(50, 49, 0, 255, 8, 8) + bounds: 400 392 8 8 + - image: solid-color(51, 49, 0, 255, 8, 8) + bounds: 408 392 8 8 + - image: solid-color(52, 49, 0, 255, 8, 8) + bounds: 416 392 8 8 + - image: solid-color(53, 49, 0, 255, 8, 8) + bounds: 424 392 8 8 + - image: solid-color(54, 49, 0, 255, 8, 8) + bounds: 432 392 8 8 + - image: solid-color(55, 49, 0, 255, 8, 8) + bounds: 440 392 8 8 + - image: solid-color(56, 49, 0, 255, 8, 8) + bounds: 448 392 8 8 + - image: solid-color(57, 49, 0, 255, 8, 8) + bounds: 456 392 8 8 + - image: solid-color(58, 49, 0, 255, 8, 8) + bounds: 464 392 8 8 + - image: solid-color(59, 49, 0, 255, 8, 8) + bounds: 472 392 8 8 + - image: solid-color(60, 49, 0, 255, 8, 8) + bounds: 480 392 8 8 + - image: solid-color(61, 49, 0, 255, 8, 8) + bounds: 488 392 8 8 + - image: solid-color(62, 49, 0, 255, 8, 8) + bounds: 496 392 8 8 + - image: solid-color(63, 49, 0, 255, 8, 8) + bounds: 504 392 8 8 + - image: solid-color(64, 49, 0, 255, 8, 8) + bounds: 512 392 8 8 + - image: solid-color(65, 49, 0, 255, 8, 8) + bounds: 520 392 8 8 + - image: solid-color(66, 49, 0, 255, 8, 8) + bounds: 528 392 8 8 + - image: solid-color(67, 49, 0, 255, 8, 8) + bounds: 536 392 8 8 + - image: solid-color(68, 49, 0, 255, 8, 8) + bounds: 544 392 8 8 + - image: solid-color(69, 49, 0, 255, 8, 8) + bounds: 552 392 8 8 + - image: solid-color(70, 49, 0, 255, 8, 8) + bounds: 560 392 8 8 + - image: solid-color(71, 49, 0, 255, 8, 8) + bounds: 568 392 8 8 + - image: solid-color(72, 49, 0, 255, 8, 8) + bounds: 576 392 8 8 + - image: solid-color(73, 49, 0, 255, 8, 8) + bounds: 584 392 8 8 + - image: solid-color(74, 49, 0, 255, 8, 8) + bounds: 592 392 8 8 + - image: solid-color(75, 49, 0, 255, 8, 8) + bounds: 600 392 8 8 + - image: solid-color(76, 49, 0, 255, 8, 8) + bounds: 608 392 8 8 + - image: solid-color(77, 49, 0, 255, 8, 8) + bounds: 616 392 8 8 + - image: solid-color(78, 49, 0, 255, 8, 8) + bounds: 624 392 8 8 + - image: solid-color(79, 49, 0, 255, 8, 8) + bounds: 632 392 8 8 + - image: solid-color(80, 49, 0, 255, 8, 8) + bounds: 640 392 8 8 + - image: solid-color(81, 49, 0, 255, 8, 8) + bounds: 648 392 8 8 + - image: solid-color(82, 49, 0, 255, 8, 8) + bounds: 656 392 8 8 + - image: solid-color(83, 49, 0, 255, 8, 8) + bounds: 664 392 8 8 + - image: solid-color(84, 49, 0, 255, 8, 8) + bounds: 672 392 8 8 + - image: solid-color(85, 49, 0, 255, 8, 8) + bounds: 680 392 8 8 + - image: solid-color(86, 49, 0, 255, 8, 8) + bounds: 688 392 8 8 + - image: solid-color(87, 49, 0, 255, 8, 8) + bounds: 696 392 8 8 + - image: solid-color(88, 49, 0, 255, 8, 8) + bounds: 704 392 8 8 + - image: solid-color(89, 49, 0, 255, 8, 8) + bounds: 712 392 8 8 + - image: solid-color(90, 49, 0, 255, 8, 8) + bounds: 720 392 8 8 + - image: solid-color(91, 49, 0, 255, 8, 8) + bounds: 728 392 8 8 + - image: solid-color(92, 49, 0, 255, 8, 8) + bounds: 736 392 8 8 + - image: solid-color(93, 49, 0, 255, 8, 8) + bounds: 744 392 8 8 + - image: solid-color(94, 49, 0, 255, 8, 8) + bounds: 752 392 8 8 + - image: solid-color(95, 49, 0, 255, 8, 8) + bounds: 760 392 8 8 + - image: solid-color(96, 49, 0, 255, 8, 8) + bounds: 768 392 8 8 + - image: solid-color(97, 49, 0, 255, 8, 8) + bounds: 776 392 8 8 + - image: solid-color(98, 49, 0, 255, 8, 8) + bounds: 784 392 8 8 + - image: solid-color(99, 49, 0, 255, 8, 8) + bounds: 792 392 8 8 + - image: solid-color(100, 49, 0, 255, 8, 8) + bounds: 800 392 8 8 + - image: solid-color(101, 49, 0, 255, 8, 8) + bounds: 808 392 8 8 + - image: solid-color(102, 49, 0, 255, 8, 8) + bounds: 816 392 8 8 + - image: solid-color(103, 49, 0, 255, 8, 8) + bounds: 824 392 8 8 + - image: solid-color(104, 49, 0, 255, 8, 8) + bounds: 832 392 8 8 + - image: solid-color(105, 49, 0, 255, 8, 8) + bounds: 840 392 8 8 + - image: solid-color(106, 49, 0, 255, 8, 8) + bounds: 848 392 8 8 + - image: solid-color(107, 49, 0, 255, 8, 8) + bounds: 856 392 8 8 + - image: solid-color(108, 49, 0, 255, 8, 8) + bounds: 864 392 8 8 + - image: solid-color(109, 49, 0, 255, 8, 8) + bounds: 872 392 8 8 + - image: solid-color(110, 49, 0, 255, 8, 8) + bounds: 880 392 8 8 + - image: solid-color(111, 49, 0, 255, 8, 8) + bounds: 888 392 8 8 + - image: solid-color(112, 49, 0, 255, 8, 8) + bounds: 896 392 8 8 + - image: solid-color(113, 49, 0, 255, 8, 8) + bounds: 904 392 8 8 + - image: solid-color(114, 49, 0, 255, 8, 8) + bounds: 912 392 8 8 + - image: solid-color(115, 49, 0, 255, 8, 8) + bounds: 920 392 8 8 + - image: solid-color(116, 49, 0, 255, 8, 8) + bounds: 928 392 8 8 + - image: solid-color(117, 49, 0, 255, 8, 8) + bounds: 936 392 8 8 + - image: solid-color(118, 49, 0, 255, 8, 8) + bounds: 944 392 8 8 + - image: solid-color(119, 49, 0, 255, 8, 8) + bounds: 952 392 8 8 + - image: solid-color(120, 49, 0, 255, 8, 8) + bounds: 960 392 8 8 + - image: solid-color(121, 49, 0, 255, 8, 8) + bounds: 968 392 8 8 + - image: solid-color(122, 49, 0, 255, 8, 8) + bounds: 976 392 8 8 + - image: solid-color(123, 49, 0, 255, 8, 8) + bounds: 984 392 8 8 + - image: solid-color(124, 49, 0, 255, 8, 8) + bounds: 992 392 8 8 + - image: solid-color(125, 49, 0, 255, 8, 8) + bounds: 1000 392 8 8 + - image: solid-color(126, 49, 0, 255, 8, 8) + bounds: 1008 392 8 8 + - image: solid-color(127, 49, 0, 255, 8, 8) + bounds: 1016 392 8 8 + - image: solid-color(0, 50, 0, 255, 8, 8) + bounds: 0 400 8 8 + - image: solid-color(1, 50, 0, 255, 8, 8) + bounds: 8 400 8 8 + - image: solid-color(2, 50, 0, 255, 8, 8) + bounds: 16 400 8 8 + - image: solid-color(3, 50, 0, 255, 8, 8) + bounds: 24 400 8 8 + - image: solid-color(4, 50, 0, 255, 8, 8) + bounds: 32 400 8 8 + - image: solid-color(5, 50, 0, 255, 8, 8) + bounds: 40 400 8 8 + - image: solid-color(6, 50, 0, 255, 8, 8) + bounds: 48 400 8 8 + - image: solid-color(7, 50, 0, 255, 8, 8) + bounds: 56 400 8 8 + - image: solid-color(8, 50, 0, 255, 8, 8) + bounds: 64 400 8 8 + - image: solid-color(9, 50, 0, 255, 8, 8) + bounds: 72 400 8 8 + - image: solid-color(10, 50, 0, 255, 8, 8) + bounds: 80 400 8 8 + - image: solid-color(11, 50, 0, 255, 8, 8) + bounds: 88 400 8 8 + - image: solid-color(12, 50, 0, 255, 8, 8) + bounds: 96 400 8 8 + - image: solid-color(13, 50, 0, 255, 8, 8) + bounds: 104 400 8 8 + - image: solid-color(14, 50, 0, 255, 8, 8) + bounds: 112 400 8 8 + - image: solid-color(15, 50, 0, 255, 8, 8) + bounds: 120 400 8 8 + - image: solid-color(16, 50, 0, 255, 8, 8) + bounds: 128 400 8 8 + - image: solid-color(17, 50, 0, 255, 8, 8) + bounds: 136 400 8 8 + - image: solid-color(18, 50, 0, 255, 8, 8) + bounds: 144 400 8 8 + - image: solid-color(19, 50, 0, 255, 8, 8) + bounds: 152 400 8 8 + - image: solid-color(20, 50, 0, 255, 8, 8) + bounds: 160 400 8 8 + - image: solid-color(21, 50, 0, 255, 8, 8) + bounds: 168 400 8 8 + - image: solid-color(22, 50, 0, 255, 8, 8) + bounds: 176 400 8 8 + - image: solid-color(23, 50, 0, 255, 8, 8) + bounds: 184 400 8 8 + - image: solid-color(24, 50, 0, 255, 8, 8) + bounds: 192 400 8 8 + - image: solid-color(25, 50, 0, 255, 8, 8) + bounds: 200 400 8 8 + - image: solid-color(26, 50, 0, 255, 8, 8) + bounds: 208 400 8 8 + - image: solid-color(27, 50, 0, 255, 8, 8) + bounds: 216 400 8 8 + - image: solid-color(28, 50, 0, 255, 8, 8) + bounds: 224 400 8 8 + - image: solid-color(29, 50, 0, 255, 8, 8) + bounds: 232 400 8 8 + - image: solid-color(30, 50, 0, 255, 8, 8) + bounds: 240 400 8 8 + - image: solid-color(31, 50, 0, 255, 8, 8) + bounds: 248 400 8 8 + - image: solid-color(32, 50, 0, 255, 8, 8) + bounds: 256 400 8 8 + - image: solid-color(33, 50, 0, 255, 8, 8) + bounds: 264 400 8 8 + - image: solid-color(34, 50, 0, 255, 8, 8) + bounds: 272 400 8 8 + - image: solid-color(35, 50, 0, 255, 8, 8) + bounds: 280 400 8 8 + - image: solid-color(36, 50, 0, 255, 8, 8) + bounds: 288 400 8 8 + - image: solid-color(37, 50, 0, 255, 8, 8) + bounds: 296 400 8 8 + - image: solid-color(38, 50, 0, 255, 8, 8) + bounds: 304 400 8 8 + - image: solid-color(39, 50, 0, 255, 8, 8) + bounds: 312 400 8 8 + - image: solid-color(40, 50, 0, 255, 8, 8) + bounds: 320 400 8 8 + - image: solid-color(41, 50, 0, 255, 8, 8) + bounds: 328 400 8 8 + - image: solid-color(42, 50, 0, 255, 8, 8) + bounds: 336 400 8 8 + - image: solid-color(43, 50, 0, 255, 8, 8) + bounds: 344 400 8 8 + - image: solid-color(44, 50, 0, 255, 8, 8) + bounds: 352 400 8 8 + - image: solid-color(45, 50, 0, 255, 8, 8) + bounds: 360 400 8 8 + - image: solid-color(46, 50, 0, 255, 8, 8) + bounds: 368 400 8 8 + - image: solid-color(47, 50, 0, 255, 8, 8) + bounds: 376 400 8 8 + - image: solid-color(48, 50, 0, 255, 8, 8) + bounds: 384 400 8 8 + - image: solid-color(49, 50, 0, 255, 8, 8) + bounds: 392 400 8 8 + - image: solid-color(50, 50, 0, 255, 8, 8) + bounds: 400 400 8 8 + - image: solid-color(51, 50, 0, 255, 8, 8) + bounds: 408 400 8 8 + - image: solid-color(52, 50, 0, 255, 8, 8) + bounds: 416 400 8 8 + - image: solid-color(53, 50, 0, 255, 8, 8) + bounds: 424 400 8 8 + - image: solid-color(54, 50, 0, 255, 8, 8) + bounds: 432 400 8 8 + - image: solid-color(55, 50, 0, 255, 8, 8) + bounds: 440 400 8 8 + - image: solid-color(56, 50, 0, 255, 8, 8) + bounds: 448 400 8 8 + - image: solid-color(57, 50, 0, 255, 8, 8) + bounds: 456 400 8 8 + - image: solid-color(58, 50, 0, 255, 8, 8) + bounds: 464 400 8 8 + - image: solid-color(59, 50, 0, 255, 8, 8) + bounds: 472 400 8 8 + - image: solid-color(60, 50, 0, 255, 8, 8) + bounds: 480 400 8 8 + - image: solid-color(61, 50, 0, 255, 8, 8) + bounds: 488 400 8 8 + - image: solid-color(62, 50, 0, 255, 8, 8) + bounds: 496 400 8 8 + - image: solid-color(63, 50, 0, 255, 8, 8) + bounds: 504 400 8 8 + - image: solid-color(64, 50, 0, 255, 8, 8) + bounds: 512 400 8 8 + - image: solid-color(65, 50, 0, 255, 8, 8) + bounds: 520 400 8 8 + - image: solid-color(66, 50, 0, 255, 8, 8) + bounds: 528 400 8 8 + - image: solid-color(67, 50, 0, 255, 8, 8) + bounds: 536 400 8 8 + - image: solid-color(68, 50, 0, 255, 8, 8) + bounds: 544 400 8 8 + - image: solid-color(69, 50, 0, 255, 8, 8) + bounds: 552 400 8 8 + - image: solid-color(70, 50, 0, 255, 8, 8) + bounds: 560 400 8 8 + - image: solid-color(71, 50, 0, 255, 8, 8) + bounds: 568 400 8 8 + - image: solid-color(72, 50, 0, 255, 8, 8) + bounds: 576 400 8 8 + - image: solid-color(73, 50, 0, 255, 8, 8) + bounds: 584 400 8 8 + - image: solid-color(74, 50, 0, 255, 8, 8) + bounds: 592 400 8 8 + - image: solid-color(75, 50, 0, 255, 8, 8) + bounds: 600 400 8 8 + - image: solid-color(76, 50, 0, 255, 8, 8) + bounds: 608 400 8 8 + - image: solid-color(77, 50, 0, 255, 8, 8) + bounds: 616 400 8 8 + - image: solid-color(78, 50, 0, 255, 8, 8) + bounds: 624 400 8 8 + - image: solid-color(79, 50, 0, 255, 8, 8) + bounds: 632 400 8 8 + - image: solid-color(80, 50, 0, 255, 8, 8) + bounds: 640 400 8 8 + - image: solid-color(81, 50, 0, 255, 8, 8) + bounds: 648 400 8 8 + - image: solid-color(82, 50, 0, 255, 8, 8) + bounds: 656 400 8 8 + - image: solid-color(83, 50, 0, 255, 8, 8) + bounds: 664 400 8 8 + - image: solid-color(84, 50, 0, 255, 8, 8) + bounds: 672 400 8 8 + - image: solid-color(85, 50, 0, 255, 8, 8) + bounds: 680 400 8 8 + - image: solid-color(86, 50, 0, 255, 8, 8) + bounds: 688 400 8 8 + - image: solid-color(87, 50, 0, 255, 8, 8) + bounds: 696 400 8 8 + - image: solid-color(88, 50, 0, 255, 8, 8) + bounds: 704 400 8 8 + - image: solid-color(89, 50, 0, 255, 8, 8) + bounds: 712 400 8 8 + - image: solid-color(90, 50, 0, 255, 8, 8) + bounds: 720 400 8 8 + - image: solid-color(91, 50, 0, 255, 8, 8) + bounds: 728 400 8 8 + - image: solid-color(92, 50, 0, 255, 8, 8) + bounds: 736 400 8 8 + - image: solid-color(93, 50, 0, 255, 8, 8) + bounds: 744 400 8 8 + - image: solid-color(94, 50, 0, 255, 8, 8) + bounds: 752 400 8 8 + - image: solid-color(95, 50, 0, 255, 8, 8) + bounds: 760 400 8 8 + - image: solid-color(96, 50, 0, 255, 8, 8) + bounds: 768 400 8 8 + - image: solid-color(97, 50, 0, 255, 8, 8) + bounds: 776 400 8 8 + - image: solid-color(98, 50, 0, 255, 8, 8) + bounds: 784 400 8 8 + - image: solid-color(99, 50, 0, 255, 8, 8) + bounds: 792 400 8 8 + - image: solid-color(100, 50, 0, 255, 8, 8) + bounds: 800 400 8 8 + - image: solid-color(101, 50, 0, 255, 8, 8) + bounds: 808 400 8 8 + - image: solid-color(102, 50, 0, 255, 8, 8) + bounds: 816 400 8 8 + - image: solid-color(103, 50, 0, 255, 8, 8) + bounds: 824 400 8 8 + - image: solid-color(104, 50, 0, 255, 8, 8) + bounds: 832 400 8 8 + - image: solid-color(105, 50, 0, 255, 8, 8) + bounds: 840 400 8 8 + - image: solid-color(106, 50, 0, 255, 8, 8) + bounds: 848 400 8 8 + - image: solid-color(107, 50, 0, 255, 8, 8) + bounds: 856 400 8 8 + - image: solid-color(108, 50, 0, 255, 8, 8) + bounds: 864 400 8 8 + - image: solid-color(109, 50, 0, 255, 8, 8) + bounds: 872 400 8 8 + - image: solid-color(110, 50, 0, 255, 8, 8) + bounds: 880 400 8 8 + - image: solid-color(111, 50, 0, 255, 8, 8) + bounds: 888 400 8 8 + - image: solid-color(112, 50, 0, 255, 8, 8) + bounds: 896 400 8 8 + - image: solid-color(113, 50, 0, 255, 8, 8) + bounds: 904 400 8 8 + - image: solid-color(114, 50, 0, 255, 8, 8) + bounds: 912 400 8 8 + - image: solid-color(115, 50, 0, 255, 8, 8) + bounds: 920 400 8 8 + - image: solid-color(116, 50, 0, 255, 8, 8) + bounds: 928 400 8 8 + - image: solid-color(117, 50, 0, 255, 8, 8) + bounds: 936 400 8 8 + - image: solid-color(118, 50, 0, 255, 8, 8) + bounds: 944 400 8 8 + - image: solid-color(119, 50, 0, 255, 8, 8) + bounds: 952 400 8 8 + - image: solid-color(120, 50, 0, 255, 8, 8) + bounds: 960 400 8 8 + - image: solid-color(121, 50, 0, 255, 8, 8) + bounds: 968 400 8 8 + - image: solid-color(122, 50, 0, 255, 8, 8) + bounds: 976 400 8 8 + - image: solid-color(123, 50, 0, 255, 8, 8) + bounds: 984 400 8 8 + - image: solid-color(124, 50, 0, 255, 8, 8) + bounds: 992 400 8 8 + - image: solid-color(125, 50, 0, 255, 8, 8) + bounds: 1000 400 8 8 + - image: solid-color(126, 50, 0, 255, 8, 8) + bounds: 1008 400 8 8 + - image: solid-color(127, 50, 0, 255, 8, 8) + bounds: 1016 400 8 8 + - image: solid-color(0, 51, 0, 255, 8, 8) + bounds: 0 408 8 8 + - image: solid-color(1, 51, 0, 255, 8, 8) + bounds: 8 408 8 8 + - image: solid-color(2, 51, 0, 255, 8, 8) + bounds: 16 408 8 8 + - image: solid-color(3, 51, 0, 255, 8, 8) + bounds: 24 408 8 8 + - image: solid-color(4, 51, 0, 255, 8, 8) + bounds: 32 408 8 8 + - image: solid-color(5, 51, 0, 255, 8, 8) + bounds: 40 408 8 8 + - image: solid-color(6, 51, 0, 255, 8, 8) + bounds: 48 408 8 8 + - image: solid-color(7, 51, 0, 255, 8, 8) + bounds: 56 408 8 8 + - image: solid-color(8, 51, 0, 255, 8, 8) + bounds: 64 408 8 8 + - image: solid-color(9, 51, 0, 255, 8, 8) + bounds: 72 408 8 8 + - image: solid-color(10, 51, 0, 255, 8, 8) + bounds: 80 408 8 8 + - image: solid-color(11, 51, 0, 255, 8, 8) + bounds: 88 408 8 8 + - image: solid-color(12, 51, 0, 255, 8, 8) + bounds: 96 408 8 8 + - image: solid-color(13, 51, 0, 255, 8, 8) + bounds: 104 408 8 8 + - image: solid-color(14, 51, 0, 255, 8, 8) + bounds: 112 408 8 8 + - image: solid-color(15, 51, 0, 255, 8, 8) + bounds: 120 408 8 8 + - image: solid-color(16, 51, 0, 255, 8, 8) + bounds: 128 408 8 8 + - image: solid-color(17, 51, 0, 255, 8, 8) + bounds: 136 408 8 8 + - image: solid-color(18, 51, 0, 255, 8, 8) + bounds: 144 408 8 8 + - image: solid-color(19, 51, 0, 255, 8, 8) + bounds: 152 408 8 8 + - image: solid-color(20, 51, 0, 255, 8, 8) + bounds: 160 408 8 8 + - image: solid-color(21, 51, 0, 255, 8, 8) + bounds: 168 408 8 8 + - image: solid-color(22, 51, 0, 255, 8, 8) + bounds: 176 408 8 8 + - image: solid-color(23, 51, 0, 255, 8, 8) + bounds: 184 408 8 8 + - image: solid-color(24, 51, 0, 255, 8, 8) + bounds: 192 408 8 8 + - image: solid-color(25, 51, 0, 255, 8, 8) + bounds: 200 408 8 8 + - image: solid-color(26, 51, 0, 255, 8, 8) + bounds: 208 408 8 8 + - image: solid-color(27, 51, 0, 255, 8, 8) + bounds: 216 408 8 8 + - image: solid-color(28, 51, 0, 255, 8, 8) + bounds: 224 408 8 8 + - image: solid-color(29, 51, 0, 255, 8, 8) + bounds: 232 408 8 8 + - image: solid-color(30, 51, 0, 255, 8, 8) + bounds: 240 408 8 8 + - image: solid-color(31, 51, 0, 255, 8, 8) + bounds: 248 408 8 8 + - image: solid-color(32, 51, 0, 255, 8, 8) + bounds: 256 408 8 8 + - image: solid-color(33, 51, 0, 255, 8, 8) + bounds: 264 408 8 8 + - image: solid-color(34, 51, 0, 255, 8, 8) + bounds: 272 408 8 8 + - image: solid-color(35, 51, 0, 255, 8, 8) + bounds: 280 408 8 8 + - image: solid-color(36, 51, 0, 255, 8, 8) + bounds: 288 408 8 8 + - image: solid-color(37, 51, 0, 255, 8, 8) + bounds: 296 408 8 8 + - image: solid-color(38, 51, 0, 255, 8, 8) + bounds: 304 408 8 8 + - image: solid-color(39, 51, 0, 255, 8, 8) + bounds: 312 408 8 8 + - image: solid-color(40, 51, 0, 255, 8, 8) + bounds: 320 408 8 8 + - image: solid-color(41, 51, 0, 255, 8, 8) + bounds: 328 408 8 8 + - image: solid-color(42, 51, 0, 255, 8, 8) + bounds: 336 408 8 8 + - image: solid-color(43, 51, 0, 255, 8, 8) + bounds: 344 408 8 8 + - image: solid-color(44, 51, 0, 255, 8, 8) + bounds: 352 408 8 8 + - image: solid-color(45, 51, 0, 255, 8, 8) + bounds: 360 408 8 8 + - image: solid-color(46, 51, 0, 255, 8, 8) + bounds: 368 408 8 8 + - image: solid-color(47, 51, 0, 255, 8, 8) + bounds: 376 408 8 8 + - image: solid-color(48, 51, 0, 255, 8, 8) + bounds: 384 408 8 8 + - image: solid-color(49, 51, 0, 255, 8, 8) + bounds: 392 408 8 8 + - image: solid-color(50, 51, 0, 255, 8, 8) + bounds: 400 408 8 8 + - image: solid-color(51, 51, 0, 255, 8, 8) + bounds: 408 408 8 8 + - image: solid-color(52, 51, 0, 255, 8, 8) + bounds: 416 408 8 8 + - image: solid-color(53, 51, 0, 255, 8, 8) + bounds: 424 408 8 8 + - image: solid-color(54, 51, 0, 255, 8, 8) + bounds: 432 408 8 8 + - image: solid-color(55, 51, 0, 255, 8, 8) + bounds: 440 408 8 8 + - image: solid-color(56, 51, 0, 255, 8, 8) + bounds: 448 408 8 8 + - image: solid-color(57, 51, 0, 255, 8, 8) + bounds: 456 408 8 8 + - image: solid-color(58, 51, 0, 255, 8, 8) + bounds: 464 408 8 8 + - image: solid-color(59, 51, 0, 255, 8, 8) + bounds: 472 408 8 8 + - image: solid-color(60, 51, 0, 255, 8, 8) + bounds: 480 408 8 8 + - image: solid-color(61, 51, 0, 255, 8, 8) + bounds: 488 408 8 8 + - image: solid-color(62, 51, 0, 255, 8, 8) + bounds: 496 408 8 8 + - image: solid-color(63, 51, 0, 255, 8, 8) + bounds: 504 408 8 8 + - image: solid-color(64, 51, 0, 255, 8, 8) + bounds: 512 408 8 8 + - image: solid-color(65, 51, 0, 255, 8, 8) + bounds: 520 408 8 8 + - image: solid-color(66, 51, 0, 255, 8, 8) + bounds: 528 408 8 8 + - image: solid-color(67, 51, 0, 255, 8, 8) + bounds: 536 408 8 8 + - image: solid-color(68, 51, 0, 255, 8, 8) + bounds: 544 408 8 8 + - image: solid-color(69, 51, 0, 255, 8, 8) + bounds: 552 408 8 8 + - image: solid-color(70, 51, 0, 255, 8, 8) + bounds: 560 408 8 8 + - image: solid-color(71, 51, 0, 255, 8, 8) + bounds: 568 408 8 8 + - image: solid-color(72, 51, 0, 255, 8, 8) + bounds: 576 408 8 8 + - image: solid-color(73, 51, 0, 255, 8, 8) + bounds: 584 408 8 8 + - image: solid-color(74, 51, 0, 255, 8, 8) + bounds: 592 408 8 8 + - image: solid-color(75, 51, 0, 255, 8, 8) + bounds: 600 408 8 8 + - image: solid-color(76, 51, 0, 255, 8, 8) + bounds: 608 408 8 8 + - image: solid-color(77, 51, 0, 255, 8, 8) + bounds: 616 408 8 8 + - image: solid-color(78, 51, 0, 255, 8, 8) + bounds: 624 408 8 8 + - image: solid-color(79, 51, 0, 255, 8, 8) + bounds: 632 408 8 8 + - image: solid-color(80, 51, 0, 255, 8, 8) + bounds: 640 408 8 8 + - image: solid-color(81, 51, 0, 255, 8, 8) + bounds: 648 408 8 8 + - image: solid-color(82, 51, 0, 255, 8, 8) + bounds: 656 408 8 8 + - image: solid-color(83, 51, 0, 255, 8, 8) + bounds: 664 408 8 8 + - image: solid-color(84, 51, 0, 255, 8, 8) + bounds: 672 408 8 8 + - image: solid-color(85, 51, 0, 255, 8, 8) + bounds: 680 408 8 8 + - image: solid-color(86, 51, 0, 255, 8, 8) + bounds: 688 408 8 8 + - image: solid-color(87, 51, 0, 255, 8, 8) + bounds: 696 408 8 8 + - image: solid-color(88, 51, 0, 255, 8, 8) + bounds: 704 408 8 8 + - image: solid-color(89, 51, 0, 255, 8, 8) + bounds: 712 408 8 8 + - image: solid-color(90, 51, 0, 255, 8, 8) + bounds: 720 408 8 8 + - image: solid-color(91, 51, 0, 255, 8, 8) + bounds: 728 408 8 8 + - image: solid-color(92, 51, 0, 255, 8, 8) + bounds: 736 408 8 8 + - image: solid-color(93, 51, 0, 255, 8, 8) + bounds: 744 408 8 8 + - image: solid-color(94, 51, 0, 255, 8, 8) + bounds: 752 408 8 8 + - image: solid-color(95, 51, 0, 255, 8, 8) + bounds: 760 408 8 8 + - image: solid-color(96, 51, 0, 255, 8, 8) + bounds: 768 408 8 8 + - image: solid-color(97, 51, 0, 255, 8, 8) + bounds: 776 408 8 8 + - image: solid-color(98, 51, 0, 255, 8, 8) + bounds: 784 408 8 8 + - image: solid-color(99, 51, 0, 255, 8, 8) + bounds: 792 408 8 8 + - image: solid-color(100, 51, 0, 255, 8, 8) + bounds: 800 408 8 8 + - image: solid-color(101, 51, 0, 255, 8, 8) + bounds: 808 408 8 8 + - image: solid-color(102, 51, 0, 255, 8, 8) + bounds: 816 408 8 8 + - image: solid-color(103, 51, 0, 255, 8, 8) + bounds: 824 408 8 8 + - image: solid-color(104, 51, 0, 255, 8, 8) + bounds: 832 408 8 8 + - image: solid-color(105, 51, 0, 255, 8, 8) + bounds: 840 408 8 8 + - image: solid-color(106, 51, 0, 255, 8, 8) + bounds: 848 408 8 8 + - image: solid-color(107, 51, 0, 255, 8, 8) + bounds: 856 408 8 8 + - image: solid-color(108, 51, 0, 255, 8, 8) + bounds: 864 408 8 8 + - image: solid-color(109, 51, 0, 255, 8, 8) + bounds: 872 408 8 8 + - image: solid-color(110, 51, 0, 255, 8, 8) + bounds: 880 408 8 8 + - image: solid-color(111, 51, 0, 255, 8, 8) + bounds: 888 408 8 8 + - image: solid-color(112, 51, 0, 255, 8, 8) + bounds: 896 408 8 8 + - image: solid-color(113, 51, 0, 255, 8, 8) + bounds: 904 408 8 8 + - image: solid-color(114, 51, 0, 255, 8, 8) + bounds: 912 408 8 8 + - image: solid-color(115, 51, 0, 255, 8, 8) + bounds: 920 408 8 8 + - image: solid-color(116, 51, 0, 255, 8, 8) + bounds: 928 408 8 8 + - image: solid-color(117, 51, 0, 255, 8, 8) + bounds: 936 408 8 8 + - image: solid-color(118, 51, 0, 255, 8, 8) + bounds: 944 408 8 8 + - image: solid-color(119, 51, 0, 255, 8, 8) + bounds: 952 408 8 8 + - image: solid-color(120, 51, 0, 255, 8, 8) + bounds: 960 408 8 8 + - image: solid-color(121, 51, 0, 255, 8, 8) + bounds: 968 408 8 8 + - image: solid-color(122, 51, 0, 255, 8, 8) + bounds: 976 408 8 8 + - image: solid-color(123, 51, 0, 255, 8, 8) + bounds: 984 408 8 8 + - image: solid-color(124, 51, 0, 255, 8, 8) + bounds: 992 408 8 8 + - image: solid-color(125, 51, 0, 255, 8, 8) + bounds: 1000 408 8 8 + - image: solid-color(126, 51, 0, 255, 8, 8) + bounds: 1008 408 8 8 + - image: solid-color(127, 51, 0, 255, 8, 8) + bounds: 1016 408 8 8 + - image: solid-color(0, 52, 0, 255, 8, 8) + bounds: 0 416 8 8 + - image: solid-color(1, 52, 0, 255, 8, 8) + bounds: 8 416 8 8 + - image: solid-color(2, 52, 0, 255, 8, 8) + bounds: 16 416 8 8 + - image: solid-color(3, 52, 0, 255, 8, 8) + bounds: 24 416 8 8 + - image: solid-color(4, 52, 0, 255, 8, 8) + bounds: 32 416 8 8 + - image: solid-color(5, 52, 0, 255, 8, 8) + bounds: 40 416 8 8 + - image: solid-color(6, 52, 0, 255, 8, 8) + bounds: 48 416 8 8 + - image: solid-color(7, 52, 0, 255, 8, 8) + bounds: 56 416 8 8 + - image: solid-color(8, 52, 0, 255, 8, 8) + bounds: 64 416 8 8 + - image: solid-color(9, 52, 0, 255, 8, 8) + bounds: 72 416 8 8 + - image: solid-color(10, 52, 0, 255, 8, 8) + bounds: 80 416 8 8 + - image: solid-color(11, 52, 0, 255, 8, 8) + bounds: 88 416 8 8 + - image: solid-color(12, 52, 0, 255, 8, 8) + bounds: 96 416 8 8 + - image: solid-color(13, 52, 0, 255, 8, 8) + bounds: 104 416 8 8 + - image: solid-color(14, 52, 0, 255, 8, 8) + bounds: 112 416 8 8 + - image: solid-color(15, 52, 0, 255, 8, 8) + bounds: 120 416 8 8 + - image: solid-color(16, 52, 0, 255, 8, 8) + bounds: 128 416 8 8 + - image: solid-color(17, 52, 0, 255, 8, 8) + bounds: 136 416 8 8 + - image: solid-color(18, 52, 0, 255, 8, 8) + bounds: 144 416 8 8 + - image: solid-color(19, 52, 0, 255, 8, 8) + bounds: 152 416 8 8 + - image: solid-color(20, 52, 0, 255, 8, 8) + bounds: 160 416 8 8 + - image: solid-color(21, 52, 0, 255, 8, 8) + bounds: 168 416 8 8 + - image: solid-color(22, 52, 0, 255, 8, 8) + bounds: 176 416 8 8 + - image: solid-color(23, 52, 0, 255, 8, 8) + bounds: 184 416 8 8 + - image: solid-color(24, 52, 0, 255, 8, 8) + bounds: 192 416 8 8 + - image: solid-color(25, 52, 0, 255, 8, 8) + bounds: 200 416 8 8 + - image: solid-color(26, 52, 0, 255, 8, 8) + bounds: 208 416 8 8 + - image: solid-color(27, 52, 0, 255, 8, 8) + bounds: 216 416 8 8 + - image: solid-color(28, 52, 0, 255, 8, 8) + bounds: 224 416 8 8 + - image: solid-color(29, 52, 0, 255, 8, 8) + bounds: 232 416 8 8 + - image: solid-color(30, 52, 0, 255, 8, 8) + bounds: 240 416 8 8 + - image: solid-color(31, 52, 0, 255, 8, 8) + bounds: 248 416 8 8 + - image: solid-color(32, 52, 0, 255, 8, 8) + bounds: 256 416 8 8 + - image: solid-color(33, 52, 0, 255, 8, 8) + bounds: 264 416 8 8 + - image: solid-color(34, 52, 0, 255, 8, 8) + bounds: 272 416 8 8 + - image: solid-color(35, 52, 0, 255, 8, 8) + bounds: 280 416 8 8 + - image: solid-color(36, 52, 0, 255, 8, 8) + bounds: 288 416 8 8 + - image: solid-color(37, 52, 0, 255, 8, 8) + bounds: 296 416 8 8 + - image: solid-color(38, 52, 0, 255, 8, 8) + bounds: 304 416 8 8 + - image: solid-color(39, 52, 0, 255, 8, 8) + bounds: 312 416 8 8 + - image: solid-color(40, 52, 0, 255, 8, 8) + bounds: 320 416 8 8 + - image: solid-color(41, 52, 0, 255, 8, 8) + bounds: 328 416 8 8 + - image: solid-color(42, 52, 0, 255, 8, 8) + bounds: 336 416 8 8 + - image: solid-color(43, 52, 0, 255, 8, 8) + bounds: 344 416 8 8 + - image: solid-color(44, 52, 0, 255, 8, 8) + bounds: 352 416 8 8 + - image: solid-color(45, 52, 0, 255, 8, 8) + bounds: 360 416 8 8 + - image: solid-color(46, 52, 0, 255, 8, 8) + bounds: 368 416 8 8 + - image: solid-color(47, 52, 0, 255, 8, 8) + bounds: 376 416 8 8 + - image: solid-color(48, 52, 0, 255, 8, 8) + bounds: 384 416 8 8 + - image: solid-color(49, 52, 0, 255, 8, 8) + bounds: 392 416 8 8 + - image: solid-color(50, 52, 0, 255, 8, 8) + bounds: 400 416 8 8 + - image: solid-color(51, 52, 0, 255, 8, 8) + bounds: 408 416 8 8 + - image: solid-color(52, 52, 0, 255, 8, 8) + bounds: 416 416 8 8 + - image: solid-color(53, 52, 0, 255, 8, 8) + bounds: 424 416 8 8 + - image: solid-color(54, 52, 0, 255, 8, 8) + bounds: 432 416 8 8 + - image: solid-color(55, 52, 0, 255, 8, 8) + bounds: 440 416 8 8 + - image: solid-color(56, 52, 0, 255, 8, 8) + bounds: 448 416 8 8 + - image: solid-color(57, 52, 0, 255, 8, 8) + bounds: 456 416 8 8 + - image: solid-color(58, 52, 0, 255, 8, 8) + bounds: 464 416 8 8 + - image: solid-color(59, 52, 0, 255, 8, 8) + bounds: 472 416 8 8 + - image: solid-color(60, 52, 0, 255, 8, 8) + bounds: 480 416 8 8 + - image: solid-color(61, 52, 0, 255, 8, 8) + bounds: 488 416 8 8 + - image: solid-color(62, 52, 0, 255, 8, 8) + bounds: 496 416 8 8 + - image: solid-color(63, 52, 0, 255, 8, 8) + bounds: 504 416 8 8 + - image: solid-color(64, 52, 0, 255, 8, 8) + bounds: 512 416 8 8 + - image: solid-color(65, 52, 0, 255, 8, 8) + bounds: 520 416 8 8 + - image: solid-color(66, 52, 0, 255, 8, 8) + bounds: 528 416 8 8 + - image: solid-color(67, 52, 0, 255, 8, 8) + bounds: 536 416 8 8 + - image: solid-color(68, 52, 0, 255, 8, 8) + bounds: 544 416 8 8 + - image: solid-color(69, 52, 0, 255, 8, 8) + bounds: 552 416 8 8 + - image: solid-color(70, 52, 0, 255, 8, 8) + bounds: 560 416 8 8 + - image: solid-color(71, 52, 0, 255, 8, 8) + bounds: 568 416 8 8 + - image: solid-color(72, 52, 0, 255, 8, 8) + bounds: 576 416 8 8 + - image: solid-color(73, 52, 0, 255, 8, 8) + bounds: 584 416 8 8 + - image: solid-color(74, 52, 0, 255, 8, 8) + bounds: 592 416 8 8 + - image: solid-color(75, 52, 0, 255, 8, 8) + bounds: 600 416 8 8 + - image: solid-color(76, 52, 0, 255, 8, 8) + bounds: 608 416 8 8 + - image: solid-color(77, 52, 0, 255, 8, 8) + bounds: 616 416 8 8 + - image: solid-color(78, 52, 0, 255, 8, 8) + bounds: 624 416 8 8 + - image: solid-color(79, 52, 0, 255, 8, 8) + bounds: 632 416 8 8 + - image: solid-color(80, 52, 0, 255, 8, 8) + bounds: 640 416 8 8 + - image: solid-color(81, 52, 0, 255, 8, 8) + bounds: 648 416 8 8 + - image: solid-color(82, 52, 0, 255, 8, 8) + bounds: 656 416 8 8 + - image: solid-color(83, 52, 0, 255, 8, 8) + bounds: 664 416 8 8 + - image: solid-color(84, 52, 0, 255, 8, 8) + bounds: 672 416 8 8 + - image: solid-color(85, 52, 0, 255, 8, 8) + bounds: 680 416 8 8 + - image: solid-color(86, 52, 0, 255, 8, 8) + bounds: 688 416 8 8 + - image: solid-color(87, 52, 0, 255, 8, 8) + bounds: 696 416 8 8 + - image: solid-color(88, 52, 0, 255, 8, 8) + bounds: 704 416 8 8 + - image: solid-color(89, 52, 0, 255, 8, 8) + bounds: 712 416 8 8 + - image: solid-color(90, 52, 0, 255, 8, 8) + bounds: 720 416 8 8 + - image: solid-color(91, 52, 0, 255, 8, 8) + bounds: 728 416 8 8 + - image: solid-color(92, 52, 0, 255, 8, 8) + bounds: 736 416 8 8 + - image: solid-color(93, 52, 0, 255, 8, 8) + bounds: 744 416 8 8 + - image: solid-color(94, 52, 0, 255, 8, 8) + bounds: 752 416 8 8 + - image: solid-color(95, 52, 0, 255, 8, 8) + bounds: 760 416 8 8 + - image: solid-color(96, 52, 0, 255, 8, 8) + bounds: 768 416 8 8 + - image: solid-color(97, 52, 0, 255, 8, 8) + bounds: 776 416 8 8 + - image: solid-color(98, 52, 0, 255, 8, 8) + bounds: 784 416 8 8 + - image: solid-color(99, 52, 0, 255, 8, 8) + bounds: 792 416 8 8 + - image: solid-color(100, 52, 0, 255, 8, 8) + bounds: 800 416 8 8 + - image: solid-color(101, 52, 0, 255, 8, 8) + bounds: 808 416 8 8 + - image: solid-color(102, 52, 0, 255, 8, 8) + bounds: 816 416 8 8 + - image: solid-color(103, 52, 0, 255, 8, 8) + bounds: 824 416 8 8 + - image: solid-color(104, 52, 0, 255, 8, 8) + bounds: 832 416 8 8 + - image: solid-color(105, 52, 0, 255, 8, 8) + bounds: 840 416 8 8 + - image: solid-color(106, 52, 0, 255, 8, 8) + bounds: 848 416 8 8 + - image: solid-color(107, 52, 0, 255, 8, 8) + bounds: 856 416 8 8 + - image: solid-color(108, 52, 0, 255, 8, 8) + bounds: 864 416 8 8 + - image: solid-color(109, 52, 0, 255, 8, 8) + bounds: 872 416 8 8 + - image: solid-color(110, 52, 0, 255, 8, 8) + bounds: 880 416 8 8 + - image: solid-color(111, 52, 0, 255, 8, 8) + bounds: 888 416 8 8 + - image: solid-color(112, 52, 0, 255, 8, 8) + bounds: 896 416 8 8 + - image: solid-color(113, 52, 0, 255, 8, 8) + bounds: 904 416 8 8 + - image: solid-color(114, 52, 0, 255, 8, 8) + bounds: 912 416 8 8 + - image: solid-color(115, 52, 0, 255, 8, 8) + bounds: 920 416 8 8 + - image: solid-color(116, 52, 0, 255, 8, 8) + bounds: 928 416 8 8 + - image: solid-color(117, 52, 0, 255, 8, 8) + bounds: 936 416 8 8 + - image: solid-color(118, 52, 0, 255, 8, 8) + bounds: 944 416 8 8 + - image: solid-color(119, 52, 0, 255, 8, 8) + bounds: 952 416 8 8 + - image: solid-color(120, 52, 0, 255, 8, 8) + bounds: 960 416 8 8 + - image: solid-color(121, 52, 0, 255, 8, 8) + bounds: 968 416 8 8 + - image: solid-color(122, 52, 0, 255, 8, 8) + bounds: 976 416 8 8 + - image: solid-color(123, 52, 0, 255, 8, 8) + bounds: 984 416 8 8 + - image: solid-color(124, 52, 0, 255, 8, 8) + bounds: 992 416 8 8 + - image: solid-color(125, 52, 0, 255, 8, 8) + bounds: 1000 416 8 8 + - image: solid-color(126, 52, 0, 255, 8, 8) + bounds: 1008 416 8 8 + - image: solid-color(127, 52, 0, 255, 8, 8) + bounds: 1016 416 8 8 + - image: solid-color(0, 53, 0, 255, 8, 8) + bounds: 0 424 8 8 + - image: solid-color(1, 53, 0, 255, 8, 8) + bounds: 8 424 8 8 + - image: solid-color(2, 53, 0, 255, 8, 8) + bounds: 16 424 8 8 + - image: solid-color(3, 53, 0, 255, 8, 8) + bounds: 24 424 8 8 + - image: solid-color(4, 53, 0, 255, 8, 8) + bounds: 32 424 8 8 + - image: solid-color(5, 53, 0, 255, 8, 8) + bounds: 40 424 8 8 + - image: solid-color(6, 53, 0, 255, 8, 8) + bounds: 48 424 8 8 + - image: solid-color(7, 53, 0, 255, 8, 8) + bounds: 56 424 8 8 + - image: solid-color(8, 53, 0, 255, 8, 8) + bounds: 64 424 8 8 + - image: solid-color(9, 53, 0, 255, 8, 8) + bounds: 72 424 8 8 + - image: solid-color(10, 53, 0, 255, 8, 8) + bounds: 80 424 8 8 + - image: solid-color(11, 53, 0, 255, 8, 8) + bounds: 88 424 8 8 + - image: solid-color(12, 53, 0, 255, 8, 8) + bounds: 96 424 8 8 + - image: solid-color(13, 53, 0, 255, 8, 8) + bounds: 104 424 8 8 + - image: solid-color(14, 53, 0, 255, 8, 8) + bounds: 112 424 8 8 + - image: solid-color(15, 53, 0, 255, 8, 8) + bounds: 120 424 8 8 + - image: solid-color(16, 53, 0, 255, 8, 8) + bounds: 128 424 8 8 + - image: solid-color(17, 53, 0, 255, 8, 8) + bounds: 136 424 8 8 + - image: solid-color(18, 53, 0, 255, 8, 8) + bounds: 144 424 8 8 + - image: solid-color(19, 53, 0, 255, 8, 8) + bounds: 152 424 8 8 + - image: solid-color(20, 53, 0, 255, 8, 8) + bounds: 160 424 8 8 + - image: solid-color(21, 53, 0, 255, 8, 8) + bounds: 168 424 8 8 + - image: solid-color(22, 53, 0, 255, 8, 8) + bounds: 176 424 8 8 + - image: solid-color(23, 53, 0, 255, 8, 8) + bounds: 184 424 8 8 + - image: solid-color(24, 53, 0, 255, 8, 8) + bounds: 192 424 8 8 + - image: solid-color(25, 53, 0, 255, 8, 8) + bounds: 200 424 8 8 + - image: solid-color(26, 53, 0, 255, 8, 8) + bounds: 208 424 8 8 + - image: solid-color(27, 53, 0, 255, 8, 8) + bounds: 216 424 8 8 + - image: solid-color(28, 53, 0, 255, 8, 8) + bounds: 224 424 8 8 + - image: solid-color(29, 53, 0, 255, 8, 8) + bounds: 232 424 8 8 + - image: solid-color(30, 53, 0, 255, 8, 8) + bounds: 240 424 8 8 + - image: solid-color(31, 53, 0, 255, 8, 8) + bounds: 248 424 8 8 + - image: solid-color(32, 53, 0, 255, 8, 8) + bounds: 256 424 8 8 + - image: solid-color(33, 53, 0, 255, 8, 8) + bounds: 264 424 8 8 + - image: solid-color(34, 53, 0, 255, 8, 8) + bounds: 272 424 8 8 + - image: solid-color(35, 53, 0, 255, 8, 8) + bounds: 280 424 8 8 + - image: solid-color(36, 53, 0, 255, 8, 8) + bounds: 288 424 8 8 + - image: solid-color(37, 53, 0, 255, 8, 8) + bounds: 296 424 8 8 + - image: solid-color(38, 53, 0, 255, 8, 8) + bounds: 304 424 8 8 + - image: solid-color(39, 53, 0, 255, 8, 8) + bounds: 312 424 8 8 + - image: solid-color(40, 53, 0, 255, 8, 8) + bounds: 320 424 8 8 + - image: solid-color(41, 53, 0, 255, 8, 8) + bounds: 328 424 8 8 + - image: solid-color(42, 53, 0, 255, 8, 8) + bounds: 336 424 8 8 + - image: solid-color(43, 53, 0, 255, 8, 8) + bounds: 344 424 8 8 + - image: solid-color(44, 53, 0, 255, 8, 8) + bounds: 352 424 8 8 + - image: solid-color(45, 53, 0, 255, 8, 8) + bounds: 360 424 8 8 + - image: solid-color(46, 53, 0, 255, 8, 8) + bounds: 368 424 8 8 + - image: solid-color(47, 53, 0, 255, 8, 8) + bounds: 376 424 8 8 + - image: solid-color(48, 53, 0, 255, 8, 8) + bounds: 384 424 8 8 + - image: solid-color(49, 53, 0, 255, 8, 8) + bounds: 392 424 8 8 + - image: solid-color(50, 53, 0, 255, 8, 8) + bounds: 400 424 8 8 + - image: solid-color(51, 53, 0, 255, 8, 8) + bounds: 408 424 8 8 + - image: solid-color(52, 53, 0, 255, 8, 8) + bounds: 416 424 8 8 + - image: solid-color(53, 53, 0, 255, 8, 8) + bounds: 424 424 8 8 + - image: solid-color(54, 53, 0, 255, 8, 8) + bounds: 432 424 8 8 + - image: solid-color(55, 53, 0, 255, 8, 8) + bounds: 440 424 8 8 + - image: solid-color(56, 53, 0, 255, 8, 8) + bounds: 448 424 8 8 + - image: solid-color(57, 53, 0, 255, 8, 8) + bounds: 456 424 8 8 + - image: solid-color(58, 53, 0, 255, 8, 8) + bounds: 464 424 8 8 + - image: solid-color(59, 53, 0, 255, 8, 8) + bounds: 472 424 8 8 + - image: solid-color(60, 53, 0, 255, 8, 8) + bounds: 480 424 8 8 + - image: solid-color(61, 53, 0, 255, 8, 8) + bounds: 488 424 8 8 + - image: solid-color(62, 53, 0, 255, 8, 8) + bounds: 496 424 8 8 + - image: solid-color(63, 53, 0, 255, 8, 8) + bounds: 504 424 8 8 + - image: solid-color(64, 53, 0, 255, 8, 8) + bounds: 512 424 8 8 + - image: solid-color(65, 53, 0, 255, 8, 8) + bounds: 520 424 8 8 + - image: solid-color(66, 53, 0, 255, 8, 8) + bounds: 528 424 8 8 + - image: solid-color(67, 53, 0, 255, 8, 8) + bounds: 536 424 8 8 + - image: solid-color(68, 53, 0, 255, 8, 8) + bounds: 544 424 8 8 + - image: solid-color(69, 53, 0, 255, 8, 8) + bounds: 552 424 8 8 + - image: solid-color(70, 53, 0, 255, 8, 8) + bounds: 560 424 8 8 + - image: solid-color(71, 53, 0, 255, 8, 8) + bounds: 568 424 8 8 + - image: solid-color(72, 53, 0, 255, 8, 8) + bounds: 576 424 8 8 + - image: solid-color(73, 53, 0, 255, 8, 8) + bounds: 584 424 8 8 + - image: solid-color(74, 53, 0, 255, 8, 8) + bounds: 592 424 8 8 + - image: solid-color(75, 53, 0, 255, 8, 8) + bounds: 600 424 8 8 + - image: solid-color(76, 53, 0, 255, 8, 8) + bounds: 608 424 8 8 + - image: solid-color(77, 53, 0, 255, 8, 8) + bounds: 616 424 8 8 + - image: solid-color(78, 53, 0, 255, 8, 8) + bounds: 624 424 8 8 + - image: solid-color(79, 53, 0, 255, 8, 8) + bounds: 632 424 8 8 + - image: solid-color(80, 53, 0, 255, 8, 8) + bounds: 640 424 8 8 + - image: solid-color(81, 53, 0, 255, 8, 8) + bounds: 648 424 8 8 + - image: solid-color(82, 53, 0, 255, 8, 8) + bounds: 656 424 8 8 + - image: solid-color(83, 53, 0, 255, 8, 8) + bounds: 664 424 8 8 + - image: solid-color(84, 53, 0, 255, 8, 8) + bounds: 672 424 8 8 + - image: solid-color(85, 53, 0, 255, 8, 8) + bounds: 680 424 8 8 + - image: solid-color(86, 53, 0, 255, 8, 8) + bounds: 688 424 8 8 + - image: solid-color(87, 53, 0, 255, 8, 8) + bounds: 696 424 8 8 + - image: solid-color(88, 53, 0, 255, 8, 8) + bounds: 704 424 8 8 + - image: solid-color(89, 53, 0, 255, 8, 8) + bounds: 712 424 8 8 + - image: solid-color(90, 53, 0, 255, 8, 8) + bounds: 720 424 8 8 + - image: solid-color(91, 53, 0, 255, 8, 8) + bounds: 728 424 8 8 + - image: solid-color(92, 53, 0, 255, 8, 8) + bounds: 736 424 8 8 + - image: solid-color(93, 53, 0, 255, 8, 8) + bounds: 744 424 8 8 + - image: solid-color(94, 53, 0, 255, 8, 8) + bounds: 752 424 8 8 + - image: solid-color(95, 53, 0, 255, 8, 8) + bounds: 760 424 8 8 + - image: solid-color(96, 53, 0, 255, 8, 8) + bounds: 768 424 8 8 + - image: solid-color(97, 53, 0, 255, 8, 8) + bounds: 776 424 8 8 + - image: solid-color(98, 53, 0, 255, 8, 8) + bounds: 784 424 8 8 + - image: solid-color(99, 53, 0, 255, 8, 8) + bounds: 792 424 8 8 + - image: solid-color(100, 53, 0, 255, 8, 8) + bounds: 800 424 8 8 + - image: solid-color(101, 53, 0, 255, 8, 8) + bounds: 808 424 8 8 + - image: solid-color(102, 53, 0, 255, 8, 8) + bounds: 816 424 8 8 + - image: solid-color(103, 53, 0, 255, 8, 8) + bounds: 824 424 8 8 + - image: solid-color(104, 53, 0, 255, 8, 8) + bounds: 832 424 8 8 + - image: solid-color(105, 53, 0, 255, 8, 8) + bounds: 840 424 8 8 + - image: solid-color(106, 53, 0, 255, 8, 8) + bounds: 848 424 8 8 + - image: solid-color(107, 53, 0, 255, 8, 8) + bounds: 856 424 8 8 + - image: solid-color(108, 53, 0, 255, 8, 8) + bounds: 864 424 8 8 + - image: solid-color(109, 53, 0, 255, 8, 8) + bounds: 872 424 8 8 + - image: solid-color(110, 53, 0, 255, 8, 8) + bounds: 880 424 8 8 + - image: solid-color(111, 53, 0, 255, 8, 8) + bounds: 888 424 8 8 + - image: solid-color(112, 53, 0, 255, 8, 8) + bounds: 896 424 8 8 + - image: solid-color(113, 53, 0, 255, 8, 8) + bounds: 904 424 8 8 + - image: solid-color(114, 53, 0, 255, 8, 8) + bounds: 912 424 8 8 + - image: solid-color(115, 53, 0, 255, 8, 8) + bounds: 920 424 8 8 + - image: solid-color(116, 53, 0, 255, 8, 8) + bounds: 928 424 8 8 + - image: solid-color(117, 53, 0, 255, 8, 8) + bounds: 936 424 8 8 + - image: solid-color(118, 53, 0, 255, 8, 8) + bounds: 944 424 8 8 + - image: solid-color(119, 53, 0, 255, 8, 8) + bounds: 952 424 8 8 + - image: solid-color(120, 53, 0, 255, 8, 8) + bounds: 960 424 8 8 + - image: solid-color(121, 53, 0, 255, 8, 8) + bounds: 968 424 8 8 + - image: solid-color(122, 53, 0, 255, 8, 8) + bounds: 976 424 8 8 + - image: solid-color(123, 53, 0, 255, 8, 8) + bounds: 984 424 8 8 + - image: solid-color(124, 53, 0, 255, 8, 8) + bounds: 992 424 8 8 + - image: solid-color(125, 53, 0, 255, 8, 8) + bounds: 1000 424 8 8 + - image: solid-color(126, 53, 0, 255, 8, 8) + bounds: 1008 424 8 8 + - image: solid-color(127, 53, 0, 255, 8, 8) + bounds: 1016 424 8 8 + - image: solid-color(0, 54, 0, 255, 8, 8) + bounds: 0 432 8 8 + - image: solid-color(1, 54, 0, 255, 8, 8) + bounds: 8 432 8 8 + - image: solid-color(2, 54, 0, 255, 8, 8) + bounds: 16 432 8 8 + - image: solid-color(3, 54, 0, 255, 8, 8) + bounds: 24 432 8 8 + - image: solid-color(4, 54, 0, 255, 8, 8) + bounds: 32 432 8 8 + - image: solid-color(5, 54, 0, 255, 8, 8) + bounds: 40 432 8 8 + - image: solid-color(6, 54, 0, 255, 8, 8) + bounds: 48 432 8 8 + - image: solid-color(7, 54, 0, 255, 8, 8) + bounds: 56 432 8 8 + - image: solid-color(8, 54, 0, 255, 8, 8) + bounds: 64 432 8 8 + - image: solid-color(9, 54, 0, 255, 8, 8) + bounds: 72 432 8 8 + - image: solid-color(10, 54, 0, 255, 8, 8) + bounds: 80 432 8 8 + - image: solid-color(11, 54, 0, 255, 8, 8) + bounds: 88 432 8 8 + - image: solid-color(12, 54, 0, 255, 8, 8) + bounds: 96 432 8 8 + - image: solid-color(13, 54, 0, 255, 8, 8) + bounds: 104 432 8 8 + - image: solid-color(14, 54, 0, 255, 8, 8) + bounds: 112 432 8 8 + - image: solid-color(15, 54, 0, 255, 8, 8) + bounds: 120 432 8 8 + - image: solid-color(16, 54, 0, 255, 8, 8) + bounds: 128 432 8 8 + - image: solid-color(17, 54, 0, 255, 8, 8) + bounds: 136 432 8 8 + - image: solid-color(18, 54, 0, 255, 8, 8) + bounds: 144 432 8 8 + - image: solid-color(19, 54, 0, 255, 8, 8) + bounds: 152 432 8 8 + - image: solid-color(20, 54, 0, 255, 8, 8) + bounds: 160 432 8 8 + - image: solid-color(21, 54, 0, 255, 8, 8) + bounds: 168 432 8 8 + - image: solid-color(22, 54, 0, 255, 8, 8) + bounds: 176 432 8 8 + - image: solid-color(23, 54, 0, 255, 8, 8) + bounds: 184 432 8 8 + - image: solid-color(24, 54, 0, 255, 8, 8) + bounds: 192 432 8 8 + - image: solid-color(25, 54, 0, 255, 8, 8) + bounds: 200 432 8 8 + - image: solid-color(26, 54, 0, 255, 8, 8) + bounds: 208 432 8 8 + - image: solid-color(27, 54, 0, 255, 8, 8) + bounds: 216 432 8 8 + - image: solid-color(28, 54, 0, 255, 8, 8) + bounds: 224 432 8 8 + - image: solid-color(29, 54, 0, 255, 8, 8) + bounds: 232 432 8 8 + - image: solid-color(30, 54, 0, 255, 8, 8) + bounds: 240 432 8 8 + - image: solid-color(31, 54, 0, 255, 8, 8) + bounds: 248 432 8 8 + - image: solid-color(32, 54, 0, 255, 8, 8) + bounds: 256 432 8 8 + - image: solid-color(33, 54, 0, 255, 8, 8) + bounds: 264 432 8 8 + - image: solid-color(34, 54, 0, 255, 8, 8) + bounds: 272 432 8 8 + - image: solid-color(35, 54, 0, 255, 8, 8) + bounds: 280 432 8 8 + - image: solid-color(36, 54, 0, 255, 8, 8) + bounds: 288 432 8 8 + - image: solid-color(37, 54, 0, 255, 8, 8) + bounds: 296 432 8 8 + - image: solid-color(38, 54, 0, 255, 8, 8) + bounds: 304 432 8 8 + - image: solid-color(39, 54, 0, 255, 8, 8) + bounds: 312 432 8 8 + - image: solid-color(40, 54, 0, 255, 8, 8) + bounds: 320 432 8 8 + - image: solid-color(41, 54, 0, 255, 8, 8) + bounds: 328 432 8 8 + - image: solid-color(42, 54, 0, 255, 8, 8) + bounds: 336 432 8 8 + - image: solid-color(43, 54, 0, 255, 8, 8) + bounds: 344 432 8 8 + - image: solid-color(44, 54, 0, 255, 8, 8) + bounds: 352 432 8 8 + - image: solid-color(45, 54, 0, 255, 8, 8) + bounds: 360 432 8 8 + - image: solid-color(46, 54, 0, 255, 8, 8) + bounds: 368 432 8 8 + - image: solid-color(47, 54, 0, 255, 8, 8) + bounds: 376 432 8 8 + - image: solid-color(48, 54, 0, 255, 8, 8) + bounds: 384 432 8 8 + - image: solid-color(49, 54, 0, 255, 8, 8) + bounds: 392 432 8 8 + - image: solid-color(50, 54, 0, 255, 8, 8) + bounds: 400 432 8 8 + - image: solid-color(51, 54, 0, 255, 8, 8) + bounds: 408 432 8 8 + - image: solid-color(52, 54, 0, 255, 8, 8) + bounds: 416 432 8 8 + - image: solid-color(53, 54, 0, 255, 8, 8) + bounds: 424 432 8 8 + - image: solid-color(54, 54, 0, 255, 8, 8) + bounds: 432 432 8 8 + - image: solid-color(55, 54, 0, 255, 8, 8) + bounds: 440 432 8 8 + - image: solid-color(56, 54, 0, 255, 8, 8) + bounds: 448 432 8 8 + - image: solid-color(57, 54, 0, 255, 8, 8) + bounds: 456 432 8 8 + - image: solid-color(58, 54, 0, 255, 8, 8) + bounds: 464 432 8 8 + - image: solid-color(59, 54, 0, 255, 8, 8) + bounds: 472 432 8 8 + - image: solid-color(60, 54, 0, 255, 8, 8) + bounds: 480 432 8 8 + - image: solid-color(61, 54, 0, 255, 8, 8) + bounds: 488 432 8 8 + - image: solid-color(62, 54, 0, 255, 8, 8) + bounds: 496 432 8 8 + - image: solid-color(63, 54, 0, 255, 8, 8) + bounds: 504 432 8 8 + - image: solid-color(64, 54, 0, 255, 8, 8) + bounds: 512 432 8 8 + - image: solid-color(65, 54, 0, 255, 8, 8) + bounds: 520 432 8 8 + - image: solid-color(66, 54, 0, 255, 8, 8) + bounds: 528 432 8 8 + - image: solid-color(67, 54, 0, 255, 8, 8) + bounds: 536 432 8 8 + - image: solid-color(68, 54, 0, 255, 8, 8) + bounds: 544 432 8 8 + - image: solid-color(69, 54, 0, 255, 8, 8) + bounds: 552 432 8 8 + - image: solid-color(70, 54, 0, 255, 8, 8) + bounds: 560 432 8 8 + - image: solid-color(71, 54, 0, 255, 8, 8) + bounds: 568 432 8 8 + - image: solid-color(72, 54, 0, 255, 8, 8) + bounds: 576 432 8 8 + - image: solid-color(73, 54, 0, 255, 8, 8) + bounds: 584 432 8 8 + - image: solid-color(74, 54, 0, 255, 8, 8) + bounds: 592 432 8 8 + - image: solid-color(75, 54, 0, 255, 8, 8) + bounds: 600 432 8 8 + - image: solid-color(76, 54, 0, 255, 8, 8) + bounds: 608 432 8 8 + - image: solid-color(77, 54, 0, 255, 8, 8) + bounds: 616 432 8 8 + - image: solid-color(78, 54, 0, 255, 8, 8) + bounds: 624 432 8 8 + - image: solid-color(79, 54, 0, 255, 8, 8) + bounds: 632 432 8 8 + - image: solid-color(80, 54, 0, 255, 8, 8) + bounds: 640 432 8 8 + - image: solid-color(81, 54, 0, 255, 8, 8) + bounds: 648 432 8 8 + - image: solid-color(82, 54, 0, 255, 8, 8) + bounds: 656 432 8 8 + - image: solid-color(83, 54, 0, 255, 8, 8) + bounds: 664 432 8 8 + - image: solid-color(84, 54, 0, 255, 8, 8) + bounds: 672 432 8 8 + - image: solid-color(85, 54, 0, 255, 8, 8) + bounds: 680 432 8 8 + - image: solid-color(86, 54, 0, 255, 8, 8) + bounds: 688 432 8 8 + - image: solid-color(87, 54, 0, 255, 8, 8) + bounds: 696 432 8 8 + - image: solid-color(88, 54, 0, 255, 8, 8) + bounds: 704 432 8 8 + - image: solid-color(89, 54, 0, 255, 8, 8) + bounds: 712 432 8 8 + - image: solid-color(90, 54, 0, 255, 8, 8) + bounds: 720 432 8 8 + - image: solid-color(91, 54, 0, 255, 8, 8) + bounds: 728 432 8 8 + - image: solid-color(92, 54, 0, 255, 8, 8) + bounds: 736 432 8 8 + - image: solid-color(93, 54, 0, 255, 8, 8) + bounds: 744 432 8 8 + - image: solid-color(94, 54, 0, 255, 8, 8) + bounds: 752 432 8 8 + - image: solid-color(95, 54, 0, 255, 8, 8) + bounds: 760 432 8 8 + - image: solid-color(96, 54, 0, 255, 8, 8) + bounds: 768 432 8 8 + - image: solid-color(97, 54, 0, 255, 8, 8) + bounds: 776 432 8 8 + - image: solid-color(98, 54, 0, 255, 8, 8) + bounds: 784 432 8 8 + - image: solid-color(99, 54, 0, 255, 8, 8) + bounds: 792 432 8 8 + - image: solid-color(100, 54, 0, 255, 8, 8) + bounds: 800 432 8 8 + - image: solid-color(101, 54, 0, 255, 8, 8) + bounds: 808 432 8 8 + - image: solid-color(102, 54, 0, 255, 8, 8) + bounds: 816 432 8 8 + - image: solid-color(103, 54, 0, 255, 8, 8) + bounds: 824 432 8 8 + - image: solid-color(104, 54, 0, 255, 8, 8) + bounds: 832 432 8 8 + - image: solid-color(105, 54, 0, 255, 8, 8) + bounds: 840 432 8 8 + - image: solid-color(106, 54, 0, 255, 8, 8) + bounds: 848 432 8 8 + - image: solid-color(107, 54, 0, 255, 8, 8) + bounds: 856 432 8 8 + - image: solid-color(108, 54, 0, 255, 8, 8) + bounds: 864 432 8 8 + - image: solid-color(109, 54, 0, 255, 8, 8) + bounds: 872 432 8 8 + - image: solid-color(110, 54, 0, 255, 8, 8) + bounds: 880 432 8 8 + - image: solid-color(111, 54, 0, 255, 8, 8) + bounds: 888 432 8 8 + - image: solid-color(112, 54, 0, 255, 8, 8) + bounds: 896 432 8 8 + - image: solid-color(113, 54, 0, 255, 8, 8) + bounds: 904 432 8 8 + - image: solid-color(114, 54, 0, 255, 8, 8) + bounds: 912 432 8 8 + - image: solid-color(115, 54, 0, 255, 8, 8) + bounds: 920 432 8 8 + - image: solid-color(116, 54, 0, 255, 8, 8) + bounds: 928 432 8 8 + - image: solid-color(117, 54, 0, 255, 8, 8) + bounds: 936 432 8 8 + - image: solid-color(118, 54, 0, 255, 8, 8) + bounds: 944 432 8 8 + - image: solid-color(119, 54, 0, 255, 8, 8) + bounds: 952 432 8 8 + - image: solid-color(120, 54, 0, 255, 8, 8) + bounds: 960 432 8 8 + - image: solid-color(121, 54, 0, 255, 8, 8) + bounds: 968 432 8 8 + - image: solid-color(122, 54, 0, 255, 8, 8) + bounds: 976 432 8 8 + - image: solid-color(123, 54, 0, 255, 8, 8) + bounds: 984 432 8 8 + - image: solid-color(124, 54, 0, 255, 8, 8) + bounds: 992 432 8 8 + - image: solid-color(125, 54, 0, 255, 8, 8) + bounds: 1000 432 8 8 + - image: solid-color(126, 54, 0, 255, 8, 8) + bounds: 1008 432 8 8 + - image: solid-color(127, 54, 0, 255, 8, 8) + bounds: 1016 432 8 8 + - image: solid-color(0, 55, 0, 255, 8, 8) + bounds: 0 440 8 8 + - image: solid-color(1, 55, 0, 255, 8, 8) + bounds: 8 440 8 8 + - image: solid-color(2, 55, 0, 255, 8, 8) + bounds: 16 440 8 8 + - image: solid-color(3, 55, 0, 255, 8, 8) + bounds: 24 440 8 8 + - image: solid-color(4, 55, 0, 255, 8, 8) + bounds: 32 440 8 8 + - image: solid-color(5, 55, 0, 255, 8, 8) + bounds: 40 440 8 8 + - image: solid-color(6, 55, 0, 255, 8, 8) + bounds: 48 440 8 8 + - image: solid-color(7, 55, 0, 255, 8, 8) + bounds: 56 440 8 8 + - image: solid-color(8, 55, 0, 255, 8, 8) + bounds: 64 440 8 8 + - image: solid-color(9, 55, 0, 255, 8, 8) + bounds: 72 440 8 8 + - image: solid-color(10, 55, 0, 255, 8, 8) + bounds: 80 440 8 8 + - image: solid-color(11, 55, 0, 255, 8, 8) + bounds: 88 440 8 8 + - image: solid-color(12, 55, 0, 255, 8, 8) + bounds: 96 440 8 8 + - image: solid-color(13, 55, 0, 255, 8, 8) + bounds: 104 440 8 8 + - image: solid-color(14, 55, 0, 255, 8, 8) + bounds: 112 440 8 8 + - image: solid-color(15, 55, 0, 255, 8, 8) + bounds: 120 440 8 8 + - image: solid-color(16, 55, 0, 255, 8, 8) + bounds: 128 440 8 8 + - image: solid-color(17, 55, 0, 255, 8, 8) + bounds: 136 440 8 8 + - image: solid-color(18, 55, 0, 255, 8, 8) + bounds: 144 440 8 8 + - image: solid-color(19, 55, 0, 255, 8, 8) + bounds: 152 440 8 8 + - image: solid-color(20, 55, 0, 255, 8, 8) + bounds: 160 440 8 8 + - image: solid-color(21, 55, 0, 255, 8, 8) + bounds: 168 440 8 8 + - image: solid-color(22, 55, 0, 255, 8, 8) + bounds: 176 440 8 8 + - image: solid-color(23, 55, 0, 255, 8, 8) + bounds: 184 440 8 8 + - image: solid-color(24, 55, 0, 255, 8, 8) + bounds: 192 440 8 8 + - image: solid-color(25, 55, 0, 255, 8, 8) + bounds: 200 440 8 8 + - image: solid-color(26, 55, 0, 255, 8, 8) + bounds: 208 440 8 8 + - image: solid-color(27, 55, 0, 255, 8, 8) + bounds: 216 440 8 8 + - image: solid-color(28, 55, 0, 255, 8, 8) + bounds: 224 440 8 8 + - image: solid-color(29, 55, 0, 255, 8, 8) + bounds: 232 440 8 8 + - image: solid-color(30, 55, 0, 255, 8, 8) + bounds: 240 440 8 8 + - image: solid-color(31, 55, 0, 255, 8, 8) + bounds: 248 440 8 8 + - image: solid-color(32, 55, 0, 255, 8, 8) + bounds: 256 440 8 8 + - image: solid-color(33, 55, 0, 255, 8, 8) + bounds: 264 440 8 8 + - image: solid-color(34, 55, 0, 255, 8, 8) + bounds: 272 440 8 8 + - image: solid-color(35, 55, 0, 255, 8, 8) + bounds: 280 440 8 8 + - image: solid-color(36, 55, 0, 255, 8, 8) + bounds: 288 440 8 8 + - image: solid-color(37, 55, 0, 255, 8, 8) + bounds: 296 440 8 8 + - image: solid-color(38, 55, 0, 255, 8, 8) + bounds: 304 440 8 8 + - image: solid-color(39, 55, 0, 255, 8, 8) + bounds: 312 440 8 8 + - image: solid-color(40, 55, 0, 255, 8, 8) + bounds: 320 440 8 8 + - image: solid-color(41, 55, 0, 255, 8, 8) + bounds: 328 440 8 8 + - image: solid-color(42, 55, 0, 255, 8, 8) + bounds: 336 440 8 8 + - image: solid-color(43, 55, 0, 255, 8, 8) + bounds: 344 440 8 8 + - image: solid-color(44, 55, 0, 255, 8, 8) + bounds: 352 440 8 8 + - image: solid-color(45, 55, 0, 255, 8, 8) + bounds: 360 440 8 8 + - image: solid-color(46, 55, 0, 255, 8, 8) + bounds: 368 440 8 8 + - image: solid-color(47, 55, 0, 255, 8, 8) + bounds: 376 440 8 8 + - image: solid-color(48, 55, 0, 255, 8, 8) + bounds: 384 440 8 8 + - image: solid-color(49, 55, 0, 255, 8, 8) + bounds: 392 440 8 8 + - image: solid-color(50, 55, 0, 255, 8, 8) + bounds: 400 440 8 8 + - image: solid-color(51, 55, 0, 255, 8, 8) + bounds: 408 440 8 8 + - image: solid-color(52, 55, 0, 255, 8, 8) + bounds: 416 440 8 8 + - image: solid-color(53, 55, 0, 255, 8, 8) + bounds: 424 440 8 8 + - image: solid-color(54, 55, 0, 255, 8, 8) + bounds: 432 440 8 8 + - image: solid-color(55, 55, 0, 255, 8, 8) + bounds: 440 440 8 8 + - image: solid-color(56, 55, 0, 255, 8, 8) + bounds: 448 440 8 8 + - image: solid-color(57, 55, 0, 255, 8, 8) + bounds: 456 440 8 8 + - image: solid-color(58, 55, 0, 255, 8, 8) + bounds: 464 440 8 8 + - image: solid-color(59, 55, 0, 255, 8, 8) + bounds: 472 440 8 8 + - image: solid-color(60, 55, 0, 255, 8, 8) + bounds: 480 440 8 8 + - image: solid-color(61, 55, 0, 255, 8, 8) + bounds: 488 440 8 8 + - image: solid-color(62, 55, 0, 255, 8, 8) + bounds: 496 440 8 8 + - image: solid-color(63, 55, 0, 255, 8, 8) + bounds: 504 440 8 8 + - image: solid-color(64, 55, 0, 255, 8, 8) + bounds: 512 440 8 8 + - image: solid-color(65, 55, 0, 255, 8, 8) + bounds: 520 440 8 8 + - image: solid-color(66, 55, 0, 255, 8, 8) + bounds: 528 440 8 8 + - image: solid-color(67, 55, 0, 255, 8, 8) + bounds: 536 440 8 8 + - image: solid-color(68, 55, 0, 255, 8, 8) + bounds: 544 440 8 8 + - image: solid-color(69, 55, 0, 255, 8, 8) + bounds: 552 440 8 8 + - image: solid-color(70, 55, 0, 255, 8, 8) + bounds: 560 440 8 8 + - image: solid-color(71, 55, 0, 255, 8, 8) + bounds: 568 440 8 8 + - image: solid-color(72, 55, 0, 255, 8, 8) + bounds: 576 440 8 8 + - image: solid-color(73, 55, 0, 255, 8, 8) + bounds: 584 440 8 8 + - image: solid-color(74, 55, 0, 255, 8, 8) + bounds: 592 440 8 8 + - image: solid-color(75, 55, 0, 255, 8, 8) + bounds: 600 440 8 8 + - image: solid-color(76, 55, 0, 255, 8, 8) + bounds: 608 440 8 8 + - image: solid-color(77, 55, 0, 255, 8, 8) + bounds: 616 440 8 8 + - image: solid-color(78, 55, 0, 255, 8, 8) + bounds: 624 440 8 8 + - image: solid-color(79, 55, 0, 255, 8, 8) + bounds: 632 440 8 8 + - image: solid-color(80, 55, 0, 255, 8, 8) + bounds: 640 440 8 8 + - image: solid-color(81, 55, 0, 255, 8, 8) + bounds: 648 440 8 8 + - image: solid-color(82, 55, 0, 255, 8, 8) + bounds: 656 440 8 8 + - image: solid-color(83, 55, 0, 255, 8, 8) + bounds: 664 440 8 8 + - image: solid-color(84, 55, 0, 255, 8, 8) + bounds: 672 440 8 8 + - image: solid-color(85, 55, 0, 255, 8, 8) + bounds: 680 440 8 8 + - image: solid-color(86, 55, 0, 255, 8, 8) + bounds: 688 440 8 8 + - image: solid-color(87, 55, 0, 255, 8, 8) + bounds: 696 440 8 8 + - image: solid-color(88, 55, 0, 255, 8, 8) + bounds: 704 440 8 8 + - image: solid-color(89, 55, 0, 255, 8, 8) + bounds: 712 440 8 8 + - image: solid-color(90, 55, 0, 255, 8, 8) + bounds: 720 440 8 8 + - image: solid-color(91, 55, 0, 255, 8, 8) + bounds: 728 440 8 8 + - image: solid-color(92, 55, 0, 255, 8, 8) + bounds: 736 440 8 8 + - image: solid-color(93, 55, 0, 255, 8, 8) + bounds: 744 440 8 8 + - image: solid-color(94, 55, 0, 255, 8, 8) + bounds: 752 440 8 8 + - image: solid-color(95, 55, 0, 255, 8, 8) + bounds: 760 440 8 8 + - image: solid-color(96, 55, 0, 255, 8, 8) + bounds: 768 440 8 8 + - image: solid-color(97, 55, 0, 255, 8, 8) + bounds: 776 440 8 8 + - image: solid-color(98, 55, 0, 255, 8, 8) + bounds: 784 440 8 8 + - image: solid-color(99, 55, 0, 255, 8, 8) + bounds: 792 440 8 8 + - image: solid-color(100, 55, 0, 255, 8, 8) + bounds: 800 440 8 8 + - image: solid-color(101, 55, 0, 255, 8, 8) + bounds: 808 440 8 8 + - image: solid-color(102, 55, 0, 255, 8, 8) + bounds: 816 440 8 8 + - image: solid-color(103, 55, 0, 255, 8, 8) + bounds: 824 440 8 8 + - image: solid-color(104, 55, 0, 255, 8, 8) + bounds: 832 440 8 8 + - image: solid-color(105, 55, 0, 255, 8, 8) + bounds: 840 440 8 8 + - image: solid-color(106, 55, 0, 255, 8, 8) + bounds: 848 440 8 8 + - image: solid-color(107, 55, 0, 255, 8, 8) + bounds: 856 440 8 8 + - image: solid-color(108, 55, 0, 255, 8, 8) + bounds: 864 440 8 8 + - image: solid-color(109, 55, 0, 255, 8, 8) + bounds: 872 440 8 8 + - image: solid-color(110, 55, 0, 255, 8, 8) + bounds: 880 440 8 8 + - image: solid-color(111, 55, 0, 255, 8, 8) + bounds: 888 440 8 8 + - image: solid-color(112, 55, 0, 255, 8, 8) + bounds: 896 440 8 8 + - image: solid-color(113, 55, 0, 255, 8, 8) + bounds: 904 440 8 8 + - image: solid-color(114, 55, 0, 255, 8, 8) + bounds: 912 440 8 8 + - image: solid-color(115, 55, 0, 255, 8, 8) + bounds: 920 440 8 8 + - image: solid-color(116, 55, 0, 255, 8, 8) + bounds: 928 440 8 8 + - image: solid-color(117, 55, 0, 255, 8, 8) + bounds: 936 440 8 8 + - image: solid-color(118, 55, 0, 255, 8, 8) + bounds: 944 440 8 8 + - image: solid-color(119, 55, 0, 255, 8, 8) + bounds: 952 440 8 8 + - image: solid-color(120, 55, 0, 255, 8, 8) + bounds: 960 440 8 8 + - image: solid-color(121, 55, 0, 255, 8, 8) + bounds: 968 440 8 8 + - image: solid-color(122, 55, 0, 255, 8, 8) + bounds: 976 440 8 8 + - image: solid-color(123, 55, 0, 255, 8, 8) + bounds: 984 440 8 8 + - image: solid-color(124, 55, 0, 255, 8, 8) + bounds: 992 440 8 8 + - image: solid-color(125, 55, 0, 255, 8, 8) + bounds: 1000 440 8 8 + - image: solid-color(126, 55, 0, 255, 8, 8) + bounds: 1008 440 8 8 + - image: solid-color(127, 55, 0, 255, 8, 8) + bounds: 1016 440 8 8 + - image: solid-color(0, 56, 0, 255, 8, 8) + bounds: 0 448 8 8 + - image: solid-color(1, 56, 0, 255, 8, 8) + bounds: 8 448 8 8 + - image: solid-color(2, 56, 0, 255, 8, 8) + bounds: 16 448 8 8 + - image: solid-color(3, 56, 0, 255, 8, 8) + bounds: 24 448 8 8 + - image: solid-color(4, 56, 0, 255, 8, 8) + bounds: 32 448 8 8 + - image: solid-color(5, 56, 0, 255, 8, 8) + bounds: 40 448 8 8 + - image: solid-color(6, 56, 0, 255, 8, 8) + bounds: 48 448 8 8 + - image: solid-color(7, 56, 0, 255, 8, 8) + bounds: 56 448 8 8 + - image: solid-color(8, 56, 0, 255, 8, 8) + bounds: 64 448 8 8 + - image: solid-color(9, 56, 0, 255, 8, 8) + bounds: 72 448 8 8 + - image: solid-color(10, 56, 0, 255, 8, 8) + bounds: 80 448 8 8 + - image: solid-color(11, 56, 0, 255, 8, 8) + bounds: 88 448 8 8 + - image: solid-color(12, 56, 0, 255, 8, 8) + bounds: 96 448 8 8 + - image: solid-color(13, 56, 0, 255, 8, 8) + bounds: 104 448 8 8 + - image: solid-color(14, 56, 0, 255, 8, 8) + bounds: 112 448 8 8 + - image: solid-color(15, 56, 0, 255, 8, 8) + bounds: 120 448 8 8 + - image: solid-color(16, 56, 0, 255, 8, 8) + bounds: 128 448 8 8 + - image: solid-color(17, 56, 0, 255, 8, 8) + bounds: 136 448 8 8 + - image: solid-color(18, 56, 0, 255, 8, 8) + bounds: 144 448 8 8 + - image: solid-color(19, 56, 0, 255, 8, 8) + bounds: 152 448 8 8 + - image: solid-color(20, 56, 0, 255, 8, 8) + bounds: 160 448 8 8 + - image: solid-color(21, 56, 0, 255, 8, 8) + bounds: 168 448 8 8 + - image: solid-color(22, 56, 0, 255, 8, 8) + bounds: 176 448 8 8 + - image: solid-color(23, 56, 0, 255, 8, 8) + bounds: 184 448 8 8 + - image: solid-color(24, 56, 0, 255, 8, 8) + bounds: 192 448 8 8 + - image: solid-color(25, 56, 0, 255, 8, 8) + bounds: 200 448 8 8 + - image: solid-color(26, 56, 0, 255, 8, 8) + bounds: 208 448 8 8 + - image: solid-color(27, 56, 0, 255, 8, 8) + bounds: 216 448 8 8 + - image: solid-color(28, 56, 0, 255, 8, 8) + bounds: 224 448 8 8 + - image: solid-color(29, 56, 0, 255, 8, 8) + bounds: 232 448 8 8 + - image: solid-color(30, 56, 0, 255, 8, 8) + bounds: 240 448 8 8 + - image: solid-color(31, 56, 0, 255, 8, 8) + bounds: 248 448 8 8 + - image: solid-color(32, 56, 0, 255, 8, 8) + bounds: 256 448 8 8 + - image: solid-color(33, 56, 0, 255, 8, 8) + bounds: 264 448 8 8 + - image: solid-color(34, 56, 0, 255, 8, 8) + bounds: 272 448 8 8 + - image: solid-color(35, 56, 0, 255, 8, 8) + bounds: 280 448 8 8 + - image: solid-color(36, 56, 0, 255, 8, 8) + bounds: 288 448 8 8 + - image: solid-color(37, 56, 0, 255, 8, 8) + bounds: 296 448 8 8 + - image: solid-color(38, 56, 0, 255, 8, 8) + bounds: 304 448 8 8 + - image: solid-color(39, 56, 0, 255, 8, 8) + bounds: 312 448 8 8 + - image: solid-color(40, 56, 0, 255, 8, 8) + bounds: 320 448 8 8 + - image: solid-color(41, 56, 0, 255, 8, 8) + bounds: 328 448 8 8 + - image: solid-color(42, 56, 0, 255, 8, 8) + bounds: 336 448 8 8 + - image: solid-color(43, 56, 0, 255, 8, 8) + bounds: 344 448 8 8 + - image: solid-color(44, 56, 0, 255, 8, 8) + bounds: 352 448 8 8 + - image: solid-color(45, 56, 0, 255, 8, 8) + bounds: 360 448 8 8 + - image: solid-color(46, 56, 0, 255, 8, 8) + bounds: 368 448 8 8 + - image: solid-color(47, 56, 0, 255, 8, 8) + bounds: 376 448 8 8 + - image: solid-color(48, 56, 0, 255, 8, 8) + bounds: 384 448 8 8 + - image: solid-color(49, 56, 0, 255, 8, 8) + bounds: 392 448 8 8 + - image: solid-color(50, 56, 0, 255, 8, 8) + bounds: 400 448 8 8 + - image: solid-color(51, 56, 0, 255, 8, 8) + bounds: 408 448 8 8 + - image: solid-color(52, 56, 0, 255, 8, 8) + bounds: 416 448 8 8 + - image: solid-color(53, 56, 0, 255, 8, 8) + bounds: 424 448 8 8 + - image: solid-color(54, 56, 0, 255, 8, 8) + bounds: 432 448 8 8 + - image: solid-color(55, 56, 0, 255, 8, 8) + bounds: 440 448 8 8 + - image: solid-color(56, 56, 0, 255, 8, 8) + bounds: 448 448 8 8 + - image: solid-color(57, 56, 0, 255, 8, 8) + bounds: 456 448 8 8 + - image: solid-color(58, 56, 0, 255, 8, 8) + bounds: 464 448 8 8 + - image: solid-color(59, 56, 0, 255, 8, 8) + bounds: 472 448 8 8 + - image: solid-color(60, 56, 0, 255, 8, 8) + bounds: 480 448 8 8 + - image: solid-color(61, 56, 0, 255, 8, 8) + bounds: 488 448 8 8 + - image: solid-color(62, 56, 0, 255, 8, 8) + bounds: 496 448 8 8 + - image: solid-color(63, 56, 0, 255, 8, 8) + bounds: 504 448 8 8 + - image: solid-color(64, 56, 0, 255, 8, 8) + bounds: 512 448 8 8 + - image: solid-color(65, 56, 0, 255, 8, 8) + bounds: 520 448 8 8 + - image: solid-color(66, 56, 0, 255, 8, 8) + bounds: 528 448 8 8 + - image: solid-color(67, 56, 0, 255, 8, 8) + bounds: 536 448 8 8 + - image: solid-color(68, 56, 0, 255, 8, 8) + bounds: 544 448 8 8 + - image: solid-color(69, 56, 0, 255, 8, 8) + bounds: 552 448 8 8 + - image: solid-color(70, 56, 0, 255, 8, 8) + bounds: 560 448 8 8 + - image: solid-color(71, 56, 0, 255, 8, 8) + bounds: 568 448 8 8 + - image: solid-color(72, 56, 0, 255, 8, 8) + bounds: 576 448 8 8 + - image: solid-color(73, 56, 0, 255, 8, 8) + bounds: 584 448 8 8 + - image: solid-color(74, 56, 0, 255, 8, 8) + bounds: 592 448 8 8 + - image: solid-color(75, 56, 0, 255, 8, 8) + bounds: 600 448 8 8 + - image: solid-color(76, 56, 0, 255, 8, 8) + bounds: 608 448 8 8 + - image: solid-color(77, 56, 0, 255, 8, 8) + bounds: 616 448 8 8 + - image: solid-color(78, 56, 0, 255, 8, 8) + bounds: 624 448 8 8 + - image: solid-color(79, 56, 0, 255, 8, 8) + bounds: 632 448 8 8 + - image: solid-color(80, 56, 0, 255, 8, 8) + bounds: 640 448 8 8 + - image: solid-color(81, 56, 0, 255, 8, 8) + bounds: 648 448 8 8 + - image: solid-color(82, 56, 0, 255, 8, 8) + bounds: 656 448 8 8 + - image: solid-color(83, 56, 0, 255, 8, 8) + bounds: 664 448 8 8 + - image: solid-color(84, 56, 0, 255, 8, 8) + bounds: 672 448 8 8 + - image: solid-color(85, 56, 0, 255, 8, 8) + bounds: 680 448 8 8 + - image: solid-color(86, 56, 0, 255, 8, 8) + bounds: 688 448 8 8 + - image: solid-color(87, 56, 0, 255, 8, 8) + bounds: 696 448 8 8 + - image: solid-color(88, 56, 0, 255, 8, 8) + bounds: 704 448 8 8 + - image: solid-color(89, 56, 0, 255, 8, 8) + bounds: 712 448 8 8 + - image: solid-color(90, 56, 0, 255, 8, 8) + bounds: 720 448 8 8 + - image: solid-color(91, 56, 0, 255, 8, 8) + bounds: 728 448 8 8 + - image: solid-color(92, 56, 0, 255, 8, 8) + bounds: 736 448 8 8 + - image: solid-color(93, 56, 0, 255, 8, 8) + bounds: 744 448 8 8 + - image: solid-color(94, 56, 0, 255, 8, 8) + bounds: 752 448 8 8 + - image: solid-color(95, 56, 0, 255, 8, 8) + bounds: 760 448 8 8 + - image: solid-color(96, 56, 0, 255, 8, 8) + bounds: 768 448 8 8 + - image: solid-color(97, 56, 0, 255, 8, 8) + bounds: 776 448 8 8 + - image: solid-color(98, 56, 0, 255, 8, 8) + bounds: 784 448 8 8 + - image: solid-color(99, 56, 0, 255, 8, 8) + bounds: 792 448 8 8 + - image: solid-color(100, 56, 0, 255, 8, 8) + bounds: 800 448 8 8 + - image: solid-color(101, 56, 0, 255, 8, 8) + bounds: 808 448 8 8 + - image: solid-color(102, 56, 0, 255, 8, 8) + bounds: 816 448 8 8 + - image: solid-color(103, 56, 0, 255, 8, 8) + bounds: 824 448 8 8 + - image: solid-color(104, 56, 0, 255, 8, 8) + bounds: 832 448 8 8 + - image: solid-color(105, 56, 0, 255, 8, 8) + bounds: 840 448 8 8 + - image: solid-color(106, 56, 0, 255, 8, 8) + bounds: 848 448 8 8 + - image: solid-color(107, 56, 0, 255, 8, 8) + bounds: 856 448 8 8 + - image: solid-color(108, 56, 0, 255, 8, 8) + bounds: 864 448 8 8 + - image: solid-color(109, 56, 0, 255, 8, 8) + bounds: 872 448 8 8 + - image: solid-color(110, 56, 0, 255, 8, 8) + bounds: 880 448 8 8 + - image: solid-color(111, 56, 0, 255, 8, 8) + bounds: 888 448 8 8 + - image: solid-color(112, 56, 0, 255, 8, 8) + bounds: 896 448 8 8 + - image: solid-color(113, 56, 0, 255, 8, 8) + bounds: 904 448 8 8 + - image: solid-color(114, 56, 0, 255, 8, 8) + bounds: 912 448 8 8 + - image: solid-color(115, 56, 0, 255, 8, 8) + bounds: 920 448 8 8 + - image: solid-color(116, 56, 0, 255, 8, 8) + bounds: 928 448 8 8 + - image: solid-color(117, 56, 0, 255, 8, 8) + bounds: 936 448 8 8 + - image: solid-color(118, 56, 0, 255, 8, 8) + bounds: 944 448 8 8 + - image: solid-color(119, 56, 0, 255, 8, 8) + bounds: 952 448 8 8 + - image: solid-color(120, 56, 0, 255, 8, 8) + bounds: 960 448 8 8 + - image: solid-color(121, 56, 0, 255, 8, 8) + bounds: 968 448 8 8 + - image: solid-color(122, 56, 0, 255, 8, 8) + bounds: 976 448 8 8 + - image: solid-color(123, 56, 0, 255, 8, 8) + bounds: 984 448 8 8 + - image: solid-color(124, 56, 0, 255, 8, 8) + bounds: 992 448 8 8 + - image: solid-color(125, 56, 0, 255, 8, 8) + bounds: 1000 448 8 8 + - image: solid-color(126, 56, 0, 255, 8, 8) + bounds: 1008 448 8 8 + - image: solid-color(127, 56, 0, 255, 8, 8) + bounds: 1016 448 8 8 + - image: solid-color(0, 57, 0, 255, 8, 8) + bounds: 0 456 8 8 + - image: solid-color(1, 57, 0, 255, 8, 8) + bounds: 8 456 8 8 + - image: solid-color(2, 57, 0, 255, 8, 8) + bounds: 16 456 8 8 + - image: solid-color(3, 57, 0, 255, 8, 8) + bounds: 24 456 8 8 + - image: solid-color(4, 57, 0, 255, 8, 8) + bounds: 32 456 8 8 + - image: solid-color(5, 57, 0, 255, 8, 8) + bounds: 40 456 8 8 + - image: solid-color(6, 57, 0, 255, 8, 8) + bounds: 48 456 8 8 + - image: solid-color(7, 57, 0, 255, 8, 8) + bounds: 56 456 8 8 + - image: solid-color(8, 57, 0, 255, 8, 8) + bounds: 64 456 8 8 + - image: solid-color(9, 57, 0, 255, 8, 8) + bounds: 72 456 8 8 + - image: solid-color(10, 57, 0, 255, 8, 8) + bounds: 80 456 8 8 + - image: solid-color(11, 57, 0, 255, 8, 8) + bounds: 88 456 8 8 + - image: solid-color(12, 57, 0, 255, 8, 8) + bounds: 96 456 8 8 + - image: solid-color(13, 57, 0, 255, 8, 8) + bounds: 104 456 8 8 + - image: solid-color(14, 57, 0, 255, 8, 8) + bounds: 112 456 8 8 + - image: solid-color(15, 57, 0, 255, 8, 8) + bounds: 120 456 8 8 + - image: solid-color(16, 57, 0, 255, 8, 8) + bounds: 128 456 8 8 + - image: solid-color(17, 57, 0, 255, 8, 8) + bounds: 136 456 8 8 + - image: solid-color(18, 57, 0, 255, 8, 8) + bounds: 144 456 8 8 + - image: solid-color(19, 57, 0, 255, 8, 8) + bounds: 152 456 8 8 + - image: solid-color(20, 57, 0, 255, 8, 8) + bounds: 160 456 8 8 + - image: solid-color(21, 57, 0, 255, 8, 8) + bounds: 168 456 8 8 + - image: solid-color(22, 57, 0, 255, 8, 8) + bounds: 176 456 8 8 + - image: solid-color(23, 57, 0, 255, 8, 8) + bounds: 184 456 8 8 + - image: solid-color(24, 57, 0, 255, 8, 8) + bounds: 192 456 8 8 + - image: solid-color(25, 57, 0, 255, 8, 8) + bounds: 200 456 8 8 + - image: solid-color(26, 57, 0, 255, 8, 8) + bounds: 208 456 8 8 + - image: solid-color(27, 57, 0, 255, 8, 8) + bounds: 216 456 8 8 + - image: solid-color(28, 57, 0, 255, 8, 8) + bounds: 224 456 8 8 + - image: solid-color(29, 57, 0, 255, 8, 8) + bounds: 232 456 8 8 + - image: solid-color(30, 57, 0, 255, 8, 8) + bounds: 240 456 8 8 + - image: solid-color(31, 57, 0, 255, 8, 8) + bounds: 248 456 8 8 + - image: solid-color(32, 57, 0, 255, 8, 8) + bounds: 256 456 8 8 + - image: solid-color(33, 57, 0, 255, 8, 8) + bounds: 264 456 8 8 + - image: solid-color(34, 57, 0, 255, 8, 8) + bounds: 272 456 8 8 + - image: solid-color(35, 57, 0, 255, 8, 8) + bounds: 280 456 8 8 + - image: solid-color(36, 57, 0, 255, 8, 8) + bounds: 288 456 8 8 + - image: solid-color(37, 57, 0, 255, 8, 8) + bounds: 296 456 8 8 + - image: solid-color(38, 57, 0, 255, 8, 8) + bounds: 304 456 8 8 + - image: solid-color(39, 57, 0, 255, 8, 8) + bounds: 312 456 8 8 + - image: solid-color(40, 57, 0, 255, 8, 8) + bounds: 320 456 8 8 + - image: solid-color(41, 57, 0, 255, 8, 8) + bounds: 328 456 8 8 + - image: solid-color(42, 57, 0, 255, 8, 8) + bounds: 336 456 8 8 + - image: solid-color(43, 57, 0, 255, 8, 8) + bounds: 344 456 8 8 + - image: solid-color(44, 57, 0, 255, 8, 8) + bounds: 352 456 8 8 + - image: solid-color(45, 57, 0, 255, 8, 8) + bounds: 360 456 8 8 + - image: solid-color(46, 57, 0, 255, 8, 8) + bounds: 368 456 8 8 + - image: solid-color(47, 57, 0, 255, 8, 8) + bounds: 376 456 8 8 + - image: solid-color(48, 57, 0, 255, 8, 8) + bounds: 384 456 8 8 + - image: solid-color(49, 57, 0, 255, 8, 8) + bounds: 392 456 8 8 + - image: solid-color(50, 57, 0, 255, 8, 8) + bounds: 400 456 8 8 + - image: solid-color(51, 57, 0, 255, 8, 8) + bounds: 408 456 8 8 + - image: solid-color(52, 57, 0, 255, 8, 8) + bounds: 416 456 8 8 + - image: solid-color(53, 57, 0, 255, 8, 8) + bounds: 424 456 8 8 + - image: solid-color(54, 57, 0, 255, 8, 8) + bounds: 432 456 8 8 + - image: solid-color(55, 57, 0, 255, 8, 8) + bounds: 440 456 8 8 + - image: solid-color(56, 57, 0, 255, 8, 8) + bounds: 448 456 8 8 + - image: solid-color(57, 57, 0, 255, 8, 8) + bounds: 456 456 8 8 + - image: solid-color(58, 57, 0, 255, 8, 8) + bounds: 464 456 8 8 + - image: solid-color(59, 57, 0, 255, 8, 8) + bounds: 472 456 8 8 + - image: solid-color(60, 57, 0, 255, 8, 8) + bounds: 480 456 8 8 + - image: solid-color(61, 57, 0, 255, 8, 8) + bounds: 488 456 8 8 + - image: solid-color(62, 57, 0, 255, 8, 8) + bounds: 496 456 8 8 + - image: solid-color(63, 57, 0, 255, 8, 8) + bounds: 504 456 8 8 + - image: solid-color(64, 57, 0, 255, 8, 8) + bounds: 512 456 8 8 + - image: solid-color(65, 57, 0, 255, 8, 8) + bounds: 520 456 8 8 + - image: solid-color(66, 57, 0, 255, 8, 8) + bounds: 528 456 8 8 + - image: solid-color(67, 57, 0, 255, 8, 8) + bounds: 536 456 8 8 + - image: solid-color(68, 57, 0, 255, 8, 8) + bounds: 544 456 8 8 + - image: solid-color(69, 57, 0, 255, 8, 8) + bounds: 552 456 8 8 + - image: solid-color(70, 57, 0, 255, 8, 8) + bounds: 560 456 8 8 + - image: solid-color(71, 57, 0, 255, 8, 8) + bounds: 568 456 8 8 + - image: solid-color(72, 57, 0, 255, 8, 8) + bounds: 576 456 8 8 + - image: solid-color(73, 57, 0, 255, 8, 8) + bounds: 584 456 8 8 + - image: solid-color(74, 57, 0, 255, 8, 8) + bounds: 592 456 8 8 + - image: solid-color(75, 57, 0, 255, 8, 8) + bounds: 600 456 8 8 + - image: solid-color(76, 57, 0, 255, 8, 8) + bounds: 608 456 8 8 + - image: solid-color(77, 57, 0, 255, 8, 8) + bounds: 616 456 8 8 + - image: solid-color(78, 57, 0, 255, 8, 8) + bounds: 624 456 8 8 + - image: solid-color(79, 57, 0, 255, 8, 8) + bounds: 632 456 8 8 + - image: solid-color(80, 57, 0, 255, 8, 8) + bounds: 640 456 8 8 + - image: solid-color(81, 57, 0, 255, 8, 8) + bounds: 648 456 8 8 + - image: solid-color(82, 57, 0, 255, 8, 8) + bounds: 656 456 8 8 + - image: solid-color(83, 57, 0, 255, 8, 8) + bounds: 664 456 8 8 + - image: solid-color(84, 57, 0, 255, 8, 8) + bounds: 672 456 8 8 + - image: solid-color(85, 57, 0, 255, 8, 8) + bounds: 680 456 8 8 + - image: solid-color(86, 57, 0, 255, 8, 8) + bounds: 688 456 8 8 + - image: solid-color(87, 57, 0, 255, 8, 8) + bounds: 696 456 8 8 + - image: solid-color(88, 57, 0, 255, 8, 8) + bounds: 704 456 8 8 + - image: solid-color(89, 57, 0, 255, 8, 8) + bounds: 712 456 8 8 + - image: solid-color(90, 57, 0, 255, 8, 8) + bounds: 720 456 8 8 + - image: solid-color(91, 57, 0, 255, 8, 8) + bounds: 728 456 8 8 + - image: solid-color(92, 57, 0, 255, 8, 8) + bounds: 736 456 8 8 + - image: solid-color(93, 57, 0, 255, 8, 8) + bounds: 744 456 8 8 + - image: solid-color(94, 57, 0, 255, 8, 8) + bounds: 752 456 8 8 + - image: solid-color(95, 57, 0, 255, 8, 8) + bounds: 760 456 8 8 + - image: solid-color(96, 57, 0, 255, 8, 8) + bounds: 768 456 8 8 + - image: solid-color(97, 57, 0, 255, 8, 8) + bounds: 776 456 8 8 + - image: solid-color(98, 57, 0, 255, 8, 8) + bounds: 784 456 8 8 + - image: solid-color(99, 57, 0, 255, 8, 8) + bounds: 792 456 8 8 + - image: solid-color(100, 57, 0, 255, 8, 8) + bounds: 800 456 8 8 + - image: solid-color(101, 57, 0, 255, 8, 8) + bounds: 808 456 8 8 + - image: solid-color(102, 57, 0, 255, 8, 8) + bounds: 816 456 8 8 + - image: solid-color(103, 57, 0, 255, 8, 8) + bounds: 824 456 8 8 + - image: solid-color(104, 57, 0, 255, 8, 8) + bounds: 832 456 8 8 + - image: solid-color(105, 57, 0, 255, 8, 8) + bounds: 840 456 8 8 + - image: solid-color(106, 57, 0, 255, 8, 8) + bounds: 848 456 8 8 + - image: solid-color(107, 57, 0, 255, 8, 8) + bounds: 856 456 8 8 + - image: solid-color(108, 57, 0, 255, 8, 8) + bounds: 864 456 8 8 + - image: solid-color(109, 57, 0, 255, 8, 8) + bounds: 872 456 8 8 + - image: solid-color(110, 57, 0, 255, 8, 8) + bounds: 880 456 8 8 + - image: solid-color(111, 57, 0, 255, 8, 8) + bounds: 888 456 8 8 + - image: solid-color(112, 57, 0, 255, 8, 8) + bounds: 896 456 8 8 + - image: solid-color(113, 57, 0, 255, 8, 8) + bounds: 904 456 8 8 + - image: solid-color(114, 57, 0, 255, 8, 8) + bounds: 912 456 8 8 + - image: solid-color(115, 57, 0, 255, 8, 8) + bounds: 920 456 8 8 + - image: solid-color(116, 57, 0, 255, 8, 8) + bounds: 928 456 8 8 + - image: solid-color(117, 57, 0, 255, 8, 8) + bounds: 936 456 8 8 + - image: solid-color(118, 57, 0, 255, 8, 8) + bounds: 944 456 8 8 + - image: solid-color(119, 57, 0, 255, 8, 8) + bounds: 952 456 8 8 + - image: solid-color(120, 57, 0, 255, 8, 8) + bounds: 960 456 8 8 + - image: solid-color(121, 57, 0, 255, 8, 8) + bounds: 968 456 8 8 + - image: solid-color(122, 57, 0, 255, 8, 8) + bounds: 976 456 8 8 + - image: solid-color(123, 57, 0, 255, 8, 8) + bounds: 984 456 8 8 + - image: solid-color(124, 57, 0, 255, 8, 8) + bounds: 992 456 8 8 + - image: solid-color(125, 57, 0, 255, 8, 8) + bounds: 1000 456 8 8 + - image: solid-color(126, 57, 0, 255, 8, 8) + bounds: 1008 456 8 8 + - image: solid-color(127, 57, 0, 255, 8, 8) + bounds: 1016 456 8 8 + - image: solid-color(0, 58, 0, 255, 8, 8) + bounds: 0 464 8 8 + - image: solid-color(1, 58, 0, 255, 8, 8) + bounds: 8 464 8 8 + - image: solid-color(2, 58, 0, 255, 8, 8) + bounds: 16 464 8 8 + - image: solid-color(3, 58, 0, 255, 8, 8) + bounds: 24 464 8 8 + - image: solid-color(4, 58, 0, 255, 8, 8) + bounds: 32 464 8 8 + - image: solid-color(5, 58, 0, 255, 8, 8) + bounds: 40 464 8 8 + - image: solid-color(6, 58, 0, 255, 8, 8) + bounds: 48 464 8 8 + - image: solid-color(7, 58, 0, 255, 8, 8) + bounds: 56 464 8 8 + - image: solid-color(8, 58, 0, 255, 8, 8) + bounds: 64 464 8 8 + - image: solid-color(9, 58, 0, 255, 8, 8) + bounds: 72 464 8 8 + - image: solid-color(10, 58, 0, 255, 8, 8) + bounds: 80 464 8 8 + - image: solid-color(11, 58, 0, 255, 8, 8) + bounds: 88 464 8 8 + - image: solid-color(12, 58, 0, 255, 8, 8) + bounds: 96 464 8 8 + - image: solid-color(13, 58, 0, 255, 8, 8) + bounds: 104 464 8 8 + - image: solid-color(14, 58, 0, 255, 8, 8) + bounds: 112 464 8 8 + - image: solid-color(15, 58, 0, 255, 8, 8) + bounds: 120 464 8 8 + - image: solid-color(16, 58, 0, 255, 8, 8) + bounds: 128 464 8 8 + - image: solid-color(17, 58, 0, 255, 8, 8) + bounds: 136 464 8 8 + - image: solid-color(18, 58, 0, 255, 8, 8) + bounds: 144 464 8 8 + - image: solid-color(19, 58, 0, 255, 8, 8) + bounds: 152 464 8 8 + - image: solid-color(20, 58, 0, 255, 8, 8) + bounds: 160 464 8 8 + - image: solid-color(21, 58, 0, 255, 8, 8) + bounds: 168 464 8 8 + - image: solid-color(22, 58, 0, 255, 8, 8) + bounds: 176 464 8 8 + - image: solid-color(23, 58, 0, 255, 8, 8) + bounds: 184 464 8 8 + - image: solid-color(24, 58, 0, 255, 8, 8) + bounds: 192 464 8 8 + - image: solid-color(25, 58, 0, 255, 8, 8) + bounds: 200 464 8 8 + - image: solid-color(26, 58, 0, 255, 8, 8) + bounds: 208 464 8 8 + - image: solid-color(27, 58, 0, 255, 8, 8) + bounds: 216 464 8 8 + - image: solid-color(28, 58, 0, 255, 8, 8) + bounds: 224 464 8 8 + - image: solid-color(29, 58, 0, 255, 8, 8) + bounds: 232 464 8 8 + - image: solid-color(30, 58, 0, 255, 8, 8) + bounds: 240 464 8 8 + - image: solid-color(31, 58, 0, 255, 8, 8) + bounds: 248 464 8 8 + - image: solid-color(32, 58, 0, 255, 8, 8) + bounds: 256 464 8 8 + - image: solid-color(33, 58, 0, 255, 8, 8) + bounds: 264 464 8 8 + - image: solid-color(34, 58, 0, 255, 8, 8) + bounds: 272 464 8 8 + - image: solid-color(35, 58, 0, 255, 8, 8) + bounds: 280 464 8 8 + - image: solid-color(36, 58, 0, 255, 8, 8) + bounds: 288 464 8 8 + - image: solid-color(37, 58, 0, 255, 8, 8) + bounds: 296 464 8 8 + - image: solid-color(38, 58, 0, 255, 8, 8) + bounds: 304 464 8 8 + - image: solid-color(39, 58, 0, 255, 8, 8) + bounds: 312 464 8 8 + - image: solid-color(40, 58, 0, 255, 8, 8) + bounds: 320 464 8 8 + - image: solid-color(41, 58, 0, 255, 8, 8) + bounds: 328 464 8 8 + - image: solid-color(42, 58, 0, 255, 8, 8) + bounds: 336 464 8 8 + - image: solid-color(43, 58, 0, 255, 8, 8) + bounds: 344 464 8 8 + - image: solid-color(44, 58, 0, 255, 8, 8) + bounds: 352 464 8 8 + - image: solid-color(45, 58, 0, 255, 8, 8) + bounds: 360 464 8 8 + - image: solid-color(46, 58, 0, 255, 8, 8) + bounds: 368 464 8 8 + - image: solid-color(47, 58, 0, 255, 8, 8) + bounds: 376 464 8 8 + - image: solid-color(48, 58, 0, 255, 8, 8) + bounds: 384 464 8 8 + - image: solid-color(49, 58, 0, 255, 8, 8) + bounds: 392 464 8 8 + - image: solid-color(50, 58, 0, 255, 8, 8) + bounds: 400 464 8 8 + - image: solid-color(51, 58, 0, 255, 8, 8) + bounds: 408 464 8 8 + - image: solid-color(52, 58, 0, 255, 8, 8) + bounds: 416 464 8 8 + - image: solid-color(53, 58, 0, 255, 8, 8) + bounds: 424 464 8 8 + - image: solid-color(54, 58, 0, 255, 8, 8) + bounds: 432 464 8 8 + - image: solid-color(55, 58, 0, 255, 8, 8) + bounds: 440 464 8 8 + - image: solid-color(56, 58, 0, 255, 8, 8) + bounds: 448 464 8 8 + - image: solid-color(57, 58, 0, 255, 8, 8) + bounds: 456 464 8 8 + - image: solid-color(58, 58, 0, 255, 8, 8) + bounds: 464 464 8 8 + - image: solid-color(59, 58, 0, 255, 8, 8) + bounds: 472 464 8 8 + - image: solid-color(60, 58, 0, 255, 8, 8) + bounds: 480 464 8 8 + - image: solid-color(61, 58, 0, 255, 8, 8) + bounds: 488 464 8 8 + - image: solid-color(62, 58, 0, 255, 8, 8) + bounds: 496 464 8 8 + - image: solid-color(63, 58, 0, 255, 8, 8) + bounds: 504 464 8 8 + - image: solid-color(64, 58, 0, 255, 8, 8) + bounds: 512 464 8 8 + - image: solid-color(65, 58, 0, 255, 8, 8) + bounds: 520 464 8 8 + - image: solid-color(66, 58, 0, 255, 8, 8) + bounds: 528 464 8 8 + - image: solid-color(67, 58, 0, 255, 8, 8) + bounds: 536 464 8 8 + - image: solid-color(68, 58, 0, 255, 8, 8) + bounds: 544 464 8 8 + - image: solid-color(69, 58, 0, 255, 8, 8) + bounds: 552 464 8 8 + - image: solid-color(70, 58, 0, 255, 8, 8) + bounds: 560 464 8 8 + - image: solid-color(71, 58, 0, 255, 8, 8) + bounds: 568 464 8 8 + - image: solid-color(72, 58, 0, 255, 8, 8) + bounds: 576 464 8 8 + - image: solid-color(73, 58, 0, 255, 8, 8) + bounds: 584 464 8 8 + - image: solid-color(74, 58, 0, 255, 8, 8) + bounds: 592 464 8 8 + - image: solid-color(75, 58, 0, 255, 8, 8) + bounds: 600 464 8 8 + - image: solid-color(76, 58, 0, 255, 8, 8) + bounds: 608 464 8 8 + - image: solid-color(77, 58, 0, 255, 8, 8) + bounds: 616 464 8 8 + - image: solid-color(78, 58, 0, 255, 8, 8) + bounds: 624 464 8 8 + - image: solid-color(79, 58, 0, 255, 8, 8) + bounds: 632 464 8 8 + - image: solid-color(80, 58, 0, 255, 8, 8) + bounds: 640 464 8 8 + - image: solid-color(81, 58, 0, 255, 8, 8) + bounds: 648 464 8 8 + - image: solid-color(82, 58, 0, 255, 8, 8) + bounds: 656 464 8 8 + - image: solid-color(83, 58, 0, 255, 8, 8) + bounds: 664 464 8 8 + - image: solid-color(84, 58, 0, 255, 8, 8) + bounds: 672 464 8 8 + - image: solid-color(85, 58, 0, 255, 8, 8) + bounds: 680 464 8 8 + - image: solid-color(86, 58, 0, 255, 8, 8) + bounds: 688 464 8 8 + - image: solid-color(87, 58, 0, 255, 8, 8) + bounds: 696 464 8 8 + - image: solid-color(88, 58, 0, 255, 8, 8) + bounds: 704 464 8 8 + - image: solid-color(89, 58, 0, 255, 8, 8) + bounds: 712 464 8 8 + - image: solid-color(90, 58, 0, 255, 8, 8) + bounds: 720 464 8 8 + - image: solid-color(91, 58, 0, 255, 8, 8) + bounds: 728 464 8 8 + - image: solid-color(92, 58, 0, 255, 8, 8) + bounds: 736 464 8 8 + - image: solid-color(93, 58, 0, 255, 8, 8) + bounds: 744 464 8 8 + - image: solid-color(94, 58, 0, 255, 8, 8) + bounds: 752 464 8 8 + - image: solid-color(95, 58, 0, 255, 8, 8) + bounds: 760 464 8 8 + - image: solid-color(96, 58, 0, 255, 8, 8) + bounds: 768 464 8 8 + - image: solid-color(97, 58, 0, 255, 8, 8) + bounds: 776 464 8 8 + - image: solid-color(98, 58, 0, 255, 8, 8) + bounds: 784 464 8 8 + - image: solid-color(99, 58, 0, 255, 8, 8) + bounds: 792 464 8 8 + - image: solid-color(100, 58, 0, 255, 8, 8) + bounds: 800 464 8 8 + - image: solid-color(101, 58, 0, 255, 8, 8) + bounds: 808 464 8 8 + - image: solid-color(102, 58, 0, 255, 8, 8) + bounds: 816 464 8 8 + - image: solid-color(103, 58, 0, 255, 8, 8) + bounds: 824 464 8 8 + - image: solid-color(104, 58, 0, 255, 8, 8) + bounds: 832 464 8 8 + - image: solid-color(105, 58, 0, 255, 8, 8) + bounds: 840 464 8 8 + - image: solid-color(106, 58, 0, 255, 8, 8) + bounds: 848 464 8 8 + - image: solid-color(107, 58, 0, 255, 8, 8) + bounds: 856 464 8 8 + - image: solid-color(108, 58, 0, 255, 8, 8) + bounds: 864 464 8 8 + - image: solid-color(109, 58, 0, 255, 8, 8) + bounds: 872 464 8 8 + - image: solid-color(110, 58, 0, 255, 8, 8) + bounds: 880 464 8 8 + - image: solid-color(111, 58, 0, 255, 8, 8) + bounds: 888 464 8 8 + - image: solid-color(112, 58, 0, 255, 8, 8) + bounds: 896 464 8 8 + - image: solid-color(113, 58, 0, 255, 8, 8) + bounds: 904 464 8 8 + - image: solid-color(114, 58, 0, 255, 8, 8) + bounds: 912 464 8 8 + - image: solid-color(115, 58, 0, 255, 8, 8) + bounds: 920 464 8 8 + - image: solid-color(116, 58, 0, 255, 8, 8) + bounds: 928 464 8 8 + - image: solid-color(117, 58, 0, 255, 8, 8) + bounds: 936 464 8 8 + - image: solid-color(118, 58, 0, 255, 8, 8) + bounds: 944 464 8 8 + - image: solid-color(119, 58, 0, 255, 8, 8) + bounds: 952 464 8 8 + - image: solid-color(120, 58, 0, 255, 8, 8) + bounds: 960 464 8 8 + - image: solid-color(121, 58, 0, 255, 8, 8) + bounds: 968 464 8 8 + - image: solid-color(122, 58, 0, 255, 8, 8) + bounds: 976 464 8 8 + - image: solid-color(123, 58, 0, 255, 8, 8) + bounds: 984 464 8 8 + - image: solid-color(124, 58, 0, 255, 8, 8) + bounds: 992 464 8 8 + - image: solid-color(125, 58, 0, 255, 8, 8) + bounds: 1000 464 8 8 + - image: solid-color(126, 58, 0, 255, 8, 8) + bounds: 1008 464 8 8 + - image: solid-color(127, 58, 0, 255, 8, 8) + bounds: 1016 464 8 8 + - image: solid-color(0, 59, 0, 255, 8, 8) + bounds: 0 472 8 8 + - image: solid-color(1, 59, 0, 255, 8, 8) + bounds: 8 472 8 8 + - image: solid-color(2, 59, 0, 255, 8, 8) + bounds: 16 472 8 8 + - image: solid-color(3, 59, 0, 255, 8, 8) + bounds: 24 472 8 8 + - image: solid-color(4, 59, 0, 255, 8, 8) + bounds: 32 472 8 8 + - image: solid-color(5, 59, 0, 255, 8, 8) + bounds: 40 472 8 8 + - image: solid-color(6, 59, 0, 255, 8, 8) + bounds: 48 472 8 8 + - image: solid-color(7, 59, 0, 255, 8, 8) + bounds: 56 472 8 8 + - image: solid-color(8, 59, 0, 255, 8, 8) + bounds: 64 472 8 8 + - image: solid-color(9, 59, 0, 255, 8, 8) + bounds: 72 472 8 8 + - image: solid-color(10, 59, 0, 255, 8, 8) + bounds: 80 472 8 8 + - image: solid-color(11, 59, 0, 255, 8, 8) + bounds: 88 472 8 8 + - image: solid-color(12, 59, 0, 255, 8, 8) + bounds: 96 472 8 8 + - image: solid-color(13, 59, 0, 255, 8, 8) + bounds: 104 472 8 8 + - image: solid-color(14, 59, 0, 255, 8, 8) + bounds: 112 472 8 8 + - image: solid-color(15, 59, 0, 255, 8, 8) + bounds: 120 472 8 8 + - image: solid-color(16, 59, 0, 255, 8, 8) + bounds: 128 472 8 8 + - image: solid-color(17, 59, 0, 255, 8, 8) + bounds: 136 472 8 8 + - image: solid-color(18, 59, 0, 255, 8, 8) + bounds: 144 472 8 8 + - image: solid-color(19, 59, 0, 255, 8, 8) + bounds: 152 472 8 8 + - image: solid-color(20, 59, 0, 255, 8, 8) + bounds: 160 472 8 8 + - image: solid-color(21, 59, 0, 255, 8, 8) + bounds: 168 472 8 8 + - image: solid-color(22, 59, 0, 255, 8, 8) + bounds: 176 472 8 8 + - image: solid-color(23, 59, 0, 255, 8, 8) + bounds: 184 472 8 8 + - image: solid-color(24, 59, 0, 255, 8, 8) + bounds: 192 472 8 8 + - image: solid-color(25, 59, 0, 255, 8, 8) + bounds: 200 472 8 8 + - image: solid-color(26, 59, 0, 255, 8, 8) + bounds: 208 472 8 8 + - image: solid-color(27, 59, 0, 255, 8, 8) + bounds: 216 472 8 8 + - image: solid-color(28, 59, 0, 255, 8, 8) + bounds: 224 472 8 8 + - image: solid-color(29, 59, 0, 255, 8, 8) + bounds: 232 472 8 8 + - image: solid-color(30, 59, 0, 255, 8, 8) + bounds: 240 472 8 8 + - image: solid-color(31, 59, 0, 255, 8, 8) + bounds: 248 472 8 8 + - image: solid-color(32, 59, 0, 255, 8, 8) + bounds: 256 472 8 8 + - image: solid-color(33, 59, 0, 255, 8, 8) + bounds: 264 472 8 8 + - image: solid-color(34, 59, 0, 255, 8, 8) + bounds: 272 472 8 8 + - image: solid-color(35, 59, 0, 255, 8, 8) + bounds: 280 472 8 8 + - image: solid-color(36, 59, 0, 255, 8, 8) + bounds: 288 472 8 8 + - image: solid-color(37, 59, 0, 255, 8, 8) + bounds: 296 472 8 8 + - image: solid-color(38, 59, 0, 255, 8, 8) + bounds: 304 472 8 8 + - image: solid-color(39, 59, 0, 255, 8, 8) + bounds: 312 472 8 8 + - image: solid-color(40, 59, 0, 255, 8, 8) + bounds: 320 472 8 8 + - image: solid-color(41, 59, 0, 255, 8, 8) + bounds: 328 472 8 8 + - image: solid-color(42, 59, 0, 255, 8, 8) + bounds: 336 472 8 8 + - image: solid-color(43, 59, 0, 255, 8, 8) + bounds: 344 472 8 8 + - image: solid-color(44, 59, 0, 255, 8, 8) + bounds: 352 472 8 8 + - image: solid-color(45, 59, 0, 255, 8, 8) + bounds: 360 472 8 8 + - image: solid-color(46, 59, 0, 255, 8, 8) + bounds: 368 472 8 8 + - image: solid-color(47, 59, 0, 255, 8, 8) + bounds: 376 472 8 8 + - image: solid-color(48, 59, 0, 255, 8, 8) + bounds: 384 472 8 8 + - image: solid-color(49, 59, 0, 255, 8, 8) + bounds: 392 472 8 8 + - image: solid-color(50, 59, 0, 255, 8, 8) + bounds: 400 472 8 8 + - image: solid-color(51, 59, 0, 255, 8, 8) + bounds: 408 472 8 8 + - image: solid-color(52, 59, 0, 255, 8, 8) + bounds: 416 472 8 8 + - image: solid-color(53, 59, 0, 255, 8, 8) + bounds: 424 472 8 8 + - image: solid-color(54, 59, 0, 255, 8, 8) + bounds: 432 472 8 8 + - image: solid-color(55, 59, 0, 255, 8, 8) + bounds: 440 472 8 8 + - image: solid-color(56, 59, 0, 255, 8, 8) + bounds: 448 472 8 8 + - image: solid-color(57, 59, 0, 255, 8, 8) + bounds: 456 472 8 8 + - image: solid-color(58, 59, 0, 255, 8, 8) + bounds: 464 472 8 8 + - image: solid-color(59, 59, 0, 255, 8, 8) + bounds: 472 472 8 8 + - image: solid-color(60, 59, 0, 255, 8, 8) + bounds: 480 472 8 8 + - image: solid-color(61, 59, 0, 255, 8, 8) + bounds: 488 472 8 8 + - image: solid-color(62, 59, 0, 255, 8, 8) + bounds: 496 472 8 8 + - image: solid-color(63, 59, 0, 255, 8, 8) + bounds: 504 472 8 8 + - image: solid-color(64, 59, 0, 255, 8, 8) + bounds: 512 472 8 8 + - image: solid-color(65, 59, 0, 255, 8, 8) + bounds: 520 472 8 8 + - image: solid-color(66, 59, 0, 255, 8, 8) + bounds: 528 472 8 8 + - image: solid-color(67, 59, 0, 255, 8, 8) + bounds: 536 472 8 8 + - image: solid-color(68, 59, 0, 255, 8, 8) + bounds: 544 472 8 8 + - image: solid-color(69, 59, 0, 255, 8, 8) + bounds: 552 472 8 8 + - image: solid-color(70, 59, 0, 255, 8, 8) + bounds: 560 472 8 8 + - image: solid-color(71, 59, 0, 255, 8, 8) + bounds: 568 472 8 8 + - image: solid-color(72, 59, 0, 255, 8, 8) + bounds: 576 472 8 8 + - image: solid-color(73, 59, 0, 255, 8, 8) + bounds: 584 472 8 8 + - image: solid-color(74, 59, 0, 255, 8, 8) + bounds: 592 472 8 8 + - image: solid-color(75, 59, 0, 255, 8, 8) + bounds: 600 472 8 8 + - image: solid-color(76, 59, 0, 255, 8, 8) + bounds: 608 472 8 8 + - image: solid-color(77, 59, 0, 255, 8, 8) + bounds: 616 472 8 8 + - image: solid-color(78, 59, 0, 255, 8, 8) + bounds: 624 472 8 8 + - image: solid-color(79, 59, 0, 255, 8, 8) + bounds: 632 472 8 8 + - image: solid-color(80, 59, 0, 255, 8, 8) + bounds: 640 472 8 8 + - image: solid-color(81, 59, 0, 255, 8, 8) + bounds: 648 472 8 8 + - image: solid-color(82, 59, 0, 255, 8, 8) + bounds: 656 472 8 8 + - image: solid-color(83, 59, 0, 255, 8, 8) + bounds: 664 472 8 8 + - image: solid-color(84, 59, 0, 255, 8, 8) + bounds: 672 472 8 8 + - image: solid-color(85, 59, 0, 255, 8, 8) + bounds: 680 472 8 8 + - image: solid-color(86, 59, 0, 255, 8, 8) + bounds: 688 472 8 8 + - image: solid-color(87, 59, 0, 255, 8, 8) + bounds: 696 472 8 8 + - image: solid-color(88, 59, 0, 255, 8, 8) + bounds: 704 472 8 8 + - image: solid-color(89, 59, 0, 255, 8, 8) + bounds: 712 472 8 8 + - image: solid-color(90, 59, 0, 255, 8, 8) + bounds: 720 472 8 8 + - image: solid-color(91, 59, 0, 255, 8, 8) + bounds: 728 472 8 8 + - image: solid-color(92, 59, 0, 255, 8, 8) + bounds: 736 472 8 8 + - image: solid-color(93, 59, 0, 255, 8, 8) + bounds: 744 472 8 8 + - image: solid-color(94, 59, 0, 255, 8, 8) + bounds: 752 472 8 8 + - image: solid-color(95, 59, 0, 255, 8, 8) + bounds: 760 472 8 8 + - image: solid-color(96, 59, 0, 255, 8, 8) + bounds: 768 472 8 8 + - image: solid-color(97, 59, 0, 255, 8, 8) + bounds: 776 472 8 8 + - image: solid-color(98, 59, 0, 255, 8, 8) + bounds: 784 472 8 8 + - image: solid-color(99, 59, 0, 255, 8, 8) + bounds: 792 472 8 8 + - image: solid-color(100, 59, 0, 255, 8, 8) + bounds: 800 472 8 8 + - image: solid-color(101, 59, 0, 255, 8, 8) + bounds: 808 472 8 8 + - image: solid-color(102, 59, 0, 255, 8, 8) + bounds: 816 472 8 8 + - image: solid-color(103, 59, 0, 255, 8, 8) + bounds: 824 472 8 8 + - image: solid-color(104, 59, 0, 255, 8, 8) + bounds: 832 472 8 8 + - image: solid-color(105, 59, 0, 255, 8, 8) + bounds: 840 472 8 8 + - image: solid-color(106, 59, 0, 255, 8, 8) + bounds: 848 472 8 8 + - image: solid-color(107, 59, 0, 255, 8, 8) + bounds: 856 472 8 8 + - image: solid-color(108, 59, 0, 255, 8, 8) + bounds: 864 472 8 8 + - image: solid-color(109, 59, 0, 255, 8, 8) + bounds: 872 472 8 8 + - image: solid-color(110, 59, 0, 255, 8, 8) + bounds: 880 472 8 8 + - image: solid-color(111, 59, 0, 255, 8, 8) + bounds: 888 472 8 8 + - image: solid-color(112, 59, 0, 255, 8, 8) + bounds: 896 472 8 8 + - image: solid-color(113, 59, 0, 255, 8, 8) + bounds: 904 472 8 8 + - image: solid-color(114, 59, 0, 255, 8, 8) + bounds: 912 472 8 8 + - image: solid-color(115, 59, 0, 255, 8, 8) + bounds: 920 472 8 8 + - image: solid-color(116, 59, 0, 255, 8, 8) + bounds: 928 472 8 8 + - image: solid-color(117, 59, 0, 255, 8, 8) + bounds: 936 472 8 8 + - image: solid-color(118, 59, 0, 255, 8, 8) + bounds: 944 472 8 8 + - image: solid-color(119, 59, 0, 255, 8, 8) + bounds: 952 472 8 8 + - image: solid-color(120, 59, 0, 255, 8, 8) + bounds: 960 472 8 8 + - image: solid-color(121, 59, 0, 255, 8, 8) + bounds: 968 472 8 8 + - image: solid-color(122, 59, 0, 255, 8, 8) + bounds: 976 472 8 8 + - image: solid-color(123, 59, 0, 255, 8, 8) + bounds: 984 472 8 8 + - image: solid-color(124, 59, 0, 255, 8, 8) + bounds: 992 472 8 8 + - image: solid-color(125, 59, 0, 255, 8, 8) + bounds: 1000 472 8 8 + - image: solid-color(126, 59, 0, 255, 8, 8) + bounds: 1008 472 8 8 + - image: solid-color(127, 59, 0, 255, 8, 8) + bounds: 1016 472 8 8 + - image: solid-color(0, 60, 0, 255, 8, 8) + bounds: 0 480 8 8 + - image: solid-color(1, 60, 0, 255, 8, 8) + bounds: 8 480 8 8 + - image: solid-color(2, 60, 0, 255, 8, 8) + bounds: 16 480 8 8 + - image: solid-color(3, 60, 0, 255, 8, 8) + bounds: 24 480 8 8 + - image: solid-color(4, 60, 0, 255, 8, 8) + bounds: 32 480 8 8 + - image: solid-color(5, 60, 0, 255, 8, 8) + bounds: 40 480 8 8 + - image: solid-color(6, 60, 0, 255, 8, 8) + bounds: 48 480 8 8 + - image: solid-color(7, 60, 0, 255, 8, 8) + bounds: 56 480 8 8 + - image: solid-color(8, 60, 0, 255, 8, 8) + bounds: 64 480 8 8 + - image: solid-color(9, 60, 0, 255, 8, 8) + bounds: 72 480 8 8 + - image: solid-color(10, 60, 0, 255, 8, 8) + bounds: 80 480 8 8 + - image: solid-color(11, 60, 0, 255, 8, 8) + bounds: 88 480 8 8 + - image: solid-color(12, 60, 0, 255, 8, 8) + bounds: 96 480 8 8 + - image: solid-color(13, 60, 0, 255, 8, 8) + bounds: 104 480 8 8 + - image: solid-color(14, 60, 0, 255, 8, 8) + bounds: 112 480 8 8 + - image: solid-color(15, 60, 0, 255, 8, 8) + bounds: 120 480 8 8 + - image: solid-color(16, 60, 0, 255, 8, 8) + bounds: 128 480 8 8 + - image: solid-color(17, 60, 0, 255, 8, 8) + bounds: 136 480 8 8 + - image: solid-color(18, 60, 0, 255, 8, 8) + bounds: 144 480 8 8 + - image: solid-color(19, 60, 0, 255, 8, 8) + bounds: 152 480 8 8 + - image: solid-color(20, 60, 0, 255, 8, 8) + bounds: 160 480 8 8 + - image: solid-color(21, 60, 0, 255, 8, 8) + bounds: 168 480 8 8 + - image: solid-color(22, 60, 0, 255, 8, 8) + bounds: 176 480 8 8 + - image: solid-color(23, 60, 0, 255, 8, 8) + bounds: 184 480 8 8 + - image: solid-color(24, 60, 0, 255, 8, 8) + bounds: 192 480 8 8 + - image: solid-color(25, 60, 0, 255, 8, 8) + bounds: 200 480 8 8 + - image: solid-color(26, 60, 0, 255, 8, 8) + bounds: 208 480 8 8 + - image: solid-color(27, 60, 0, 255, 8, 8) + bounds: 216 480 8 8 + - image: solid-color(28, 60, 0, 255, 8, 8) + bounds: 224 480 8 8 + - image: solid-color(29, 60, 0, 255, 8, 8) + bounds: 232 480 8 8 + - image: solid-color(30, 60, 0, 255, 8, 8) + bounds: 240 480 8 8 + - image: solid-color(31, 60, 0, 255, 8, 8) + bounds: 248 480 8 8 + - image: solid-color(32, 60, 0, 255, 8, 8) + bounds: 256 480 8 8 + - image: solid-color(33, 60, 0, 255, 8, 8) + bounds: 264 480 8 8 + - image: solid-color(34, 60, 0, 255, 8, 8) + bounds: 272 480 8 8 + - image: solid-color(35, 60, 0, 255, 8, 8) + bounds: 280 480 8 8 + - image: solid-color(36, 60, 0, 255, 8, 8) + bounds: 288 480 8 8 + - image: solid-color(37, 60, 0, 255, 8, 8) + bounds: 296 480 8 8 + - image: solid-color(38, 60, 0, 255, 8, 8) + bounds: 304 480 8 8 + - image: solid-color(39, 60, 0, 255, 8, 8) + bounds: 312 480 8 8 + - image: solid-color(40, 60, 0, 255, 8, 8) + bounds: 320 480 8 8 + - image: solid-color(41, 60, 0, 255, 8, 8) + bounds: 328 480 8 8 + - image: solid-color(42, 60, 0, 255, 8, 8) + bounds: 336 480 8 8 + - image: solid-color(43, 60, 0, 255, 8, 8) + bounds: 344 480 8 8 + - image: solid-color(44, 60, 0, 255, 8, 8) + bounds: 352 480 8 8 + - image: solid-color(45, 60, 0, 255, 8, 8) + bounds: 360 480 8 8 + - image: solid-color(46, 60, 0, 255, 8, 8) + bounds: 368 480 8 8 + - image: solid-color(47, 60, 0, 255, 8, 8) + bounds: 376 480 8 8 + - image: solid-color(48, 60, 0, 255, 8, 8) + bounds: 384 480 8 8 + - image: solid-color(49, 60, 0, 255, 8, 8) + bounds: 392 480 8 8 + - image: solid-color(50, 60, 0, 255, 8, 8) + bounds: 400 480 8 8 + - image: solid-color(51, 60, 0, 255, 8, 8) + bounds: 408 480 8 8 + - image: solid-color(52, 60, 0, 255, 8, 8) + bounds: 416 480 8 8 + - image: solid-color(53, 60, 0, 255, 8, 8) + bounds: 424 480 8 8 + - image: solid-color(54, 60, 0, 255, 8, 8) + bounds: 432 480 8 8 + - image: solid-color(55, 60, 0, 255, 8, 8) + bounds: 440 480 8 8 + - image: solid-color(56, 60, 0, 255, 8, 8) + bounds: 448 480 8 8 + - image: solid-color(57, 60, 0, 255, 8, 8) + bounds: 456 480 8 8 + - image: solid-color(58, 60, 0, 255, 8, 8) + bounds: 464 480 8 8 + - image: solid-color(59, 60, 0, 255, 8, 8) + bounds: 472 480 8 8 + - image: solid-color(60, 60, 0, 255, 8, 8) + bounds: 480 480 8 8 + - image: solid-color(61, 60, 0, 255, 8, 8) + bounds: 488 480 8 8 + - image: solid-color(62, 60, 0, 255, 8, 8) + bounds: 496 480 8 8 + - image: solid-color(63, 60, 0, 255, 8, 8) + bounds: 504 480 8 8 + - image: solid-color(64, 60, 0, 255, 8, 8) + bounds: 512 480 8 8 + - image: solid-color(65, 60, 0, 255, 8, 8) + bounds: 520 480 8 8 + - image: solid-color(66, 60, 0, 255, 8, 8) + bounds: 528 480 8 8 + - image: solid-color(67, 60, 0, 255, 8, 8) + bounds: 536 480 8 8 + - image: solid-color(68, 60, 0, 255, 8, 8) + bounds: 544 480 8 8 + - image: solid-color(69, 60, 0, 255, 8, 8) + bounds: 552 480 8 8 + - image: solid-color(70, 60, 0, 255, 8, 8) + bounds: 560 480 8 8 + - image: solid-color(71, 60, 0, 255, 8, 8) + bounds: 568 480 8 8 + - image: solid-color(72, 60, 0, 255, 8, 8) + bounds: 576 480 8 8 + - image: solid-color(73, 60, 0, 255, 8, 8) + bounds: 584 480 8 8 + - image: solid-color(74, 60, 0, 255, 8, 8) + bounds: 592 480 8 8 + - image: solid-color(75, 60, 0, 255, 8, 8) + bounds: 600 480 8 8 + - image: solid-color(76, 60, 0, 255, 8, 8) + bounds: 608 480 8 8 + - image: solid-color(77, 60, 0, 255, 8, 8) + bounds: 616 480 8 8 + - image: solid-color(78, 60, 0, 255, 8, 8) + bounds: 624 480 8 8 + - image: solid-color(79, 60, 0, 255, 8, 8) + bounds: 632 480 8 8 + - image: solid-color(80, 60, 0, 255, 8, 8) + bounds: 640 480 8 8 + - image: solid-color(81, 60, 0, 255, 8, 8) + bounds: 648 480 8 8 + - image: solid-color(82, 60, 0, 255, 8, 8) + bounds: 656 480 8 8 + - image: solid-color(83, 60, 0, 255, 8, 8) + bounds: 664 480 8 8 + - image: solid-color(84, 60, 0, 255, 8, 8) + bounds: 672 480 8 8 + - image: solid-color(85, 60, 0, 255, 8, 8) + bounds: 680 480 8 8 + - image: solid-color(86, 60, 0, 255, 8, 8) + bounds: 688 480 8 8 + - image: solid-color(87, 60, 0, 255, 8, 8) + bounds: 696 480 8 8 + - image: solid-color(88, 60, 0, 255, 8, 8) + bounds: 704 480 8 8 + - image: solid-color(89, 60, 0, 255, 8, 8) + bounds: 712 480 8 8 + - image: solid-color(90, 60, 0, 255, 8, 8) + bounds: 720 480 8 8 + - image: solid-color(91, 60, 0, 255, 8, 8) + bounds: 728 480 8 8 + - image: solid-color(92, 60, 0, 255, 8, 8) + bounds: 736 480 8 8 + - image: solid-color(93, 60, 0, 255, 8, 8) + bounds: 744 480 8 8 + - image: solid-color(94, 60, 0, 255, 8, 8) + bounds: 752 480 8 8 + - image: solid-color(95, 60, 0, 255, 8, 8) + bounds: 760 480 8 8 + - image: solid-color(96, 60, 0, 255, 8, 8) + bounds: 768 480 8 8 + - image: solid-color(97, 60, 0, 255, 8, 8) + bounds: 776 480 8 8 + - image: solid-color(98, 60, 0, 255, 8, 8) + bounds: 784 480 8 8 + - image: solid-color(99, 60, 0, 255, 8, 8) + bounds: 792 480 8 8 + - image: solid-color(100, 60, 0, 255, 8, 8) + bounds: 800 480 8 8 + - image: solid-color(101, 60, 0, 255, 8, 8) + bounds: 808 480 8 8 + - image: solid-color(102, 60, 0, 255, 8, 8) + bounds: 816 480 8 8 + - image: solid-color(103, 60, 0, 255, 8, 8) + bounds: 824 480 8 8 + - image: solid-color(104, 60, 0, 255, 8, 8) + bounds: 832 480 8 8 + - image: solid-color(105, 60, 0, 255, 8, 8) + bounds: 840 480 8 8 + - image: solid-color(106, 60, 0, 255, 8, 8) + bounds: 848 480 8 8 + - image: solid-color(107, 60, 0, 255, 8, 8) + bounds: 856 480 8 8 + - image: solid-color(108, 60, 0, 255, 8, 8) + bounds: 864 480 8 8 + - image: solid-color(109, 60, 0, 255, 8, 8) + bounds: 872 480 8 8 + - image: solid-color(110, 60, 0, 255, 8, 8) + bounds: 880 480 8 8 + - image: solid-color(111, 60, 0, 255, 8, 8) + bounds: 888 480 8 8 + - image: solid-color(112, 60, 0, 255, 8, 8) + bounds: 896 480 8 8 + - image: solid-color(113, 60, 0, 255, 8, 8) + bounds: 904 480 8 8 + - image: solid-color(114, 60, 0, 255, 8, 8) + bounds: 912 480 8 8 + - image: solid-color(115, 60, 0, 255, 8, 8) + bounds: 920 480 8 8 + - image: solid-color(116, 60, 0, 255, 8, 8) + bounds: 928 480 8 8 + - image: solid-color(117, 60, 0, 255, 8, 8) + bounds: 936 480 8 8 + - image: solid-color(118, 60, 0, 255, 8, 8) + bounds: 944 480 8 8 + - image: solid-color(119, 60, 0, 255, 8, 8) + bounds: 952 480 8 8 + - image: solid-color(120, 60, 0, 255, 8, 8) + bounds: 960 480 8 8 + - image: solid-color(121, 60, 0, 255, 8, 8) + bounds: 968 480 8 8 + - image: solid-color(122, 60, 0, 255, 8, 8) + bounds: 976 480 8 8 + - image: solid-color(123, 60, 0, 255, 8, 8) + bounds: 984 480 8 8 + - image: solid-color(124, 60, 0, 255, 8, 8) + bounds: 992 480 8 8 + - image: solid-color(125, 60, 0, 255, 8, 8) + bounds: 1000 480 8 8 + - image: solid-color(126, 60, 0, 255, 8, 8) + bounds: 1008 480 8 8 + - image: solid-color(127, 60, 0, 255, 8, 8) + bounds: 1016 480 8 8 + - image: solid-color(0, 61, 0, 255, 8, 8) + bounds: 0 488 8 8 + - image: solid-color(1, 61, 0, 255, 8, 8) + bounds: 8 488 8 8 + - image: solid-color(2, 61, 0, 255, 8, 8) + bounds: 16 488 8 8 + - image: solid-color(3, 61, 0, 255, 8, 8) + bounds: 24 488 8 8 + - image: solid-color(4, 61, 0, 255, 8, 8) + bounds: 32 488 8 8 + - image: solid-color(5, 61, 0, 255, 8, 8) + bounds: 40 488 8 8 + - image: solid-color(6, 61, 0, 255, 8, 8) + bounds: 48 488 8 8 + - image: solid-color(7, 61, 0, 255, 8, 8) + bounds: 56 488 8 8 + - image: solid-color(8, 61, 0, 255, 8, 8) + bounds: 64 488 8 8 + - image: solid-color(9, 61, 0, 255, 8, 8) + bounds: 72 488 8 8 + - image: solid-color(10, 61, 0, 255, 8, 8) + bounds: 80 488 8 8 + - image: solid-color(11, 61, 0, 255, 8, 8) + bounds: 88 488 8 8 + - image: solid-color(12, 61, 0, 255, 8, 8) + bounds: 96 488 8 8 + - image: solid-color(13, 61, 0, 255, 8, 8) + bounds: 104 488 8 8 + - image: solid-color(14, 61, 0, 255, 8, 8) + bounds: 112 488 8 8 + - image: solid-color(15, 61, 0, 255, 8, 8) + bounds: 120 488 8 8 + - image: solid-color(16, 61, 0, 255, 8, 8) + bounds: 128 488 8 8 + - image: solid-color(17, 61, 0, 255, 8, 8) + bounds: 136 488 8 8 + - image: solid-color(18, 61, 0, 255, 8, 8) + bounds: 144 488 8 8 + - image: solid-color(19, 61, 0, 255, 8, 8) + bounds: 152 488 8 8 + - image: solid-color(20, 61, 0, 255, 8, 8) + bounds: 160 488 8 8 + - image: solid-color(21, 61, 0, 255, 8, 8) + bounds: 168 488 8 8 + - image: solid-color(22, 61, 0, 255, 8, 8) + bounds: 176 488 8 8 + - image: solid-color(23, 61, 0, 255, 8, 8) + bounds: 184 488 8 8 + - image: solid-color(24, 61, 0, 255, 8, 8) + bounds: 192 488 8 8 + - image: solid-color(25, 61, 0, 255, 8, 8) + bounds: 200 488 8 8 + - image: solid-color(26, 61, 0, 255, 8, 8) + bounds: 208 488 8 8 + - image: solid-color(27, 61, 0, 255, 8, 8) + bounds: 216 488 8 8 + - image: solid-color(28, 61, 0, 255, 8, 8) + bounds: 224 488 8 8 + - image: solid-color(29, 61, 0, 255, 8, 8) + bounds: 232 488 8 8 + - image: solid-color(30, 61, 0, 255, 8, 8) + bounds: 240 488 8 8 + - image: solid-color(31, 61, 0, 255, 8, 8) + bounds: 248 488 8 8 + - image: solid-color(32, 61, 0, 255, 8, 8) + bounds: 256 488 8 8 + - image: solid-color(33, 61, 0, 255, 8, 8) + bounds: 264 488 8 8 + - image: solid-color(34, 61, 0, 255, 8, 8) + bounds: 272 488 8 8 + - image: solid-color(35, 61, 0, 255, 8, 8) + bounds: 280 488 8 8 + - image: solid-color(36, 61, 0, 255, 8, 8) + bounds: 288 488 8 8 + - image: solid-color(37, 61, 0, 255, 8, 8) + bounds: 296 488 8 8 + - image: solid-color(38, 61, 0, 255, 8, 8) + bounds: 304 488 8 8 + - image: solid-color(39, 61, 0, 255, 8, 8) + bounds: 312 488 8 8 + - image: solid-color(40, 61, 0, 255, 8, 8) + bounds: 320 488 8 8 + - image: solid-color(41, 61, 0, 255, 8, 8) + bounds: 328 488 8 8 + - image: solid-color(42, 61, 0, 255, 8, 8) + bounds: 336 488 8 8 + - image: solid-color(43, 61, 0, 255, 8, 8) + bounds: 344 488 8 8 + - image: solid-color(44, 61, 0, 255, 8, 8) + bounds: 352 488 8 8 + - image: solid-color(45, 61, 0, 255, 8, 8) + bounds: 360 488 8 8 + - image: solid-color(46, 61, 0, 255, 8, 8) + bounds: 368 488 8 8 + - image: solid-color(47, 61, 0, 255, 8, 8) + bounds: 376 488 8 8 + - image: solid-color(48, 61, 0, 255, 8, 8) + bounds: 384 488 8 8 + - image: solid-color(49, 61, 0, 255, 8, 8) + bounds: 392 488 8 8 + - image: solid-color(50, 61, 0, 255, 8, 8) + bounds: 400 488 8 8 + - image: solid-color(51, 61, 0, 255, 8, 8) + bounds: 408 488 8 8 + - image: solid-color(52, 61, 0, 255, 8, 8) + bounds: 416 488 8 8 + - image: solid-color(53, 61, 0, 255, 8, 8) + bounds: 424 488 8 8 + - image: solid-color(54, 61, 0, 255, 8, 8) + bounds: 432 488 8 8 + - image: solid-color(55, 61, 0, 255, 8, 8) + bounds: 440 488 8 8 + - image: solid-color(56, 61, 0, 255, 8, 8) + bounds: 448 488 8 8 + - image: solid-color(57, 61, 0, 255, 8, 8) + bounds: 456 488 8 8 + - image: solid-color(58, 61, 0, 255, 8, 8) + bounds: 464 488 8 8 + - image: solid-color(59, 61, 0, 255, 8, 8) + bounds: 472 488 8 8 + - image: solid-color(60, 61, 0, 255, 8, 8) + bounds: 480 488 8 8 + - image: solid-color(61, 61, 0, 255, 8, 8) + bounds: 488 488 8 8 + - image: solid-color(62, 61, 0, 255, 8, 8) + bounds: 496 488 8 8 + - image: solid-color(63, 61, 0, 255, 8, 8) + bounds: 504 488 8 8 + - image: solid-color(64, 61, 0, 255, 8, 8) + bounds: 512 488 8 8 + - image: solid-color(65, 61, 0, 255, 8, 8) + bounds: 520 488 8 8 + - image: solid-color(66, 61, 0, 255, 8, 8) + bounds: 528 488 8 8 + - image: solid-color(67, 61, 0, 255, 8, 8) + bounds: 536 488 8 8 + - image: solid-color(68, 61, 0, 255, 8, 8) + bounds: 544 488 8 8 + - image: solid-color(69, 61, 0, 255, 8, 8) + bounds: 552 488 8 8 + - image: solid-color(70, 61, 0, 255, 8, 8) + bounds: 560 488 8 8 + - image: solid-color(71, 61, 0, 255, 8, 8) + bounds: 568 488 8 8 + - image: solid-color(72, 61, 0, 255, 8, 8) + bounds: 576 488 8 8 + - image: solid-color(73, 61, 0, 255, 8, 8) + bounds: 584 488 8 8 + - image: solid-color(74, 61, 0, 255, 8, 8) + bounds: 592 488 8 8 + - image: solid-color(75, 61, 0, 255, 8, 8) + bounds: 600 488 8 8 + - image: solid-color(76, 61, 0, 255, 8, 8) + bounds: 608 488 8 8 + - image: solid-color(77, 61, 0, 255, 8, 8) + bounds: 616 488 8 8 + - image: solid-color(78, 61, 0, 255, 8, 8) + bounds: 624 488 8 8 + - image: solid-color(79, 61, 0, 255, 8, 8) + bounds: 632 488 8 8 + - image: solid-color(80, 61, 0, 255, 8, 8) + bounds: 640 488 8 8 + - image: solid-color(81, 61, 0, 255, 8, 8) + bounds: 648 488 8 8 + - image: solid-color(82, 61, 0, 255, 8, 8) + bounds: 656 488 8 8 + - image: solid-color(83, 61, 0, 255, 8, 8) + bounds: 664 488 8 8 + - image: solid-color(84, 61, 0, 255, 8, 8) + bounds: 672 488 8 8 + - image: solid-color(85, 61, 0, 255, 8, 8) + bounds: 680 488 8 8 + - image: solid-color(86, 61, 0, 255, 8, 8) + bounds: 688 488 8 8 + - image: solid-color(87, 61, 0, 255, 8, 8) + bounds: 696 488 8 8 + - image: solid-color(88, 61, 0, 255, 8, 8) + bounds: 704 488 8 8 + - image: solid-color(89, 61, 0, 255, 8, 8) + bounds: 712 488 8 8 + - image: solid-color(90, 61, 0, 255, 8, 8) + bounds: 720 488 8 8 + - image: solid-color(91, 61, 0, 255, 8, 8) + bounds: 728 488 8 8 + - image: solid-color(92, 61, 0, 255, 8, 8) + bounds: 736 488 8 8 + - image: solid-color(93, 61, 0, 255, 8, 8) + bounds: 744 488 8 8 + - image: solid-color(94, 61, 0, 255, 8, 8) + bounds: 752 488 8 8 + - image: solid-color(95, 61, 0, 255, 8, 8) + bounds: 760 488 8 8 + - image: solid-color(96, 61, 0, 255, 8, 8) + bounds: 768 488 8 8 + - image: solid-color(97, 61, 0, 255, 8, 8) + bounds: 776 488 8 8 + - image: solid-color(98, 61, 0, 255, 8, 8) + bounds: 784 488 8 8 + - image: solid-color(99, 61, 0, 255, 8, 8) + bounds: 792 488 8 8 + - image: solid-color(100, 61, 0, 255, 8, 8) + bounds: 800 488 8 8 + - image: solid-color(101, 61, 0, 255, 8, 8) + bounds: 808 488 8 8 + - image: solid-color(102, 61, 0, 255, 8, 8) + bounds: 816 488 8 8 + - image: solid-color(103, 61, 0, 255, 8, 8) + bounds: 824 488 8 8 + - image: solid-color(104, 61, 0, 255, 8, 8) + bounds: 832 488 8 8 + - image: solid-color(105, 61, 0, 255, 8, 8) + bounds: 840 488 8 8 + - image: solid-color(106, 61, 0, 255, 8, 8) + bounds: 848 488 8 8 + - image: solid-color(107, 61, 0, 255, 8, 8) + bounds: 856 488 8 8 + - image: solid-color(108, 61, 0, 255, 8, 8) + bounds: 864 488 8 8 + - image: solid-color(109, 61, 0, 255, 8, 8) + bounds: 872 488 8 8 + - image: solid-color(110, 61, 0, 255, 8, 8) + bounds: 880 488 8 8 + - image: solid-color(111, 61, 0, 255, 8, 8) + bounds: 888 488 8 8 + - image: solid-color(112, 61, 0, 255, 8, 8) + bounds: 896 488 8 8 + - image: solid-color(113, 61, 0, 255, 8, 8) + bounds: 904 488 8 8 + - image: solid-color(114, 61, 0, 255, 8, 8) + bounds: 912 488 8 8 + - image: solid-color(115, 61, 0, 255, 8, 8) + bounds: 920 488 8 8 + - image: solid-color(116, 61, 0, 255, 8, 8) + bounds: 928 488 8 8 + - image: solid-color(117, 61, 0, 255, 8, 8) + bounds: 936 488 8 8 + - image: solid-color(118, 61, 0, 255, 8, 8) + bounds: 944 488 8 8 + - image: solid-color(119, 61, 0, 255, 8, 8) + bounds: 952 488 8 8 + - image: solid-color(120, 61, 0, 255, 8, 8) + bounds: 960 488 8 8 + - image: solid-color(121, 61, 0, 255, 8, 8) + bounds: 968 488 8 8 + - image: solid-color(122, 61, 0, 255, 8, 8) + bounds: 976 488 8 8 + - image: solid-color(123, 61, 0, 255, 8, 8) + bounds: 984 488 8 8 + - image: solid-color(124, 61, 0, 255, 8, 8) + bounds: 992 488 8 8 + - image: solid-color(125, 61, 0, 255, 8, 8) + bounds: 1000 488 8 8 + - image: solid-color(126, 61, 0, 255, 8, 8) + bounds: 1008 488 8 8 + - image: solid-color(127, 61, 0, 255, 8, 8) + bounds: 1016 488 8 8 + - image: solid-color(0, 62, 0, 255, 8, 8) + bounds: 0 496 8 8 + - image: solid-color(1, 62, 0, 255, 8, 8) + bounds: 8 496 8 8 + - image: solid-color(2, 62, 0, 255, 8, 8) + bounds: 16 496 8 8 + - image: solid-color(3, 62, 0, 255, 8, 8) + bounds: 24 496 8 8 + - image: solid-color(4, 62, 0, 255, 8, 8) + bounds: 32 496 8 8 + - image: solid-color(5, 62, 0, 255, 8, 8) + bounds: 40 496 8 8 + - image: solid-color(6, 62, 0, 255, 8, 8) + bounds: 48 496 8 8 + - image: solid-color(7, 62, 0, 255, 8, 8) + bounds: 56 496 8 8 + - image: solid-color(8, 62, 0, 255, 8, 8) + bounds: 64 496 8 8 + - image: solid-color(9, 62, 0, 255, 8, 8) + bounds: 72 496 8 8 + - image: solid-color(10, 62, 0, 255, 8, 8) + bounds: 80 496 8 8 + - image: solid-color(11, 62, 0, 255, 8, 8) + bounds: 88 496 8 8 + - image: solid-color(12, 62, 0, 255, 8, 8) + bounds: 96 496 8 8 + - image: solid-color(13, 62, 0, 255, 8, 8) + bounds: 104 496 8 8 + - image: solid-color(14, 62, 0, 255, 8, 8) + bounds: 112 496 8 8 + - image: solid-color(15, 62, 0, 255, 8, 8) + bounds: 120 496 8 8 + - image: solid-color(16, 62, 0, 255, 8, 8) + bounds: 128 496 8 8 + - image: solid-color(17, 62, 0, 255, 8, 8) + bounds: 136 496 8 8 + - image: solid-color(18, 62, 0, 255, 8, 8) + bounds: 144 496 8 8 + - image: solid-color(19, 62, 0, 255, 8, 8) + bounds: 152 496 8 8 + - image: solid-color(20, 62, 0, 255, 8, 8) + bounds: 160 496 8 8 + - image: solid-color(21, 62, 0, 255, 8, 8) + bounds: 168 496 8 8 + - image: solid-color(22, 62, 0, 255, 8, 8) + bounds: 176 496 8 8 + - image: solid-color(23, 62, 0, 255, 8, 8) + bounds: 184 496 8 8 + - image: solid-color(24, 62, 0, 255, 8, 8) + bounds: 192 496 8 8 + - image: solid-color(25, 62, 0, 255, 8, 8) + bounds: 200 496 8 8 + - image: solid-color(26, 62, 0, 255, 8, 8) + bounds: 208 496 8 8 + - image: solid-color(27, 62, 0, 255, 8, 8) + bounds: 216 496 8 8 + - image: solid-color(28, 62, 0, 255, 8, 8) + bounds: 224 496 8 8 + - image: solid-color(29, 62, 0, 255, 8, 8) + bounds: 232 496 8 8 + - image: solid-color(30, 62, 0, 255, 8, 8) + bounds: 240 496 8 8 + - image: solid-color(31, 62, 0, 255, 8, 8) + bounds: 248 496 8 8 + - image: solid-color(32, 62, 0, 255, 8, 8) + bounds: 256 496 8 8 + - image: solid-color(33, 62, 0, 255, 8, 8) + bounds: 264 496 8 8 + - image: solid-color(34, 62, 0, 255, 8, 8) + bounds: 272 496 8 8 + - image: solid-color(35, 62, 0, 255, 8, 8) + bounds: 280 496 8 8 + - image: solid-color(36, 62, 0, 255, 8, 8) + bounds: 288 496 8 8 + - image: solid-color(37, 62, 0, 255, 8, 8) + bounds: 296 496 8 8 + - image: solid-color(38, 62, 0, 255, 8, 8) + bounds: 304 496 8 8 + - image: solid-color(39, 62, 0, 255, 8, 8) + bounds: 312 496 8 8 + - image: solid-color(40, 62, 0, 255, 8, 8) + bounds: 320 496 8 8 + - image: solid-color(41, 62, 0, 255, 8, 8) + bounds: 328 496 8 8 + - image: solid-color(42, 62, 0, 255, 8, 8) + bounds: 336 496 8 8 + - image: solid-color(43, 62, 0, 255, 8, 8) + bounds: 344 496 8 8 + - image: solid-color(44, 62, 0, 255, 8, 8) + bounds: 352 496 8 8 + - image: solid-color(45, 62, 0, 255, 8, 8) + bounds: 360 496 8 8 + - image: solid-color(46, 62, 0, 255, 8, 8) + bounds: 368 496 8 8 + - image: solid-color(47, 62, 0, 255, 8, 8) + bounds: 376 496 8 8 + - image: solid-color(48, 62, 0, 255, 8, 8) + bounds: 384 496 8 8 + - image: solid-color(49, 62, 0, 255, 8, 8) + bounds: 392 496 8 8 + - image: solid-color(50, 62, 0, 255, 8, 8) + bounds: 400 496 8 8 + - image: solid-color(51, 62, 0, 255, 8, 8) + bounds: 408 496 8 8 + - image: solid-color(52, 62, 0, 255, 8, 8) + bounds: 416 496 8 8 + - image: solid-color(53, 62, 0, 255, 8, 8) + bounds: 424 496 8 8 + - image: solid-color(54, 62, 0, 255, 8, 8) + bounds: 432 496 8 8 + - image: solid-color(55, 62, 0, 255, 8, 8) + bounds: 440 496 8 8 + - image: solid-color(56, 62, 0, 255, 8, 8) + bounds: 448 496 8 8 + - image: solid-color(57, 62, 0, 255, 8, 8) + bounds: 456 496 8 8 + - image: solid-color(58, 62, 0, 255, 8, 8) + bounds: 464 496 8 8 + - image: solid-color(59, 62, 0, 255, 8, 8) + bounds: 472 496 8 8 + - image: solid-color(60, 62, 0, 255, 8, 8) + bounds: 480 496 8 8 + - image: solid-color(61, 62, 0, 255, 8, 8) + bounds: 488 496 8 8 + - image: solid-color(62, 62, 0, 255, 8, 8) + bounds: 496 496 8 8 + - image: solid-color(63, 62, 0, 255, 8, 8) + bounds: 504 496 8 8 + - image: solid-color(64, 62, 0, 255, 8, 8) + bounds: 512 496 8 8 + - image: solid-color(65, 62, 0, 255, 8, 8) + bounds: 520 496 8 8 + - image: solid-color(66, 62, 0, 255, 8, 8) + bounds: 528 496 8 8 + - image: solid-color(67, 62, 0, 255, 8, 8) + bounds: 536 496 8 8 + - image: solid-color(68, 62, 0, 255, 8, 8) + bounds: 544 496 8 8 + - image: solid-color(69, 62, 0, 255, 8, 8) + bounds: 552 496 8 8 + - image: solid-color(70, 62, 0, 255, 8, 8) + bounds: 560 496 8 8 + - image: solid-color(71, 62, 0, 255, 8, 8) + bounds: 568 496 8 8 + - image: solid-color(72, 62, 0, 255, 8, 8) + bounds: 576 496 8 8 + - image: solid-color(73, 62, 0, 255, 8, 8) + bounds: 584 496 8 8 + - image: solid-color(74, 62, 0, 255, 8, 8) + bounds: 592 496 8 8 + - image: solid-color(75, 62, 0, 255, 8, 8) + bounds: 600 496 8 8 + - image: solid-color(76, 62, 0, 255, 8, 8) + bounds: 608 496 8 8 + - image: solid-color(77, 62, 0, 255, 8, 8) + bounds: 616 496 8 8 + - image: solid-color(78, 62, 0, 255, 8, 8) + bounds: 624 496 8 8 + - image: solid-color(79, 62, 0, 255, 8, 8) + bounds: 632 496 8 8 + - image: solid-color(80, 62, 0, 255, 8, 8) + bounds: 640 496 8 8 + - image: solid-color(81, 62, 0, 255, 8, 8) + bounds: 648 496 8 8 + - image: solid-color(82, 62, 0, 255, 8, 8) + bounds: 656 496 8 8 + - image: solid-color(83, 62, 0, 255, 8, 8) + bounds: 664 496 8 8 + - image: solid-color(84, 62, 0, 255, 8, 8) + bounds: 672 496 8 8 + - image: solid-color(85, 62, 0, 255, 8, 8) + bounds: 680 496 8 8 + - image: solid-color(86, 62, 0, 255, 8, 8) + bounds: 688 496 8 8 + - image: solid-color(87, 62, 0, 255, 8, 8) + bounds: 696 496 8 8 + - image: solid-color(88, 62, 0, 255, 8, 8) + bounds: 704 496 8 8 + - image: solid-color(89, 62, 0, 255, 8, 8) + bounds: 712 496 8 8 + - image: solid-color(90, 62, 0, 255, 8, 8) + bounds: 720 496 8 8 + - image: solid-color(91, 62, 0, 255, 8, 8) + bounds: 728 496 8 8 + - image: solid-color(92, 62, 0, 255, 8, 8) + bounds: 736 496 8 8 + - image: solid-color(93, 62, 0, 255, 8, 8) + bounds: 744 496 8 8 + - image: solid-color(94, 62, 0, 255, 8, 8) + bounds: 752 496 8 8 + - image: solid-color(95, 62, 0, 255, 8, 8) + bounds: 760 496 8 8 + - image: solid-color(96, 62, 0, 255, 8, 8) + bounds: 768 496 8 8 + - image: solid-color(97, 62, 0, 255, 8, 8) + bounds: 776 496 8 8 + - image: solid-color(98, 62, 0, 255, 8, 8) + bounds: 784 496 8 8 + - image: solid-color(99, 62, 0, 255, 8, 8) + bounds: 792 496 8 8 + - image: solid-color(100, 62, 0, 255, 8, 8) + bounds: 800 496 8 8 + - image: solid-color(101, 62, 0, 255, 8, 8) + bounds: 808 496 8 8 + - image: solid-color(102, 62, 0, 255, 8, 8) + bounds: 816 496 8 8 + - image: solid-color(103, 62, 0, 255, 8, 8) + bounds: 824 496 8 8 + - image: solid-color(104, 62, 0, 255, 8, 8) + bounds: 832 496 8 8 + - image: solid-color(105, 62, 0, 255, 8, 8) + bounds: 840 496 8 8 + - image: solid-color(106, 62, 0, 255, 8, 8) + bounds: 848 496 8 8 + - image: solid-color(107, 62, 0, 255, 8, 8) + bounds: 856 496 8 8 + - image: solid-color(108, 62, 0, 255, 8, 8) + bounds: 864 496 8 8 + - image: solid-color(109, 62, 0, 255, 8, 8) + bounds: 872 496 8 8 + - image: solid-color(110, 62, 0, 255, 8, 8) + bounds: 880 496 8 8 + - image: solid-color(111, 62, 0, 255, 8, 8) + bounds: 888 496 8 8 + - image: solid-color(112, 62, 0, 255, 8, 8) + bounds: 896 496 8 8 + - image: solid-color(113, 62, 0, 255, 8, 8) + bounds: 904 496 8 8 + - image: solid-color(114, 62, 0, 255, 8, 8) + bounds: 912 496 8 8 + - image: solid-color(115, 62, 0, 255, 8, 8) + bounds: 920 496 8 8 + - image: solid-color(116, 62, 0, 255, 8, 8) + bounds: 928 496 8 8 + - image: solid-color(117, 62, 0, 255, 8, 8) + bounds: 936 496 8 8 + - image: solid-color(118, 62, 0, 255, 8, 8) + bounds: 944 496 8 8 + - image: solid-color(119, 62, 0, 255, 8, 8) + bounds: 952 496 8 8 + - image: solid-color(120, 62, 0, 255, 8, 8) + bounds: 960 496 8 8 + - image: solid-color(121, 62, 0, 255, 8, 8) + bounds: 968 496 8 8 + - image: solid-color(122, 62, 0, 255, 8, 8) + bounds: 976 496 8 8 + - image: solid-color(123, 62, 0, 255, 8, 8) + bounds: 984 496 8 8 + - image: solid-color(124, 62, 0, 255, 8, 8) + bounds: 992 496 8 8 + - image: solid-color(125, 62, 0, 255, 8, 8) + bounds: 1000 496 8 8 + - image: solid-color(126, 62, 0, 255, 8, 8) + bounds: 1008 496 8 8 + - image: solid-color(127, 62, 0, 255, 8, 8) + bounds: 1016 496 8 8 + - image: solid-color(0, 63, 0, 255, 8, 8) + bounds: 0 504 8 8 + - image: solid-color(1, 63, 0, 255, 8, 8) + bounds: 8 504 8 8 + - image: solid-color(2, 63, 0, 255, 8, 8) + bounds: 16 504 8 8 + - image: solid-color(3, 63, 0, 255, 8, 8) + bounds: 24 504 8 8 + - image: solid-color(4, 63, 0, 255, 8, 8) + bounds: 32 504 8 8 + - image: solid-color(5, 63, 0, 255, 8, 8) + bounds: 40 504 8 8 + - image: solid-color(6, 63, 0, 255, 8, 8) + bounds: 48 504 8 8 + - image: solid-color(7, 63, 0, 255, 8, 8) + bounds: 56 504 8 8 + - image: solid-color(8, 63, 0, 255, 8, 8) + bounds: 64 504 8 8 + - image: solid-color(9, 63, 0, 255, 8, 8) + bounds: 72 504 8 8 + - image: solid-color(10, 63, 0, 255, 8, 8) + bounds: 80 504 8 8 + - image: solid-color(11, 63, 0, 255, 8, 8) + bounds: 88 504 8 8 + - image: solid-color(12, 63, 0, 255, 8, 8) + bounds: 96 504 8 8 + - image: solid-color(13, 63, 0, 255, 8, 8) + bounds: 104 504 8 8 + - image: solid-color(14, 63, 0, 255, 8, 8) + bounds: 112 504 8 8 + - image: solid-color(15, 63, 0, 255, 8, 8) + bounds: 120 504 8 8 + - image: solid-color(16, 63, 0, 255, 8, 8) + bounds: 128 504 8 8 + - image: solid-color(17, 63, 0, 255, 8, 8) + bounds: 136 504 8 8 + - image: solid-color(18, 63, 0, 255, 8, 8) + bounds: 144 504 8 8 + - image: solid-color(19, 63, 0, 255, 8, 8) + bounds: 152 504 8 8 + - image: solid-color(20, 63, 0, 255, 8, 8) + bounds: 160 504 8 8 + - image: solid-color(21, 63, 0, 255, 8, 8) + bounds: 168 504 8 8 + - image: solid-color(22, 63, 0, 255, 8, 8) + bounds: 176 504 8 8 + - image: solid-color(23, 63, 0, 255, 8, 8) + bounds: 184 504 8 8 + - image: solid-color(24, 63, 0, 255, 8, 8) + bounds: 192 504 8 8 + - image: solid-color(25, 63, 0, 255, 8, 8) + bounds: 200 504 8 8 + - image: solid-color(26, 63, 0, 255, 8, 8) + bounds: 208 504 8 8 + - image: solid-color(27, 63, 0, 255, 8, 8) + bounds: 216 504 8 8 + - image: solid-color(28, 63, 0, 255, 8, 8) + bounds: 224 504 8 8 + - image: solid-color(29, 63, 0, 255, 8, 8) + bounds: 232 504 8 8 + - image: solid-color(30, 63, 0, 255, 8, 8) + bounds: 240 504 8 8 + - image: solid-color(31, 63, 0, 255, 8, 8) + bounds: 248 504 8 8 + - image: solid-color(32, 63, 0, 255, 8, 8) + bounds: 256 504 8 8 + - image: solid-color(33, 63, 0, 255, 8, 8) + bounds: 264 504 8 8 + - image: solid-color(34, 63, 0, 255, 8, 8) + bounds: 272 504 8 8 + - image: solid-color(35, 63, 0, 255, 8, 8) + bounds: 280 504 8 8 + - image: solid-color(36, 63, 0, 255, 8, 8) + bounds: 288 504 8 8 + - image: solid-color(37, 63, 0, 255, 8, 8) + bounds: 296 504 8 8 + - image: solid-color(38, 63, 0, 255, 8, 8) + bounds: 304 504 8 8 + - image: solid-color(39, 63, 0, 255, 8, 8) + bounds: 312 504 8 8 + - image: solid-color(40, 63, 0, 255, 8, 8) + bounds: 320 504 8 8 + - image: solid-color(41, 63, 0, 255, 8, 8) + bounds: 328 504 8 8 + - image: solid-color(42, 63, 0, 255, 8, 8) + bounds: 336 504 8 8 + - image: solid-color(43, 63, 0, 255, 8, 8) + bounds: 344 504 8 8 + - image: solid-color(44, 63, 0, 255, 8, 8) + bounds: 352 504 8 8 + - image: solid-color(45, 63, 0, 255, 8, 8) + bounds: 360 504 8 8 + - image: solid-color(46, 63, 0, 255, 8, 8) + bounds: 368 504 8 8 + - image: solid-color(47, 63, 0, 255, 8, 8) + bounds: 376 504 8 8 + - image: solid-color(48, 63, 0, 255, 8, 8) + bounds: 384 504 8 8 + - image: solid-color(49, 63, 0, 255, 8, 8) + bounds: 392 504 8 8 + - image: solid-color(50, 63, 0, 255, 8, 8) + bounds: 400 504 8 8 + - image: solid-color(51, 63, 0, 255, 8, 8) + bounds: 408 504 8 8 + - image: solid-color(52, 63, 0, 255, 8, 8) + bounds: 416 504 8 8 + - image: solid-color(53, 63, 0, 255, 8, 8) + bounds: 424 504 8 8 + - image: solid-color(54, 63, 0, 255, 8, 8) + bounds: 432 504 8 8 + - image: solid-color(55, 63, 0, 255, 8, 8) + bounds: 440 504 8 8 + - image: solid-color(56, 63, 0, 255, 8, 8) + bounds: 448 504 8 8 + - image: solid-color(57, 63, 0, 255, 8, 8) + bounds: 456 504 8 8 + - image: solid-color(58, 63, 0, 255, 8, 8) + bounds: 464 504 8 8 + - image: solid-color(59, 63, 0, 255, 8, 8) + bounds: 472 504 8 8 + - image: solid-color(60, 63, 0, 255, 8, 8) + bounds: 480 504 8 8 + - image: solid-color(61, 63, 0, 255, 8, 8) + bounds: 488 504 8 8 + - image: solid-color(62, 63, 0, 255, 8, 8) + bounds: 496 504 8 8 + - image: solid-color(63, 63, 0, 255, 8, 8) + bounds: 504 504 8 8 + - image: solid-color(64, 63, 0, 255, 8, 8) + bounds: 512 504 8 8 + - image: solid-color(65, 63, 0, 255, 8, 8) + bounds: 520 504 8 8 + - image: solid-color(66, 63, 0, 255, 8, 8) + bounds: 528 504 8 8 + - image: solid-color(67, 63, 0, 255, 8, 8) + bounds: 536 504 8 8 + - image: solid-color(68, 63, 0, 255, 8, 8) + bounds: 544 504 8 8 + - image: solid-color(69, 63, 0, 255, 8, 8) + bounds: 552 504 8 8 + - image: solid-color(70, 63, 0, 255, 8, 8) + bounds: 560 504 8 8 + - image: solid-color(71, 63, 0, 255, 8, 8) + bounds: 568 504 8 8 + - image: solid-color(72, 63, 0, 255, 8, 8) + bounds: 576 504 8 8 + - image: solid-color(73, 63, 0, 255, 8, 8) + bounds: 584 504 8 8 + - image: solid-color(74, 63, 0, 255, 8, 8) + bounds: 592 504 8 8 + - image: solid-color(75, 63, 0, 255, 8, 8) + bounds: 600 504 8 8 + - image: solid-color(76, 63, 0, 255, 8, 8) + bounds: 608 504 8 8 + - image: solid-color(77, 63, 0, 255, 8, 8) + bounds: 616 504 8 8 + - image: solid-color(78, 63, 0, 255, 8, 8) + bounds: 624 504 8 8 + - image: solid-color(79, 63, 0, 255, 8, 8) + bounds: 632 504 8 8 + - image: solid-color(80, 63, 0, 255, 8, 8) + bounds: 640 504 8 8 + - image: solid-color(81, 63, 0, 255, 8, 8) + bounds: 648 504 8 8 + - image: solid-color(82, 63, 0, 255, 8, 8) + bounds: 656 504 8 8 + - image: solid-color(83, 63, 0, 255, 8, 8) + bounds: 664 504 8 8 + - image: solid-color(84, 63, 0, 255, 8, 8) + bounds: 672 504 8 8 + - image: solid-color(85, 63, 0, 255, 8, 8) + bounds: 680 504 8 8 + - image: solid-color(86, 63, 0, 255, 8, 8) + bounds: 688 504 8 8 + - image: solid-color(87, 63, 0, 255, 8, 8) + bounds: 696 504 8 8 + - image: solid-color(88, 63, 0, 255, 8, 8) + bounds: 704 504 8 8 + - image: solid-color(89, 63, 0, 255, 8, 8) + bounds: 712 504 8 8 + - image: solid-color(90, 63, 0, 255, 8, 8) + bounds: 720 504 8 8 + - image: solid-color(91, 63, 0, 255, 8, 8) + bounds: 728 504 8 8 + - image: solid-color(92, 63, 0, 255, 8, 8) + bounds: 736 504 8 8 + - image: solid-color(93, 63, 0, 255, 8, 8) + bounds: 744 504 8 8 + - image: solid-color(94, 63, 0, 255, 8, 8) + bounds: 752 504 8 8 + - image: solid-color(95, 63, 0, 255, 8, 8) + bounds: 760 504 8 8 + - image: solid-color(96, 63, 0, 255, 8, 8) + bounds: 768 504 8 8 + - image: solid-color(97, 63, 0, 255, 8, 8) + bounds: 776 504 8 8 + - image: solid-color(98, 63, 0, 255, 8, 8) + bounds: 784 504 8 8 + - image: solid-color(99, 63, 0, 255, 8, 8) + bounds: 792 504 8 8 + - image: solid-color(100, 63, 0, 255, 8, 8) + bounds: 800 504 8 8 + - image: solid-color(101, 63, 0, 255, 8, 8) + bounds: 808 504 8 8 + - image: solid-color(102, 63, 0, 255, 8, 8) + bounds: 816 504 8 8 + - image: solid-color(103, 63, 0, 255, 8, 8) + bounds: 824 504 8 8 + - image: solid-color(104, 63, 0, 255, 8, 8) + bounds: 832 504 8 8 + - image: solid-color(105, 63, 0, 255, 8, 8) + bounds: 840 504 8 8 + - image: solid-color(106, 63, 0, 255, 8, 8) + bounds: 848 504 8 8 + - image: solid-color(107, 63, 0, 255, 8, 8) + bounds: 856 504 8 8 + - image: solid-color(108, 63, 0, 255, 8, 8) + bounds: 864 504 8 8 + - image: solid-color(109, 63, 0, 255, 8, 8) + bounds: 872 504 8 8 + - image: solid-color(110, 63, 0, 255, 8, 8) + bounds: 880 504 8 8 + - image: solid-color(111, 63, 0, 255, 8, 8) + bounds: 888 504 8 8 + - image: solid-color(112, 63, 0, 255, 8, 8) + bounds: 896 504 8 8 + - image: solid-color(113, 63, 0, 255, 8, 8) + bounds: 904 504 8 8 + - image: solid-color(114, 63, 0, 255, 8, 8) + bounds: 912 504 8 8 + - image: solid-color(115, 63, 0, 255, 8, 8) + bounds: 920 504 8 8 + - image: solid-color(116, 63, 0, 255, 8, 8) + bounds: 928 504 8 8 + - image: solid-color(117, 63, 0, 255, 8, 8) + bounds: 936 504 8 8 + - image: solid-color(118, 63, 0, 255, 8, 8) + bounds: 944 504 8 8 + - image: solid-color(119, 63, 0, 255, 8, 8) + bounds: 952 504 8 8 + - image: solid-color(120, 63, 0, 255, 8, 8) + bounds: 960 504 8 8 + - image: solid-color(121, 63, 0, 255, 8, 8) + bounds: 968 504 8 8 + - image: solid-color(122, 63, 0, 255, 8, 8) + bounds: 976 504 8 8 + - image: solid-color(123, 63, 0, 255, 8, 8) + bounds: 984 504 8 8 + - image: solid-color(124, 63, 0, 255, 8, 8) + bounds: 992 504 8 8 + - image: solid-color(125, 63, 0, 255, 8, 8) + bounds: 1000 504 8 8 + - image: solid-color(126, 63, 0, 255, 8, 8) + bounds: 1008 504 8 8 + - image: solid-color(127, 63, 0, 255, 8, 8) + bounds: 1016 504 8 8 diff --git a/gfx/wr/wrench/benchmarks/overlapping-text-shadows.yaml b/gfx/wr/wrench/benchmarks/overlapping-text-shadows.yaml new file mode 100644 index 0000000000..d32d4aa45c --- /dev/null +++ b/gfx/wr/wrench/benchmarks/overlapping-text-shadows.yaml @@ -0,0 +1,807 @@ +root: + items: + - + type: "shadow" + offset: [0, 0] + color: red + - + type: "shadow" + offset: [1, 1] + color: red + - + type: "shadow" + offset: [2, 2] + color: red + - + type: "shadow" + offset: [3, 3] + color: red + - + type: "shadow" + offset: [4, 4] + color: red + - + type: "shadow" + offset: [5, 5] + color: red + - + type: "shadow" + offset: [6, 6] + color: red + - + type: "shadow" + offset: [7, 7] + color: red + - + type: "shadow" + offset: [8, 8] + color: red + - + type: "shadow" + offset: [9, 9] + color: red + - + type: "shadow" + offset: [10, 10] + color: red + - + type: "shadow" + offset: [11, 11] + color: red + - + type: "shadow" + offset: [12, 12] + color: red + - + type: "shadow" + offset: [13, 13] + color: red + - + type: "shadow" + offset: [14, 14] + color: red + - + type: "shadow" + offset: [15, 15] + color: red + - + type: "shadow" + offset: [16, 16] + color: red + - + type: "shadow" + offset: [17, 17] + color: red + - + type: "shadow" + offset: [18, 18] + color: red + - + type: "shadow" + offset: [19, 19] + color: red + - + type: "shadow" + offset: [20, 20] + color: red + - + type: "shadow" + offset: [21, 21] + color: red + - + type: "shadow" + offset: [22, 22] + color: red + - + type: "shadow" + offset: [23, 23] + color: red + - + type: "shadow" + offset: [24, 24] + color: red + - + type: "shadow" + offset: [25, 25] + color: red + - + type: "shadow" + offset: [26, 26] + color: red + - + type: "shadow" + offset: [27, 27] + color: red + - + type: "shadow" + offset: [28, 28] + color: red + - + type: "shadow" + offset: [29, 29] + color: red + - + type: "shadow" + offset: [30, 30] + color: red + - + type: "shadow" + offset: [31, 31] + color: red + - + type: "shadow" + offset: [32, 32] + color: red + - + type: "shadow" + offset: [33, 33] + color: red + - + type: "shadow" + offset: [34, 34] + color: red + - + type: "shadow" + offset: [35, 35] + color: red + - + type: "shadow" + offset: [36, 36] + color: red + - + type: "shadow" + offset: [37, 37] + color: red + - + type: "shadow" + offset: [38, 38] + color: red + - + type: "shadow" + offset: [39, 39] + color: red + - + type: "shadow" + offset: [40, 40] + color: red + - + type: "shadow" + offset: [41, 41] + color: red + - + type: "shadow" + offset: [42, 42] + color: red + - + type: "shadow" + offset: [43, 43] + color: red + - + type: "shadow" + offset: [44, 44] + color: red + - + type: "shadow" + offset: [45, 45] + color: red + - + type: "shadow" + offset: [46, 46] + color: red + - + type: "shadow" + offset: [47, 47] + color: red + - + type: "shadow" + offset: [48, 48] + color: red + - + type: "shadow" + offset: [49, 49] + color: red + - + type: "shadow" + offset: [50, 50] + color: red + - + type: "shadow" + offset: [51, 51] + color: red + - + type: "shadow" + offset: [52, 52] + color: red + - + type: "shadow" + offset: [53, 53] + color: red + - + type: "shadow" + offset: [54, 54] + color: red + - + type: "shadow" + offset: [55, 55] + color: red + - + type: "shadow" + offset: [56, 56] + color: red + - + type: "shadow" + offset: [57, 57] + color: red + - + type: "shadow" + offset: [58, 58] + color: red + - + type: "shadow" + offset: [59, 59] + color: red + - + type: "shadow" + offset: [60, 60] + color: red + - + type: "shadow" + offset: [61, 61] + color: red + - + type: "shadow" + offset: [62, 62] + color: red + - + type: "shadow" + offset: [63, 63] + color: red + - + type: "shadow" + offset: [64, 64] + color: red + - + type: "shadow" + offset: [65, 65] + color: red + - + type: "shadow" + offset: [66, 66] + color: red + - + type: "shadow" + offset: [67, 67] + color: red + - + type: "shadow" + offset: [68, 68] + color: red + - + type: "shadow" + offset: [69, 69] + color: red + - + type: "shadow" + offset: [70, 70] + color: red + - + type: "shadow" + offset: [71, 71] + color: red + - + type: "shadow" + offset: [72, 72] + color: red + - + type: "shadow" + offset: [73, 73] + color: red + - + type: "shadow" + offset: [74, 74] + color: red + - + type: "shadow" + offset: [75, 75] + color: red + - + type: "shadow" + offset: [76, 76] + color: red + - + type: "shadow" + offset: [77, 77] + color: red + - + type: "shadow" + offset: [78, 78] + color: red + - + type: "shadow" + offset: [79, 79] + color: red + - + type: "shadow" + offset: [80, 80] + color: red + - + type: "shadow" + offset: [81, 81] + color: red + - + type: "shadow" + offset: [82, 82] + color: red + - + type: "shadow" + offset: [83, 83] + color: red + - + type: "shadow" + offset: [84, 84] + color: red + - + type: "shadow" + offset: [85, 85] + color: red + - + type: "shadow" + offset: [86, 86] + color: red + - + type: "shadow" + offset: [87, 87] + color: red + - + type: "shadow" + offset: [88, 88] + color: red + - + type: "shadow" + offset: [89, 89] + color: red + - + type: "shadow" + offset: [90, 90] + color: red + - + type: "shadow" + offset: [91, 91] + color: red + - + type: "shadow" + offset: [92, 92] + color: red + - + type: "shadow" + offset: [93, 93] + color: red + - + type: "shadow" + offset: [94, 94] + color: red + - + type: "shadow" + offset: [95, 95] + color: red + - + type: "shadow" + offset: [96, 96] + color: red + - + type: "shadow" + offset: [97, 97] + color: red + - + type: "shadow" + offset: [98, 98] + color: red + - + type: "shadow" + offset: [99, 99] + color: red + - + type: "shadow" + offset: [100, 100] + color: red + - + type: "shadow" + offset: [101, 101] + color: red + - + type: "shadow" + offset: [102, 102] + color: red + - + type: "shadow" + offset: [103, 103] + color: red + - + type: "shadow" + offset: [104, 104] + color: red + - + type: "shadow" + offset: [105, 105] + color: red + - + type: "shadow" + offset: [106, 106] + color: red + - + type: "shadow" + offset: [107, 107] + color: red + - + type: "shadow" + offset: [108, 108] + color: red + - + type: "shadow" + offset: [109, 109] + color: red + - + type: "shadow" + offset: [110, 110] + color: red + - + type: "shadow" + offset: [111, 111] + color: red + - + type: "shadow" + offset: [112, 112] + color: red + - + type: "shadow" + offset: [113, 113] + color: red + - + type: "shadow" + offset: [114, 114] + color: red + - + type: "shadow" + offset: [115, 115] + color: red + - + type: "shadow" + offset: [116, 116] + color: red + - + type: "shadow" + offset: [117, 117] + color: red + - + type: "shadow" + offset: [118, 118] + color: red + - + type: "shadow" + offset: [119, 119] + color: red + - + type: "shadow" + offset: [120, 120] + color: red + - + type: "shadow" + offset: [121, 121] + color: red + - + type: "shadow" + offset: [122, 122] + color: red + - + type: "shadow" + offset: [123, 123] + color: red + - + type: "shadow" + offset: [124, 124] + color: red + - + type: "shadow" + offset: [125, 125] + color: red + - + type: "shadow" + offset: [126, 126] + color: red + - + type: "shadow" + offset: [127, 127] + color: red + - + type: "shadow" + offset: [128, 128] + color: red + - + type: "shadow" + offset: [129, 129] + color: red + - + type: "shadow" + offset: [130, 130] + color: red + - + type: "shadow" + offset: [131, 131] + color: red + - + type: "shadow" + offset: [132, 132] + color: red + - + type: "shadow" + offset: [133, 133] + color: red + - + type: "shadow" + offset: [134, 134] + color: red + - + type: "shadow" + offset: [135, 135] + color: red + - + type: "shadow" + offset: [136, 136] + color: red + - + type: "shadow" + offset: [137, 137] + color: red + - + type: "shadow" + offset: [138, 138] + color: red + - + type: "shadow" + offset: [139, 139] + color: red + - + type: "shadow" + offset: [140, 140] + color: red + - + type: "shadow" + offset: [141, 141] + color: red + - + type: "shadow" + offset: [142, 142] + color: red + - + type: "shadow" + offset: [143, 143] + color: red + - + type: "shadow" + offset: [144, 144] + color: red + - + type: "shadow" + offset: [145, 145] + color: red + - + type: "shadow" + offset: [146, 146] + color: red + - + type: "shadow" + offset: [147, 147] + color: red + - + type: "shadow" + offset: [148, 148] + color: red + - + type: "shadow" + offset: [149, 149] + color: red + - + type: "shadow" + offset: [150, 150] + color: red + - + type: "shadow" + offset: [151, 151] + color: red + - + type: "shadow" + offset: [152, 152] + color: red + - + type: "shadow" + offset: [153, 153] + color: red + - + type: "shadow" + offset: [154, 154] + color: red + - + type: "shadow" + offset: [155, 155] + color: red + - + type: "shadow" + offset: [156, 156] + color: red + - + type: "shadow" + offset: [157, 157] + color: red + - + type: "shadow" + offset: [158, 158] + color: red + - + type: "shadow" + offset: [159, 159] + color: red + - + type: "shadow" + offset: [160, 160] + color: red + - + type: "shadow" + offset: [161, 161] + color: red + - + type: "shadow" + offset: [162, 162] + color: red + - + type: "shadow" + offset: [163, 163] + color: red + - + type: "shadow" + offset: [164, 164] + color: red + - + type: "shadow" + offset: [165, 165] + color: red + - + type: "shadow" + offset: [166, 166] + color: red + - + type: "shadow" + offset: [167, 167] + color: red + - + type: "shadow" + offset: [168, 168] + color: red + - + type: "shadow" + offset: [169, 169] + color: red + - + type: "shadow" + offset: [170, 170] + color: red + - + type: "shadow" + offset: [171, 171] + color: red + - + type: "shadow" + offset: [172, 172] + color: red + - + type: "shadow" + offset: [173, 173] + color: red + - + type: "shadow" + offset: [174, 174] + color: red + - + type: "shadow" + offset: [175, 175] + color: red + - + type: "shadow" + offset: [176, 176] + color: red + - + type: "shadow" + offset: [177, 177] + color: red + - + type: "shadow" + offset: [178, 178] + color: red + - + type: "shadow" + offset: [179, 179] + color: red + - + type: "shadow" + offset: [180, 180] + color: red + - + type: "shadow" + offset: [181, 181] + color: red + - + type: "shadow" + offset: [182, 182] + color: red + - + type: "shadow" + offset: [183, 183] + color: red + - + type: "shadow" + offset: [184, 184] + color: red + - + type: "shadow" + offset: [185, 185] + color: red + - + type: "shadow" + offset: [186, 186] + color: red + - + type: "shadow" + offset: [187, 187] + color: red + - + type: "shadow" + offset: [188, 188] + color: red + - + type: "shadow" + offset: [189, 189] + color: red + - + type: "shadow" + offset: [190, 190] + color: red + - + type: "shadow" + offset: [191, 191] + color: red + - + type: "shadow" + offset: [192, 192] + color: red + - + type: "shadow" + offset: [193, 193] + color: red + - + type: "shadow" + offset: [194, 194] + color: red + - + type: "shadow" + offset: [195, 195] + color: red + - + type: "shadow" + offset: [196, 196] + color: red + - + type: "shadow" + offset: [197, 197] + color: red + - + type: "shadow" + offset: [198, 198] + color: red + - + type: "shadow" + offset: [199, 199] + color: red + - text: "Much overdraw many pixels" + origin: 20 70 + size: 60 + - + type: "pop-all-shadows" diff --git a/gfx/wr/wrench/benchmarks/radial-gradient.yaml b/gfx/wr/wrench/benchmarks/radial-gradient.yaml new file mode 100644 index 0000000000..e71d301371 --- /dev/null +++ b/gfx/wr/wrench/benchmarks/radial-gradient.yaml @@ -0,0 +1,52 @@ +--- +root: + items: + - type: radial-gradient + bounds: [ 0, 0, 1980, 1080] + center: [ 990, 540 ] + start-radius: 5 + end-radius: 8000 + stops: [ 0.0, black, 1.0, white ] + repeat: false + - type: radial-gradient + bounds: [ 0, 0, 1980, 1080] + center: [ 990, 540 ] + start-radius: 5 + end-radius: 8000 + stops: [ 0.0, black, 1.0, white ] + repeat: false + - type: radial-gradient + bounds: [ 0, 0, 1980, 1080] + center: [ 990, 540 ] + start-radius: 5 + end-radius: 8000 + stops: [ 0.0, black, 1.0, white ] + repeat: false + - type: radial-gradient + bounds: [ 0, 0, 1980, 1080] + center: [ 990, 540 ] + start-radius: 5 + end-radius: 8000 + stops: [ 0.0, black, 1.0, white ] + repeat: false + - type: radial-gradient + bounds: [ 0, 0, 1980, 1080] + center: [ 990, 540 ] + start-radius: 5 + end-radius: 8000 + stops: [ 0.0, black, 1.0, white ] + repeat: false + - type: radial-gradient + bounds: [ 0, 0, 1980, 1080] + center: [ 990, 540 ] + start-radius: 5 + end-radius: 8000 + stops: [ 0.0, black, 1.0, white ] + repeat: false + - type: radial-gradient + bounds: [ 0, 0, 1980, 1080] + center: [ 990, 540 ] + start-radius: 5 + end-radius: 8000 + stops: [ 0.0, black, 1.0, white ] + repeat: false diff --git a/gfx/wr/wrench/benchmarks/simple-batching.yaml b/gfx/wr/wrench/benchmarks/simple-batching.yaml new file mode 100644 index 0000000000..4f2cf019b2 --- /dev/null +++ b/gfx/wr/wrench/benchmarks/simple-batching.yaml @@ -0,0 +1,45 @@ +--- +root: + items: + - type: rect + bounds: [0, 0, 512, 512] + color: green + - type: rect + bounds: [0, 0, 512, 512] + color: green + - type: rect + bounds: [0, 0, 512, 512] + color: green + - type: rect + bounds: [0, 0, 512, 512] + color: green + - type: rect + bounds: [0, 0, 512, 512] + color: green + - type: rect + bounds: [0, 0, 512, 512] + color: green + - type: rect + bounds: [0, 0, 512, 512] + color: green + - type: rect + bounds: [0, 0, 512, 512] + color: green + - type: rect + bounds: [0, 0, 512, 512] + color: green + - type: rect + bounds: [0, 0, 512, 512] + color: green + - type: rect + bounds: [0, 0, 512, 512] + color: green + - type: rect + bounds: [0, 0, 512, 512] + color: green + - type: rect + bounds: [0, 0, 512, 512] + color: green + - type: rect + bounds: [0, 0, 512, 512] + color: green diff --git a/gfx/wr/wrench/benchmarks/text-rendering.yaml b/gfx/wr/wrench/benchmarks/text-rendering.yaml new file mode 100644 index 0000000000..6b7ac3fb3a --- /dev/null +++ b/gfx/wr/wrench/benchmarks/text-rendering.yaml @@ -0,0 +1,260 @@ +root: + items: + - text: "Cats making all the muffins knock over christmas tree" + origin: 20 30 + size: 20 + - text: "Cat ipsum dolor sit amet, poop in the plant pot and demand to be let outside at once, and expect owner to wait for me as i think about it." + origin: 20 50 + size: 9 + - text: "Slap owner's face at 5am until human fills food dish licks your face." + origin: 20 80 + size: 18 + - text: "Play riveting piece on synthesizer keyboard cat snacks, yet meow go back to sleep owner brings food and water tries to" + origin: 20 100 + size: 10 + - text: "pet on head, so scratch get sprayed by water because bad cat nap all day, kitty scratches couch bad kitty." + origin: 20 112 + size: 10 + - text: "Touch water with paw then recoil in horror climb a tree, wait for a fireman jump to fireman then" + origin: 20 130 + size: 12 + - text: "scratch his face and mark territory when in doubt, wash." + origin: 20 150 + size: 12 + - text: "Friends are not food warm up laptop with butt lick butt fart rainbows until owner yells pee in litter box hiss at cats if it fits," + origin: 20 170 + size: 10 + - text: "i sits swat at dog, or chase the pig around the house yet thug cat but hiss and stare at nothing then run suddenly away." + origin: 20 180 + size: 10 + - text: "Howl uncontrollably for no reason pushes butt to face eat a plant, kill a hand for cough hairball on conveniently placed pants." + origin: 20 200 + size: 10 + - text: "Wake up human for food at 4am. Decide to want nothing to do with my owner today pelt around the house and up and down stairs chasing phantoms." + origin: 20 220 + size: 8 + - text: "Poop on grasses." + origin: 20 240 + size: 16 + - text: "Hunt by meowing loudly at 5am next to human slave food dispenser bleghbleghvomit my" + origin: 20 260 + size: 10 + - text: "furball really tie the room together and throwup on your pillow, so scamper." + origin: 20 270 + size: 10 + - text: "Spread kitty litter all over house." + origin: 20 290 + size: 18 + - text: "Friends are not food curl into a furry donut or going to catch the red" + origin: 20 320 + size: 16 + - text: "dot today going to catch the red dot today or destroy the blinds or purr." + origin: 20 340 + size: 16 + + - text: "Cats making all the muffins knock over christmas tree" + origin: 850 30 + size: 20 + color: red + - text: "Cat ipsum dolor sit amet, poop in the plant pot and demand to be let outside at once, and expect owner to wait for me as i think about it." + origin: 850 50 + size: 9 + color: red + - text: "Slap owner's face at 5am until human fills food dish licks your face." + origin: 850 80 + size: 18 + color: red + - text: "Play riveting piece on synthesizer keyboard cat snacks, yet meow go back to sleep owner brings food and water tries to" + origin: 850 100 + size: 10 + color: red + - text: "pet on head, so scratch get sprayed by water because bad cat nap all day, kitty scratches couch bad kitty." + origin: 850 112 + size: 10 + color: red + - text: "Touch water with paw then recoil in horror climb a tree, wait for a fireman jump to fireman then" + origin: 850 130 + size: 12 + color: red + - text: "scratch his face and mark territory when in doubt, wash." + origin: 850 150 + size: 12 + color: red + - text: "Friends are not food warm up laptop with butt lick butt fart rainbows until owner yells pee in litter box hiss at cats if it fits," + origin: 850 170 + size: 10 + color: red + - text: "i sits swat at dog, or chase the pig around the house yet thug cat but hiss and stare at nothing then run suddenly away." + origin: 850 180 + size: 10 + color: red + - text: "Howl uncontrollably for no reason pushes butt to face eat a plant, kill a hand for cough hairball on conveniently placed pants." + origin: 850 200 + size: 10 + color: red + - text: "Wake up human for food at 4am. Decide to want nothing to do with my owner today pelt around the house and up and down stairs chasing phantoms." + origin: 850 220 + size: 8 + color: red + - text: "Poop on grasses." + origin: 850 240 + size: 16 + color: red + - text: "Hunt by meowing loudly at 5am next to human slave food dispenser bleghbleghvomit my" + origin: 850 260 + size: 10 + color: red + - text: "furball really tie the room together and throwup on your pillow, so scamper." + origin: 850 270 + size: 10 + color: red + - text: "Spread kitty litter all over house." + origin: 850 290 + size: 18 + color: red + - text: "Friends are not food curl into a furry donut or going to catch the red" + origin: 850 320 + size: 16 + color: red + - text: "dot today going to catch the red dot today or destroy the blinds or purr." + origin: 850 340 + size: 16 + color: red + + - text: "Cats making all the muffins knock over christmas tree" + origin: 20 430 + size: 20 + color: green + - text: "Cat ipsum dolor sit amet, poop in the plant pot and demand to be let outside at once, and expect owner to wait for me as i think about it." + origin: 20 450 + size: 9 + color: green + - text: "Slap owner's face at 5am until human fills food dish licks your face." + origin: 20 480 + size: 18 + color: green + - text: "Play riveting piece on synthesizer keyboard cat snacks, yet meow go back to sleep owner brings food and water tries to" + origin: 20 500 + size: 10 + color: green + - text: "pet on head, so scratch get sprayed by water because bad cat nap all day, kitty scratches couch bad kitty." + origin: 20 512 + size: 10 + color: green + - text: "Touch water with paw then recoil in horror climb a tree, wait for a fireman jump to fireman then" + origin: 20 530 + size: 12 + color: green + - text: "scratch his face and mark territory when in doubt, wash." + origin: 20 550 + size: 12 + color: green + - text: "Friends are not food warm up laptop with butt lick butt fart rainbows until owner yells pee in litter box hiss at cats if it fits," + origin: 20 570 + size: 10 + color: green + - text: "i sits swat at dog, or chase the pig around the house yet thug cat but hiss and stare at nothing then run suddenly away." + origin: 20 580 + size: 10 + color: green + - text: "Howl uncontrollably for no reason pushes butt to face eat a plant, kill a hand for cough hairball on conveniently placed pants." + origin: 20 600 + size: 10 + color: green + - text: "Wake up human for food at 4am. Decide to want nothing to do with my owner today pelt around the house and up and down stairs chasing phantoms." + origin: 20 620 + size: 8 + color: green + - text: "Poop on grasses." + origin: 20 640 + size: 16 + color: green + - text: "Hunt by meowing loudly at 5am next to human slave food dispenser bleghbleghvomit my" + origin: 20 660 + size: 10 + color: green + - text: "furball really tie the room together and throwup on your pillow, so scamper." + origin: 20 670 + size: 10 + color: green + - text: "Spread kitty litter all over house." + origin: 20 690 + size: 18 + color: green + - text: "Friends are not food curl into a furry donut or going to catch the red" + origin: 20 720 + size: 16 + color: green + - text: "dot today going to catch the red dot today or destroy the blinds or purr." + origin: 20 740 + size: 16 + color: green + + - text: "Cats making all the muffins knock over christmas tree" + origin: 850 430 + size: 20 + color: blue + - text: "Cat ipsum dolor sit amet, poop in the plant pot and demand to be let outside at once, and expect owner to wait for me as i think about it." + origin: 850 450 + size: 9 + color: blue + - text: "Slap owner's face at 5am until human fills food dish licks your face." + origin: 850 480 + size: 18 + color: blue + - text: "Play riveting piece on synthesizer keyboard cat snacks, yet meow go back to sleep owner brings food and water tries to" + origin: 850 500 + size: 10 + color: blue + - text: "pet on head, so scratch get sprayed by water because bad cat nap all day, kitty scratches couch bad kitty." + origin: 850 512 + size: 10 + color: blue + - text: "Touch water with paw then recoil in horror climb a tree, wait for a fireman jump to fireman then" + origin: 850 530 + size: 12 + color: blue + - text: "scratch his face and mark territory when in doubt, wash." + origin: 850 550 + size: 12 + color: blue + - text: "Friends are not food warm up laptop with butt lick butt fart rainbows until owner yells pee in litter box hiss at cats if it fits," + origin: 850 570 + size: 10 + color: blue + - text: "i sits swat at dog, or chase the pig around the house yet thug cat but hiss and stare at nothing then run suddenly away." + origin: 850 580 + size: 10 + color: blue + - text: "Howl uncontrollably for no reason pushes butt to face eat a plant, kill a hand for cough hairball on conveniently placed pants." + origin: 850 600 + size: 10 + color: blue + - text: "Wake up human for food at 4am. Decide to want nothing to do with my owner today pelt around the house and up and down stairs chasing phantoms." + origin: 850 620 + size: 8 + color: blue + - text: "Poop on grasses." + origin: 850 640 + size: 16 + color: blue + - text: "Hunt by meowing loudly at 5am next to human slave food dispenser bleghbleghvomit my" + origin: 850 660 + size: 10 + color: blue + - text: "furball really tie the room together and throwup on your pillow, so scamper." + origin: 850 670 + size: 10 + color: blue + - text: "Spread kitty litter all over house." + origin: 850 690 + size: 18 + color: blue + - text: "Friends are not food curl into a furry donut or going to catch the red" + origin: 850 720 + size: 16 + color: blue + - text: "dot today going to catch the red dot today or destroy the blinds or purr." + origin: 850 740 + size: 16 + color: blue diff --git a/gfx/wr/wrench/benchmarks/transforms-simple.yaml b/gfx/wr/wrench/benchmarks/transforms-simple.yaml new file mode 100644 index 0000000000..53956da401 --- /dev/null +++ b/gfx/wr/wrench/benchmarks/transforms-simple.yaml @@ -0,0 +1,44 @@ +--- +root: + items: + - type: stacking-context + bounds: [0, 0, 1024, 1024] + items: + - type: stacking-context + bounds: [0, 0, 1024, 1024] + transform: rotate(45) + items: + - type: rect + bounds: [0, 0, 1024, 1024] + color: [255, 0, 0, 0.5] + - type: rect + bounds: [0, 0, 1024, 1024] + color: [255, 0, 0, 0.5] + - type: rect + bounds: [0, 0, 1024, 1024] + color: [255, 0, 0, 0.5] + - type: rect + bounds: [0, 0, 1024, 1024] + color: [255, 0, 0, 0.5] + - type: rect + bounds: [0, 0, 1024, 1024] + color: [255, 0, 0, 0.5] + - type: rect + bounds: [0, 0, 1024, 1024] + color: [255, 0, 0, 0.5] + - type: rect + bounds: [0, 0, 1024, 1024] + color: [255, 0, 0, 0.5] + - type: rect + bounds: [0, 0, 1024, 1024] + color: [255, 0, 0, 0.5] + - type: rect + bounds: [0, 0, 1024, 1024] + color: [255, 0, 0, 0.5] + - type: rect + bounds: [0, 0, 1024, 1024] + color: [255, 0, 0, 0.5] + - type: rect + bounds: [0, 0, 1024, 1024] + color: [255, 0, 0, 0.5] + diff --git a/gfx/wr/wrench/benchmarks/unaligned-gradient.yaml b/gfx/wr/wrench/benchmarks/unaligned-gradient.yaml new file mode 100644 index 0000000000..ea7738202d --- /dev/null +++ b/gfx/wr/wrench/benchmarks/unaligned-gradient.yaml @@ -0,0 +1,62 @@ +root: + items: + - type: gradient + bounds: [ 0, 0, 1980, 1080] + start: [ 0, -2000 ] + end: [ 1, 4000 ] + stops: [ 0.0, red, 1.0, green ] + repeat: false + - type: gradient + bounds: [ 0, 0, 1980, 1080] + start: [ 0, -2000 ] + end: [ 1, 4000 ] + stops: [ 0.0, red, 1.0, green ] + repeat: false + - type: gradient + bounds: [ 0, 0, 1980, 1080] + start: [ 0, -2000 ] + end: [ 1, 4000 ] + stops: [ 0.0, red, 1.0, green ] + repeat: false + - type: gradient + bounds: [ 0, 0, 1980, 1080] + start: [ 0, -2000 ] + end: [ 1, 4000 ] + stops: [ 0.0, red, 1.0, green ] + repeat: false + - type: gradient + bounds: [ 0, 0, 1980, 1080] + start: [ 0, -2000 ] + end: [ 1, 4000 ] + stops: [ 0.0, red, 1.0, green ] + repeat: false + - type: gradient + bounds: [ 0, 0, 1980, 1080] + start: [ 0, -2000 ] + end: [ 1, 4000 ] + stops: [ 0.0, red, 1.0, green ] + repeat: false + - type: gradient + bounds: [ 0, 0, 1980, 1080] + start: [ 0, -2000 ] + end: [ 1, 4000 ] + stops: [ 0.0, red, 1.0, green ] + repeat: false + - type: gradient + bounds: [ 0, 0, 1980, 1080] + start: [ 0, -2000 ] + end: [ 1, 4000 ] + stops: [ 0.0, red, 1.0, green ] + repeat: false + - type: gradient + bounds: [ 0, 0, 1980, 1080] + start: [ 0, -2000 ] + end: [ 1, 4000 ] + stops: [ 0.0, red, 1.0, green ] + repeat: false + - type: gradient + bounds: [ 0, 0, 1980, 1080] + start: [ 0, -2000 ] + end: [ 1, 4000 ] + stops: [ 0.0, red, 1.0, green ] + repeat: false diff --git a/gfx/wr/wrench/build.rs b/gfx/wr/wrench/build.rs new file mode 100644 index 0000000000..974ef3180c --- /dev/null +++ b/gfx/wr/wrench/build.rs @@ -0,0 +1,28 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +use std::env; +use std::fs; +use std::path::PathBuf; + +fn main() { + let target = env::var("TARGET").unwrap(); + let out_dir = env::var_os("OUT_DIR").unwrap(); + let out_dir = PathBuf::from(out_dir); + + println!("cargo:rerun-if-changed=res/wrench.exe.manifest"); + if target.contains("windows") { + let src = PathBuf::from("res/wrench.exe.manifest"); + let mut dst = out_dir + .parent() + .unwrap() + .parent() + .unwrap() + .parent() + .unwrap() + .to_owned(); + dst.push("wrench.exe.manifest"); + fs::copy(&src, &dst).unwrap(); + } +} diff --git a/gfx/wr/wrench/examples/animated.anim b/gfx/wr/wrench/examples/animated.anim new file mode 100644 index 0000000000..ee834e6cc2 --- /dev/null +++ b/gfx/wr/wrench/examples/animated.anim @@ -0,0 +1,13 @@ +--- + anim.color: + - red + - green + - blue + rect.pos: + - [100, 100, 100, 100] + - [100, 100, 120, 100] + - [100, 100, 140, 100] + bs.offset: + - [0, 0] + - [2, 0] + - [4, 0] diff --git a/gfx/wr/wrench/examples/animated.yaml b/gfx/wr/wrench/examples/animated.yaml new file mode 100644 index 0000000000..7f9026ad6e --- /dev/null +++ b/gfx/wr/wrench/examples/animated.yaml @@ -0,0 +1,13 @@ +--- +root: + items: + - type: rect + bounds: key(rect.pos) + color: key(anim.color) + - type: box-shadow + bounds: [ 100, 300, 100, 100 ] + blur-radius: 3 + border-radius: 10 + color: blue + clip-mode: outset + offset: key(bs.offset) diff --git a/gfx/wr/wrench/invalidation/basic.yaml b/gfx/wr/wrench/invalidation/basic.yaml new file mode 100644 index 0000000000..c7d1b6f450 --- /dev/null +++ b/gfx/wr/wrench/invalidation/basic.yaml @@ -0,0 +1,6 @@ +--- +root: + items: + - type: rect + color: red + bounds: 100 100 500 100 diff --git a/gfx/wr/wrench/invalidation/composite_nop_1.yaml b/gfx/wr/wrench/invalidation/composite_nop_1.yaml new file mode 100644 index 0000000000..ce6cc46977 --- /dev/null +++ b/gfx/wr/wrench/invalidation/composite_nop_1.yaml @@ -0,0 +1,6 @@ +--- +root: + items: + - type: rect + color: red + bounds: 100 100 100 100 diff --git a/gfx/wr/wrench/invalidation/composite_nop_2.yaml b/gfx/wr/wrench/invalidation/composite_nop_2.yaml new file mode 100644 index 0000000000..a99663ed54 --- /dev/null +++ b/gfx/wr/wrench/invalidation/composite_nop_2.yaml @@ -0,0 +1,6 @@ +--- +root: + items: + - type: rect + color: red + bounds: 100 120 100 100 diff --git a/gfx/wr/wrench/reftests/aa/aa-dist-bug-ref.yaml b/gfx/wr/wrench/reftests/aa/aa-dist-bug-ref.yaml new file mode 100644 index 0000000000..c83fff2a0b --- /dev/null +++ b/gfx/wr/wrench/reftests/aa/aa-dist-bug-ref.yaml @@ -0,0 +1,6 @@ +--- +root: + items: + - type: rect + color: red + bounds: [340, 184, 50, 20] diff --git a/gfx/wr/wrench/reftests/aa/aa-dist-bug.yaml b/gfx/wr/wrench/reftests/aa/aa-dist-bug.yaml new file mode 100644 index 0000000000..19b747aabc --- /dev/null +++ b/gfx/wr/wrench/reftests/aa/aa-dist-bug.yaml @@ -0,0 +1,43 @@ +# Test that when the AA range is > 1, the AA is correctly applied to +# an ellipse clip. This is a regression test for issue #2576. +# The rectangles below mask out most of the box shadow and rounded +# corners, which are not relevant to what is being tested here. +--- +root: + items: + - type: stacking-context + transform: rotate-z(-45) rotate-x(-60) + transform-origin: 300 300 + items: + - type: box-shadow + bounds: [0, 0, 150, 150] + color: black + offset: [150, 50] + border-radius: 8 + + - type: clip + bounds: [90, 0, 150, 150] + complex: + - rect: [90, 0, 150, 150] + radius: 8 + items: + - type: rect + color: red + border-radius: 8 + bounds: [90, 0, 150, 150] + + - type: rect + color: white + bounds: [250, 100, 240, 84] + + - type: rect + color: white + bounds: [250, 204, 240, 70] + + - type: rect + color: white + bounds: [240, 100, 100, 150] + + - type: rect + color: white + bounds: [390, 100, 100, 150] diff --git a/gfx/wr/wrench/reftests/aa/fractional-radii-ref.yaml b/gfx/wr/wrench/reftests/aa/fractional-radii-ref.yaml new file mode 100644 index 0000000000..364d6e7529 --- /dev/null +++ b/gfx/wr/wrench/reftests/aa/fractional-radii-ref.yaml @@ -0,0 +1,18 @@ +--- +root: + items: + - type: rect + bounds: 20 50 100 100 + color: blue + + - type: rect + bounds: 140 50 100 100 + color: blue + + - type: rect + bounds: 260 50 100 100 + color: blue + + - type: rect + bounds: 380 50 100 100 + color: blue diff --git a/gfx/wr/wrench/reftests/aa/fractional-radii.yaml b/gfx/wr/wrench/reftests/aa/fractional-radii.yaml new file mode 100644 index 0000000000..9293c1b1e9 --- /dev/null +++ b/gfx/wr/wrench/reftests/aa/fractional-radii.yaml @@ -0,0 +1,42 @@ +--- +root: + items: + - type: clip + bounds: [20, 50, 100, 100] + complex: + - rect: [20, 50, 100, 100] + radius: 0 + items: + - type: rect + bounds: 20 50 100 100 + color: blue + + - type: clip + bounds: [140, 50, 100, 100] + complex: + - rect: [140, 50, 100, 100] + radius: 0.001 + items: + - type: rect + bounds: 140 50 100 100 + color: blue + + - type: clip + bounds: [260, 50, 100, 100] + complex: + - rect: [260, 50, 100, 100] + radius: 0.01 + items: + - type: rect + bounds: 260 50 100 100 + color: blue + + - type: clip + bounds: [380, 50, 100, 100] + complex: + - rect: [380, 50, 100, 100] + radius: 0.1 + items: + - type: rect + bounds: 380 50 100 100 + color: blue diff --git a/gfx/wr/wrench/reftests/aa/reftest.list b/gfx/wr/wrench/reftests/aa/reftest.list new file mode 100644 index 0000000000..7ed4e0a108 --- /dev/null +++ b/gfx/wr/wrench/reftests/aa/reftest.list @@ -0,0 +1,3 @@ +skip_on(android) fuzzy(1,1) fuzzy-if(platform(swgl),8,5) == rounded-rects.yaml rounded-rects-ref.png # Too wide for Android +== aa-dist-bug.yaml aa-dist-bug-ref.yaml +== fractional-radii.yaml fractional-radii-ref.yaml diff --git a/gfx/wr/wrench/reftests/aa/rounded-rects-ref.png b/gfx/wr/wrench/reftests/aa/rounded-rects-ref.png Binary files differnew file mode 100644 index 0000000000..7e84f0d569 --- /dev/null +++ b/gfx/wr/wrench/reftests/aa/rounded-rects-ref.png diff --git a/gfx/wr/wrench/reftests/aa/rounded-rects.yaml b/gfx/wr/wrench/reftests/aa/rounded-rects.yaml new file mode 100644 index 0000000000..c82349a008 --- /dev/null +++ b/gfx/wr/wrench/reftests/aa/rounded-rects.yaml @@ -0,0 +1,41 @@ +--- +root: + items: + - + bounds: 0 0 1000 1000 + type: stacking-context + items: + - type: clip + bounds: [50, 50, 200, 200] + complex: + - rect: [50, 50, 200, 200] + radius: 8 + items: + - type: rect + bounds: 50 50 200 200 + color: red + + - type: clip + bounds: [270, 50, 200, 200] + complex: + - rect: [270, 50, 200, 200] + radius: [16, 32, 48, 64] + items: + - type: rect + bounds: 270 50 200 200 + color: green + + - type: clip + bounds: [490, 50, 500, 500] + complex: + - rect: [490, 50, 500, 500] + radius: { + top-left: [32, 16], + top-right: [40, 24], + bottom-left: [48, 64], + bottom-right: [52, 80], + } + items: + - type: rect + bounds: 490 50 500 500 + color: blue diff --git a/gfx/wr/wrench/reftests/backface/backface-3d-leaf.yaml b/gfx/wr/wrench/reftests/backface/backface-3d-leaf.yaml new file mode 100644 index 0000000000..1a7be55eae --- /dev/null +++ b/gfx/wr/wrench/reftests/backface/backface-3d-leaf.yaml @@ -0,0 +1,18 @@ +# In this test, the leaf green rectangle has only its back visible +# due to rotate-x(180) transformation, preserve-3d style, +# and "backface-visible = false", so it's completely hidden. +--- +root: + items: + - type: rect + color: red + bounds: 0 0 1024 768 + - type: stacking-context + bounds: 0 0 1024 768 + transform-style: preserve-3d + transform: rotate-x(180) + items: + - type: rect + bounds: 0 0 200 200 + color: green + backface-visible: false diff --git a/gfx/wr/wrench/reftests/backface/backface-both-sides-ref.yaml b/gfx/wr/wrench/reftests/backface/backface-both-sides-ref.yaml new file mode 100644 index 0000000000..aa0bd8e57c --- /dev/null +++ b/gfx/wr/wrench/reftests/backface/backface-both-sides-ref.yaml @@ -0,0 +1,8 @@ +--- +root: + items: + - type: stacking-context + items: + - type: rect + color: red + bounds: 100 0 100 100 diff --git a/gfx/wr/wrench/reftests/backface/backface-both-sides.yaml b/gfx/wr/wrench/reftests/backface/backface-both-sides.yaml new file mode 100644 index 0000000000..0212c3002d --- /dev/null +++ b/gfx/wr/wrench/reftests/backface/backface-both-sides.yaml @@ -0,0 +1,25 @@ +# In this test, both rectangles have invisible back faces and are +# parented to a preserve-3d context that is rotated by 180 degrees. +# The red one is also rotated 180 degrees, and should be visible. +--- +root: + items: + - type: stacking-context + items: + - type: stacking-context + transform: rotate-y(180) + transform-style: preserve-3d + transform-origin: 50 50 + items: + - type: rect + color: green + bounds: 0 0 100 100 + backface-visible: false + - type: stacking-context + transform: rotate-y(180) + transform-origin: 0 0 + backface-visible: false + items: + - type: rect + color: red + bounds: 0 0 100 100 diff --git a/gfx/wr/wrench/reftests/backface/backface-double-flip.yaml b/gfx/wr/wrench/reftests/backface/backface-double-flip.yaml new file mode 100644 index 0000000000..b242e95627 --- /dev/null +++ b/gfx/wr/wrench/reftests/backface/backface-double-flip.yaml @@ -0,0 +1,21 @@ +# In this test, the red rectangle has backface visibility turned off. +# However its world transformation makes it front-facing. +# However it's still invisible because it's back-facing in the picture space +# of the transformed stacking context. +--- +root: + items: + - type: stacking-context + items: + - type: stacking-context + transform: rotate-y(180) + transform-style: preserve-3d + transform-origin: 50 50 + items: + - type: stacking-context + transform: rotate-y(180) + items: + - type: rect + color: red + backface-visible: false + bounds: 0 0 100 100 diff --git a/gfx/wr/wrench/reftests/backface/backface-flatten.yaml b/gfx/wr/wrench/reftests/backface/backface-flatten.yaml new file mode 100644 index 0000000000..e754d45bc9 --- /dev/null +++ b/gfx/wr/wrench/reftests/backface/backface-flatten.yaml @@ -0,0 +1,31 @@ +# In this test, there is a flattened ref frame between an element +# and the picture it's rendered into. The element should be considered +# invisible as it's back face oriented at this flattening step. +# If WR only checks the "final" transform, it will consider it visible. + +--- +root: + transform: rotate-x(1) + items: + - type: stacking-context + transform-style: preserve-3d + #transform: rotate-x(1) + items: + - type: stacking-context + bounds: 0 0 200 200 + transform: rotate-y(30) + transform-style: flat + items: + - type: stacking-context + bounds: 0 0 200 200 + transform: rotate-y(-100) + transform-style: preserve-3d + items: + - type: stacking-context + #transform: rotate-x(1) + transform-style: flat + items: + - type: rect + bounds: 0 0 200 200 + color: green + backface-visible: false diff --git a/gfx/wr/wrench/reftests/backface/backface-hidden.yaml b/gfx/wr/wrench/reftests/backface/backface-hidden.yaml new file mode 100644 index 0000000000..afa9d653b8 --- /dev/null +++ b/gfx/wr/wrench/reftests/backface/backface-hidden.yaml @@ -0,0 +1,18 @@ +# In this test, the leaf green rectangle has only its back visible +# due to rotate-x(180) transformation, +# and "backface-visible = false", so it's completely hidden. +--- +root: + items: + - type: rect + color: red + bounds: 0 0 1024 768 + - type: stacking-context + bounds: 0 0 1024 768 + transform: rotate-x(180) + transform-style: preserve-3d + items: + - type: rect + bounds: 0 0 1024 768 + color: green + backface-visible: false diff --git a/gfx/wr/wrench/reftests/backface/backface-leaf-ref.yaml b/gfx/wr/wrench/reftests/backface/backface-leaf-ref.yaml new file mode 100644 index 0000000000..17d39b4d61 --- /dev/null +++ b/gfx/wr/wrench/reftests/backface/backface-leaf-ref.yaml @@ -0,0 +1,12 @@ +--- +root: + items: + - type: rect + color: red + bounds: 0 0 1024 768 + - type: stacking-context + bounds: 0 0 1024 768 + items: + - type: rect + bounds: 0 568 200 200 + color: green diff --git a/gfx/wr/wrench/reftests/backface/backface-leaf.yaml b/gfx/wr/wrench/reftests/backface/backface-leaf.yaml new file mode 100644 index 0000000000..d1c1b893be --- /dev/null +++ b/gfx/wr/wrench/reftests/backface/backface-leaf.yaml @@ -0,0 +1,16 @@ +# In this test, the leaf green rectangle "backface-visible = false" which is ignored +# because it doesn't have any transform, and it's not in preserve-3d context. +--- +root: + items: + - type: rect + color: red + bounds: 0 0 1024 768 + - type: stacking-context + bounds: 0 0 1024 768 + transform: rotate-x(180) + items: + - type: rect + bounds: 0 0 200 200 + color: green + backface-visible: false diff --git a/gfx/wr/wrench/reftests/backface/backface-picture-ref.yaml b/gfx/wr/wrench/reftests/backface/backface-picture-ref.yaml new file mode 100644 index 0000000000..3013f72f20 --- /dev/null +++ b/gfx/wr/wrench/reftests/backface/backface-picture-ref.yaml @@ -0,0 +1,6 @@ +--- +root: + items: + - type: rect + color: red + bounds: 0 0 100 100 diff --git a/gfx/wr/wrench/reftests/backface/backface-picture.yaml b/gfx/wr/wrench/reftests/backface/backface-picture.yaml new file mode 100644 index 0000000000..189c23d5b5 --- /dev/null +++ b/gfx/wr/wrench/reftests/backface/backface-picture.yaml @@ -0,0 +1,21 @@ +# In this test we ensure that "backface-visiblity" property +# is not inherited, and the red rect rotated by 180 degrees +# is still rendered. +--- +root: + items: + - type: stacking-context + items: + - type: stacking-context + transform-style: preserve-3d + backface-visible: false + items: + - type: stacking-context + transform: rotate-y(180) + transform-origin: 50 50 + items: + - type: stacking-context + items: + - type: rect + color: red + bounds: 0 0 100 100 diff --git a/gfx/wr/wrench/reftests/backface/backface-ref.yaml b/gfx/wr/wrench/reftests/backface/backface-ref.yaml new file mode 100644 index 0000000000..614cf5f465 --- /dev/null +++ b/gfx/wr/wrench/reftests/backface/backface-ref.yaml @@ -0,0 +1,6 @@ +--- +root: + items: + - type: rect + color: red + bounds: 0 0 1024 768 diff --git a/gfx/wr/wrench/reftests/backface/backface-sc.yaml b/gfx/wr/wrench/reftests/backface/backface-sc.yaml new file mode 100644 index 0000000000..350baca592 --- /dev/null +++ b/gfx/wr/wrench/reftests/backface/backface-sc.yaml @@ -0,0 +1,17 @@ +# This test is similar to "backface-leaf.yaml" but with the whole +# stacking context (containing a green rect) turning invisible +# because of the "rotate-x(180)" transform. +--- +root: + items: + - type: rect + color: red + bounds: 0 0 1024 768 + - type: stacking-context + bounds: 0 0 1024 768 + transform: rotate-x(180) + backface-visible: false + items: + - type: rect + bounds: 0 0 200 200 + color: green diff --git a/gfx/wr/wrench/reftests/backface/backface-vis-3d.yaml b/gfx/wr/wrench/reftests/backface/backface-vis-3d.yaml new file mode 100644 index 0000000000..c58026a5cc --- /dev/null +++ b/gfx/wr/wrench/reftests/backface/backface-vis-3d.yaml @@ -0,0 +1,16 @@ +# Verifies that a 3d context selects the correct reference (containing block) spatial node. +root: + items: + - type: stacking-context + bounds: 100 0 100 100 + transform: scale-x(-1) + items: + - type: stacking-context + bounds: 0 0 100 100 + transform: rotate-y(180) + transform-style: preserve-3d + items: + - type: rect + bounds: 0 0 100 100 + color: red + backface-visible: false diff --git a/gfx/wr/wrench/reftests/backface/blank.yaml b/gfx/wr/wrench/reftests/backface/blank.yaml new file mode 100644 index 0000000000..c4eb3ab673 --- /dev/null +++ b/gfx/wr/wrench/reftests/backface/blank.yaml @@ -0,0 +1,2 @@ +--- +root: diff --git a/gfx/wr/wrench/reftests/backface/reftest.list b/gfx/wr/wrench/reftests/backface/reftest.list new file mode 100644 index 0000000000..70ab29b4a4 --- /dev/null +++ b/gfx/wr/wrench/reftests/backface/reftest.list @@ -0,0 +1,9 @@ +== backface-leaf.yaml backface-leaf-ref.yaml +== backface-3d-leaf.yaml backface-ref.yaml +== backface-hidden.yaml backface-ref.yaml +== backface-sc.yaml backface-ref.yaml +== backface-picture.yaml backface-picture-ref.yaml +== backface-double-flip.yaml blank.yaml +== backface-both-sides.yaml backface-both-sides-ref.yaml +== backface-vis-3d.yaml blank.yaml +== backface-flatten.yaml blank.yaml diff --git a/gfx/wr/wrench/reftests/blend/blank.yaml b/gfx/wr/wrench/reftests/blend/blank.yaml new file mode 100644 index 0000000000..c4eb3ab673 --- /dev/null +++ b/gfx/wr/wrench/reftests/blend/blank.yaml @@ -0,0 +1,2 @@ +--- +root: diff --git a/gfx/wr/wrench/reftests/blend/darken-ref.yaml b/gfx/wr/wrench/reftests/blend/darken-ref.yaml new file mode 100644 index 0000000000..a83cf68244 --- /dev/null +++ b/gfx/wr/wrench/reftests/blend/darken-ref.yaml @@ -0,0 +1,6 @@ +--- +root: + items: + - type: rect + bounds: [0, 0, 100, 100] + color: [10, 20, 10] diff --git a/gfx/wr/wrench/reftests/blend/darken.yaml b/gfx/wr/wrench/reftests/blend/darken.yaml new file mode 100644 index 0000000000..2de68d8724 --- /dev/null +++ b/gfx/wr/wrench/reftests/blend/darken.yaml @@ -0,0 +1,16 @@ +--- +root: + items: + - type: stacking-context + blend-container: true + items: + - type: rect + bounds: [0, 0, 100, 100] + color: [10, 20, 30] + - type: stacking-context + bounds: [0, 0, 100, 100] + mix-blend-mode: darken + items: + - type: rect + bounds: [0, 0, 100, 100] + color: [30, 20, 10] diff --git a/gfx/wr/wrench/reftests/blend/difference-ref.yaml b/gfx/wr/wrench/reftests/blend/difference-ref.yaml new file mode 100644 index 0000000000..b913384f24 --- /dev/null +++ b/gfx/wr/wrench/reftests/blend/difference-ref.yaml @@ -0,0 +1,6 @@ +--- +root: + items: + - type: rect + bounds: [0, 0, 100, 100] + color: [0, 0, 0] diff --git a/gfx/wr/wrench/reftests/blend/difference-transparent-ref.yaml b/gfx/wr/wrench/reftests/blend/difference-transparent-ref.yaml new file mode 100644 index 0000000000..8ed801fb15 --- /dev/null +++ b/gfx/wr/wrench/reftests/blend/difference-transparent-ref.yaml @@ -0,0 +1,23 @@ +--- +root: + items: + - type: rect + bounds: [0, 0, 100, 100] + + # First blend black rect with green in place + # Cs = (1 - αb) x Cs + αb x B(Cb, Cs) + # B(Cb, Cs) = | Cb - Cs | = (0, 0, 0) + # 0.5 * (0, 255, 0) + 0.5 * (0, 0, 0) = (0, 127.5, 0) + # + # Now, composite the resulting color with src-over; the alpha is the original alpha for the top layer + # while the color is the blending result + # co = αs x Fa x Cs + αb x Fb x Cb - this is premultiplied + # αo = αs + αb x (1 – αs) + # Source over: Fa = 1; Fb = 1 – αs + # co = 0.5 * 1 * (0, 127.5, 0) + 0.5 * 0.5 * (0, 255, 0) = (0, 63.5, 0) + 0.25 * (0, 255, 0) = (0, 127.5, 0) + # ao = 0.5 + 0.5 * 0.5 = 0.75 + # Co = co/ao = (0, 127.5, 0) / 0.75 + # + # Now alpha composite on white background + # co = 0.75 * 1 * (0, 127.5, 0) / 0.75 + 1 * 0.25 * (255, 255, 255) = (0, 127.5, 0) + (63.75, 63.75, 63.75) = (63.75, 159, 63.75) = (64, 191, 64) + color: [64, 191, 64] diff --git a/gfx/wr/wrench/reftests/blend/difference-transparent.yaml b/gfx/wr/wrench/reftests/blend/difference-transparent.yaml new file mode 100644 index 0000000000..bd828d454a --- /dev/null +++ b/gfx/wr/wrench/reftests/blend/difference-transparent.yaml @@ -0,0 +1,22 @@ +--- +root: + items: + - type: rect + bounds: [0, 0, 100, 100] + color: white + # this stacking context should create an isolated group for its children + # causing the yellow rect to not blend with the green backdrop + - type: stacking-context + blend-container: true + bounds: [0, 0, 100, 100] + items: + - type: rect + bounds: [0, 0, 100, 100] + color: [0, 255, 0, 0.5] + - type: stacking-context + bounds: [0, 0, 100, 100] + mix-blend-mode: difference + items: + - type: rect + bounds: [0, 0, 100, 100] + color: [0, 255, 0, 0.5] diff --git a/gfx/wr/wrench/reftests/blend/difference.yaml b/gfx/wr/wrench/reftests/blend/difference.yaml new file mode 100644 index 0000000000..0c8d0fcd02 --- /dev/null +++ b/gfx/wr/wrench/reftests/blend/difference.yaml @@ -0,0 +1,16 @@ +--- +root: + items: + - type: stacking-context + blend-container: true + items: + - type: rect + bounds: [0, 0, 100, 100] + color: green + - type: stacking-context + bounds: [0, 0, 100, 100] + mix-blend-mode: difference + items: + - type: rect + bounds: [0, 0, 100, 100] + color: green diff --git a/gfx/wr/wrench/reftests/blend/isolated-2-ref.yaml b/gfx/wr/wrench/reftests/blend/isolated-2-ref.yaml new file mode 100644 index 0000000000..3226b6edda --- /dev/null +++ b/gfx/wr/wrench/reftests/blend/isolated-2-ref.yaml @@ -0,0 +1,21 @@ +--- +root: + items: + - type: rect + bounds: [10, 10, 130, 130] + color: [255, 255, 0] + - type: stacking-context + bounds: [10, 10, 130, 130] + items: + - type: rect + bounds: [0, 0, 100, 100] + color: [0, 255, 0] + - type: stacking-context + bounds: [20, 20, 100, 100] + items: + - type: rect + bounds: [0, 0, 100, 100] + color: [255, 0, 0] + - type: rect + bounds: [0, 0, 80, 80] + color: [0, 0, 0] diff --git a/gfx/wr/wrench/reftests/blend/isolated-2.yaml b/gfx/wr/wrench/reftests/blend/isolated-2.yaml new file mode 100644 index 0000000000..87bbac3caa --- /dev/null +++ b/gfx/wr/wrench/reftests/blend/isolated-2.yaml @@ -0,0 +1,25 @@ +# translation of wpt/css-tests/compositing-1_dev/html/mix-blend-mode-stacking-context-creates-isolation.htm +--- +root: + items: + - type: rect + bounds: [10, 10, 130, 130] + color: [255, 255, 0] + # this stacking context should create an isolated group for its children + # inside there should be overlapping red and green rects + # where they intersect should be a black rect + # the rects should not blend with the yellow backdrop + - type: stacking-context + blend-container: true + bounds: [10, 10, 130, 130] + items: + - type: rect + bounds: [0, 0, 100, 100] + color: [0, 255, 0] + - type: stacking-context + bounds: [20, 20, 100, 100] + mix-blend-mode: multiply + items: + - type: rect + bounds: [0, 0, 100, 100] + color: [255, 0, 0] diff --git a/gfx/wr/wrench/reftests/blend/isolated-premultiplied-2-ref.yaml b/gfx/wr/wrench/reftests/blend/isolated-premultiplied-2-ref.yaml new file mode 100644 index 0000000000..f5de6dc33d --- /dev/null +++ b/gfx/wr/wrench/reftests/blend/isolated-premultiplied-2-ref.yaml @@ -0,0 +1,6 @@ +--- +root: + items: + - type: rect + bounds: [0, 0, 100, 100] + color: [229, 239, 229] diff --git a/gfx/wr/wrench/reftests/blend/isolated-premultiplied-2.yaml b/gfx/wr/wrench/reftests/blend/isolated-premultiplied-2.yaml new file mode 100644 index 0000000000..4ad5737d8c --- /dev/null +++ b/gfx/wr/wrench/reftests/blend/isolated-premultiplied-2.yaml @@ -0,0 +1,13 @@ +--- +root: + items: + - type: stacking-context + bounds: [0, 0, 100, 100] + items: + - type: stacking-context + bounds: [0, 0, 100, 100] + mix-blend-mode: lighten + items: + - type: rect + bounds: [0, 0, 100, 100] + color: [0, 100, 0, 0.1] diff --git a/gfx/wr/wrench/reftests/blend/isolated-premultiplied.yaml b/gfx/wr/wrench/reftests/blend/isolated-premultiplied.yaml new file mode 100644 index 0000000000..a8d738a389 --- /dev/null +++ b/gfx/wr/wrench/reftests/blend/isolated-premultiplied.yaml @@ -0,0 +1,24 @@ +--- +root: + items: + - type: stacking-context + bounds: [0, 0, 100, 100] + items: + # this stacking context should force its parent to be an isolated group + # we don't want it to actually draw anything so just make it draw a white rect + - type: stacking-context + bounds: [0, 0, 100, 100] + mix-blend-mode: lighten + items: + - type: rect + bounds: [500, 500, 100, 100] + color: [255, 255, 255] + + # transparent white, should be invisible + - type: rect + bounds: [0, 0, 100, 100] + color: [255, 255, 255, 0.5] + # transparent white, should be invisible + - type: image + bounds: [200, 0, 100, 100] + src: "transparent-white.png" diff --git a/gfx/wr/wrench/reftests/blend/isolated-ref.yaml b/gfx/wr/wrench/reftests/blend/isolated-ref.yaml new file mode 100644 index 0000000000..0f9061997a --- /dev/null +++ b/gfx/wr/wrench/reftests/blend/isolated-ref.yaml @@ -0,0 +1,6 @@ +--- +root: + items: + - type: rect + bounds: [0, 0, 100, 100] + color: [255, 255, 0] diff --git a/gfx/wr/wrench/reftests/blend/isolated-with-filter.yaml b/gfx/wr/wrench/reftests/blend/isolated-with-filter.yaml new file mode 100644 index 0000000000..483d802cc3 --- /dev/null +++ b/gfx/wr/wrench/reftests/blend/isolated-with-filter.yaml @@ -0,0 +1,18 @@ +--- +root: + items: + - type: rect + bounds: [0, 0, 100, 100] + color: [255, 0, 0] + # the presence of this filter shouldn't break isolated groups + - type: stacking-context + bounds: [0, 0, 100, 100] + filters: opacity(1.0) + items: + - type: stacking-context + bounds: [0, 0, 100, 100] + mix-blend-mode: difference + items: + - type: rect + bounds: [0, 0, 100, 100] + color: [255, 255, 0] diff --git a/gfx/wr/wrench/reftests/blend/isolated.yaml b/gfx/wr/wrench/reftests/blend/isolated.yaml new file mode 100644 index 0000000000..456adba4b9 --- /dev/null +++ b/gfx/wr/wrench/reftests/blend/isolated.yaml @@ -0,0 +1,18 @@ +--- +root: + items: + - type: rect + bounds: [0, 0, 100, 100] + color: [255, 0, 0] + # this stacking context should create an isolated group for its children + # causing the yellow rect to not blend with the green backdrop + - type: stacking-context + bounds: [0, 0, 100, 100] + items: + - type: stacking-context + bounds: [0, 0, 100, 100] + mix-blend-mode: difference + items: + - type: rect + bounds: [0, 0, 100, 100] + color: [255, 255, 0] diff --git a/gfx/wr/wrench/reftests/blend/large-ref.yaml b/gfx/wr/wrench/reftests/blend/large-ref.yaml new file mode 100644 index 0000000000..c7e8433414 --- /dev/null +++ b/gfx/wr/wrench/reftests/blend/large-ref.yaml @@ -0,0 +1,9 @@ +--- +root: + items: + - type: stacking-context + bounds: 0 0 2000 2000 + items: + - type: rect + bounds: 0 0 2000 2000 + color: [0, 128, 0, 1] diff --git a/gfx/wr/wrench/reftests/blend/large.yaml b/gfx/wr/wrench/reftests/blend/large.yaml new file mode 100644 index 0000000000..8167265236 --- /dev/null +++ b/gfx/wr/wrench/reftests/blend/large.yaml @@ -0,0 +1,13 @@ +--- +root: + items: + - type: stacking-context + bounds: 0 0 2000 2000 + items: + - type: stacking-context + bounds: 0 0 2000 2000 + mix-blend-mode: screen + items: + - type: rect + bounds: 0 0 2000 2000 + color: [0, 128, 0, 1] diff --git a/gfx/wr/wrench/reftests/blend/lighten-ref.yaml b/gfx/wr/wrench/reftests/blend/lighten-ref.yaml new file mode 100644 index 0000000000..5720f140a6 --- /dev/null +++ b/gfx/wr/wrench/reftests/blend/lighten-ref.yaml @@ -0,0 +1,6 @@ +--- +root: + items: + - type: rect + bounds: [0, 0, 100, 100] + color: [30, 20, 30] diff --git a/gfx/wr/wrench/reftests/blend/lighten.yaml b/gfx/wr/wrench/reftests/blend/lighten.yaml new file mode 100644 index 0000000000..426e2323b9 --- /dev/null +++ b/gfx/wr/wrench/reftests/blend/lighten.yaml @@ -0,0 +1,16 @@ +--- +root: + items: + - type: stacking-context + blend-container: true + items: + - type: rect + bounds: [0, 0, 100, 100] + color: [10, 20, 30] + - type: stacking-context + bounds: [0, 0, 100, 100] + mix-blend-mode: lighten + items: + - type: rect + bounds: [0, 0, 100, 100] + color: [30, 20, 10] diff --git a/gfx/wr/wrench/reftests/blend/multi-mix-blend-mode-ref.yaml b/gfx/wr/wrench/reftests/blend/multi-mix-blend-mode-ref.yaml new file mode 100644 index 0000000000..ae366a09e0 --- /dev/null +++ b/gfx/wr/wrench/reftests/blend/multi-mix-blend-mode-ref.yaml @@ -0,0 +1,14 @@ +--- +root: + items: + - type: rect + bounds: 0 0 800 200 + color: [255, 0, 0, 1] + + - type: rect + bounds: 50 50 100 100 + color: [255, 255, 0, 1] + + - type: rect + bounds: 300 50 400 100 + color: [255, 0, 255, 1] diff --git a/gfx/wr/wrench/reftests/blend/multi-mix-blend-mode.yaml b/gfx/wr/wrench/reftests/blend/multi-mix-blend-mode.yaml new file mode 100644 index 0000000000..d3ba8fcaf0 --- /dev/null +++ b/gfx/wr/wrench/reftests/blend/multi-mix-blend-mode.yaml @@ -0,0 +1,25 @@ +--- +root: + items: + - type: stacking-context + blend-container: true + items: + - type: rect + bounds: 0 0 800 200 + color: [255, 0, 0, 1] + + - type: stacking-context + bounds: 50 50 100 100 + mix-blend-mode: difference + items: + - type: rect + bounds: 0 0 100 100 + color: [0, 255, 0, 1] + + - type: stacking-context + bounds: 300 50 100 100 + mix-blend-mode: difference + items: + - type: rect + bounds: 0 0 400 100 + color: [0, 0, 255, 1] diff --git a/gfx/wr/wrench/reftests/blend/multiply-2-ref.yaml b/gfx/wr/wrench/reftests/blend/multiply-2-ref.yaml new file mode 100644 index 0000000000..6d4679a79d --- /dev/null +++ b/gfx/wr/wrench/reftests/blend/multiply-2-ref.yaml @@ -0,0 +1,6 @@ +--- +root: + items: + - type: rect + bounds: [0, 0, 100, 100] + color: [0, 128, 0] diff --git a/gfx/wr/wrench/reftests/blend/multiply-2.yaml b/gfx/wr/wrench/reftests/blend/multiply-2.yaml new file mode 100644 index 0000000000..0ad1ef35d6 --- /dev/null +++ b/gfx/wr/wrench/reftests/blend/multiply-2.yaml @@ -0,0 +1,16 @@ +--- +root: + items: + - type: stacking-context + blend-container: true + items: + - type: rect + bounds: [0, 0, 100, 100] + color: [0, 255, 0] + - type: stacking-context + bounds: [0, 0, 100, 100] + mix-blend-mode: multiply + items: + - type: rect + bounds: [0, 0, 100, 100] + color: [255, 128, 0] diff --git a/gfx/wr/wrench/reftests/blend/multiply-3.yaml b/gfx/wr/wrench/reftests/blend/multiply-3.yaml new file mode 100644 index 0000000000..05e1aa20f6 --- /dev/null +++ b/gfx/wr/wrench/reftests/blend/multiply-3.yaml @@ -0,0 +1,20 @@ +--- +root: + items: + - type: stacking-context + blend-container: true + items: + - type: rect + bounds: [0, 0, 100, 100] + color: [0, 255, 0] + - type: stacking-context + bounds: [0, 0, 100, 100] + mix-blend-mode: multiply + items: + - type: stacking-context + bounds: [0, 0, 100, 100] + mix-blend-mode: multiply + items: + - type: rect + bounds: [0, 0, 100, 100] + color: [255, 128, 0] diff --git a/gfx/wr/wrench/reftests/blend/multiply-ref.yaml b/gfx/wr/wrench/reftests/blend/multiply-ref.yaml new file mode 100644 index 0000000000..0b9aeed906 --- /dev/null +++ b/gfx/wr/wrench/reftests/blend/multiply-ref.yaml @@ -0,0 +1,6 @@ +--- +root: + items: + - type: rect + bounds: [0, 0, 100, 100] + color: green diff --git a/gfx/wr/wrench/reftests/blend/multiply.yaml b/gfx/wr/wrench/reftests/blend/multiply.yaml new file mode 100644 index 0000000000..f9fa6cbb75 --- /dev/null +++ b/gfx/wr/wrench/reftests/blend/multiply.yaml @@ -0,0 +1,16 @@ +--- +root: + items: + - type: stacking-context + blend-container: true + items: + - type: rect + bounds: [0, 0, 100, 100] + color: green + - type: stacking-context + bounds: [25, 25, 50, 50] + mix-blend-mode: multiply + items: + - type: rect + bounds: [0, 0, 50, 50] + color: green diff --git a/gfx/wr/wrench/reftests/blend/reftest.list b/gfx/wr/wrench/reftests/blend/reftest.list new file mode 100644 index 0000000000..b4826d6837 --- /dev/null +++ b/gfx/wr/wrench/reftests/blend/reftest.list @@ -0,0 +1,24 @@ +== multiply.yaml multiply-ref.yaml +fuzzy(1,32) == multiply-2.yaml multiply-2-ref.yaml +fuzzy(1,32) == color_targets(4) alpha_targets(0) multiply-3.yaml multiply-2-ref.yaml +== difference.yaml difference-ref.yaml +fuzzy(1,30000) == difference-transparent.yaml difference-transparent-ref.yaml +== darken.yaml darken-ref.yaml +== lighten.yaml lighten-ref.yaml + +fuzzy(1,32) == repeated-difference.yaml repeated-difference-ref.yaml + +== isolated.yaml isolated-ref.yaml +fuzzy(3,397) == isolated-2.yaml isolated-2-ref.yaml +== isolated-with-filter.yaml isolated-ref.yaml +== isolated-premultiplied.yaml blank.yaml +== isolated-premultiplied-2.yaml isolated-premultiplied-2-ref.yaml + +== large.yaml large-ref.yaml + +# fuzzy because dithering is different for gradients +# drawn in different render targets +fuzzy(1,2502) == transparent-composite-1.yaml transparent-composite-1-ref.yaml +fuzzy(1,2502) == transparent-composite-2.yaml transparent-composite-2-ref.yaml + +fuzzy(2,420) == multi-mix-blend-mode.yaml multi-mix-blend-mode-ref.yaml diff --git a/gfx/wr/wrench/reftests/blend/repeated-difference-ref.yaml b/gfx/wr/wrench/reftests/blend/repeated-difference-ref.yaml new file mode 100644 index 0000000000..30d53325ba --- /dev/null +++ b/gfx/wr/wrench/reftests/blend/repeated-difference-ref.yaml @@ -0,0 +1,7 @@ +--- +root: + items: + - + bounds: [0, 0, 100, 100] + type: rect + color: [0, 255, 0] diff --git a/gfx/wr/wrench/reftests/blend/repeated-difference.yaml b/gfx/wr/wrench/reftests/blend/repeated-difference.yaml new file mode 100644 index 0000000000..a04e6cb274 --- /dev/null +++ b/gfx/wr/wrench/reftests/blend/repeated-difference.yaml @@ -0,0 +1,31 @@ +--- +root: + items: + - + bounds: [0, 0, 100, 100] + type: rect + color: [255, 255, 255] + - type: stacking-context + blend-container: true + items: + - + bounds: [0, 0, 100, 100] + type: stacking-context + mix-blend-mode: difference + items: + - + bounds: [0, 0, 100, 100] + type: rect + color: [255, 255, 255] + - type: stacking-context + blend-container: true + items: + - + bounds: [0, 0, 100, 100] + type: stacking-context + mix-blend-mode: difference + items: + - + bounds: [0, 0, 100, 100] + type: rect + color: [0, 255, 0] diff --git a/gfx/wr/wrench/reftests/blend/transparent-composite-1-ref.yaml b/gfx/wr/wrench/reftests/blend/transparent-composite-1-ref.yaml new file mode 100644 index 0000000000..235801c5e1 --- /dev/null +++ b/gfx/wr/wrench/reftests/blend/transparent-composite-1-ref.yaml @@ -0,0 +1,8 @@ +--- +root: + items: + - type: gradient + bounds: [0, 0, 100, 100] + start: [0, 0] + end: [0, 100] + stops: [0.0, [0,0,0,0], 1.0, green] diff --git a/gfx/wr/wrench/reftests/blend/transparent-composite-1.yaml b/gfx/wr/wrench/reftests/blend/transparent-composite-1.yaml new file mode 100644 index 0000000000..319b636843 --- /dev/null +++ b/gfx/wr/wrench/reftests/blend/transparent-composite-1.yaml @@ -0,0 +1,12 @@ +--- +root: + items: + - type: stacking-context + bounds: [0, 0, 100, 100] + mix-blend-mode: darken + items: + - type: gradient + bounds: [0, 0, 100, 100] + start: [0, 0] + end: [0, 100] + stops: [0.0, [0,0,0,0], 1.0, green] diff --git a/gfx/wr/wrench/reftests/blend/transparent-composite-2-ref.yaml b/gfx/wr/wrench/reftests/blend/transparent-composite-2-ref.yaml new file mode 100644 index 0000000000..235801c5e1 --- /dev/null +++ b/gfx/wr/wrench/reftests/blend/transparent-composite-2-ref.yaml @@ -0,0 +1,8 @@ +--- +root: + items: + - type: gradient + bounds: [0, 0, 100, 100] + start: [0, 0] + end: [0, 100] + stops: [0.0, [0,0,0,0], 1.0, green] diff --git a/gfx/wr/wrench/reftests/blend/transparent-composite-2.yaml b/gfx/wr/wrench/reftests/blend/transparent-composite-2.yaml new file mode 100644 index 0000000000..e064f68f95 --- /dev/null +++ b/gfx/wr/wrench/reftests/blend/transparent-composite-2.yaml @@ -0,0 +1,16 @@ +--- +root: + items: + - type: stacking-context + bounds: [0, 0, 100, 100] + mix-blend-mode: darken + items: + - type: stacking-context + bounds: [0, 0, 100, 100] + mix-blend-mode: darken + items: + - type: gradient + bounds: [0, 0, 100, 100] + start: [0, 0] + end: [0, 100] + stops: [0.0, [0,0,0,0], 1.0, green] diff --git a/gfx/wr/wrench/reftests/blend/transparent-white.png b/gfx/wr/wrench/reftests/blend/transparent-white.png Binary files differnew file mode 100644 index 0000000000..6019b2b817 --- /dev/null +++ b/gfx/wr/wrench/reftests/blend/transparent-white.png diff --git a/gfx/wr/wrench/reftests/border/blank.yaml b/gfx/wr/wrench/reftests/border/blank.yaml new file mode 100644 index 0000000000..e3b000bcb2 --- /dev/null +++ b/gfx/wr/wrench/reftests/border/blank.yaml @@ -0,0 +1,3 @@ +--- +root: + diff --git a/gfx/wr/wrench/reftests/border/border-clamp-corner-radius.png b/gfx/wr/wrench/reftests/border/border-clamp-corner-radius.png Binary files differnew file mode 100644 index 0000000000..bdeda43864 --- /dev/null +++ b/gfx/wr/wrench/reftests/border/border-clamp-corner-radius.png diff --git a/gfx/wr/wrench/reftests/border/border-clamp-corner-radius.yaml b/gfx/wr/wrench/reftests/border/border-clamp-corner-radius.yaml new file mode 100644 index 0000000000..10859274c7 --- /dev/null +++ b/gfx/wr/wrench/reftests/border/border-clamp-corner-radius.yaml @@ -0,0 +1,24 @@ +--- +root: + items: + - type: stacking-context + bounds: [0, 0, 420, 250] + items: + - type: border + bounds: [ 0, 0, 200, 200 ] + width: 10 + border-type: normal + style: solid + radius: 180 + color: blue + - type: border + bounds: [ 200, 0, 200, 200 ] + width: 10 + border-type: normal + style: solid + radius: + top-left: [180, 180] + top-right: [0, 0] + bottom-left: [0, 0] + bottom-right: [180, 180] + color: blue
\ No newline at end of file diff --git a/gfx/wr/wrench/reftests/border/border-dashed-dotted-caching.png b/gfx/wr/wrench/reftests/border/border-dashed-dotted-caching.png Binary files differnew file mode 100644 index 0000000000..3eb49ff3e3 --- /dev/null +++ b/gfx/wr/wrench/reftests/border/border-dashed-dotted-caching.png diff --git a/gfx/wr/wrench/reftests/border/border-dashed-dotted-caching.yaml b/gfx/wr/wrench/reftests/border/border-dashed-dotted-caching.yaml new file mode 100644 index 0000000000..ca224852fd --- /dev/null +++ b/gfx/wr/wrench/reftests/border/border-dashed-dotted-caching.yaml @@ -0,0 +1,76 @@ +--- +root: + items: + - type: stacking-context + bounds: [0, 0, 500, 500] + items: + + - type: border + bounds: [ 0, 10, 25, 30 ] + width: [ 10 ] + border-type: normal + style: [ dashed ] + color: [ blue ] + + - type: border + bounds: [ 0, 60, 200, 30 ] + width: [ 10 ] + border-type: normal + style: [ dashed ] + color: [ blue ] + + - type: border + bounds: [ 0, 110, 300, 30 ] + width: [ 10 ] + border-type: normal + style: [ dashed ] + color: [ blue ] + + - type: border + bounds: [ 0, 160, 400, 30 ] + width: [ 10 ] + border-type: normal + style: [ dashed ] + color: [ blue ] + + - type: border + bounds: [ 0, 210, 500, 30 ] + width: [ 10 ] + border-type: normal + style: [ dashed ] + color: [ blue ] + + - type: border + bounds: [ 0, 260, 25, 30 ] + width: [ 10 ] + border-type: normal + style: [ dotted ] + color: [ blue ] + + - type: border + bounds: [ 0, 310, 200, 30 ] + width: [ 10 ] + border-type: normal + style: [ dotted ] + color: [ blue ] + + - type: border + bounds: [ 0, 360, 300, 30 ] + width: [ 10 ] + border-type: normal + style: [ dotted ] + color: [ blue ] + + - type: border + bounds: [ 0, 410, 400, 30 ] + width: [ 10 ] + border-type: normal + style: [ dotted ] + color: [ blue ] + + - type: border + bounds: [ 0, 460, 500, 30 ] + width: [ 10 ] + border-type: normal + style: [ dotted ] + color: [ blue ] diff --git a/gfx/wr/wrench/reftests/border/border-double-1px-ref.yaml b/gfx/wr/wrench/reftests/border/border-double-1px-ref.yaml new file mode 100644 index 0000000000..f0c9eca1ca --- /dev/null +++ b/gfx/wr/wrench/reftests/border/border-double-1px-ref.yaml @@ -0,0 +1,17 @@ +--- +root: + items: + - type: stacking-context + items: + - type: border + bounds: [ 10, 10, 100, 20 ] + width: 1 + border-type: normal + style: solid + color: red + - type: border + bounds: [ 12, 12, 96, 16 ] + width: 1 + border-type: normal + style: solid + color: red diff --git a/gfx/wr/wrench/reftests/border/border-double-1px.yaml b/gfx/wr/wrench/reftests/border/border-double-1px.yaml new file mode 100644 index 0000000000..3a5f084108 --- /dev/null +++ b/gfx/wr/wrench/reftests/border/border-double-1px.yaml @@ -0,0 +1,11 @@ +--- +root: + items: + - type: stacking-context + items: + - type: border + bounds: [ 10, 10, 100, 20 ] + width: 3 + border-type: normal + style: double + color: red diff --git a/gfx/wr/wrench/reftests/border/border-double-simple-2-ref.yaml b/gfx/wr/wrench/reftests/border/border-double-simple-2-ref.yaml new file mode 100644 index 0000000000..e7fa39f125 --- /dev/null +++ b/gfx/wr/wrench/reftests/border/border-double-simple-2-ref.yaml @@ -0,0 +1,12 @@ +--- +root: + items: + - type: stacking-context + bounds: [0, 0, 500, 500] + items: + - type: border + bounds: [ 0, 0, 500, 500 ] + width: [ 1 ] + border-type: normal + style: [ solid ] + color: [ black ] diff --git a/gfx/wr/wrench/reftests/border/border-double-simple-2.yaml b/gfx/wr/wrench/reftests/border/border-double-simple-2.yaml new file mode 100644 index 0000000000..6fa6d634cd --- /dev/null +++ b/gfx/wr/wrench/reftests/border/border-double-simple-2.yaml @@ -0,0 +1,12 @@ +--- +root: + items: + - type: stacking-context + bounds: [0, 0, 500, 500] + items: + - type: border + bounds: [ 0, 0, 500, 500 ] + width: [ 1 ] + border-type: normal + style: [ double ] + color: [ black ] diff --git a/gfx/wr/wrench/reftests/border/border-double-simple-ref.yaml b/gfx/wr/wrench/reftests/border/border-double-simple-ref.yaml new file mode 100644 index 0000000000..564e4df163 --- /dev/null +++ b/gfx/wr/wrench/reftests/border/border-double-simple-ref.yaml @@ -0,0 +1,21 @@ +--- +root: + items: + - type: stacking-context + bounds: [0, 0, 50, 50] + items: + - type: border + bounds: [ 0, 0, 50, 50 ] + width: [ 4, 4, 4, 4 ] + border-type: normal + style: [ solid, solid, solid, solid ] + color: [ blue, blue, blue, blue ] + - type: stacking-context + bounds: [8, 8, 34, 34] + items: + - type: border + bounds: [ 0, 0, 34, 34 ] + width: [ 4, 4, 4, 4 ] + border-type: normal + style: [ solid, solid, solid, solid ] + color: [ blue, blue, blue, blue ] diff --git a/gfx/wr/wrench/reftests/border/border-double-simple.yaml b/gfx/wr/wrench/reftests/border/border-double-simple.yaml new file mode 100644 index 0000000000..4830485a8f --- /dev/null +++ b/gfx/wr/wrench/reftests/border/border-double-simple.yaml @@ -0,0 +1,12 @@ +--- +root: + items: + - type: stacking-context + bounds: [0, 0, 500, 500] + items: + - type: border + bounds: [ 0, 0, 50, 50 ] + width: [ 12, 12, 12, 12 ] + border-type: normal + style: [ double, double, double, double ] + color: [ blue, blue, blue, blue ] diff --git a/gfx/wr/wrench/reftests/border/border-gradient-nine-patch.png b/gfx/wr/wrench/reftests/border/border-gradient-nine-patch.png Binary files differnew file mode 100644 index 0000000000..1f082e656e --- /dev/null +++ b/gfx/wr/wrench/reftests/border/border-gradient-nine-patch.png diff --git a/gfx/wr/wrench/reftests/border/border-gradient-nine-patch.yaml b/gfx/wr/wrench/reftests/border/border-gradient-nine-patch.yaml new file mode 100644 index 0000000000..9a2d6991a0 --- /dev/null +++ b/gfx/wr/wrench/reftests/border/border-gradient-nine-patch.yaml @@ -0,0 +1,12 @@ +--- +root: + items: + - type: border + bounds: [ 0, 0, 200, 200 ] + width: 30 + border-type: gradient + start: [ 0, 200 ] + end: [ 200, 0 ] + stops: [ 0.0, red, 0.177, red, 0.177, yellow, 0.50, yellow, 0.50, red ] + slice: [ 50 ] + outset: 0 diff --git a/gfx/wr/wrench/reftests/border/border-gradient-simple-ref.yaml b/gfx/wr/wrench/reftests/border/border-gradient-simple-ref.yaml new file mode 100644 index 0000000000..d961c12041 --- /dev/null +++ b/gfx/wr/wrench/reftests/border/border-gradient-simple-ref.yaml @@ -0,0 +1,55 @@ +--- +root: + items: + - type: stacking-context + bounds: [0, 0, 50, 50] + items: + - type: gradient # top left + bounds: [ 0, 0, 10, 10] + start: [ 25, 0 ] + end: [ 25, 50 ] + stops: [ 0.0, red, 1.0, green ] + repeat: false + - type: gradient # top right + bounds: [ 40, 0, 10, 10] + start: [ -15, 0 ] + end: [ -15, 50 ] + stops: [ 0.0, red, 1.0, green ] + repeat: false + - type: gradient # bottom left + bounds: [ 0, 40, 10, 10] + start: [ 25, -40 ] + end: [ 25, 10 ] + stops: [ 0.0, red, 1.0, green ] + repeat: false + - type: gradient # bottom right + bounds: [ 40, 40, 10, 10] + start: [ -15, -40 ] + end: [ -15, 10 ] + stops: [ 0.0, red, 1.0, green ] + repeat: false + - type: gradient # top + bounds: [ 10, 0, 30, 10] + start: [ 15, 0 ] + end: [ 15, 50 ] + stops: [ 0.0, red, 1.0, green ] + repeat: false + - type: gradient # right + bounds: [ 40, 10, 10, 30] + start: [ -15, -10 ] + end: [ -15, 40 ] + stops: [ 0.0, red, 1.0, green ] + repeat: false + - type: gradient # bottom + bounds: [ 10, 40, 30, 10] + start: [ 15, -40 ] + end: [ 15, 10 ] + stops: [ 0.0, red, 1.0, green ] + repeat: false + - type: gradient # left + bounds: [ 0, 10, 10, 30] + start: [ 25, -10 ] + end: [ 25, 40 ] + stops: [ 0.0, red, 1.0, green ] + repeat: false + diff --git a/gfx/wr/wrench/reftests/border/border-gradient-simple.yaml b/gfx/wr/wrench/reftests/border/border-gradient-simple.yaml new file mode 100644 index 0000000000..ef2d5a033a --- /dev/null +++ b/gfx/wr/wrench/reftests/border/border-gradient-simple.yaml @@ -0,0 +1,14 @@ +--- +root: + items: + - type: stacking-context + bounds: [0, 0, 50, 50] + items: + - type: border + bounds: [ 0, 0, 50, 50 ] + width: [ 10, 10, 10, 10 ] + border-type: gradient + start: [ 25, 0 ] + end: [ 25, 50 ] + stops: [ 0.0, red, 1.0, green ] + outset: [ 0, 0, 0, 0 ] diff --git a/gfx/wr/wrench/reftests/border/border-groove-simple-ref.yaml b/gfx/wr/wrench/reftests/border/border-groove-simple-ref.yaml new file mode 100644 index 0000000000..9dfe5f3358 --- /dev/null +++ b/gfx/wr/wrench/reftests/border/border-groove-simple-ref.yaml @@ -0,0 +1,21 @@ +--- +root: + items: + - type: stacking-context + bounds: [0, 0, 50, 50] + items: + - type: border + bounds: [ 0, 0, 50, 50 ] + width: [ 6, 6, 6, 6 ] + border-type: normal + style: [ solid, solid, solid, solid ] + color: [ 0 0 170 1.0, 0 0 255 1.0, 0 0 255 1.0, 0 0 170 1.0 ] + - type: stacking-context + bounds: [6, 6, 38, 38] + items: + - type: border + bounds: [ 0, 0, 38, 38 ] + width: [ 6, 6, 6, 6 ] + border-type: normal + style: [ solid, solid, solid, solid ] + color: [ 0 0 255 1.0, 0 0 170 1.0, 0 0 170 1.0, 0 0 255 1.0 ] diff --git a/gfx/wr/wrench/reftests/border/border-groove-simple.yaml b/gfx/wr/wrench/reftests/border/border-groove-simple.yaml new file mode 100644 index 0000000000..0d992d5dc6 --- /dev/null +++ b/gfx/wr/wrench/reftests/border/border-groove-simple.yaml @@ -0,0 +1,12 @@ +--- +root: + items: + - type: stacking-context + bounds: [0, 0, 500, 500] + items: + - type: border + bounds: [ 0, 0, 50, 50 ] + width: [ 12, 12, 12, 12 ] + border-type: normal + style: [ groove, groove, groove, groove ] + color: [ blue, blue, blue, blue ] diff --git a/gfx/wr/wrench/reftests/border/border-image-crash-ref.yaml b/gfx/wr/wrench/reftests/border/border-image-crash-ref.yaml new file mode 100644 index 0000000000..9ea9184348 --- /dev/null +++ b/gfx/wr/wrench/reftests/border/border-image-crash-ref.yaml @@ -0,0 +1,21 @@ +--- +root: + items: + - type: stacking-context + bounds: [0, 0, 500, 500] + items: + - type: border + bounds: [ 100, 100, 192, 192 ] + width: 32 + border-type: image + image-source: "border-image-src.png" + image-width: 32 + image-height: 32 + slice: [ 3, 0, 1, 36 ] + outset: 0 + repeat-vertical: stretch + repeat-horizontal: stretch + fill: true + - type: rect + bounds: [ 100, 100, 192, 192 ] + color: white diff --git a/gfx/wr/wrench/reftests/border/border-image-crash.yaml b/gfx/wr/wrench/reftests/border/border-image-crash.yaml new file mode 100644 index 0000000000..9ea9184348 --- /dev/null +++ b/gfx/wr/wrench/reftests/border/border-image-crash.yaml @@ -0,0 +1,21 @@ +--- +root: + items: + - type: stacking-context + bounds: [0, 0, 500, 500] + items: + - type: border + bounds: [ 100, 100, 192, 192 ] + width: 32 + border-type: image + image-source: "border-image-src.png" + image-width: 32 + image-height: 32 + slice: [ 3, 0, 1, 36 ] + outset: 0 + repeat-vertical: stretch + repeat-horizontal: stretch + fill: true + - type: rect + bounds: [ 100, 100, 192, 192 ] + color: white diff --git a/gfx/wr/wrench/reftests/border/border-image-empty-slice-ref.png b/gfx/wr/wrench/reftests/border/border-image-empty-slice-ref.png Binary files differnew file mode 100644 index 0000000000..8ba6808ac9 --- /dev/null +++ b/gfx/wr/wrench/reftests/border/border-image-empty-slice-ref.png diff --git a/gfx/wr/wrench/reftests/border/border-image-empty-slice.yaml b/gfx/wr/wrench/reftests/border/border-image-empty-slice.yaml new file mode 100644 index 0000000000..16f22b32f4 --- /dev/null +++ b/gfx/wr/wrench/reftests/border/border-image-empty-slice.yaml @@ -0,0 +1,50 @@ +--- +root: + items: + - type: stacking-context + bounds: [0, 0, 500, 500] + items: + - type: border + bounds: [ 20, 20, 192, 192 ] + width: 32 + border-type: image + image-source: "border-image-src.png" + image-width: 96 + image-height: 96 + slice: [ 32, 0, 32, 0 ] + outset: 0 + repeat-vertical: round + repeat-horizontal: round + - type: border + bounds: [ 240, 20, 192, 192 ] + width: 32 + border-type: image + image-source: "border-image-src.png" + image-width: 96 + image-height: 96 + slice: [ 0, 32, 0, 32 ] + outset: 0 + repeat-vertical: round + repeat-horizontal: round + - type: border + bounds: [ 20, 240, 192, 192 ] + width: 32 + border-type: image + image-source: "border-image-src.png" + image-width: 96 + image-height: 96 + slice: [ 32, 0, 0, 32 ] + outset: 0 + repeat-vertical: round + repeat-horizontal: round + - type: border + bounds: [ 240, 240, 192, 192 ] + width: 32 + border-type: image + image-source: "border-image-src.png" + image-width: 96 + image-height: 96 + slice: [ 0, 32, 32, 0 ] + outset: 0 + repeat-vertical: round + repeat-horizontal: round diff --git a/gfx/wr/wrench/reftests/border/border-image-fill-2-ref.png b/gfx/wr/wrench/reftests/border/border-image-fill-2-ref.png Binary files differnew file mode 100644 index 0000000000..5bb7dc8fb2 --- /dev/null +++ b/gfx/wr/wrench/reftests/border/border-image-fill-2-ref.png diff --git a/gfx/wr/wrench/reftests/border/border-image-fill-2.yaml b/gfx/wr/wrench/reftests/border/border-image-fill-2.yaml new file mode 100644 index 0000000000..653c4f34e4 --- /dev/null +++ b/gfx/wr/wrench/reftests/border/border-image-fill-2.yaml @@ -0,0 +1,55 @@ +--- +root: + items: + - type: stacking-context + bounds: [0, 0, 500, 500] + items: + - type: border + bounds: [ 20, 20, 200, 200 ] + width: [20, 40] + border-type: image + image-source: "border-image-src-2.png" + image-width: 100 + image-height: 50 + slice: [ 20, 40 ] + outset: 0 + repeat-vertical: repeat + repeat-horizontal: repeat + fill: true + - type: border + bounds: [ 240, 20, 200, 200 ] + width: [20, 40] + slice: [ 20, 40 ] + border-type: image + image-source: "border-image-src-2.png" + image-width: 100 + image-height: 50 + slice: [ 20, 40 ] + outset: 0 + repeat-vertical: stretch + repeat-horizontal: repeat + fill: true + - type: border + bounds: [ 20, 240, 200, 200 ] + width: [20, 40] + border-type: image + image-source: "border-image-src-2.png" + image-width: 100 + image-height: 50 + slice: [ 20, 40 ] + outset: 0 + repeat-vertical: repeat + repeat-horizontal: stretch + fill: true + - type: border + bounds: [ 240, 240, 200, 200 ] + width: [20, 40] + border-type: image + image-source: "border-image-src-2.png" + image-width: 100 + image-height: 50 + slice: [ 20, 40 ] + outset: 0 + repeat-vertical: stretch + repeat-horizontal: stretch + fill: true diff --git a/gfx/wr/wrench/reftests/border/border-image-fill-ref.png b/gfx/wr/wrench/reftests/border/border-image-fill-ref.png Binary files differnew file mode 100644 index 0000000000..9d618bc76e --- /dev/null +++ b/gfx/wr/wrench/reftests/border/border-image-fill-ref.png diff --git a/gfx/wr/wrench/reftests/border/border-image-fill.yaml b/gfx/wr/wrench/reftests/border/border-image-fill.yaml new file mode 100644 index 0000000000..0e27b993c5 --- /dev/null +++ b/gfx/wr/wrench/reftests/border/border-image-fill.yaml @@ -0,0 +1,54 @@ +--- +root: + items: + - type: stacking-context + bounds: [0, 0, 500, 500] + items: + - type: border + bounds: [ 100, 100, 192, 192 ] + width: 32 + border-type: image + image-source: "border-image-src.png" + image-width: 96 + image-height: 96 + slice: [ 32 ] + outset: 0 + repeat-vertical: repeat + repeat-horizontal: repeat + fill: true + - type: border + bounds: [ 300, 100, 192, 192 ] + width: 32 + border-type: image + image-source: "border-image-src.png" + image-width: 96 + image-height: 96 + slice: [ 32 ] + outset: 0 + repeat-vertical: stretch + repeat-horizontal: repeat + fill: true + - type: border + bounds: [ 100, 300, 192, 192 ] + width: 32 + border-type: image + image-source: "border-image-src.png" + image-width: 96 + image-height: 96 + slice: [ 32 ] + outset: 0 + repeat-vertical: repeat + repeat-horizontal: stretch + fill: true + - type: border + bounds: [ 300, 300, 192, 192 ] + width: 32 + border-type: image + image-source: "border-image-src.png" + image-width: 96 + image-height: 96 + slice: [ 32 ] + outset: 0 + repeat-vertical: stretch + repeat-horizontal: stretch + fill: true diff --git a/gfx/wr/wrench/reftests/border/border-image-ref.png b/gfx/wr/wrench/reftests/border/border-image-ref.png Binary files differnew file mode 100644 index 0000000000..73e4eb5256 --- /dev/null +++ b/gfx/wr/wrench/reftests/border/border-image-ref.png diff --git a/gfx/wr/wrench/reftests/border/border-image-round-ref.png b/gfx/wr/wrench/reftests/border/border-image-round-ref.png Binary files differnew file mode 100644 index 0000000000..62a18fbba9 --- /dev/null +++ b/gfx/wr/wrench/reftests/border/border-image-round-ref.png diff --git a/gfx/wr/wrench/reftests/border/border-image-round.yaml b/gfx/wr/wrench/reftests/border/border-image-round.yaml new file mode 100644 index 0000000000..e46a90c056 --- /dev/null +++ b/gfx/wr/wrench/reftests/border/border-image-round.yaml @@ -0,0 +1,42 @@ +--- +root: + items: + - type: stacking-context + bounds: [0, 0, 500, 500] + items: + # The pattern fits exactly a whole number of times in the border. + - type: border + bounds: [ 50, 50, 192, 192 ] + width: 32 + border-type: image + image-source: "border-image-src.png" + image-width: 96 + image-height: 96 + slice: [ 32 ] + outset: 0 + repeat-vertical: round + repeat-horizontal: round + # The pattern has to be stretched to fit. + - type: border + bounds: [ 300, 50, 200, 200 ] + width: 32 + border-type: image + image-source: "border-image-src.png" + image-width: 96 + image-height: 96 + slice: [ 32 ] + outset: 0 + repeat-vertical: round + repeat-horizontal: round + # The pattern has to be shrunk to fit. + - type: border + bounds: [ 550, 50, 180, 180 ] + width: 32 + border-type: image + image-source: "border-image-src.png" + image-width: 96 + image-height: 96 + slice: [ 32 ] + outset: 0 + repeat-vertical: round + repeat-horizontal: round diff --git a/gfx/wr/wrench/reftests/border/border-image-src-2.png b/gfx/wr/wrench/reftests/border/border-image-src-2.png Binary files differnew file mode 100644 index 0000000000..5ebebaf21f --- /dev/null +++ b/gfx/wr/wrench/reftests/border/border-image-src-2.png diff --git a/gfx/wr/wrench/reftests/border/border-image-src.png b/gfx/wr/wrench/reftests/border/border-image-src.png Binary files differnew file mode 100644 index 0000000000..128e560d90 --- /dev/null +++ b/gfx/wr/wrench/reftests/border/border-image-src.png diff --git a/gfx/wr/wrench/reftests/border/border-image.yaml b/gfx/wr/wrench/reftests/border/border-image.yaml new file mode 100644 index 0000000000..5dbc0acb1e --- /dev/null +++ b/gfx/wr/wrench/reftests/border/border-image.yaml @@ -0,0 +1,17 @@ +--- +root: + items: + - type: stacking-context + bounds: [0, 0, 500, 500] + items: + - type: border + bounds: [ 100, 100, 192, 192 ] + width: 32 + border-type: image + image-source: "border-image-src.png" + image-width: 96 + image-height: 96 + slice: [ 32 ] + outset: 0 + repeat-vertical: stretch + repeat-horizontal: stretch diff --git a/gfx/wr/wrench/reftests/border/border-invisible-ref.yaml b/gfx/wr/wrench/reftests/border/border-invisible-ref.yaml new file mode 100644 index 0000000000..949868c9b2 --- /dev/null +++ b/gfx/wr/wrench/reftests/border/border-invisible-ref.yaml @@ -0,0 +1,9 @@ +--- +root: + items: + - type: stacking-context + bounds: [0, 0, 100, 100] + items: + - type: rect + bounds: [99, 10, 1, 90] + color: black diff --git a/gfx/wr/wrench/reftests/border/border-invisible.yaml b/gfx/wr/wrench/reftests/border/border-invisible.yaml new file mode 100644 index 0000000000..4838786299 --- /dev/null +++ b/gfx/wr/wrench/reftests/border/border-invisible.yaml @@ -0,0 +1,17 @@ +--- # checks that invisible border corners don't render +root: + items: + - type: stacking-context + bounds: [0, 0, 100, 100] + items: + - type: border + bounds: [ 10, 10, 90, 90 ] + width: [0, 0, 0, 1] + border-type: normal + style: solid + radius: + top-left: 10 + bottom-right: 0 + top-right: 0 + bottom-left: 3 + color: [red, black, red, red] diff --git a/gfx/wr/wrench/reftests/border/border-no-bogus-line-ref.png b/gfx/wr/wrench/reftests/border/border-no-bogus-line-ref.png Binary files differnew file mode 100644 index 0000000000..fefa2bcbce --- /dev/null +++ b/gfx/wr/wrench/reftests/border/border-no-bogus-line-ref.png diff --git a/gfx/wr/wrench/reftests/border/border-no-bogus-line.yaml b/gfx/wr/wrench/reftests/border/border-no-bogus-line.yaml new file mode 100644 index 0000000000..a030211da9 --- /dev/null +++ b/gfx/wr/wrench/reftests/border/border-no-bogus-line.yaml @@ -0,0 +1,13 @@ +--- +root: + items: + - type: stacking-context + bounds: [0, 0, 100, 100] + items: + - type: border + bounds: [ 10, 10, 90, 80 ] + width: 3 + border-type: normal + style: solid + color: [ black, black, black, black ] + radius: 40.5 diff --git a/gfx/wr/wrench/reftests/border/border-none-ref.yaml b/gfx/wr/wrench/reftests/border/border-none-ref.yaml new file mode 100644 index 0000000000..e011c78eb5 --- /dev/null +++ b/gfx/wr/wrench/reftests/border/border-none-ref.yaml @@ -0,0 +1,9 @@ +--- +root: + items: + - type: stacking-context + bounds: [0, 0, 500, 500] + items: + - type: rect + bounds: [ 0, 0, 500, 12 ] + color: black diff --git a/gfx/wr/wrench/reftests/border/border-none.yaml b/gfx/wr/wrench/reftests/border/border-none.yaml new file mode 100644 index 0000000000..4b423c7da5 --- /dev/null +++ b/gfx/wr/wrench/reftests/border/border-none.yaml @@ -0,0 +1,12 @@ +--- +root: + items: + - type: stacking-context + bounds: [0, 0, 500, 500] + items: + - type: border + bounds: [ 0, 0, 500, 500 ] + width: [ 12, 12, 12, 12 ] + border-type: normal + style: [ solid, none, none, none ] + color: [ black ] diff --git a/gfx/wr/wrench/reftests/border/border-overlapping-corner-ref.yaml b/gfx/wr/wrench/reftests/border/border-overlapping-corner-ref.yaml new file mode 100644 index 0000000000..3ffbaacc00 --- /dev/null +++ b/gfx/wr/wrench/reftests/border/border-overlapping-corner-ref.yaml @@ -0,0 +1,19 @@ +--- +root: + items: + - type: stacking-context + bounds: [0, 0, 200, 200] + items: + - type: clip + bounds: [ 0, 0, 200, 200 ] + complex: + - rect: [ 10, 10, 180, 180 ] + radius: + top-left: [180, 180] + top-right: [0, 0] + bottom-left: [0, 0] + bottom-right: [180, 180] + items: + - type: rect + bounds: [ 0, 0, 200, 200 ] + color: [ 0, 0, 255, 0.5 ] diff --git a/gfx/wr/wrench/reftests/border/border-overlapping-corner.yaml b/gfx/wr/wrench/reftests/border/border-overlapping-corner.yaml new file mode 100644 index 0000000000..08e71fabef --- /dev/null +++ b/gfx/wr/wrench/reftests/border/border-overlapping-corner.yaml @@ -0,0 +1,17 @@ +--- # Checks that corners are clipped correctly when they overlap with an adjacent corner +root: + items: + - type: stacking-context + bounds: [0, 0, 200, 200] + items: + - type: border + bounds: [ 10, 10, 180, 180 ] + width: 90 + border-type: normal + style: solid + radius: + top-left: 180 + bottom-right: 180 + top-right: 0 + bottom-left: 0 + color: [ [0, 0, 255, 0.5] ] diff --git a/gfx/wr/wrench/reftests/border/border-overlapping-edge-ref.yaml b/gfx/wr/wrench/reftests/border/border-overlapping-edge-ref.yaml new file mode 100644 index 0000000000..5cb34e5ae2 --- /dev/null +++ b/gfx/wr/wrench/reftests/border/border-overlapping-edge-ref.yaml @@ -0,0 +1,9 @@ +--- +root: + items: + - type: stacking-context + bounds: [0, 0, 120, 40] + items: + - type: rect + bounds: [ 10, 10, 100, 20 ] + color: [ 0, 0, 255, 0.5 ] diff --git a/gfx/wr/wrench/reftests/border/border-overlapping-edge.yaml b/gfx/wr/wrench/reftests/border/border-overlapping-edge.yaml new file mode 100644 index 0000000000..e39e06fddc --- /dev/null +++ b/gfx/wr/wrench/reftests/border/border-overlapping-edge.yaml @@ -0,0 +1,12 @@ +--- # Checks that segments are clipped correctly when opposite edges of the border overlap +root: + items: + - type: stacking-context + bounds: [0, 0, 120, 40] + items: + - type: border + bounds: [ 10, 10, 100, 20 ] + width: 15 + border-type: normal + style: solid + color: [ [0, 0, 255, 0.5] ] diff --git a/gfx/wr/wrench/reftests/border/border-radial-gradient-nine-patch.png b/gfx/wr/wrench/reftests/border/border-radial-gradient-nine-patch.png Binary files differnew file mode 100644 index 0000000000..fd1ed84b8d --- /dev/null +++ b/gfx/wr/wrench/reftests/border/border-radial-gradient-nine-patch.png diff --git a/gfx/wr/wrench/reftests/border/border-radial-gradient-nine-patch.yaml b/gfx/wr/wrench/reftests/border/border-radial-gradient-nine-patch.yaml new file mode 100644 index 0000000000..d3936a7424 --- /dev/null +++ b/gfx/wr/wrench/reftests/border/border-radial-gradient-nine-patch.yaml @@ -0,0 +1,12 @@ +--- +root: + items: + - type: border + bounds: [ 0, 0, 200, 200 ] + width: 20 + border-type: radial-gradient + center: [ 100, 100 ] + radius: [ 200, 200 ] + stops: [ 0.0, red, 0.5, red, 0.5, green ] + slice: [ 50 ] + outset: 0 diff --git a/gfx/wr/wrench/reftests/border/border-radial-gradient-simple-ref.yaml b/gfx/wr/wrench/reftests/border/border-radial-gradient-simple-ref.yaml new file mode 100644 index 0000000000..7c3e93fd76 --- /dev/null +++ b/gfx/wr/wrench/reftests/border/border-radial-gradient-simple-ref.yaml @@ -0,0 +1,54 @@ +--- +root: + items: + - type: stacking-context + bounds: [0, 0, 50, 50] + items: + - type: radial-gradient # top left + bounds: [ 0, 0, 10, 10] + center: [ 25, 25 ] + radius: [50, 50] + stops: [ 0.0, red, 1.0, green ] + repeat: false + - type: radial-gradient # top right + bounds: [ 40, 0, 10, 10] + center: [ -15, 25 ] + radius: [50, 50] + stops: [ 0.0, red, 1.0, green ] + repeat: false + - type: radial-gradient # bottom left + bounds: [ 0, 40, 10, 10] + center: [ 25, -15 ] + radius: [50, 50] + stops: [ 0.0, red, 1.0, green ] + repeat: false + - type: radial-gradient # bottom right + bounds: [ 40, 40, 10, 10] + center: [ -15, -15 ] + radius: [50, 50] + stops: [ 0.0, red, 1.0, green ] + repeat: false + - type: radial-gradient # top + bounds: [ 10, 0, 30, 10] + center: [ 15, 25 ] + radius: [50, 50] + stops: [ 0.0, red, 1.0, green ] + repeat: false + - type: radial-gradient # right + bounds: [ 40, 10, 10, 30] + center: [ -15, 15 ] + radius: [50, 50] + stops: [ 0.0, red, 1.0, green ] + repeat: false + - type: radial-gradient # bottom + bounds: [ 10, 40, 30, 10] + center: [ 15, -15 ] + radius: [50, 50] + stops: [ 0.0, red, 1.0, green ] + repeat: false + - type: radial-gradient # left + bounds: [ 0, 10, 10, 30] + center: [ 25, 15 ] + radius: [50, 50] + stops: [ 0.0, red, 1.0, green ] + repeat: false diff --git a/gfx/wr/wrench/reftests/border/border-radial-gradient-simple.yaml b/gfx/wr/wrench/reftests/border/border-radial-gradient-simple.yaml new file mode 100644 index 0000000000..d5110ce4ae --- /dev/null +++ b/gfx/wr/wrench/reftests/border/border-radial-gradient-simple.yaml @@ -0,0 +1,14 @@ +--- +root: + items: + - type: stacking-context + bounds: [0, 0, 50, 50] + items: + - type: border + bounds: [ 0, 0, 50, 50 ] + width: [ 10, 10, 10, 10 ] + border-type: radial-gradient + center: [ 25, 25 ] + radius: [ 50, 50 ] + stops: [ 0.0, red, 1.0, green ] + outset: [ 0, 0, 0, 0 ] diff --git a/gfx/wr/wrench/reftests/border/border-radii.png b/gfx/wr/wrench/reftests/border/border-radii.png Binary files differnew file mode 100644 index 0000000000..87d5b674fd --- /dev/null +++ b/gfx/wr/wrench/reftests/border/border-radii.png diff --git a/gfx/wr/wrench/reftests/border/border-radii.yaml b/gfx/wr/wrench/reftests/border/border-radii.yaml new file mode 100644 index 0000000000..c0b2fda968 --- /dev/null +++ b/gfx/wr/wrench/reftests/border/border-radii.yaml @@ -0,0 +1,17 @@ +--- +root: + items: + - type: stacking-context + bounds: [0, 0, 100, 100] + items: + - type: border + bounds: [ 10, 10, 90, 90 ] + width: 10 + border-type: normal + style: solid + radius: + top-left: 16 + bottom-right: 16 + top-right: 8 + bottom-left: 8 + color: [ blue, blue, blue, blue ] diff --git a/gfx/wr/wrench/reftests/border/border-ridge-simple-ref.yaml b/gfx/wr/wrench/reftests/border/border-ridge-simple-ref.yaml new file mode 100644 index 0000000000..b940962d45 --- /dev/null +++ b/gfx/wr/wrench/reftests/border/border-ridge-simple-ref.yaml @@ -0,0 +1,21 @@ +--- +root: + items: + - type: stacking-context + bounds: [0, 0, 50, 50] + items: + - type: border + bounds: [ 0, 0, 50, 50 ] + width: [ 6, 6, 6, 6 ] + border-type: normal + style: [ solid, solid, solid, solid ] + color: [ 0 0 255 1.0, 0 0 170 1.0, 0 0 170 1.0, 0 0 255 1.0 ] + - type: stacking-context + bounds: [6, 6, 38, 38] + items: + - type: border + bounds: [ 0, 0, 38, 38 ] + width: [ 6, 6, 6, 6 ] + border-type: normal + style: [ solid, solid, solid, solid ] + color: [ 0 0 170 1.0, 0 0 255 1.0, 0 0 255 1.0, 0 0 170 1.0 ] diff --git a/gfx/wr/wrench/reftests/border/border-ridge-simple.yaml b/gfx/wr/wrench/reftests/border/border-ridge-simple.yaml new file mode 100644 index 0000000000..906b40fa42 --- /dev/null +++ b/gfx/wr/wrench/reftests/border/border-ridge-simple.yaml @@ -0,0 +1,12 @@ +--- +root: + items: + - type: stacking-context + bounds: [0, 0, 500, 500] + items: + - type: border + bounds: [ 0, 0, 50, 50 ] + width: [ 12, 12, 12, 12 ] + border-type: normal + style: [ ridge, ridge, ridge, ridge ] + color: [ blue, blue, blue, blue ] diff --git a/gfx/wr/wrench/reftests/border/border-suite-2.png b/gfx/wr/wrench/reftests/border/border-suite-2.png Binary files differnew file mode 100644 index 0000000000..4e7f6abc68 --- /dev/null +++ b/gfx/wr/wrench/reftests/border/border-suite-2.png diff --git a/gfx/wr/wrench/reftests/border/border-suite-2.yaml b/gfx/wr/wrench/reftests/border/border-suite-2.yaml new file mode 100644 index 0000000000..f86b20da30 --- /dev/null +++ b/gfx/wr/wrench/reftests/border/border-suite-2.yaml @@ -0,0 +1,171 @@ +--- +root: + items: + - type: stacking-context + bounds: [0, 0, 1000, 1000] + items: + - type: border + bounds: [ 10, 10, 100, 100 ] + width: [ 20, 20, 20, 20 ] + border-type: normal + style: groove + color: [ red, green, blue, yellow ] + radius: 0 + - type: border + bounds: [ 120, 10, 100, 100 ] + width: [ 20, 20, 20, 20 ] + border-type: normal + style: groove + color: [ red, green, blue, yellow ] + radius: 10 + - type: border + bounds: [ 230, 10, 100, 100 ] + width: [ 20, 20, 20, 20 ] + border-type: normal + style: groove + color: [ red, green, blue, yellow ] + radius: 20 + - type: border + bounds: [ 340, 10, 100, 100 ] + width: [ 20, 20, 20, 20 ] + border-type: normal + style: groove + color: [ red, green, blue, yellow ] + radius: 30 + - type: border + bounds: [ 450, 10, 100, 100 ] + width: [ 20, 20, 20, 20 ] + border-type: normal + style: groove + color: [ red, green, blue, yellow ] + radius: 40 + - type: border + bounds: [ 560, 10, 100, 100 ] + width: [ 20, 20, 20, 20 ] + border-type: normal + style: groove + color: [ red, green, blue, yellow ] + radius: 50 + + - type: border + bounds: [ 10, 120, 100, 100 ] + width: [ 20, 20, 20, 20 ] + border-type: normal + style: ridge + color: [ red, green, blue, yellow ] + radius: 0 + - type: border + bounds: [ 120, 120, 100, 100 ] + width: [ 20, 20, 20, 20 ] + border-type: normal + style: ridge + color: [ red, green, blue, yellow ] + radius: 10 + - type: border + bounds: [ 230, 120, 100, 100 ] + width: [ 20, 20, 20, 20 ] + border-type: normal + style: ridge + color: [ red, green, blue, yellow ] + radius: 20 + - type: border + bounds: [ 340, 120, 100, 100 ] + width: [ 20, 20, 20, 20 ] + border-type: normal + style: ridge + color: [ red, green, blue, yellow ] + radius: 30 + - type: border + bounds: [ 450, 120, 100, 100 ] + width: [ 20, 20, 20, 20 ] + border-type: normal + style: ridge + color: [ red, green, blue, yellow ] + radius: 40 + - type: border + bounds: [ 560, 120, 100, 100 ] + width: [ 20, 20, 20, 20 ] + border-type: normal + style: ridge + color: [ red, green, blue, yellow ] + radius: 50 + + - type: border + bounds: [ 10, 230, 100, 100 ] + width: 1 + border-type: normal + style: dashed + color: [ red, green, blue, black ] + radius: 16 + - type: border + bounds: [ 120, 230, 100, 100 ] + width: 2 + border-type: normal + style: dashed + color: [ red, green, blue, black ] + radius: 32 + - type: border + bounds: [ 230, 230, 100, 100 ] + width: 3 + border-type: normal + style: dashed + color: [ red, green, blue, black ] + radius: 32 + - type: border + bounds: [ 340, 230, 100, 100 ] + width: 8 + border-type: normal + style: dashed + color: [ red, green, blue, black ] + radius: 32 + - type: border + bounds: [ 450, 230, 200, 100 ] + width: 4 + border-type: normal + style: dotted + color: [ red, green, blue, black ] + radius: { + top-left: [32, 48], + top-right: [64, 32], + bottom-left: [10, 40], + bottom-right: [48, 48], + } + + - type: border + bounds: [ 10, 340, 200, 200 ] + width: [4, 8, 16, 8] + border-type: normal + style: dashed + color: [ red, green, blue, black ] + radius: { + top-left: [32, 64], + top-right: [32, 32], + bottom-left: [64, 32], + bottom-right: [32, 32], + } + - type: border + bounds: [ 230, 340, 200, 200 ] + width: 4 + border-type: normal + style: dashed + color: [ red, green, blue, black ] + radius: { + top-left: [64, 128], + top-right: [16, 32], + bottom-left: [40, 18], + bottom-right: [100, 50], + } + - type: border + bounds: [ 450, 340, 200, 100 ] + width: 8 + border-type: normal + style: dotted + color: [ red, green, blue, black ] + radius: 32 + - type: border + bounds: [ 450, 450, 200, 100 ] + width: [8, 8, 12, 12] + border-type: normal + style: dotted + color: [ red, green, blue, black ] + radius: 40 diff --git a/gfx/wr/wrench/reftests/border/border-suite-3.png b/gfx/wr/wrench/reftests/border/border-suite-3.png Binary files differnew file mode 100644 index 0000000000..4a3f9c2556 --- /dev/null +++ b/gfx/wr/wrench/reftests/border/border-suite-3.png diff --git a/gfx/wr/wrench/reftests/border/border-suite-3.yaml b/gfx/wr/wrench/reftests/border/border-suite-3.yaml new file mode 100644 index 0000000000..2deb821071 --- /dev/null +++ b/gfx/wr/wrench/reftests/border/border-suite-3.yaml @@ -0,0 +1,57 @@ +--- +root: + items: + - type: stacking-context + bounds: [0, 0, 1000, 1000] + items: + - type: border + bounds: [ 10, 10, 200, 200 ] + width: 10 + border-type: normal + style: [ solid, double, solid, double ] + color: [ red, green, blue, black ] + radius: 16 + - type: border + bounds: [ 230, 10, 200, 200 ] + width: 16 + border-type: normal + style: [ solid, double, solid, double ] + color: [ red, green, blue, black ] + - type: border + bounds: [ 450, 10, 200, 200 ] + width: 10 + border-type: normal + style: [ solid, double, solid, double ] + color: [ red, green, blue, black ] + radius: { + top-left: [32, 48], + top-right: [64, 32], + bottom-left: [10, 40], + bottom-right: [48, 48], + } + + - type: border + bounds: [ 10, 230, 200, 200 ] + width: 24 + border-type: normal + style: [ inset, double, ridge, groove ] + color: [ red, green, blue, black ] + radius: 16 + - type: border + bounds: [ 230, 230, 200, 200 ] + width: 32 + border-type: normal + style: [ outset, double, ridge, groove ] + color: [ red, green, blue, black ] + - type: border + bounds: [ 450, 230, 200, 200 ] + width: 18 + border-type: normal + style: [ outset, double, ridge, groove ] + color: [ red, green, blue, black ] + radius: { + top-left: [32, 48], + top-right: [64, 32], + bottom-left: [10, 40], + bottom-right: [48, 48], + } diff --git a/gfx/wr/wrench/reftests/border/border-suite.png b/gfx/wr/wrench/reftests/border/border-suite.png Binary files differnew file mode 100644 index 0000000000..79232ec1e6 --- /dev/null +++ b/gfx/wr/wrench/reftests/border/border-suite.png diff --git a/gfx/wr/wrench/reftests/border/border-suite.yaml b/gfx/wr/wrench/reftests/border/border-suite.yaml new file mode 100644 index 0000000000..5c74679a0a --- /dev/null +++ b/gfx/wr/wrench/reftests/border/border-suite.yaml @@ -0,0 +1,351 @@ +--- +root: + items: + - type: stacking-context + bounds: [0, 0, 1000, 1000] + items: + - type: border + bounds: [ 10, 10, 100, 100 ] + width: [ 1, 1, 1, 1 ] + border-type: normal + style: solid + color: [ red, green, blue, black ] + radius: { + top-left: [20, 20], + top-right: [10, 10], + bottom-left: [25, 25], + bottom-right: [0, 0], + } + - type: border + bounds: [ 120, 10, 100, 100 ] + width: [ 2, 2, 2, 2 ] + border-type: normal + style: solid + color: [ red, green, blue, black ] + radius: { + top-left: [20, 20], + top-right: [10, 10], + bottom-left: [25, 25], + bottom-right: [0, 0], + } + - type: border + bounds: [ 230, 10, 100, 100 ] + width: [ 3, 3, 3, 3 ] + border-type: normal + style: solid + color: [ red, green, blue, black ] + radius: { + top-left: [20, 20], + top-right: [10, 10], + bottom-left: [25, 25], + bottom-right: [0, 0], + } + - type: border + bounds: [ 340, 10, 100, 100 ] + width: [ 5, 5, 5, 5 ] + border-type: normal + style: solid + color: [ red, green, blue, black ] + radius: { + top-left: [20, 20], + top-right: [10, 10], + bottom-left: [25, 25], + bottom-right: [0, 0], + } + - type: border + bounds: [ 450, 10, 100, 100 ] + width: [ 5, 5, 5, 5 ] + border-type: normal + style: double + color: [ red, green, blue, black ] + radius: { + top-left: [20, 20], + top-right: [10, 10], + bottom-left: [25, 25], + bottom-right: [0, 0], + } + - type: border + bounds: [ 560, 10, 100, 100 ] + width: [ 10, 10, 10, 10 ] + border-type: normal + style: double + color: [ red, green, blue, black ] + radius: { + top-left: [20, 20], + top-right: [10, 10], + bottom-left: [25, 25], + bottom-right: [0, 0], + } + + - type: border + bounds: [ 10, 120, 100, 100 ] + width: 10 + border-type: normal + style: inset + color: [ red, green, blue, black ] + - type: border + bounds: [ 120, 120, 100, 100 ] + width: 10 + border-type: normal + style: outset + color: [ red, green, blue, black ] + - type: border + bounds: [ 230, 120, 100, 100 ] + width: 10 + border-type: normal + style: inset + color: [ red, green, blue, black ] + radius: 10 + - type: border + bounds: [ 340, 120, 100, 100 ] + width: 10 + border-type: normal + style: outset + color: [ red, green, blue, black ] + radius: 20 + - type: border + bounds: [ 450, 120, 100, 100 ] + width: 10 + border-type: normal + style: outset + color: [ red, green, blue, black ] + radius: 35 + - type: border + bounds: [ 560, 120, 100, 100 ] + width: 10 + border-type: normal + style: outset + color: [ red, green, blue, black ] + radius: 50 + + - type: border + bounds: [ 10, 230, 100, 100 ] + width: [ 1, 1, 1, 1 ] + border-type: normal + style: solid + color: [ red, green, blue, black ] + radius: { + top-left: [20, 40], + top-right: [30, 10], + bottom-left: [21, 7], + bottom-right: [0, 5], + } + - type: border + bounds: [ 120, 230, 100, 100 ] + width: [ 2, 2, 2, 2 ] + border-type: normal + style: solid + color: [ red, green, blue, black ] + radius: { + top-left: [20, 40], + top-right: [30, 10], + bottom-left: [21, 7], + bottom-right: [0, 5], + } + - type: border + bounds: [ 230, 230, 100, 100 ] + width: [ 3, 3, 3, 3 ] + border-type: normal + style: solid + color: [ red, green, blue, black ] + radius: { + top-left: [20, 40], + top-right: [30, 10], + bottom-left: [21, 7], + bottom-right: [0, 5], + } + - type: border + bounds: [ 340, 230, 100, 100 ] + width: [ 5, 5, 5, 5 ] + border-type: normal + style: solid + color: [ red, green, blue, black ] + radius: { + top-left: [20, 40], + top-right: [30, 10], + bottom-left: [21, 7], + bottom-right: [0, 5], + } + - type: border + bounds: [ 450, 230, 100, 100 ] + width: [ 5, 5, 5, 5 ] + border-type: normal + style: double + color: [ red, green, blue, black ] + radius: { + top-left: [20, 40], + top-right: [30, 10], + bottom-left: [21, 7], + bottom-right: [0, 5], + } + - type: border + bounds: [ 560, 230, 100, 100 ] + width: [ 10, 10, 10, 10 ] + border-type: normal + style: double + color: [ red, green, blue, black ] + radius: { + top-left: [20, 40], + top-right: [30, 10], + bottom-left: [21, 7], + bottom-right: [0, 5], + } + + - type: border + bounds: [ 10, 340, 100, 100 ] + width: [ 20, 20, 20, 20 ] + border-type: normal + style: solid + color: [ red, green, blue, black ] + radius: { + top-left: [20, 40], + top-right: [30, 10], + bottom-left: [21, 7], + bottom-right: [0, 5], + } + - type: border + bounds: [ 120, 340, 100, 100 ] + width: [ 20, 20, 20, 20 ] + border-type: normal + style: solid + color: [ red, green, blue, black ] + radius: { + top-left: [20, 40], + top-right: [30, 10], + bottom-left: [21, 7], + bottom-right: [0, 5], + } + - type: border + bounds: [ 230, 340, 100, 100 ] + width: [ 20, 20, 20, 20 ] + border-type: normal + style: solid + color: [ red, green, blue, black ] + radius: { + top-left: [20, 40], + top-right: [30, 10], + bottom-left: [21, 7], + bottom-right: [0, 5], + } + - type: border + bounds: [ 340, 340, 100, 100 ] + width: [ 20, 20, 20, 20 ] + border-type: normal + style: solid + color: [ red, green, blue, black ] + radius: { + top-left: [20, 40], + top-right: [30, 10], + bottom-left: [21, 7], + bottom-right: [0, 5], + } + - type: border + bounds: [ 450, 340, 100, 100 ] + width: [ 20, 20, 20, 20 ] + border-type: normal + style: double + color: [ red, green, blue, black ] + radius: { + top-left: [20, 40], + top-right: [30, 10], + bottom-left: [21, 7], + bottom-right: [0, 5], + } + - type: border + bounds: [ 560, 340, 100, 100 ] + width: [ 20, 20, 20, 20 ] + border-type: normal + style: double + color: [ red, green, blue, black ] + radius: { + top-left: [20, 40], + top-right: [30, 10], + bottom-left: [21, 7], + bottom-right: [0, 5], + } + + - type: border + bounds: [ 10, 450, 100, 100 ] + width: [ 20, 20, 20, 20 ] + border-type: normal + style: solid + color: [ red, green, blue, black ] + radius: 0 + - type: border + bounds: [ 120, 450, 100, 100 ] + width: [ 20, 20, 20, 20 ] + border-type: normal + style: solid + color: [ red, green, blue, black ] + radius: 10 + - type: border + bounds: [ 230, 450, 100, 100 ] + width: [ 20, 20, 20, 20 ] + border-type: normal + style: solid + color: [ red, green, blue, black ] + radius: 20 + - type: border + bounds: [ 340, 450, 100, 100 ] + width: [ 20, 20, 20, 20 ] + border-type: normal + style: solid + color: [ red, green, blue, black ] + radius: 30 + - type: border + bounds: [ 450, 450, 100, 100 ] + width: [ 20, 20, 20, 20 ] + border-type: normal + style: solid + color: [ red, green, blue, black ] + radius: 40 + - type: border + bounds: [ 560, 450, 100, 100 ] + width: [ 20, 20, 20, 20 ] + border-type: normal + style: solid + color: [ red, green, blue, black ] + radius: 50 + + - type: border + bounds: [ 10, 560, 100, 100 ] + width: [ 20, 20, 20, 20 ] + border-type: normal + style: double + color: [ red, green, blue, black ] + radius: 0 + - type: border + bounds: [ 120, 560, 100, 100 ] + width: [ 20, 20, 20, 20 ] + border-type: normal + style: double + color: [ red, green, blue, black ] + radius: 10 + - type: border + bounds: [ 230, 560, 100, 100 ] + width: [ 20, 20, 20, 20 ] + border-type: normal + style: double + color: [ red, green, blue, black ] + radius: 20 + - type: border + bounds: [ 340, 560, 100, 100 ] + width: [ 20, 20, 20, 20 ] + border-type: normal + style: double + color: [ red, green, blue, black ] + radius: 30 + - type: border + bounds: [ 450, 560, 100, 100 ] + width: [ 20, 20, 20, 20 ] + border-type: normal + style: double + color: [ red, green, blue, black ] + radius: 40 + - type: border + bounds: [ 560, 560, 100, 100 ] + width: [ 20, 20, 20, 20 ] + border-type: normal + style: double + color: [ red, green, blue, black ] + radius: 50 diff --git a/gfx/wr/wrench/reftests/border/degenerate-curve.png b/gfx/wr/wrench/reftests/border/degenerate-curve.png Binary files differnew file mode 100644 index 0000000000..9c3805e33e --- /dev/null +++ b/gfx/wr/wrench/reftests/border/degenerate-curve.png diff --git a/gfx/wr/wrench/reftests/border/degenerate-curve.yaml b/gfx/wr/wrench/reftests/border/degenerate-curve.yaml new file mode 100644 index 0000000000..c66ac6356f --- /dev/null +++ b/gfx/wr/wrench/reftests/border/degenerate-curve.yaml @@ -0,0 +1,258 @@ +--- +root: + items: + - + bounds: [0, 0, 1024, 740] + type: "stacking-context" + "scroll-policy": scrollable + "transform-style": flat + items: + - type: clip + bounds: [28, 18, 144, 122] + complex: + - rect: [28, 18, 144, 122] + radius: + "top-left": [61, 61] + "top-right": [61, 61] + "bottom-left": [0, 0] + "bottom-right": [61, 61] + items: + - type: rect + color: 255 0 0 1.0000 + bounds: [28, 18, 144, 122] + - + bounds: [28, 18, 144, 122] + type: border + width: [18, 0, 18, 0] + "border-type": normal + color: 0 0 255 1.0000 + style: + - solid + - none + - solid + - none + radius: + "top-left": [61, 61] + "top-right": [61, 61] + "bottom-left": [0, 0] + "bottom-right": [61, 61] + - type: clip + bounds: [28, 160, 144, 122] + complex: + - rect: [28, 160, 144, 122] + radius: [61, 61] + items: + - type: rect + bounds: [28, 160, 144, 122] + color: 255 0 0 1.0000 + - + bounds: [28, 160, 144, 122] + type: border + width: [18, 0, 18, 0] + "border-type": normal + color: 0 0 255 1.0000 + style: + - solid + - none + - solid + - none + radius: [61, 61] + - type: clip + bounds: [28, 302, 154, 122] + complex: + - rect: [28, 302, 154, 122] + radius: + "top-left": [0, 0] + "top-right": [61, 61] + "bottom-left": [0, 0] + "bottom-right": [61, 61] + items: + - type: rect + bounds: [28, 302, 154, 122] + color: 255 0 0 1.0000 + - type: border + bounds: [28, 302, 154, 122] + width: [18, 0, 18, 10] + "border-type": normal + color: + - 0 0 255 1.0000 + - 0 0 255 1.0000 + - 0 0 255 1.0000 + - 0 0 255 1.0000 + style: + - solid + - none + - solid + - solid + radius: + "top-left": [0, 0] + "top-right": [61, 61] + "bottom-left": [0, 0] + "bottom-right": [61, 61] + - type: clip + bounds: [202, 18, 145, 122] + complex: + - rect: [202, 18, 144.03334, 122] + radius: + "top-left": [61, 61] + "top-right": [61, 61] + "bottom-left": [0, 0] + "bottom-right": [61, 61] + items: + - type: rect + bounds: [202, 18, 144.03334, 122] + color: 255 0 0 1.0000 + - type: border + bounds: [202, 18, 144.03334, 122] + width: [18, 0.016666668, 18, 0.016666668] + "border-type": normal + color: + - 0 0 255 1.0000 + - 255 0 0 1.0000 + - 0 0 255 1.0000 + - 255 0 0 1.0000 + style: solid + radius: + "top-left": [61, 61] + "top-right": [61, 61] + "bottom-left": [0, 0] + "bottom-right": [61, 61] + - type: clip + bounds: [202, 160, 144, 122] + complex: + - rect: [202, 160, 144, 122] + radius: [61, 61] + items: + - type: rect + bounds: [202, 160, 144, 122] + color: 255 0 0 1.0000 + - type: border + bounds: [202, 160, 144, 122] + width: [18, 0, 18, 0] + "border-type": normal + color: + - 0 0 255 1.0000 + - 255 0 0 1.0000 + - 0 0 255 1.0000 + - 255 0 0 1.0000 + style: solid + radius: [61, 61] + - type: clip + bounds: [202, 302, 154, 122] + complex: + - rect: [202, 302, 154, 122] + radius: + "top-left": [0, 0] + "top-right": [72, 72] + "bottom-left": [0, 0] + "bottom-right": [0, 0] + items: + - type: rect + bounds: [202, 302, 154, 122] + color: 255 0 0 1.0000 + - + bounds: [202, 302, 154, 122] + type: border + width: [18, 0, 18, 10] + "border-type": normal + color: + - 0 0 255 1.0000 + - 0 0 255 1.0000 + - 0 0 255 1.0000 + - 0 0 255 1.0000 + style: + - solid + - none + - solid + - solid + radius: + "top-left": [0, 0] + "top-right": [72, 72] + "bottom-left": [0, 0] + "bottom-right": [0, 0] + - type: clip + bounds: [376, 18, 144, 122] + complex: + - rect: [376, 18, 144, 122] + radius: [61, 61] + items: + - type: rect + bounds: [376, 18, 144, 122] + color: 255 0 0 1.0000 + - + bounds: [376, 18, 144, 122] + type: border + width: [18, 0, 18, 0] + "border-type": normal + color: + - 0 0 255 1.0000 + - 255 0 0 1.0000 + - 0 0 255 1.0000 + - 255 0 0 1.0000 + style: + - solid + - hidden + - solid + - hidden + radius: [61, 61] + - type: clip + bounds: [376, 160, 144, 122] + complex: + - rect: [376, 160, 144, 122] + radius: [61, 61] + items: + - type: rect + bounds: [376, 160, 144, 122] + color: 255 0 0 1.0000 + - + bounds: [376, 160, 144, 122] + clip: [-17895698, -17895698, 35791396, 35791396] + type: border + width: [18, 0, 18, 0] + "border-type": normal + color: + - 0 0 255 1.0000 + - 255 0 0 1.0000 + - 0 0 255 1.0000 + - 255 0 0 1.0000 + style: + - solid + - none + - solid + - none + radius: [61, 61] + - type: clip + bounds: [376, 302, 144, 122] + complex: + - rect: [376, 302, 144, 122] + radius: + "top-left": [0, 0] + "top-right": [72, 72] + "bottom-left": [72, 72] + "bottom-right": [0, 0] + items: + - type: rect + bounds: [376, 302, 144, 122] + color: 255 0 0 1.0000 + - + bounds: [376, 302, 144, 122] + type: border + width: [18, 0, 18, 0] + "border-type": normal + color: + - 0 0 255 1.0000 + - 255 0 0 1.0000 + - 0 0 255 1.0000 + - 0 0 255 1.0000 + style: + - solid + - none + - solid + - hidden + radius: + "top-left": [0, 0] + "top-right": [72, 72] + "bottom-left": [72, 72] + "bottom-right": [0, 0] + id: [0, 1] +pipelines: [] diff --git a/gfx/wr/wrench/reftests/border/discontinued-dash.png b/gfx/wr/wrench/reftests/border/discontinued-dash.png Binary files differnew file mode 100644 index 0000000000..67625e1928 --- /dev/null +++ b/gfx/wr/wrench/reftests/border/discontinued-dash.png diff --git a/gfx/wr/wrench/reftests/border/discontinued-dash.yaml b/gfx/wr/wrench/reftests/border/discontinued-dash.yaml new file mode 100644 index 0000000000..886f9cfe59 --- /dev/null +++ b/gfx/wr/wrench/reftests/border/discontinued-dash.yaml @@ -0,0 +1,12 @@ +--- +root: + items: + - type: stacking-context + bounds: [0, 0, 500, 500] + items: + - type: border + bounds: [ 10, 10, 300, 300] + width: [ 10, 10, 10, 10 ] + border-type: normal + style: [ dashed, solid, solid, solid ] + color: [ black, black, black, black ] diff --git a/gfx/wr/wrench/reftests/border/dotted-corner-small-radius.png b/gfx/wr/wrench/reftests/border/dotted-corner-small-radius.png Binary files differnew file mode 100644 index 0000000000..a83ca988b0 --- /dev/null +++ b/gfx/wr/wrench/reftests/border/dotted-corner-small-radius.png diff --git a/gfx/wr/wrench/reftests/border/dotted-corner-small-radius.yaml b/gfx/wr/wrench/reftests/border/dotted-corner-small-radius.yaml new file mode 100644 index 0000000000..4e40c251e4 --- /dev/null +++ b/gfx/wr/wrench/reftests/border/dotted-corner-small-radius.yaml @@ -0,0 +1,11 @@ +--- +root: + items: + - bounds: [5, 5, 490, 490] + "clip-rect": [5, 5, 490, 490] + "backface-visible": true + type: border + width: 25 + "border-type": normal + color: black + style: dotted diff --git a/gfx/wr/wrench/reftests/border/green-square.yaml b/gfx/wr/wrench/reftests/border/green-square.yaml new file mode 100644 index 0000000000..2f13625928 --- /dev/null +++ b/gfx/wr/wrench/reftests/border/green-square.yaml @@ -0,0 +1,9 @@ +--- +root: + items: + - type: stacking-context + bounds: [0, 0, 500, 500] + items: + - type: rect + bounds: [ 0, 0, 400, 400 ] + color: green diff --git a/gfx/wr/wrench/reftests/border/max-scale-ref.yaml b/gfx/wr/wrench/reftests/border/max-scale-ref.yaml new file mode 100644 index 0000000000..0647a7a864 --- /dev/null +++ b/gfx/wr/wrench/reftests/border/max-scale-ref.yaml @@ -0,0 +1,9 @@ +--- +root: + items: + - type: border + bounds: [ 0, 0, 4000, 1 ] + width: [ 1, 0, 0, 0 ] + border-type: normal + style: solid + color: red diff --git a/gfx/wr/wrench/reftests/border/max-scale.yaml b/gfx/wr/wrench/reftests/border/max-scale.yaml new file mode 100644 index 0000000000..cf292d5798 --- /dev/null +++ b/gfx/wr/wrench/reftests/border/max-scale.yaml @@ -0,0 +1,12 @@ +--- +root: + items: + - type: stacking-context + transform: scale(3000, 1) + items: + - type: border + bounds: [ 0, 0, 100, 100 ] + width: [ 1, 0, 0, 0 ] + border-type: normal + style: solid + color: red diff --git a/gfx/wr/wrench/reftests/border/no-aa.yaml b/gfx/wr/wrench/reftests/border/no-aa.yaml new file mode 100644 index 0000000000..f937a865f4 --- /dev/null +++ b/gfx/wr/wrench/reftests/border/no-aa.yaml @@ -0,0 +1,20 @@ +--- +root: + items: + - type: stacking-context + bounds: [0, 0, 500, 500] + items: + - type: border + bounds: [ 0, 0, 400, 400 ] + width: [ 200, 200, 200, 200 ] + border-type: normal + style: solid + color: [ green, green, transparent, transparent ] + do_aa: false + - type: border + bounds: [ 0, 0, 400, 400 ] + width: [ 200, 200, 200, 200 ] + border-type: normal + style: solid + color: [ transparent, transparent, green, green ] + do_aa: false diff --git a/gfx/wr/wrench/reftests/border/overlapping.png b/gfx/wr/wrench/reftests/border/overlapping.png Binary files differnew file mode 100644 index 0000000000..38dcdc79e2 --- /dev/null +++ b/gfx/wr/wrench/reftests/border/overlapping.png diff --git a/gfx/wr/wrench/reftests/border/overlapping.yaml b/gfx/wr/wrench/reftests/border/overlapping.yaml new file mode 100644 index 0000000000..3340411eff --- /dev/null +++ b/gfx/wr/wrench/reftests/border/overlapping.yaml @@ -0,0 +1,19 @@ +--- +root: + items: + - type: stacking-context + bounds: [0, 0, 1000, 1000] + items: + - type: clip + bounds: [ 0, 0, 200, 200 ] + complex: + - rect: [ 0, 0, 200, 200 ] + radius: + top-left: [180, 180] + top-right: [0, 0] + bottom-left: [0, 0] + bottom-right: [180, 180] + items: + - type: rect + bounds: [ 0, 0, 200, 200 ] + color: blue diff --git a/gfx/wr/wrench/reftests/border/reftest.list b/gfx/wr/wrench/reftests/border/reftest.list new file mode 100644 index 0000000000..4f428036ab --- /dev/null +++ b/gfx/wr/wrench/reftests/border/reftest.list @@ -0,0 +1,35 @@ +platform(linux,mac) == border-clamp-corner-radius.yaml border-clamp-corner-radius.png +fuzzy(1,840) == border-gradient-simple.yaml border-gradient-simple-ref.yaml +platform(linux,mac) == border-gradient-nine-patch.yaml border-gradient-nine-patch.png +== border-radial-gradient-simple.yaml border-radial-gradient-simple-ref.yaml +platform(linux,mac) == border-radial-gradient-nine-patch.yaml border-radial-gradient-nine-patch.png +== fuzzy(1,10) border-radii.yaml border-radii.png +== border-none.yaml border-none-ref.yaml +fuzzy(128,69) == border-overlapping-corner.yaml border-overlapping-corner-ref.yaml +== border-overlapping-edge.yaml border-overlapping-edge-ref.yaml +== border-invisible.yaml border-invisible-ref.yaml +platform(linux,mac) fuzzy(3,80) == border-suite.yaml border-suite.png +platform(linux,mac) fuzzy(8,105) == border-suite-2.yaml border-suite-2.png +platform(linux,mac) fuzzy(1,10) == border-suite-3.yaml border-suite-3.png +skip_on(android,device) == border-double-simple.yaml border-double-simple-ref.yaml # Fails on Pixel2 +== border-double-simple-2.yaml border-double-simple-2-ref.yaml +skip_on(android,device) fuzzy(64,24) == border-groove-simple.yaml border-groove-simple-ref.yaml # Fails on Pixel2 +skip_on(android,device) fuzzy(64,24) == border-ridge-simple.yaml border-ridge-simple-ref.yaml # Fails on Pixel2 +platform(linux,mac) fuzzy(1,3) == degenerate-curve.yaml degenerate-curve.png +platform(linux,mac) == border-image.yaml border-image-ref.png +platform(linux,mac) == border-image-empty-slice.yaml border-image-empty-slice-ref.png +platform(linux,mac) == border-image-round.yaml border-image-round-ref.png +== border-image-crash.yaml border-image-crash-ref.yaml +fuzzy(1,5000) == border-image-fill.yaml border-image-fill-ref.png +fuzzy(2,25360) == border-image-fill-2.yaml border-image-fill-2-ref.png +== border-no-bogus-line.yaml border-no-bogus-line-ref.png +platform(linux,mac) fuzzy(1,130) == dotted-corner-small-radius.yaml dotted-corner-small-radius.png +fuzzy-if(platform(swgl),1,20) == overlapping.yaml overlapping.png +== zero-width.yaml blank.yaml +platform(linux,mac) == small-dotted-border.yaml small-dotted-border.png +fuzzy(1,30) == discontinued-dash.yaml discontinued-dash.png +platform(linux,mac) == border-dashed-dotted-caching.yaml border-dashed-dotted-caching.png +!= small-inset-outset.yaml small-inset-outset-notref.yaml +fuzzy(1,90) == no-aa.yaml green-square.yaml +skip_on(android,device) == border-double-1px.yaml border-double-1px-ref.yaml # Fails on Pixel2 +== max-scale.yaml max-scale-ref.yaml diff --git a/gfx/wr/wrench/reftests/border/small-dotted-border.png b/gfx/wr/wrench/reftests/border/small-dotted-border.png Binary files differnew file mode 100644 index 0000000000..dc4132d6d7 --- /dev/null +++ b/gfx/wr/wrench/reftests/border/small-dotted-border.png diff --git a/gfx/wr/wrench/reftests/border/small-dotted-border.yaml b/gfx/wr/wrench/reftests/border/small-dotted-border.yaml new file mode 100644 index 0000000000..2fb189bce2 --- /dev/null +++ b/gfx/wr/wrench/reftests/border/small-dotted-border.yaml @@ -0,0 +1,19 @@ +--- +root: + items: + - type: stacking-context + bounds: [0, 0, 500, 500] + items: + - type: border + bounds: [ 0, 0, 100, 20 ] + width: [ 1, 1, 1, 1 ] + border-type: normal + style: [ dotted, dotted, dotted, dotted ] + color: [ black, black, black, black ] + + - type: border + bounds: [ 0, 30, 100, 20 ] + width: [ 2, 2, 2, 2 ] + border-type: normal + style: [ dotted, dotted, dotted, dotted ] + color: [ black, black, black, black ] diff --git a/gfx/wr/wrench/reftests/border/small-inset-outset-notref.yaml b/gfx/wr/wrench/reftests/border/small-inset-outset-notref.yaml new file mode 100644 index 0000000000..e55bdc84c6 --- /dev/null +++ b/gfx/wr/wrench/reftests/border/small-inset-outset-notref.yaml @@ -0,0 +1,12 @@ +--- +root: + items: + - type: stacking-context + bounds: [0, 0, 500, 500] + items: + - type: border + bounds: [ 0, 0, 200, 200 ] + width: 1 + border-type: normal + style: solid + color: black diff --git a/gfx/wr/wrench/reftests/border/small-inset-outset.yaml b/gfx/wr/wrench/reftests/border/small-inset-outset.yaml new file mode 100644 index 0000000000..f7bc42807b --- /dev/null +++ b/gfx/wr/wrench/reftests/border/small-inset-outset.yaml @@ -0,0 +1,12 @@ +--- +root: + items: + - type: stacking-context + bounds: [0, 0, 500, 500] + items: + - type: border + bounds: [ 0, 0, 200, 200 ] + width: 1 + border-type: normal + style: inset + color: black diff --git a/gfx/wr/wrench/reftests/border/zero-width.yaml b/gfx/wr/wrench/reftests/border/zero-width.yaml new file mode 100644 index 0000000000..6d12d05bf8 --- /dev/null +++ b/gfx/wr/wrench/reftests/border/zero-width.yaml @@ -0,0 +1,12 @@ +root: + items: + - type: stacking-context + bounds: [0, 0, 500, 500] + items: + - type: border + bounds: [ 0, 0, 50, 50 ] + width: [ 0, 0, 0, 0 ] + border-type: normal + style: [ solid, solid, solid, solid ] + color: [ blue, blue, blue, blue ] + diff --git a/gfx/wr/wrench/reftests/boxshadow/blank.yaml b/gfx/wr/wrench/reftests/boxshadow/blank.yaml new file mode 100644 index 0000000000..c4eb3ab673 --- /dev/null +++ b/gfx/wr/wrench/reftests/boxshadow/blank.yaml @@ -0,0 +1,2 @@ +--- +root: diff --git a/gfx/wr/wrench/reftests/boxshadow/box-shadow-blurred-overlapping-radii-ref.yaml b/gfx/wr/wrench/reftests/boxshadow/box-shadow-blurred-overlapping-radii-ref.yaml new file mode 100644 index 0000000000..5e2da4fa8a --- /dev/null +++ b/gfx/wr/wrench/reftests/boxshadow/box-shadow-blurred-overlapping-radii-ref.yaml @@ -0,0 +1,20 @@ + +--- +root: + items: + - type: stacking-context + bounds: [0, 0, 1000, 1000] + items: + - type: box-shadow + bounds: [ 0, 1, 265, 265 ] + color: red + clip-mode: outset + offset: 350 -1 + blur-radius: 1 + spread-radius: -80 + border-radius: + top-left: [185, 185] + top-right: [0, 0] + bottom-left: [0, 0] + bottom-right: [185, 185] + diff --git a/gfx/wr/wrench/reftests/boxshadow/box-shadow-blurred-overlapping-radii.yaml b/gfx/wr/wrench/reftests/boxshadow/box-shadow-blurred-overlapping-radii.yaml new file mode 100644 index 0000000000..ebc4b263a1 --- /dev/null +++ b/gfx/wr/wrench/reftests/boxshadow/box-shadow-blurred-overlapping-radii.yaml @@ -0,0 +1,19 @@ + +--- +root: + items: + - type: stacking-context + bounds: [0, 0, 1000, 1000] + items: + - type: box-shadow + bounds: [ 0, 1, 265, 265 ] + color: red + clip-mode: outset + offset: 350 -1 + blur-radius: 1 + spread-radius: -80 + border-radius: + top-left: [250, 250] + top-right: [0, 0] + bottom-left: [0, 0] + bottom-right: [250, 250] diff --git a/gfx/wr/wrench/reftests/boxshadow/box-shadow-border-radii.png b/gfx/wr/wrench/reftests/boxshadow/box-shadow-border-radii.png Binary files differnew file mode 100644 index 0000000000..ccdcf2e3ca --- /dev/null +++ b/gfx/wr/wrench/reftests/boxshadow/box-shadow-border-radii.png diff --git a/gfx/wr/wrench/reftests/boxshadow/box-shadow-border-radii.yaml b/gfx/wr/wrench/reftests/boxshadow/box-shadow-border-radii.yaml new file mode 100644 index 0000000000..d52601e019 --- /dev/null +++ b/gfx/wr/wrench/reftests/boxshadow/box-shadow-border-radii.yaml @@ -0,0 +1,36 @@ +--- +root: + items: + - type: stacking-context + bounds: [0, 0, 1000, 1000] + items: + - type: box-shadow + bounds: [ 50, 50, 100, 100 ] + color: red + clip-mode: outset + blur-radius: 10 + border-radius: { + top-left: [20, 30], + top-right: [10, 30], + bottom-left: [50, 25], + bottom-right: [0, 0], + } + + - type: box-shadow + bounds: [ 200, 50, 100, 100 ] + color: green + clip-mode: inset + blur-radius: 10 + border-radius: { + top-left: [20, 30], + top-right: [10, 30], + bottom-left: [50, 25], + bottom-right: [0, 0], + } + + - type: box-shadow + bounds: [ 350, 50, 100, 100 ] + color: blue + clip-mode: outset + blur-radius: 10 + border-radius: [ 10, 20, 30, 40 ] diff --git a/gfx/wr/wrench/reftests/boxshadow/box-shadow-cache.png b/gfx/wr/wrench/reftests/boxshadow/box-shadow-cache.png Binary files differnew file mode 100644 index 0000000000..b40d70bd1c --- /dev/null +++ b/gfx/wr/wrench/reftests/boxshadow/box-shadow-cache.png diff --git a/gfx/wr/wrench/reftests/boxshadow/box-shadow-cache.yaml b/gfx/wr/wrench/reftests/boxshadow/box-shadow-cache.yaml new file mode 100644 index 0000000000..721c6fe4e0 --- /dev/null +++ b/gfx/wr/wrench/reftests/boxshadow/box-shadow-cache.yaml @@ -0,0 +1,98 @@ +--- +root: + items: + - type: stacking-context + bounds: [0, 0, 1000, 1000] + items: + - type: box-shadow + bounds: [ 50, 50, 100, 100 ] + color: red + clip-mode: outset + blur-radius: 10 + border-radius: { + top-left: [20, 30], + top-right: [10, 30], + bottom-left: [50, 25], + bottom-right: [0, 0], + } + + - type: box-shadow + bounds: [ 50, 200, 100, 100 ] + color: red + clip-mode: outset + blur-radius: 10 + border-radius: { + top-left: [20, 30], + top-right: [10, 30], + bottom-left: [50, 25], + bottom-right: [0, 0], + } + + - type: box-shadow + bounds: [ 50, 350, 100, 100 ] + color: red + clip-mode: outset + blur-radius: 10 + border-radius: { + top-left: [20, 30], + top-right: [10, 30], + bottom-left: [50, 25], + bottom-right: [0, 0], + } + + - type: box-shadow + bounds: [ 200, 50, 100, 100 ] + color: green + clip-mode: inset + blur-radius: 10 + border-radius: { + top-left: [20, 30], + top-right: [10, 30], + bottom-left: [50, 25], + bottom-right: [0, 0], + } + + - type: box-shadow + bounds: [ 200, 200, 100, 100 ] + color: green + clip-mode: inset + blur-radius: 10 + border-radius: { + top-left: [20, 30], + top-right: [10, 30], + bottom-left: [50, 25], + bottom-right: [0, 0], + } + + - type: box-shadow + bounds: [ 200, 350, 100, 100 ] + color: green + clip-mode: inset + blur-radius: 10 + border-radius: { + top-left: [20, 30], + top-right: [10, 30], + bottom-left: [50, 25], + bottom-right: [0, 0], + } + + - type: box-shadow + bounds: [ 350, 50, 100, 100 ] + color: blue + clip-mode: outset + blur-radius: 10 + border-radius: [ 10, 20, 30, 40 ] + + - type: box-shadow + bounds: [ 350, 200, 100, 100 ] + color: blue + clip-mode: outset + blur-radius: 10 + border-radius: [ 10, 20, 30, 40 ] + + - type: box-shadow + bounds: [ 350, 350, 100, 100 ] + color: blue + clip-mode: outset + blur-radius: 10 + border-radius: [ 10, 20, 30, 40 ] diff --git a/gfx/wr/wrench/reftests/boxshadow/box-shadow-clip-ref.yaml b/gfx/wr/wrench/reftests/boxshadow/box-shadow-clip-ref.yaml new file mode 100644 index 0000000000..7b181c8002 --- /dev/null +++ b/gfx/wr/wrench/reftests/boxshadow/box-shadow-clip-ref.yaml @@ -0,0 +1,40 @@ +--- +root: + items: + - type: stacking-context + bounds: [0, 0, 1000, 1000] + items: + - type: clip + bounds: [0, 0, 100, 200] + items: + - type: box-shadow + bounds: [ 20, 20, 200, 80 ] + color: blue + offset: [10, 20] + clip-mode: outset + - type: clip + bounds: [200, 0, 100, 200] + items: + - type: box-shadow + bounds: [ 220, 20, 200, 80 ] + color: red + offset: [10, 20] + blur-radius: 10 + clip-mode: outset + - type: clip + bounds: [0, 200, 100, 200] + items: + - type: box-shadow + bounds: [ 20, 220, 200, 80 ] + color: green + offset: [10, 20] + clip-mode: inset + - type: clip + bounds: [200, 200, 100, 200] + items: + - type: box-shadow + bounds: [ 220, 220, 200, 80 ] + color: yellow + offset: [10, 20] + blur-radius: 10 + clip-mode: inset diff --git a/gfx/wr/wrench/reftests/boxshadow/box-shadow-clip.yaml b/gfx/wr/wrench/reftests/boxshadow/box-shadow-clip.yaml new file mode 100644 index 0000000000..c027b54379 --- /dev/null +++ b/gfx/wr/wrench/reftests/boxshadow/box-shadow-clip.yaml @@ -0,0 +1,32 @@ +--- +root: + items: + - type: stacking-context + bounds: [0, 0, 1000, 1000] + items: + - type: box-shadow + bounds: [ 20, 20, 200, 80 ] + clip-rect: [0, 0, 100, 200] + color: blue + offset: [10, 20] + clip-mode: outset + - type: box-shadow + bounds: [ 220, 20, 200, 80 ] + clip-rect: [200, 0, 100, 200] + color: red + offset: [10, 20] + blur-radius: 10 + clip-mode: outset + - type: box-shadow + bounds: [ 20, 220, 200, 80 ] + clip-rect: [0, 200, 100, 200] + color: green + offset: [10, 20] + clip-mode: inset + - type: box-shadow + bounds: [ 220, 220, 200, 80 ] + clip-rect: [200, 200, 100, 200] + color: yellow + offset: [10, 20] + blur-radius: 10 + clip-mode: inset diff --git a/gfx/wr/wrench/reftests/boxshadow/box-shadow-empty.yaml b/gfx/wr/wrench/reftests/boxshadow/box-shadow-empty.yaml new file mode 100644 index 0000000000..d3640d53f5 --- /dev/null +++ b/gfx/wr/wrench/reftests/boxshadow/box-shadow-empty.yaml @@ -0,0 +1,13 @@ +--- +root: + items: + - type: stacking-context + bounds: [50, 50, 500, 500] + items: + - type: box-shadow + bounds: [ 10, 10, 400, 400 ] + blur-radius: 0 + clip-mode: outset + offset: [0, 0] + spread-radius: 0 + color: [255, 0, 0] diff --git a/gfx/wr/wrench/reftests/boxshadow/box-shadow-huge-radius.png b/gfx/wr/wrench/reftests/boxshadow/box-shadow-huge-radius.png Binary files differnew file mode 100644 index 0000000000..2bbad8d318 --- /dev/null +++ b/gfx/wr/wrench/reftests/boxshadow/box-shadow-huge-radius.png diff --git a/gfx/wr/wrench/reftests/boxshadow/box-shadow-huge-radius.yaml b/gfx/wr/wrench/reftests/boxshadow/box-shadow-huge-radius.yaml new file mode 100644 index 0000000000..9ff601af49 --- /dev/null +++ b/gfx/wr/wrench/reftests/boxshadow/box-shadow-huge-radius.yaml @@ -0,0 +1,128 @@ +--- +root: + items: + - + bounds: [0, 0, 0, 0] + "clip-rect": [0, 0, 0, 0] + "clip-and-scroll": "root-scroll-node" + "backface-visible": true + type: "stacking-context" + "transform-style": flat + "raster-space": screen + filters: [] + items: + - + bounds: [0, 148, 1368, 588] + "clip-rect": [0, 148, 1368, 588] + "clip-and-scroll": "root-scroll-node" + "backface-visible": true + type: clip + id: 2 + - + bounds: [0, 0, 0, 0] + "clip-rect": [0, 0, 0, 0] + "clip-and-scroll": "root-scroll-node" + "backface-visible": true + type: "clip-chain" + id: 3 + clips: [2] + - + bounds: [16, 164, 16200, 200] + "clip-rect": [40, 188, 1328, 216] + "clip-and-scroll": [2, 3] + "backface-visible": true + type: "box-shadow" + "box-bounds": [16, 164, 16200, 200] + offset: [32, 32] + color: 0 0 255 1.0000 + "blur-radius": 6 + "spread-radius": 0 + "border-radius": + "top-left": [16200, 200] + "top-right": [0, 0] + "bottom-left": [0, 0] + "bottom-right": [0, 0] + "clip-mode": outset + - + bounds: [16, 164, 1352, 200] + "clip-rect": [16, 164, 1352, 200] + "clip-and-scroll": "root-scroll-node" + "backface-visible": true + type: clip + id: 4 + complex: + - + rect: [16, 164, 16200, 200] + radius: + "top-left": [16200, 200] + "top-right": [0, 0] + "bottom-left": [0, 0] + "bottom-right": [0, 0] + "clip-mode": clip + - + bounds: [0, 0, 0, 0] + "clip-rect": [0, 0, 0, 0] + "clip-and-scroll": [2, 3] + "backface-visible": true + type: "clip-chain" + id: 5 + clips: [4] + parent: 3 + - + bounds: [16, 164, 16200, 200] + "clip-rect": [16, 164, 16200, 200] + "clip-and-scroll": [4, 5] + "backface-visible": true + type: rect + color: 255 0 255 1.0000 + - + bounds: [16, 402, 200, 200] + "clip-rect": [40, 426, 216, 216] + "clip-and-scroll": [2, 3] + "backface-visible": true + type: "box-shadow" + "box-bounds": [16, 402, 200, 200] + offset: [32, 32] + color: 0 255 255 1.0000 + "blur-radius": 6 + "spread-radius": 0 + "border-radius": + "top-left": [0, 0] + "top-right": [200, 200] + "bottom-left": [0, 0] + "bottom-right": [0, 0] + "clip-mode": outset + - + bounds: [16, 402, 200, 200] + "clip-rect": [16, 402, 200, 200] + "clip-and-scroll": "root-scroll-node" + "backface-visible": true + type: clip + id: 6 + complex: + - + rect: [16, 402, 200, 200] + radius: + "top-left": [0, 0] + "top-right": [200, 200] + "bottom-left": [0, 0] + "bottom-right": [0, 0] + "clip-mode": clip + - + bounds: [0, 0, 0, 0] + "clip-rect": [0, 0, 0, 0] + "clip-and-scroll": [2, 3] + "backface-visible": true + type: "clip-chain" + id: 7 + clips: [6] + parent: 3 + - + bounds: [16, 402, 200, 200] + "clip-rect": [16, 402, 200, 200] + "clip-and-scroll": [6, 7] + "backface-visible": true + type: rect + color: 0 128 0 1.0000 + id: [0, 0] +pipelines: [] diff --git a/gfx/wr/wrench/reftests/boxshadow/box-shadow-large-blur-radius-2.png b/gfx/wr/wrench/reftests/boxshadow/box-shadow-large-blur-radius-2.png Binary files differnew file mode 100644 index 0000000000..73ce9dc35f --- /dev/null +++ b/gfx/wr/wrench/reftests/boxshadow/box-shadow-large-blur-radius-2.png diff --git a/gfx/wr/wrench/reftests/boxshadow/box-shadow-large-blur-radius-2.yaml b/gfx/wr/wrench/reftests/boxshadow/box-shadow-large-blur-radius-2.yaml new file mode 100644 index 0000000000..0a82cb5bee --- /dev/null +++ b/gfx/wr/wrench/reftests/boxshadow/box-shadow-large-blur-radius-2.yaml @@ -0,0 +1,14 @@ +--- +root: + items: + - type: stacking-context + bounds: [50, 50, 1500, 200] + items: + - type: box-shadow + bounds: [ 10, 10, 900, 900 ] + blur-radius: 5000 + clip-mode: outset + offset: [10, 10] + spread-radius: 10 + color: [255, 0, 0] + border-radius: 10 diff --git a/gfx/wr/wrench/reftests/boxshadow/box-shadow-large-blur-radius-3.png b/gfx/wr/wrench/reftests/boxshadow/box-shadow-large-blur-radius-3.png Binary files differnew file mode 100644 index 0000000000..91e3f286c6 --- /dev/null +++ b/gfx/wr/wrench/reftests/boxshadow/box-shadow-large-blur-radius-3.png diff --git a/gfx/wr/wrench/reftests/boxshadow/box-shadow-large-blur-radius-3.yaml b/gfx/wr/wrench/reftests/boxshadow/box-shadow-large-blur-radius-3.yaml new file mode 100644 index 0000000000..49d53e721f --- /dev/null +++ b/gfx/wr/wrench/reftests/boxshadow/box-shadow-large-blur-radius-3.yaml @@ -0,0 +1,14 @@ +--- +root: + items: + - type: stacking-context + bounds: [50, 50, 1500, 200] + items: + - type: box-shadow + bounds: [ 10, 10, 1500, 100 ] + blur-radius: 200 + clip-mode: outset + offset: [10, 100] + spread-radius: 10 + color: [255, 0, 0] + border-radius: 10 diff --git a/gfx/wr/wrench/reftests/boxshadow/box-shadow-large-blur-radius-ref.yaml b/gfx/wr/wrench/reftests/boxshadow/box-shadow-large-blur-radius-ref.yaml new file mode 100644 index 0000000000..29555c8f1d --- /dev/null +++ b/gfx/wr/wrench/reftests/boxshadow/box-shadow-large-blur-radius-ref.yaml @@ -0,0 +1,13 @@ +--- +root: + items: + - type: stacking-context + bounds: [50, 50, 500, 500] + items: + - type: box-shadow + bounds: [ 10, 10, 400, 400 ] + blur-radius: 300 + clip-mode: outset + offset: [0, 0] + spread-radius: 0 + color: [255, 0, 0] diff --git a/gfx/wr/wrench/reftests/boxshadow/box-shadow-large-blur-radius.yaml b/gfx/wr/wrench/reftests/boxshadow/box-shadow-large-blur-radius.yaml new file mode 100644 index 0000000000..13b2239658 --- /dev/null +++ b/gfx/wr/wrench/reftests/boxshadow/box-shadow-large-blur-radius.yaml @@ -0,0 +1,13 @@ +--- +root: + items: + - type: stacking-context + bounds: [50, 50, 500, 500] + items: + - type: box-shadow + bounds: [ 10, 10, 400, 400 ] + blur-radius: 2000 + clip-mode: outset + offset: [0, 0] + spread-radius: 0 + color: [255, 0, 0] diff --git a/gfx/wr/wrench/reftests/boxshadow/box-shadow-spread-radii-ref.yaml b/gfx/wr/wrench/reftests/boxshadow/box-shadow-spread-radii-ref.yaml new file mode 100644 index 0000000000..e44008fcb5 --- /dev/null +++ b/gfx/wr/wrench/reftests/boxshadow/box-shadow-spread-radii-ref.yaml @@ -0,0 +1,21 @@ +# This emulates the result of box-shadow-spread.yaml without with a spread +# amount of 0 compensated by manually inflating and offsetting the rectangle +# and border radii. +--- +root: + items: + - type: stacking-context + bounds: [0, 0, 1000, 1000] + items: + - type: box-shadow + bounds: [ 0, 0, 280, 280 ] + color: blue + clip-mode: outset + offset: 300 20 + blur-radius: 4 + spread-radius: 0 + border-radius: + top-left: [0, 0] + top-right: [140, 140] + bottom-left: [140, 140] + bottom-right: [0, 0] diff --git a/gfx/wr/wrench/reftests/boxshadow/box-shadow-spread-radii.yaml b/gfx/wr/wrench/reftests/boxshadow/box-shadow-spread-radii.yaml new file mode 100644 index 0000000000..902c7d089b --- /dev/null +++ b/gfx/wr/wrench/reftests/boxshadow/box-shadow-spread-radii.yaml @@ -0,0 +1,18 @@ +--- +root: + items: + - type: stacking-context + bounds: [0, 0, 1000, 1000] + items: + - type: box-shadow + bounds: [ 0, 0, 200, 200 ] + color: blue + clip-mode: outset + offset: 340 60 + blur-radius: 4 + spread-radius: 40 + border-radius: + top-left: [0, 0] + top-right: [100, 100] + bottom-left: [100, 100] + bottom-right: [0, 0] diff --git a/gfx/wr/wrench/reftests/boxshadow/box-shadow-spread.png b/gfx/wr/wrench/reftests/boxshadow/box-shadow-spread.png Binary files differnew file mode 100644 index 0000000000..6fbd03aaff --- /dev/null +++ b/gfx/wr/wrench/reftests/boxshadow/box-shadow-spread.png diff --git a/gfx/wr/wrench/reftests/boxshadow/box-shadow-spread.yaml b/gfx/wr/wrench/reftests/boxshadow/box-shadow-spread.yaml new file mode 100644 index 0000000000..0add751910 --- /dev/null +++ b/gfx/wr/wrench/reftests/boxshadow/box-shadow-spread.yaml @@ -0,0 +1,68 @@ +--- +root: + items: + - type: stacking-context + bounds: [0, 0, 1000, 1000] + items: + - type: box-shadow + bounds: [ 20, 20, 80, 80 ] + color: blue + clip-mode: inset + spread-radius: 10 + border-radius: 20 + + - type: box-shadow + bounds: [ 120, 20, 80, 80 ] + color: blue + clip-mode: inset + spread-radius: 10 + border-radius: 25 + + - type: box-shadow + bounds: [ 220, 20, 80, 80 ] + color: blue + clip-mode: inset + spread-radius: 10 + border-radius: 10 + + - type: box-shadow + bounds: [ 320, 20, 80, 80 ] + color: blue + clip-mode: inset + spread-radius: 10 + border-radius: 9 + + - type: box-shadow + bounds: [ 420, 20, 80, 80 ] + color: blue + clip-mode: inset + spread-radius: 10 + border-radius: 8 + + - type: box-shadow + bounds: [ 520, 20, 80, 80 ] + color: blue + clip-mode: inset + spread-radius: 10 + border-radius: 7 + + - type: box-shadow + bounds: [ 620, 20, 80, 80 ] + color: blue + clip-mode: inset + spread-radius: 10 + border-radius: 6 + + - type: box-shadow + bounds: [ 720, 20, 80, 80 ] + color: blue + clip-mode: inset + spread-radius: 10 + border-radius: 5 + + - type: box-shadow + bounds: [ 820, 20, 80, 80 ] + color: blue + clip-mode: inset + spread-radius: 10 + border-radius: 4 diff --git a/gfx/wr/wrench/reftests/boxshadow/box-shadow-stretch-mode-x.png b/gfx/wr/wrench/reftests/boxshadow/box-shadow-stretch-mode-x.png Binary files differnew file mode 100644 index 0000000000..53edfc789d --- /dev/null +++ b/gfx/wr/wrench/reftests/boxshadow/box-shadow-stretch-mode-x.png diff --git a/gfx/wr/wrench/reftests/boxshadow/box-shadow-stretch-mode-x.yaml b/gfx/wr/wrench/reftests/boxshadow/box-shadow-stretch-mode-x.yaml new file mode 100644 index 0000000000..225433e4fe --- /dev/null +++ b/gfx/wr/wrench/reftests/boxshadow/box-shadow-stretch-mode-x.yaml @@ -0,0 +1,8 @@ +--- +root: + items: + - type: box-shadow + bounds: [ 50, 50, 100, 800 ] + color: red + blur-radius: 16 + border-radius: 32 diff --git a/gfx/wr/wrench/reftests/boxshadow/box-shadow-stretch-mode-y.png b/gfx/wr/wrench/reftests/boxshadow/box-shadow-stretch-mode-y.png Binary files differnew file mode 100644 index 0000000000..8d1d0ebf3c --- /dev/null +++ b/gfx/wr/wrench/reftests/boxshadow/box-shadow-stretch-mode-y.png diff --git a/gfx/wr/wrench/reftests/boxshadow/box-shadow-stretch-mode-y.yaml b/gfx/wr/wrench/reftests/boxshadow/box-shadow-stretch-mode-y.yaml new file mode 100644 index 0000000000..f90366b79f --- /dev/null +++ b/gfx/wr/wrench/reftests/boxshadow/box-shadow-stretch-mode-y.yaml @@ -0,0 +1,9 @@ +--- +root: + items: + - type: box-shadow + bounds: [ 50, 50, 800, 100 ] + color: green + clip-mode: inset + blur-radius: 16 + border-radius: 32 diff --git a/gfx/wr/wrench/reftests/boxshadow/box-shadow-suite-blur.png b/gfx/wr/wrench/reftests/boxshadow/box-shadow-suite-blur.png Binary files differnew file mode 100644 index 0000000000..40f384f6ec --- /dev/null +++ b/gfx/wr/wrench/reftests/boxshadow/box-shadow-suite-blur.png diff --git a/gfx/wr/wrench/reftests/boxshadow/box-shadow-suite-blur.yaml b/gfx/wr/wrench/reftests/boxshadow/box-shadow-suite-blur.yaml new file mode 100644 index 0000000000..29ab5a2a43 --- /dev/null +++ b/gfx/wr/wrench/reftests/boxshadow/box-shadow-suite-blur.yaml @@ -0,0 +1,154 @@ +--- +root: + items: + - type: stacking-context + bounds: [0, 0, 1000, 1000] + items: + # 1st row + - type: box-shadow + bounds: [ 50, 50, 100, 100 ] + color: red + clip-mode: outset + blur-radius: 5 + + - type: box-shadow + bounds: [ 200, 50, 100, 100 ] + color: red + clip-mode: outset + offset: 20 0 + blur-radius: 5 + + - type: box-shadow + bounds: [ 350, 50, 100, 100 ] + color: red + clip-mode: outset + offset: 0 -40 + blur-radius: 5 + + - type: box-shadow + bounds: [ 500, 50, 100, 100 ] + color: red + clip-mode: outset + spread-radius: 30 + blur-radius: 5 + + - type: box-shadow + bounds: [ 650, 50, 100, 100 ] + color: red + clip-mode: outset + spread-radius: 30 + offset: 50 -10 + blur-radius: 5 + + # 2nd row + - type: box-shadow + bounds: [ 50, 250, 100, 100 ] + color: green + border-radius: 32 + blur-radius: 5 + + - type: box-shadow + bounds: [ 200, 250, 100, 100 ] + color: green + offset: 20 0 + border-radius: 32 + blur-radius: 5 + + - type: box-shadow + bounds: [ 350, 250, 100, 100 ] + color: green + offset: 0 -40 + border-radius: 32 + blur-radius: 5 + + - type: box-shadow + bounds: [ 500, 250, 100, 100 ] + color: green + spread-radius: 30 + border-radius: 32 + blur-radius: 5 + + - type: box-shadow + bounds: [ 650, 250, 100, 100 ] + color: green + spread-radius: 30 + offset: 50 -10 + border-radius: 32 + blur-radius: 5 + + # 3rd row + - type: box-shadow + bounds: [ 50, 450, 100, 100 ] + color: red + clip-mode: inset + blur-radius: 5 + + - type: box-shadow + bounds: [ 200, 450, 100, 100 ] + color: red + clip-mode: inset + offset: 20 0 + blur-radius: 5 + + - type: box-shadow + bounds: [ 350, 450, 100, 100 ] + color: red + clip-mode: inset + offset: 0 -40 + blur-radius: 5 + + - type: box-shadow + bounds: [ 500, 450, 100, 100 ] + color: red + clip-mode: inset + spread-radius: 30 + blur-radius: 5 + + - type: box-shadow + bounds: [ 650, 450, 100, 100 ] + color: red + clip-mode: inset + spread-radius: 30 + offset: 50 -10 + blur-radius: 5 + + # 4th row + - type: box-shadow + bounds: [ 50, 650, 100, 100 ] + color: red + clip-mode: inset + border-radius: 32 + blur-radius: 5 + + - type: box-shadow + bounds: [ 200, 650, 100, 100 ] + color: red + clip-mode: inset + offset: 20 0 + border-radius: 32 + blur-radius: 5 + + - type: box-shadow + bounds: [ 350, 650, 100, 100 ] + color: red + clip-mode: inset + offset: 0 -40 + border-radius: 32 + blur-radius: 5 + + - type: box-shadow + bounds: [ 500, 650, 100, 100 ] + color: red + clip-mode: inset + spread-radius: 30 + border-radius: 32 + blur-radius: 5 + + - type: box-shadow + bounds: [ 650, 650, 100, 100 ] + color: red + clip-mode: inset + spread-radius: 30 + offset: 50 -10 + border-radius: 32 + blur-radius: 5 diff --git a/gfx/wr/wrench/reftests/boxshadow/box-shadow-suite-no-blur.png b/gfx/wr/wrench/reftests/boxshadow/box-shadow-suite-no-blur.png Binary files differnew file mode 100644 index 0000000000..e4ba60b1e5 --- /dev/null +++ b/gfx/wr/wrench/reftests/boxshadow/box-shadow-suite-no-blur.png diff --git a/gfx/wr/wrench/reftests/boxshadow/box-shadow-suite-no-blur.yaml b/gfx/wr/wrench/reftests/boxshadow/box-shadow-suite-no-blur.yaml new file mode 100644 index 0000000000..8544da8ccc --- /dev/null +++ b/gfx/wr/wrench/reftests/boxshadow/box-shadow-suite-no-blur.yaml @@ -0,0 +1,134 @@ +--- +root: + items: + - type: stacking-context + bounds: [0, 0, 1000, 1000] + items: + # 1st row + - type: box-shadow + bounds: [ 50, 50, 100, 100 ] + color: red + clip-mode: outset + + - type: box-shadow + bounds: [ 200, 50, 100, 100 ] + color: red + clip-mode: outset + offset: 20 0 + + - type: box-shadow + bounds: [ 350, 50, 100, 100 ] + color: red + clip-mode: outset + offset: 0 -40 + + - type: box-shadow + bounds: [ 500, 50, 100, 100 ] + color: red + clip-mode: outset + spread-radius: 30 + + - type: box-shadow + bounds: [ 650, 50, 100, 100 ] + color: red + clip-mode: outset + spread-radius: 30 + offset: 50 -10 + + # 2nd row + - type: box-shadow + bounds: [ 50, 250, 100, 100 ] + color: green + border-radius: 32 + + - type: box-shadow + bounds: [ 200, 250, 100, 100 ] + color: green + offset: 20 0 + border-radius: 32 + + - type: box-shadow + bounds: [ 350, 250, 100, 100 ] + color: green + offset: 0 -40 + border-radius: 32 + + - type: box-shadow + bounds: [ 500, 250, 100, 100 ] + color: green + spread-radius: 30 + border-radius: 32 + + - type: box-shadow + bounds: [ 650, 250, 100, 100 ] + color: green + spread-radius: 30 + offset: 50 -10 + border-radius: 32 + + # 3rd row + - type: box-shadow + bounds: [ 50, 450, 100, 100 ] + color: red + clip-mode: inset + + - type: box-shadow + bounds: [ 200, 450, 100, 100 ] + color: red + clip-mode: inset + offset: 20 0 + + - type: box-shadow + bounds: [ 350, 450, 100, 100 ] + color: red + clip-mode: inset + offset: 0 -40 + + - type: box-shadow + bounds: [ 500, 450, 100, 100 ] + color: red + clip-mode: inset + spread-radius: 30 + + - type: box-shadow + bounds: [ 650, 450, 100, 100 ] + color: red + clip-mode: inset + spread-radius: 30 + offset: 50 -10 + + # 4th row + - type: box-shadow + bounds: [ 50, 650, 100, 100 ] + color: red + clip-mode: inset + border-radius: 32 + + - type: box-shadow + bounds: [ 200, 650, 100, 100 ] + color: red + clip-mode: inset + offset: 20 0 + border-radius: 32 + + - type: box-shadow + bounds: [ 350, 650, 100, 100 ] + color: red + clip-mode: inset + offset: 0 -40 + border-radius: 32 + + - type: box-shadow + bounds: [ 500, 650, 100, 100 ] + color: red + clip-mode: inset + spread-radius: 30 + border-radius: 32 + + - type: box-shadow + bounds: [ 650, 650, 100, 100 ] + color: red + clip-mode: inset + spread-radius: 30 + offset: 50 -10 + border-radius: 32 diff --git a/gfx/wr/wrench/reftests/boxshadow/boxshadow-spread-only-ref.png b/gfx/wr/wrench/reftests/boxshadow/boxshadow-spread-only-ref.png Binary files differnew file mode 100644 index 0000000000..a05bf7314e --- /dev/null +++ b/gfx/wr/wrench/reftests/boxshadow/boxshadow-spread-only-ref.png diff --git a/gfx/wr/wrench/reftests/boxshadow/boxshadow-spread-only.yaml b/gfx/wr/wrench/reftests/boxshadow/boxshadow-spread-only.yaml new file mode 100644 index 0000000000..d8dabde293 --- /dev/null +++ b/gfx/wr/wrench/reftests/boxshadow/boxshadow-spread-only.yaml @@ -0,0 +1,13 @@ +--- +root: + items: + - type: stacking-context + bounds: [0, 0, 600, 600] + items: + - type: box-shadow + bounds: [ 40, 40, 400, 400 ] + blur-radius: 0 + spread-radius: 20 + clip-mode: outset + border-radius: 200 + color: black diff --git a/gfx/wr/wrench/reftests/boxshadow/inset-alpha.png b/gfx/wr/wrench/reftests/boxshadow/inset-alpha.png Binary files differnew file mode 100644 index 0000000000..bc4c0a1f37 --- /dev/null +++ b/gfx/wr/wrench/reftests/boxshadow/inset-alpha.png diff --git a/gfx/wr/wrench/reftests/boxshadow/inset-alpha.yaml b/gfx/wr/wrench/reftests/boxshadow/inset-alpha.yaml new file mode 100644 index 0000000000..7764f0a276 --- /dev/null +++ b/gfx/wr/wrench/reftests/boxshadow/inset-alpha.yaml @@ -0,0 +1,14 @@ +--- +root: + items: + - type: stacking-context + bounds: [0, 0, 100, 100] + items: + - type: rect + bounds: [ 0, 0, 100, 100 ] + color: [0, 255, 0] + - type: box-shadow + bounds: [ 0, 0, 100, 100 ] + clip-mode: inset + color: [255, 255, 255, 0.1] + blur-radius: 100 diff --git a/gfx/wr/wrench/reftests/boxshadow/inset-border-radius-ref.yaml b/gfx/wr/wrench/reftests/boxshadow/inset-border-radius-ref.yaml new file mode 100644 index 0000000000..62d5dd10c9 --- /dev/null +++ b/gfx/wr/wrench/reftests/boxshadow/inset-border-radius-ref.yaml @@ -0,0 +1,16 @@ +--- +root: + items: + - type: stacking-context + bounds: [0, 0, 100, 100] + items: + - type: clip + bounds: [0, 0, 100, 100] + complex: + - rect: [ 10, 10, 80, 80 ] + radius: 10 + items: + - type: box-shadow + bounds: [ 10, 10, 80, 80 ] + blur-radius: 25 + clip-mode: inset diff --git a/gfx/wr/wrench/reftests/boxshadow/inset-border-radius.png b/gfx/wr/wrench/reftests/boxshadow/inset-border-radius.png Binary files differnew file mode 100644 index 0000000000..418fabe810 --- /dev/null +++ b/gfx/wr/wrench/reftests/boxshadow/inset-border-radius.png diff --git a/gfx/wr/wrench/reftests/boxshadow/inset-border-radius.yaml b/gfx/wr/wrench/reftests/boxshadow/inset-border-radius.yaml new file mode 100644 index 0000000000..cb5c274f5a --- /dev/null +++ b/gfx/wr/wrench/reftests/boxshadow/inset-border-radius.yaml @@ -0,0 +1,11 @@ +--- +root: + items: + - type: stacking-context + bounds: [0, 0, 100, 100] + items: + - type: box-shadow + bounds: [ 10, 10, 80, 80 ] + blur-radius: 25 + clip-mode: inset + border-radius: 10 diff --git a/gfx/wr/wrench/reftests/boxshadow/inset-downscale.png b/gfx/wr/wrench/reftests/boxshadow/inset-downscale.png Binary files differnew file mode 100644 index 0000000000..aef7968600 --- /dev/null +++ b/gfx/wr/wrench/reftests/boxshadow/inset-downscale.png diff --git a/gfx/wr/wrench/reftests/boxshadow/inset-downscale.yaml b/gfx/wr/wrench/reftests/boxshadow/inset-downscale.yaml new file mode 100644 index 0000000000..dd0c3abc2d --- /dev/null +++ b/gfx/wr/wrench/reftests/boxshadow/inset-downscale.yaml @@ -0,0 +1,10 @@ +--- +root: + items: + - type: stacking-context + bounds: [50, 50, 400, 200] + items: + - type: box-shadow + bounds: [ 10, 10, 400, 200 ] + blur-radius: 50 + clip-mode: inset diff --git a/gfx/wr/wrench/reftests/boxshadow/inset-empty.yaml b/gfx/wr/wrench/reftests/boxshadow/inset-empty.yaml new file mode 100644 index 0000000000..85d2840546 --- /dev/null +++ b/gfx/wr/wrench/reftests/boxshadow/inset-empty.yaml @@ -0,0 +1,13 @@ +--- +root: + items: + - type: stacking-context + bounds: [50, 50, 500, 500] + items: + - type: box-shadow + bounds: [ 10, 10, 400, 400 ] + blur-radius: 0 + clip-mode: inset + offset: [0, 0] + spread-radius: 0 + color: [255, 0, 0] diff --git a/gfx/wr/wrench/reftests/boxshadow/inset-large-offset-ref.png b/gfx/wr/wrench/reftests/boxshadow/inset-large-offset-ref.png Binary files differnew file mode 100644 index 0000000000..e1d189eaa0 --- /dev/null +++ b/gfx/wr/wrench/reftests/boxshadow/inset-large-offset-ref.png diff --git a/gfx/wr/wrench/reftests/boxshadow/inset-large-offset.yaml b/gfx/wr/wrench/reftests/boxshadow/inset-large-offset.yaml new file mode 100644 index 0000000000..1cc2355d02 --- /dev/null +++ b/gfx/wr/wrench/reftests/boxshadow/inset-large-offset.yaml @@ -0,0 +1,13 @@ +--- +root: + items: + - type: stacking-context + bounds: [50, 50, 500, 500] + items: + - type: box-shadow + bounds: [ 10, 10, 400, 400 ] + blur-radius: 1 + clip-mode: inset + offset: [0, 200] + spread-radius: 0 + color: [255, 0, 0] diff --git a/gfx/wr/wrench/reftests/boxshadow/inset-mask-region.png b/gfx/wr/wrench/reftests/boxshadow/inset-mask-region.png Binary files differnew file mode 100644 index 0000000000..c0f81bdccf --- /dev/null +++ b/gfx/wr/wrench/reftests/boxshadow/inset-mask-region.png diff --git a/gfx/wr/wrench/reftests/boxshadow/inset-mask-region.yaml b/gfx/wr/wrench/reftests/boxshadow/inset-mask-region.yaml new file mode 100644 index 0000000000..08f52af181 --- /dev/null +++ b/gfx/wr/wrench/reftests/boxshadow/inset-mask-region.yaml @@ -0,0 +1,11 @@ +--- +root: + items: + - type: stacking-context + items: + - type: box-shadow + bounds: [ 50, 50, 400.1, 400.1 ] + color: red + blur-radius: 10 + clip-mode: inset + border-radius: 185 diff --git a/gfx/wr/wrench/reftests/boxshadow/inset-neg-offset.png b/gfx/wr/wrench/reftests/boxshadow/inset-neg-offset.png Binary files differnew file mode 100644 index 0000000000..b6b232a1d0 --- /dev/null +++ b/gfx/wr/wrench/reftests/boxshadow/inset-neg-offset.png diff --git a/gfx/wr/wrench/reftests/boxshadow/inset-neg-offset.yaml b/gfx/wr/wrench/reftests/boxshadow/inset-neg-offset.yaml new file mode 100644 index 0000000000..9fe63176c0 --- /dev/null +++ b/gfx/wr/wrench/reftests/boxshadow/inset-neg-offset.yaml @@ -0,0 +1,18 @@ +--- +root: + items: + - type: stacking-context + bounds: [0, 0, 1000, 1000] + items: + - type: box-shadow + bounds: [ 22, 22, 200, 80 ] + color: blue + clip-mode: inset + offset: -2 -2 + blur-radius: 20 + spread-radius: 0 + border-radius: + top-left: [0, 0] + top-right: [0, 0] + bottom-left: [0, 0] + bottom-right: [0, 0] diff --git a/gfx/wr/wrench/reftests/boxshadow/inset-no-blur-radius-ref.png b/gfx/wr/wrench/reftests/boxshadow/inset-no-blur-radius-ref.png Binary files differnew file mode 100644 index 0000000000..dfc23875e3 --- /dev/null +++ b/gfx/wr/wrench/reftests/boxshadow/inset-no-blur-radius-ref.png diff --git a/gfx/wr/wrench/reftests/boxshadow/inset-no-blur-radius.yaml b/gfx/wr/wrench/reftests/boxshadow/inset-no-blur-radius.yaml new file mode 100644 index 0000000000..eb9c783718 --- /dev/null +++ b/gfx/wr/wrench/reftests/boxshadow/inset-no-blur-radius.yaml @@ -0,0 +1,13 @@ +--- +root: + items: + - type: stacking-context + bounds: [0, 0, 100, 100] + items: + - type: box-shadow + bounds: [ 10, 10, 80, 80 ] + blur-radius: 0 + clip-mode: inset + border-radius: 10 + offset: 10 10 + color: [255, 0, 0] diff --git a/gfx/wr/wrench/reftests/boxshadow/inset-offset.png b/gfx/wr/wrench/reftests/boxshadow/inset-offset.png Binary files differnew file mode 100644 index 0000000000..d5f41456fe --- /dev/null +++ b/gfx/wr/wrench/reftests/boxshadow/inset-offset.png diff --git a/gfx/wr/wrench/reftests/boxshadow/inset-offset.yaml b/gfx/wr/wrench/reftests/boxshadow/inset-offset.yaml new file mode 100644 index 0000000000..17fa232f3a --- /dev/null +++ b/gfx/wr/wrench/reftests/boxshadow/inset-offset.yaml @@ -0,0 +1,18 @@ +--- +root: + items: + - type: stacking-context + bounds: [0, 0, 1000, 1000] + items: + - type: box-shadow + bounds: [ 22, 22, 200, 80 ] + color: blue + clip-mode: inset + offset: 5 5 + blur-radius: 20 + spread-radius: 0 + border-radius: + top-left: [0, 0] + top-right: [0, 0] + bottom-left: [0, 0] + bottom-right: [0, 0] diff --git a/gfx/wr/wrench/reftests/boxshadow/inset-simple-ref.yaml b/gfx/wr/wrench/reftests/boxshadow/inset-simple-ref.yaml new file mode 100644 index 0000000000..526a1fa4e0 --- /dev/null +++ b/gfx/wr/wrench/reftests/boxshadow/inset-simple-ref.yaml @@ -0,0 +1,9 @@ +--- +root: + items: + - type: stacking-context + bounds: [50, 50, 100, 100] + items: + - type: rect + bounds: [ 10, 10, 80, 80 ] + color: [0, 255, 0] diff --git a/gfx/wr/wrench/reftests/boxshadow/inset-simple.yaml b/gfx/wr/wrench/reftests/boxshadow/inset-simple.yaml new file mode 100644 index 0000000000..78f6ef18c1 --- /dev/null +++ b/gfx/wr/wrench/reftests/boxshadow/inset-simple.yaml @@ -0,0 +1,13 @@ +--- +root: + items: + - type: stacking-context + bounds: [50, 50, 100, 100] + items: + - type: rect + bounds: [ 10, 10, 80, 80 ] + color: [0, 255, 0] + - type: box-shadow + bounds: [ 10, 10, 80, 80 ] + blur-radius: 25 + clip-mode: inset diff --git a/gfx/wr/wrench/reftests/boxshadow/inset-spread-large-ref.yaml b/gfx/wr/wrench/reftests/boxshadow/inset-spread-large-ref.yaml new file mode 100644 index 0000000000..bdeec79e35 --- /dev/null +++ b/gfx/wr/wrench/reftests/boxshadow/inset-spread-large-ref.yaml @@ -0,0 +1,9 @@ +--- +root: + items: + - type: stacking-context + bounds: [50, 50, 100, 100] + items: + - type: rect + bounds: [ 10, 10, 80, 80 ] + color: [255, 0, 0] diff --git a/gfx/wr/wrench/reftests/boxshadow/inset-spread-large.yaml b/gfx/wr/wrench/reftests/boxshadow/inset-spread-large.yaml new file mode 100644 index 0000000000..05cc5e40f2 --- /dev/null +++ b/gfx/wr/wrench/reftests/boxshadow/inset-spread-large.yaml @@ -0,0 +1,12 @@ +--- +root: + items: + - type: stacking-context + bounds: [50, 50, 100, 100] + items: + - type: box-shadow + bounds: [ 10, 10, 80, 80 ] + blur-radius: 5 + clip-mode: inset + spread-radius: 200 + color: [255, 0, 0] diff --git a/gfx/wr/wrench/reftests/boxshadow/inset-spread-ref.yaml b/gfx/wr/wrench/reftests/boxshadow/inset-spread-ref.yaml new file mode 100644 index 0000000000..76802f9db0 --- /dev/null +++ b/gfx/wr/wrench/reftests/boxshadow/inset-spread-ref.yaml @@ -0,0 +1,10 @@ +--- +root: + items: + - type: stacking-context + bounds: [50, 50, 100, 100] + items: + - type: rect + bounds: [ 10, 10, 80, 80 ] + color: [255, 255, 255] + diff --git a/gfx/wr/wrench/reftests/boxshadow/inset-spread.yaml b/gfx/wr/wrench/reftests/boxshadow/inset-spread.yaml new file mode 100644 index 0000000000..de09797dcf --- /dev/null +++ b/gfx/wr/wrench/reftests/boxshadow/inset-spread.yaml @@ -0,0 +1,12 @@ +--- +root: + items: + - type: stacking-context + bounds: [50, 50, 100, 100] + items: + - type: box-shadow + bounds: [ 10, 10, 80, 80 ] + blur-radius: 5 + clip-mode: inset + spread-radius: 20 + color: [0, 0, 0] diff --git a/gfx/wr/wrench/reftests/boxshadow/inset-subpx.png b/gfx/wr/wrench/reftests/boxshadow/inset-subpx.png Binary files differnew file mode 100644 index 0000000000..89ca1e44b1 --- /dev/null +++ b/gfx/wr/wrench/reftests/boxshadow/inset-subpx.png diff --git a/gfx/wr/wrench/reftests/boxshadow/inset-subpx.yaml b/gfx/wr/wrench/reftests/boxshadow/inset-subpx.yaml new file mode 100644 index 0000000000..22dc3f0959 --- /dev/null +++ b/gfx/wr/wrench/reftests/boxshadow/inset-subpx.yaml @@ -0,0 +1,12 @@ +--- +root: + items: + - type: stacking-context + bounds: [0, 0, 1000, 1000] + items: + - type: box-shadow + bounds: [ 76, 67.5, 59.016666, 39 ] + offset: [30, 9] + blur-radius: 7 + color: blue + clip-mode: inset diff --git a/gfx/wr/wrench/reftests/boxshadow/invalid-ref.yaml b/gfx/wr/wrench/reftests/boxshadow/invalid-ref.yaml new file mode 100644 index 0000000000..4f2245ccaa --- /dev/null +++ b/gfx/wr/wrench/reftests/boxshadow/invalid-ref.yaml @@ -0,0 +1,5 @@ +--- +root: + items: + - type: stacking-context + bounds: [0, 0, 1000, 1000] diff --git a/gfx/wr/wrench/reftests/boxshadow/invalid.yaml b/gfx/wr/wrench/reftests/boxshadow/invalid.yaml new file mode 100644 index 0000000000..6c1fecb995 --- /dev/null +++ b/gfx/wr/wrench/reftests/boxshadow/invalid.yaml @@ -0,0 +1,12 @@ +--- +root: + items: + - type: stacking-context + bounds: [0, 0, 1000, 1000] + items: + - type: box-shadow + bounds: [ 100, 100, 200, 10 ] + blur-radius: 10.5 + offset: [15, 15] + spread-radius: -15 + color: red diff --git a/gfx/wr/wrench/reftests/boxshadow/no-stretch.png b/gfx/wr/wrench/reftests/boxshadow/no-stretch.png Binary files differnew file mode 100644 index 0000000000..ac2ac859f4 --- /dev/null +++ b/gfx/wr/wrench/reftests/boxshadow/no-stretch.png diff --git a/gfx/wr/wrench/reftests/boxshadow/no-stretch.yaml b/gfx/wr/wrench/reftests/boxshadow/no-stretch.yaml new file mode 100644 index 0000000000..4276ffa929 --- /dev/null +++ b/gfx/wr/wrench/reftests/boxshadow/no-stretch.yaml @@ -0,0 +1,21 @@ +# Test that box-shadows with overlapping corners +# are drawn with simple mode (not stretched). +--- +root: + items: + - type: stacking-context + bounds: [0, 0, 1000, 1000] + items: + - type: box-shadow + bounds: [ 50, 50, 150, 150 ] + color: red + clip-mode: outset + blur-radius: 2.4 + offset: [100, 0] + spread-radius: -40 + border-radius: { + top-left: 112, + top-right: 48, + bottom-left: 48, + bottom-right: 112, + } diff --git a/gfx/wr/wrench/reftests/boxshadow/overlap1.png b/gfx/wr/wrench/reftests/boxshadow/overlap1.png Binary files differnew file mode 100644 index 0000000000..a47c3ad696 --- /dev/null +++ b/gfx/wr/wrench/reftests/boxshadow/overlap1.png diff --git a/gfx/wr/wrench/reftests/boxshadow/overlap1.yaml b/gfx/wr/wrench/reftests/boxshadow/overlap1.yaml new file mode 100644 index 0000000000..1744983da6 --- /dev/null +++ b/gfx/wr/wrench/reftests/boxshadow/overlap1.yaml @@ -0,0 +1,18 @@ +--- +root: + items: + - type: stacking-context + bounds: [0, 0, 1000, 1000] + items: + - type: box-shadow + bounds: [ 50, 10, 200, 80 ] + color: black + clip-mode: outset + offset: 0 150 + blur-radius: 20 + border-radius: + top-left: [100, 40] + top-right: [0, 0] + bottom-left: [100, 40] + bottom-right: [0, 0] + diff --git a/gfx/wr/wrench/reftests/boxshadow/overlap2.png b/gfx/wr/wrench/reftests/boxshadow/overlap2.png Binary files differnew file mode 100644 index 0000000000..83347eb8b5 --- /dev/null +++ b/gfx/wr/wrench/reftests/boxshadow/overlap2.png diff --git a/gfx/wr/wrench/reftests/boxshadow/overlap2.yaml b/gfx/wr/wrench/reftests/boxshadow/overlap2.yaml new file mode 100644 index 0000000000..59ffb2c438 --- /dev/null +++ b/gfx/wr/wrench/reftests/boxshadow/overlap2.yaml @@ -0,0 +1,19 @@ +--- +root: + items: + - type: stacking-context + bounds: [0, 0, 1000, 1000] + items: + - type: box-shadow + bounds: [ 0, 0, 200, 200 ] + color: red + clip-mode: outset + offset: 200 0 + blur-radius: 1 + spread-radius: 0 + border-radius: + top-left: [100, 100] + top-right: [0, 0] + bottom-left: [0, 0] + bottom-right: [150, 150] + diff --git a/gfx/wr/wrench/reftests/boxshadow/reftest.list b/gfx/wr/wrench/reftests/boxshadow/reftest.list new file mode 100644 index 0000000000..403812ad5f --- /dev/null +++ b/gfx/wr/wrench/reftests/boxshadow/reftest.list @@ -0,0 +1,37 @@ +!= inset-simple.yaml inset-simple-ref.yaml +!= inset-spread.yaml inset-spread-ref.yaml +== inset-no-blur-radius.yaml inset-no-blur-radius-ref.png +== inset-spread-large.yaml inset-spread-large-ref.yaml +platform(linux,mac) == inset-alpha.yaml inset-alpha.png +platform(linux,mac) == boxshadow-spread-only.yaml boxshadow-spread-only-ref.png +== box-shadow-clip.yaml box-shadow-clip-ref.yaml +fuzzy(1,402) fuzzy-if(platform(swgl),2,1402) == inset-large-offset.yaml inset-large-offset-ref.png +platform(linux,mac) == inset-border-radius.yaml inset-border-radius.png +platform(linux,mac) == inset-offset.yaml inset-offset.png +platform(linux,mac) == inset-neg-offset.yaml inset-neg-offset.png +== box-shadow-empty.yaml blank.yaml +platform(linux,mac) == box-shadow-suite-no-blur.yaml box-shadow-suite-no-blur.png +platform(linux,mac) == box-shadow-suite-blur.yaml box-shadow-suite-blur.png +fuzzy(1,8) == box-shadow-large-blur-radius.yaml box-shadow-large-blur-radius-ref.yaml +fuzzy(1,6388) == rounding.yaml rounding-ref.yaml +platform(linux,mac) == box-shadow-border-radii.yaml box-shadow-border-radii.png +skip_on(android) == box-shadow-spread.yaml box-shadow-spread.png # Too wide for Android +== box-shadow-spread-radii.yaml box-shadow-spread-radii-ref.yaml +== invalid.yaml invalid-ref.yaml +== inset-empty.yaml blank.yaml +platform(linux,mac) == inset-subpx.yaml inset-subpx.png +platform(linux,mac) fuzzy(1,4) == inset-downscale.yaml inset-downscale.png +platform(linux,mac) fuzzy(1,979) == box-shadow-cache.yaml box-shadow-cache.png +platform(linux,mac) fuzzy(1,685) == overlap1.yaml overlap1.png +fuzzy(2,757) fuzzy-if(platform(swgl),15,2456) == overlap2.yaml overlap2.png +platform(linux,mac) fuzzy(1,48) == no-stretch.yaml no-stretch.png +platform(linux,mac) fuzzy(1,9) == box-shadow-stretch-mode-x.yaml box-shadow-stretch-mode-x.png +platform(linux,mac) fuzzy(1,41) == box-shadow-stretch-mode-y.yaml box-shadow-stretch-mode-y.png +platform(linux,mac) fuzzy(1,14) == inset-mask-region.yaml inset-mask-region.png +== box-shadow-blurred-overlapping-radii.yaml box-shadow-blurred-overlapping-radii-ref.yaml + +fuzzy(1,5) platform(linux,mac) == box-shadow-huge-radius.yaml box-shadow-huge-radius.png + +platform(linux,mac) == box-shadow-large-blur-radius-2.yaml box-shadow-large-blur-radius-2.png +platform(linux,mac) fuzzy(1,8) == box-shadow-large-blur-radius-3.yaml box-shadow-large-blur-radius-3.png +platform(linux,mac) fuzzy(1,79) == scale.yaml scale.png diff --git a/gfx/wr/wrench/reftests/boxshadow/rounding-ref.yaml b/gfx/wr/wrench/reftests/boxshadow/rounding-ref.yaml new file mode 100644 index 0000000000..e6e2fb8464 --- /dev/null +++ b/gfx/wr/wrench/reftests/boxshadow/rounding-ref.yaml @@ -0,0 +1,18 @@ +--- +root: + items: + - type: stacking-context + bounds: [0, 0, 1000, 1000] + items: + - type: rect + bounds: [100, 100, 500, 500] + color: green + - type: rect + bounds: [200, 200, 300, 300] + color: black + - type: box-shadow + bounds: [200, 200, 300, 300] + blur-radius: 20 + clip-mode: inset + spread-radius: 100 + color: green diff --git a/gfx/wr/wrench/reftests/boxshadow/rounding.yaml b/gfx/wr/wrench/reftests/boxshadow/rounding.yaml new file mode 100644 index 0000000000..8078b2e1d6 --- /dev/null +++ b/gfx/wr/wrench/reftests/boxshadow/rounding.yaml @@ -0,0 +1,15 @@ +--- +root: + items: + - type: stacking-context + bounds: [0, 0, 1000, 1000] + items: + - type: rect + bounds: [100, 100, 500, 500] + color: black + - type: box-shadow + bounds: [100, 100, 500, 500] + blur-radius: 20 + clip-mode: inset + spread-radius: 200 + color: green diff --git a/gfx/wr/wrench/reftests/boxshadow/scale.png b/gfx/wr/wrench/reftests/boxshadow/scale.png Binary files differnew file mode 100644 index 0000000000..2f635e9180 --- /dev/null +++ b/gfx/wr/wrench/reftests/boxshadow/scale.png diff --git a/gfx/wr/wrench/reftests/boxshadow/scale.yaml b/gfx/wr/wrench/reftests/boxshadow/scale.yaml new file mode 100644 index 0000000000..12263b4eb9 --- /dev/null +++ b/gfx/wr/wrench/reftests/boxshadow/scale.yaml @@ -0,0 +1,183 @@ +# Test that box shadows are drawn with correct symmetry in +# a variety of cases. This test checks for various scale +# factors, in combination with box shadows clipped by the +# screen rect. It also has come large box shadows that check +# the symmetry still works with segmentation enabled. +--- +root: + items: + - type: stacking-context + transform: scale(0.3) + items: + - type: box-shadow + bounds: [ -70, 50, 100, 100 ] + color: black + blur-radius: 1 + clip-mode: inset + - type: stacking-context + transform: scale(0.4) + items: + - type: box-shadow + bounds: [ -70, 150, 100, 100 ] + color: black + blur-radius: 1 + clip-mode: inset + - type: stacking-context + transform: scale(0.5) + items: + - type: box-shadow + bounds: [ -70, 250, 100, 100 ] + color: black + blur-radius: 1 + clip-mode: inset + - type: stacking-context + transform: scale(0.6) + items: + - type: box-shadow + bounds: [ -70, 350, 100, 100 ] + color: black + blur-radius: 1 + clip-mode: inset + - type: stacking-context + transform: scale(0.7) + items: + - type: box-shadow + bounds: [ -70, 450, 100, 100 ] + color: black + blur-radius: 1 + clip-mode: inset + - type: stacking-context + transform: scale(0.73) + items: + - type: box-shadow + bounds: [ -70, 550, 100, 100 ] + color: black + blur-radius: 1 + clip-mode: inset + - type: stacking-context + transform: scale(0.75) + items: + - type: box-shadow + bounds: [ -70, 650, 100, 100 ] + color: black + blur-radius: 1 + clip-mode: inset + - type: stacking-context + transform: scale(0.77) + items: + - type: box-shadow + bounds: [ -70, 750, 100, 100 ] + color: black + blur-radius: 1 + clip-mode: inset + - type: stacking-context + transform: scale(0.8) + items: + - type: box-shadow + bounds: [ -70, 850, 100, 100 ] + color: black + blur-radius: 1 + clip-mode: inset + - type: stacking-context + items: + - type: box-shadow + bounds: [ -70, 800, 100, 100 ] + color: black + blur-radius: 1 + clip-mode: inset + + - type: stacking-context + transform: scale(0.3) + items: + - type: box-shadow + bounds: [ 50, 50, 100, 100 ] + color: black + blur-radius: 1 + clip-mode: inset + - type: stacking-context + transform: scale(0.4) + items: + - type: box-shadow + bounds: [ 50, 150, 100, 100 ] + color: black + blur-radius: 1 + clip-mode: inset + - type: stacking-context + transform: scale(0.5) + items: + - type: box-shadow + bounds: [ 50, 250, 100, 100 ] + color: black + blur-radius: 1 + clip-mode: inset + - type: stacking-context + transform: scale(0.6) + items: + - type: box-shadow + bounds: [ 50, 350, 100, 100 ] + color: black + blur-radius: 1 + clip-mode: inset + - type: stacking-context + transform: scale(0.7) + items: + - type: box-shadow + bounds: [ 50, 450, 100, 100 ] + color: black + blur-radius: 1 + clip-mode: inset + - type: stacking-context + transform: scale(0.73) + items: + - type: box-shadow + bounds: [ 50, 550, 100, 100 ] + color: black + blur-radius: 1 + clip-mode: inset + - type: stacking-context + transform: scale(0.75) + items: + - type: box-shadow + bounds: [ 50, 650, 100, 100 ] + color: black + blur-radius: 1 + clip-mode: inset + - type: stacking-context + transform: scale(0.77) + items: + - type: box-shadow + bounds: [ 50, 750, 100, 100 ] + color: black + blur-radius: 1 + clip-mode: inset + - type: stacking-context + transform: scale(0.8) + items: + - type: box-shadow + bounds: [ 50, 850, 100, 100 ] + color: black + blur-radius: 1 + clip-mode: inset + - type: stacking-context + items: + - type: box-shadow + bounds: [ 50, 800, 100, 100 ] + color: black + blur-radius: 1 + clip-mode: inset + + - type: stacking-context + items: + - type: box-shadow + bounds: [ 200, -100, 600, 200 ] + color: black + blur-radius: 5 + clip-mode: inset + + - type: stacking-context + items: + - type: box-shadow + bounds: [ 200, 200, 600, 200 ] + color: black + blur-radius: 5 + clip-mode: outset diff --git a/gfx/wr/wrench/reftests/clip/blank.yaml b/gfx/wr/wrench/reftests/clip/blank.yaml new file mode 100644 index 0000000000..c4eb3ab673 --- /dev/null +++ b/gfx/wr/wrench/reftests/clip/blank.yaml @@ -0,0 +1,2 @@ +--- +root: diff --git a/gfx/wr/wrench/reftests/clip/border-with-rounded-clip.png b/gfx/wr/wrench/reftests/clip/border-with-rounded-clip.png Binary files differnew file mode 100644 index 0000000000..f340005714 --- /dev/null +++ b/gfx/wr/wrench/reftests/clip/border-with-rounded-clip.png diff --git a/gfx/wr/wrench/reftests/clip/border-with-rounded-clip.yaml b/gfx/wr/wrench/reftests/clip/border-with-rounded-clip.yaml new file mode 100644 index 0000000000..12785ef444 --- /dev/null +++ b/gfx/wr/wrench/reftests/clip/border-with-rounded-clip.yaml @@ -0,0 +1,21 @@ +--- +root: + items: + - + bounds: [10, 10, 938, 200] + clip-rect: [10, 10, 938, 200] + type: clip + id: 2 + complex: + - + rect: [10, 10, 938, 200] + radius: [97, 97] + "clip-mode": clip + - + bounds: [10, 10, 100, 200] + clip-and-scroll: 2 + type: border + width: [100, 50, 100, 50] + border-type: normal + color: green + style: solid diff --git a/gfx/wr/wrench/reftests/clip/clip-3d-transform-ref.yaml b/gfx/wr/wrench/reftests/clip/clip-3d-transform-ref.yaml new file mode 100644 index 0000000000..58d66bec5a --- /dev/null +++ b/gfx/wr/wrench/reftests/clip/clip-3d-transform-ref.yaml @@ -0,0 +1,8 @@ +--- +root: + items: + - + bounds: [0, 0, 200, 200] + "clip-rect": [0, 0, 200, 200] + type: rect + color: green diff --git a/gfx/wr/wrench/reftests/clip/clip-3d-transform.yaml b/gfx/wr/wrench/reftests/clip/clip-3d-transform.yaml new file mode 100644 index 0000000000..f844b382ad --- /dev/null +++ b/gfx/wr/wrench/reftests/clip/clip-3d-transform.yaml @@ -0,0 +1,30 @@ +# This tests that clipping works well inside of a transformation with a 3d component that +# is still axis-aligned and lacking a perspective component. These two spaces should exist +# within a compatible coordinate system for local clipping (no masking). +--- +root: + items: + - + bounds: [0, 0, 0, 0] + "clip-rect": [0, 0, 0, 0] + "backface-visible": true + type: "stacking-context" + "scroll-policy": scrollable + transform: [0.5, 0, -0.8660254, 0, 0, 1, 0, 0, 0.8660254, 0, 0.5, 0, 0, 0, 0, 1] + "transform-style": flat + filters: [] + items: + - + bounds: [0, 0, 800, 400] + "clip-rect": [0, 0, 800, 400] + "backface-visible": true + type: clip + id: 2 + "content-size": [800, 400] + - + bounds: [0, 0, 400, 200] + "clip-rect": [0, 0, 400, 200] + "backface-visible": true + type: rect + clip-and-scroll: 2 + color: green diff --git a/gfx/wr/wrench/reftests/clip/clip-45-degree-rotation-ref.png b/gfx/wr/wrench/reftests/clip/clip-45-degree-rotation-ref.png Binary files differnew file mode 100644 index 0000000000..0d3bad68cf --- /dev/null +++ b/gfx/wr/wrench/reftests/clip/clip-45-degree-rotation-ref.png diff --git a/gfx/wr/wrench/reftests/clip/clip-45-degree-rotation.yaml b/gfx/wr/wrench/reftests/clip/clip-45-degree-rotation.yaml new file mode 100644 index 0000000000..316f249a3e --- /dev/null +++ b/gfx/wr/wrench/reftests/clip/clip-45-degree-rotation.yaml @@ -0,0 +1,32 @@ +# Test that transformed content is clipped properly by clips with a different transform. +--- +root: + items: + - + bounds: [0, 0, 0, 0] + "clip-rect": [0, 0, 0, 0] + type: "stacking-context" + transform: rotate(-45) translate(200, 0) + items: + - + bounds: [0, 0, 300, 300] + "clip-rect": [0, 0, 300, 300] + type: rect + color: red + - + bounds: [0, 0, 300, 300] + "clip-rect": [0, 0, 300, 300] + type: clip + id: 5 + - + bounds: [0, 0, 0, 0] + "clip-rect": [0, 0, 0, 0] + clip-and-scroll: 5 + type: "stacking-context" + transform: rotate(45) translate(-300, 0) + items: + - + bounds: [0, 0, 1598, 1200] + "clip-rect": [0, 0, 1598, 1200] + type: rect + color: green diff --git a/gfx/wr/wrench/reftests/clip/clip-and-filter-with-rotation-ref.yaml b/gfx/wr/wrench/reftests/clip/clip-and-filter-with-rotation-ref.yaml new file mode 100644 index 0000000000..c092030714 --- /dev/null +++ b/gfx/wr/wrench/reftests/clip/clip-and-filter-with-rotation-ref.yaml @@ -0,0 +1,18 @@ +# Test that filtered content is clipped properly in a rotated context +--- +root: + items: + - + bounds: [16, 16, 0, 0] + type: "reference-frame" + transform: rotate(10) + id: 7 + items: + - + bounds: [0, 0, 0, 0] + type: "stacking-context" + items: + - + bounds: [0, 0, 324, 295] + type: rect + color: red diff --git a/gfx/wr/wrench/reftests/clip/clip-and-filter-with-rotation.yaml b/gfx/wr/wrench/reftests/clip/clip-and-filter-with-rotation.yaml new file mode 100644 index 0000000000..3c71e0148f --- /dev/null +++ b/gfx/wr/wrench/reftests/clip/clip-and-filter-with-rotation.yaml @@ -0,0 +1,35 @@ +# Test that filtered content is clipped properly in a rotated context +--- +root: + items: + - + bounds: [16, 16, 0, 0] + type: "reference-frame" + transform: rotate(10) + id: 7 + items: + - + bounds: [0, 0, 0, 0] + type: "stacking-context" + items: + - + bounds: [0, 0, 324, 295] + type: clip + id: 2 + # note it's important that we use clip-node here; clip-and-scroll in yaml + # defaults to push/pop, but we want to specifically attach this clip-chain + # to the stacking context and not the children (as gecko does in the bug) + - + bounds: [0, 0, 0, 0] + clip-node: 2 + type: "stacking-context" + filters: ["contrast(1.1)"] # any blend-style filter will do + items: + - + bounds: [-150, -150, 624, 624] + type: rect + color: blue + - + bounds: [0, 0, 324, 295] + type: rect + color: red diff --git a/gfx/wr/wrench/reftests/clip/clip-corner-overlap-ref.yaml b/gfx/wr/wrench/reftests/clip/clip-corner-overlap-ref.yaml new file mode 100644 index 0000000000..e9592b5831 --- /dev/null +++ b/gfx/wr/wrench/reftests/clip/clip-corner-overlap-ref.yaml @@ -0,0 +1,113 @@ +--- +root: + items: + - type: stacking-context + bounds: [0, 0, 1000, 1000] + items: + - type: clip + bounds: [ 50, 50, 200, 100 ] + complex: + - rect: [ 50, 50, 200, 100 ] + radius: + top-left: [200, 100] + top-right: [0, 0] + bottom-left: [0, 0] + bottom-right: [0, 0] + items: + - type: rect + bounds: [ 50, 50, 200, 100 ] + color: blue + - type: clip + bounds: [ 50, 150, 200, 100 ] + complex: + - rect: [ 50, 150, 200, 100 ] + radius: + top-left: [0, 0] + top-right: [0, 0] + bottom-left: [200, 100] + bottom-right: [0, 0] + items: + - type: rect + bounds: [ 50, 150, 200, 100 ] + color: blue + + - type: clip + bounds: [ 300, 50, 100, 200 ] + complex: + - rect: [ 300, 50, 100, 200 ] + radius: + top-left: [100, 200] + top-right: [0, 0] + bottom-left: [0, 0] + bottom-right: [0, 0] + items: + - type: rect + bounds: [ 300, 50, 100, 200 ] + color: green + - type: clip + bounds: [ 400, 50, 100, 200 ] + complex: + - rect: [ 400, 50, 100, 200 ] + radius: + top-left: [0, 0] + top-right: [100, 200] + bottom-left: [0, 0] + bottom-right: [0, 0] + items: + - type: rect + bounds: [ 400, 50, 100, 200 ] + color: green + + - type: clip + bounds: [ 50, 300, 200, 100 ] + complex: + - rect: [ 50, 300, 200, 100 ] + radius: + top-left: [0, 0] + top-right: [200, 100] + bottom-left: [0, 0] + bottom-right: [0, 0] + items: + - type: rect + bounds: [ 50, 300, 200, 100 ] + color: red + - type: clip + bounds: [ 50, 400, 200, 100 ] + complex: + - rect: [ 50, 400, 200, 100 ] + radius: + top-left: [0, 0] + top-right: [0, 0] + bottom-left: [0, 0] + bottom-right: [200, 100] + items: + - type: rect + bounds: [ 50, 400, 200, 100 ] + color: red + + - type: clip + bounds: [ 300, 300, 100, 200 ] + complex: + - rect: [ 300, 300, 100, 200 ] + radius: + top-left: [0, 0] + top-right: [0, 0] + bottom-left: [100, 200] + bottom-right: [0, 0] + items: + - type: rect + bounds: [ 300, 300, 100, 200 ] + color: yellow + - type: clip + bounds: [ 400, 300, 100, 200 ] + complex: + - rect: [ 400, 300, 100, 200 ] + radius: + top-left: [0, 0] + top-right: [0, 0] + bottom-left: [0, 0] + bottom-right: [100, 200] + items: + - type: rect + bounds: [ 400, 300, 100, 200 ] + color: yellow diff --git a/gfx/wr/wrench/reftests/clip/clip-corner-overlap.yaml b/gfx/wr/wrench/reftests/clip/clip-corner-overlap.yaml new file mode 100644 index 0000000000..2fa2225652 --- /dev/null +++ b/gfx/wr/wrench/reftests/clip/clip-corner-overlap.yaml @@ -0,0 +1,61 @@ +--- +root: + items: + - type: stacking-context + bounds: [0, 0, 1000, 1000] + items: + - type: clip + bounds: [ 50, 50, 200, 200 ] + complex: + - rect: [ 50, 50, 200, 200 ] + radius: + top-left: [200, 100] + top-right: [0, 0] + bottom-left: [200, 100] + bottom-right: [0, 0] + items: + - type: rect + bounds: [ 50, 50, 200, 200 ] + color: blue + + - type: clip + bounds: [ 300, 50, 200, 200 ] + complex: + - rect: [ 300, 50, 200, 200 ] + radius: + top-left: [100, 200] + top-right: [100, 200] + bottom-left: [0, 0] + bottom-right: [0, 0] + items: + - type: rect + bounds: [ 300, 50, 200, 200 ] + color: green + + - type: clip + bounds: [ 50, 300, 200, 200 ] + complex: + - rect: [ 50, 300, 200, 200 ] + radius: + top-left: [0, 0] + top-right: [200, 100] + bottom-left: [0, 0] + bottom-right: [200, 100] + items: + - type: rect + bounds: [ 50, 300, 200, 200 ] + color: red + + - type: clip + bounds: [ 300, 300, 200, 200 ] + complex: + - rect: [ 300, 300, 200, 200 ] + radius: + top-left: [0, 0] + top-right: [0, 0] + bottom-left: [100, 200] + bottom-right: [100, 200] + items: + - type: rect + bounds: [ 300, 300, 200, 200 ] + color: yellow diff --git a/gfx/wr/wrench/reftests/clip/clip-ellipse.png b/gfx/wr/wrench/reftests/clip/clip-ellipse.png Binary files differnew file mode 100644 index 0000000000..4962482557 --- /dev/null +++ b/gfx/wr/wrench/reftests/clip/clip-ellipse.png diff --git a/gfx/wr/wrench/reftests/clip/clip-ellipse.yaml b/gfx/wr/wrench/reftests/clip/clip-ellipse.yaml new file mode 100644 index 0000000000..e0c93c7985 --- /dev/null +++ b/gfx/wr/wrench/reftests/clip/clip-ellipse.yaml @@ -0,0 +1,63 @@ +--- +root: + items: + - type: rect + bounds: [20, 20, 100, 100] + color: red + complex-clip: + rect: [20, 20, 100, 100] + radius: [32, 16] + + - type: rect + bounds: [130, 20, 100, 100] + color: green + complex-clip: + rect: [130, 20, 100, 100] + radius: [32, 16] + clip-mode: clip-out + + - type: rect + bounds: [20, 130, 100, 100] + color: red + complex-clip: + rect: [20, 130, 100, 100] + radius: [16, 32] + + - type: rect + bounds: [130, 130, 100, 100] + color: green + complex-clip: + rect: [130, 130, 100, 100] + radius: [16, 32] + clip-mode: clip-out + + - type: rect + bounds: [20, 240, 100, 100] + color: red + complex-clip: + rect: [20, 240, 100, 100] + radius: [128, 32] + + - type: rect + bounds: [130, 240, 100, 100] + color: green + complex-clip: + rect: [130, 240, 100, 100] + radius: [128, 32] + clip-mode: clip-out + + - type: rect + bounds: [20, 350, 100, 100] + color: red + complex-clip: + rect: [20, 350, 100, 100] + radius: [32, 128] + + - type: rect + bounds: [130, 350, 100, 100] + color: green + complex-clip: + rect: [130, 350, 100, 100] + radius: [32, 128] + clip-mode: clip-out + diff --git a/gfx/wr/wrench/reftests/clip/clip-empty-inner-rect-ref.yaml b/gfx/wr/wrench/reftests/clip/clip-empty-inner-rect-ref.yaml new file mode 100644 index 0000000000..0dea07f57d --- /dev/null +++ b/gfx/wr/wrench/reftests/clip/clip-empty-inner-rect-ref.yaml @@ -0,0 +1,20 @@ +# In this case, the inner rectangle of the clip is empty, because +# the size is 200 and each corner radius is 100. +# The blue rect should be fully invisible +--- +root: + items: + - + type: "stacking-context" + bounds: [0, 0, 0, 0] + items: + - + type: clip + bounds: [0, 0, 200, 200] + complex: + - rect: [ 0, 0, 200, 200 ] + radius: 100 + items: + - type: rect + bounds: [ 0, 0, 200, 200 ] + color: red diff --git a/gfx/wr/wrench/reftests/clip/clip-empty-inner-rect.yaml b/gfx/wr/wrench/reftests/clip/clip-empty-inner-rect.yaml new file mode 100644 index 0000000000..f8165f90d3 --- /dev/null +++ b/gfx/wr/wrench/reftests/clip/clip-empty-inner-rect.yaml @@ -0,0 +1,28 @@ +# In this case, the inner rectangle of the clip is empty, because +# the size is 200 and each corner radius is 100. +# The blue rect should be fully invisible +--- +root: + items: + - + type: "stacking-context" + bounds: [0, 0, 0, 0] + items: + - + type: clip + bounds: [0, 0, 200, 200] + complex: + - rect: [ 0, 0, 200, 200 ] + radius: 100 + items: + - type: rect + bounds: [ 0, 0, 200, 200 ] + color: red + - type: "stacking-context" + bounds: [0, 0, 0, 0] + transform: translate(0, 0, 1) + items: + - + type: rect + bounds: [0, 0, 25, 25] + color: blue diff --git a/gfx/wr/wrench/reftests/clip/clip-mode.png b/gfx/wr/wrench/reftests/clip/clip-mode.png Binary files differnew file mode 100644 index 0000000000..69f2b8b4ae --- /dev/null +++ b/gfx/wr/wrench/reftests/clip/clip-mode.png diff --git a/gfx/wr/wrench/reftests/clip/clip-mode.yaml b/gfx/wr/wrench/reftests/clip/clip-mode.yaml new file mode 100644 index 0000000000..9c10cfdb3d --- /dev/null +++ b/gfx/wr/wrench/reftests/clip/clip-mode.yaml @@ -0,0 +1,17 @@ +--- +root: + items: + - type: rect + bounds: [20, 20, 100, 100] + color: red + complex-clip: + rect: [20, 20, 100, 100] + radius: 32 + + - type: rect + bounds: [130, 20, 100, 100] + color: green + complex-clip: + rect: [130, 20, 100, 100] + radius: 32 + clip-mode: clip-out diff --git a/gfx/wr/wrench/reftests/clip/clip-out-rotation.yaml b/gfx/wr/wrench/reftests/clip/clip-out-rotation.yaml new file mode 100644 index 0000000000..43d4aa3697 --- /dev/null +++ b/gfx/wr/wrench/reftests/clip/clip-out-rotation.yaml @@ -0,0 +1,41 @@ +# Test that transformed content is clipped out properly by clips with a different transform. +# Also verifies that we aren't trying to render the clip mask at all for this clip-out case. +# +# The clip is a 500x500 rounded cornered rectangle rotated by 15 degrees. It fully contains the +# bounds of the red rect and has a clip-out mode (within the conservative logic of our +# `project_inner_rect` transformation), so nothing is visible, and no mask is rendered. +--- +root: + items: + - + bounds: [0, 0, 0, 0] + type: "reference-frame" + id: 2 + - + bounds: [0, 0, 0, 0] + type: "stacking-context" + transform: rotate(-15) translate(200, 0) + items: + - + bounds: [0, 0, 1000, 1000] + type: clip + id: 5 + complex: + - + rect: [0, 0, 500, 500] + radius: [5, 5] + clip-mode: clip-out + # uncomment this to see the clip area + #- + # bounds: [0, 0, 500, 500] + # type: rect + # color: green + - + bounds: [0, 0, 0, 0] + type: "stacking-context" + clip-and-scroll: [2, 5] + items: + - + bounds: [225, 150, 300, 300] + type: rect + color: red diff --git a/gfx/wr/wrench/reftests/clip/clip-thin-rotated-ref.yaml b/gfx/wr/wrench/reftests/clip/clip-thin-rotated-ref.yaml new file mode 100644 index 0000000000..e09079424d --- /dev/null +++ b/gfx/wr/wrench/reftests/clip/clip-thin-rotated-ref.yaml @@ -0,0 +1,13 @@ +# Test checks if a rotated clip with a long and thin rectangle would still +# correctly affect the primitive with regards to the inner bounds. +--- +root: + items: + - + bounds: [0, 0, 0, 0] + type: "stacking-context" + items: + - + bounds: [100, 100, 14, 14] + type: rect + color: blue diff --git a/gfx/wr/wrench/reftests/clip/clip-thin-rotated.yaml b/gfx/wr/wrench/reftests/clip/clip-thin-rotated.yaml new file mode 100644 index 0000000000..d0e626af91 --- /dev/null +++ b/gfx/wr/wrench/reftests/clip/clip-thin-rotated.yaml @@ -0,0 +1,41 @@ +# Test checks if a rotated clip with a long and thin rectangle would still +# correctly affect the primitive with regards to the inner bounds. +--- +root: + items: + - + bounds: [0, 0, 0, 0] + type: "reference-frame" + id: 2 + - + bounds: [0, 0, 0, 0] + type: "stacking-context" + transform: rotate(45) translate(200, 0) + items: + - + bounds: [0, 0, 20, 1000] + type: clip + id: 5 + # uncomment this to see the clip area + #- + # bounds: [0, 0, 20, 1000] + # type: rect + # color: green + - # we aren't supposed to see this one + bounds: [0, 0, 0, 0] + type: "stacking-context" + clip-and-scroll: [2, 5] + items: + - + bounds: [120, 120, 10, 10] + type: rect + color: red + - + bounds: [0, 0, 0, 0] + type: "stacking-context" + clip-and-scroll: [2, 5] + items: + - + bounds: [100, 100, 14, 14] + type: rect + color: blue diff --git a/gfx/wr/wrench/reftests/clip/clipped-occlusion-ref.yaml b/gfx/wr/wrench/reftests/clip/clipped-occlusion-ref.yaml new file mode 100644 index 0000000000..69a5fb0624 --- /dev/null +++ b/gfx/wr/wrench/reftests/clip/clipped-occlusion-ref.yaml @@ -0,0 +1,7 @@ +--- +root: + items: + - + type: rect + bounds: [0, 0, 500, 500] + color: red diff --git a/gfx/wr/wrench/reftests/clip/clipped-occlusion.yaml b/gfx/wr/wrench/reftests/clip/clipped-occlusion.yaml new file mode 100644 index 0000000000..05a055a5a3 --- /dev/null +++ b/gfx/wr/wrench/reftests/clip/clipped-occlusion.yaml @@ -0,0 +1,23 @@ +# This is a regression test for https://bugzilla.mozilla.org/show_bug.cgi?id=1594567 +# The single clip node from the primitive inside the scroll frame will be promoted +# to a 'shared clip' in the picture cache for the scroll frame. Ensure that this clip +# (zero sized in this test) is included in the tile occlusion culling. +--- +root: + items: + - + type: rect + bounds: [0, 0, 500, 500] + color: red + - + type: scroll-frame + content-size: [1000, 10000] + bounds: [0, -5000, 1000, 10000] + items: + - type: clip + bounds: [0, 0, 0, 0] + items: + - + bounds: [0, -5000, 1000, 10000] + type: rect + color: green diff --git a/gfx/wr/wrench/reftests/clip/custom-clip-chain-node-ancestors-ref.yaml b/gfx/wr/wrench/reftests/clip/custom-clip-chain-node-ancestors-ref.yaml new file mode 100644 index 0000000000..c84fe7a612 --- /dev/null +++ b/gfx/wr/wrench/reftests/clip/custom-clip-chain-node-ancestors-ref.yaml @@ -0,0 +1,9 @@ +--- +root: + items: + - + bounds: [10, 10, 100, 100] + "clip-rect": [10, 10, 100, 100] + "backface-visible": true + type: rect + color: 0 255 0 1 diff --git a/gfx/wr/wrench/reftests/clip/custom-clip-chain-node-ancestors.yaml b/gfx/wr/wrench/reftests/clip/custom-clip-chain-node-ancestors.yaml new file mode 100644 index 0000000000..9824da4f9c --- /dev/null +++ b/gfx/wr/wrench/reftests/clip/custom-clip-chain-node-ancestors.yaml @@ -0,0 +1,32 @@ +# This test ensures that custom clip chains are not affected by the ancestors +# of their clipping nodes. In this case the node, 3, will probably be optimized +# away since its ancestor 2 has a tighter bounding rect. On the other hand, a +# clip chain which includes 3 should only get the rectangle specified by that +# node and not be affected by 2 at all. +--- +root: + items: + - + bounds: [25, 25, 50, 50] + "clip-rect": [25, 25, 50, 50] + type: clip + id: 2 + - + bounds: [10, 10, 100, 100] + clip-rect: [10, 10, 100, 100] + clip-and-scroll: 2 + type: clip + id: 3 + "content-size": [800, 1000] + - + bounds: [0, 0, 0, 0] + clip-rect: [0, 0, 0, 0] + type: "clip-chain" + id: 10 + clips: [3] + - + bounds: [0, 0, 200, 200] + clip-rect: [0, 0, 200, 200] + clip-and-scroll: [root-scroll-node, 10] + type: rect + color: 0 255 0 1 diff --git a/gfx/wr/wrench/reftests/clip/custom-clip-chains-ref.yaml b/gfx/wr/wrench/reftests/clip/custom-clip-chains-ref.yaml new file mode 100644 index 0000000000..e30bcfd2a4 --- /dev/null +++ b/gfx/wr/wrench/reftests/clip/custom-clip-chains-ref.yaml @@ -0,0 +1,17 @@ +root: + items: + - type: clip + id: 2 + bounds: [0, 0, 200, 200] + complex: + - rect: [0, 0, 200, 200] + radius: { + top-left: 20, + top-right: 20, + bottom-left: 20, + bottom-right: 20, + } + items: + - type: rect + bounds: [0, 0, 200, 200] + color: green diff --git a/gfx/wr/wrench/reftests/clip/custom-clip-chains.yaml b/gfx/wr/wrench/reftests/clip/custom-clip-chains.yaml new file mode 100644 index 0000000000..62e2fde8c5 --- /dev/null +++ b/gfx/wr/wrench/reftests/clip/custom-clip-chains.yaml @@ -0,0 +1,62 @@ +# This tests a clip chain (clipid=6) that is composed of two clips (clipid=3 +# and clipid=4) with a parent clip chain (composed of two more clips (clipid=1 +# and clipid=2). This effectively tests a "complex" clip chain that includes +# and is applied to multiple non-hierarchical reference frames as well as +# having a similarly complicated parent. Each clip is a rounded corner which, +# when rotated, clips a box with all corners rounded. +root: + items: + - + bounds: [0, 0, 200, 200] + type: stacking-context + transform: rotate(180) + items: + - type: clip + id: 10 + bounds: [0, 0, 200, 200] + complex: + - rect: [0, 0, 200, 200] + radius: { + top-left: 20, + } + - type: clip + id: 2 + bounds: [0, 0, 200, 200] + complex: + - rect: [0, 0, 200, 200] + radius: { + top-right: 20, + } + - + bounds: [0, 0, 200, 200] + type: stacking-context + transform: rotate(-90) + items: + - type: clip + id: 3 + bounds: [0, 0, 200, 200] + complex: + - rect: [0, 0, 200, 200] + radius: { + bottom-left: 20, + } + - type: clip + id: 4 + bounds: [0, 0, 200, 200] + complex: + - rect: [0, 0, 200, 200] + radius: { + top-left: 20, + } + + - type: clip-chain + id: 5 + clips: [10, 2] + - type: clip-chain + id: 6 + parent: 5 + clips: [3, 4] + - type: rect + bounds: [0, 0, 200, 200] + color: green + clip-and-scroll: [root-scroll-node, 6] diff --git a/gfx/wr/wrench/reftests/clip/fixed-position-clipping-ref.yaml b/gfx/wr/wrench/reftests/clip/fixed-position-clipping-ref.yaml new file mode 100644 index 0000000000..abbc91f897 --- /dev/null +++ b/gfx/wr/wrench/reftests/clip/fixed-position-clipping-ref.yaml @@ -0,0 +1,15 @@ +--- +root: + items: + - + bounds: [10, 10, 100, 100] + clip-rect: [10, 10, 100, 100] + type: rect + color: 0 255 0 1.0 + - + bounds: [110, 10, 100, 100] + clip-rect: [110, 10, 100, 100] + type: rect + color: 0 255 0 1.0 + id: [0, 1] +pipelines: [] diff --git a/gfx/wr/wrench/reftests/clip/fixed-position-clipping.yaml b/gfx/wr/wrench/reftests/clip/fixed-position-clipping.yaml new file mode 100644 index 0000000000..8eaa388710 --- /dev/null +++ b/gfx/wr/wrench/reftests/clip/fixed-position-clipping.yaml @@ -0,0 +1,49 @@ +# This test ensures that children of fixed position stacking contexts are not +# clipped by parent clipping nodes. The contents of the fixed position stacking +# contexts below should not be clipped by their parent clipping nodes, but +# instead should be promoted to be children of the top-level reference frame. +--- +root: + items: + - + clip-rect: [15, 15, 30, 30] + type: scroll-frame + content-size: [60, 60] + bounds: [15, 15, 30, 30] + items: + - + bounds: [10, 10, 100, 100] + clip-rect: [10, 10, 100, 100] + clip-and-scroll: root-reference-frame + type: stacking-context + items: + - + bounds: [0, 0, 100, 100] + clip-rect: [0, 0, 100, 100] + clip-and-scroll: root-reference-frame + type: rect + color: 0 255 0 1.0 + # The same test as above, except this time the stacking context also starts its + # own reference frame. + - + clip-rect: [115, 15, 30, 30] + type: scroll-frame + content-size: [60, 60] + bounds: [115, 15, 30, 30] + items: + - + bounds: [110, 10, 100, 100] + clip-rect: [110, 10, 100, 100] + clip-and-scroll: root-reference-frame + id: 4 + type: stacking-context + transform: [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1] + items: + - + bounds: [0, 0, 100, 100] + clip-rect: [0, 0, 100, 100] + clip-and-scroll: 4 + type: rect + color: 0 255 0 1.0 + id: [0, 1] +pipelines: [] diff --git a/gfx/wr/wrench/reftests/clip/iframe-nested-in-stacking-context-ref.yaml b/gfx/wr/wrench/reftests/clip/iframe-nested-in-stacking-context-ref.yaml new file mode 100644 index 0000000000..c8f3148ea5 --- /dev/null +++ b/gfx/wr/wrench/reftests/clip/iframe-nested-in-stacking-context-ref.yaml @@ -0,0 +1,6 @@ +--- +root: + items: + - type: rect + bounds: [50, 50, 50, 100] + color: red diff --git a/gfx/wr/wrench/reftests/clip/iframe-nested-in-stacking-context.yaml b/gfx/wr/wrench/reftests/clip/iframe-nested-in-stacking-context.yaml new file mode 100644 index 0000000000..5976ccd511 --- /dev/null +++ b/gfx/wr/wrench/reftests/clip/iframe-nested-in-stacking-context.yaml @@ -0,0 +1,23 @@ +# Ensure that a stacking context with a simple clip that encloses +# an iframe correctly propagates the stacking context clip to the +# clip on the iframe. +--- +root: + items: + - type: clip + id: 2 + bounds: [50, 50, 50, 100] + - type: stacking-context + bounds: [50, 50, 100, 100] + clip-node: 2 + items: + - type: iframe + id: [1, 3] + bounds: [0, 0, 100, 100] +pipelines: + - + id: [1, 3] + items: + - type: rect + color: red + bounds: [0, 0, 100, 100] diff --git a/gfx/wr/wrench/reftests/clip/reftest.list b/gfx/wr/wrench/reftests/clip/reftest.list new file mode 100644 index 0000000000..7f6cb1025b --- /dev/null +++ b/gfx/wr/wrench/reftests/clip/reftest.list @@ -0,0 +1,18 @@ + platform(linux,mac) == border-with-rounded-clip.yaml border-with-rounded-clip.png +== clip-mode.yaml clip-mode.png +== clip-ellipse.yaml clip-ellipse.png +platform(linux,mac) == clip-45-degree-rotation.yaml clip-45-degree-rotation-ref.png +== clip-3d-transform.yaml clip-3d-transform-ref.yaml +fuzzy(1,4) == clip-corner-overlap.yaml clip-corner-overlap-ref.yaml +fuzzy(9,60) == custom-clip-chains.yaml custom-clip-chains-ref.yaml +== custom-clip-chain-node-ancestors.yaml custom-clip-chain-node-ancestors-ref.yaml +== fixed-position-clipping.yaml fixed-position-clipping-ref.yaml +platform(linux,mac) == segmentation-with-other-coordinate-system-clip.yaml segmentation-with-other-coordinate-system-clip.png +== segmentation-across-rotation.yaml segmentation-across-rotation-ref.yaml +skip_on(android,device) == color_targets(3) alpha_targets(1) stacking-context-clip.yaml stacking-context-clip-ref.yaml +== snapping.yaml snapping-ref.yaml +fuzzy(70,2400) == clip-and-filter-with-rotation.yaml clip-and-filter-with-rotation-ref.yaml +color_targets(1) alpha_targets(0) == clip-out-rotation.yaml blank.yaml # Unexpected color targets, see bug 1580795 +== clipped-occlusion.yaml clipped-occlusion-ref.yaml +== clip-empty-inner-rect.yaml clip-empty-inner-rect-ref.yaml +== iframe-nested-in-stacking-context.yaml iframe-nested-in-stacking-context-ref.yaml diff --git a/gfx/wr/wrench/reftests/clip/segmentation-across-rotation-ref.yaml b/gfx/wr/wrench/reftests/clip/segmentation-across-rotation-ref.yaml new file mode 100644 index 0000000000..6d14bab91c --- /dev/null +++ b/gfx/wr/wrench/reftests/clip/segmentation-across-rotation-ref.yaml @@ -0,0 +1,6 @@ +--- +root: + items: + - type: rect + color: [0, 255, 0, 1] + bounds: [100, 100, 100, 100] diff --git a/gfx/wr/wrench/reftests/clip/segmentation-across-rotation.yaml b/gfx/wr/wrench/reftests/clip/segmentation-across-rotation.yaml new file mode 100644 index 0000000000..c90cf79e4e --- /dev/null +++ b/gfx/wr/wrench/reftests/clip/segmentation-across-rotation.yaml @@ -0,0 +1,30 @@ +# This test ensures that a clip that is segmented, with segments +# that have no intersection with the world-space outer bounds of +# the clip rectangle render correctly. In this case the first clip +# defines the outer bounds of the clip rectangle and the rotation +# ensures that the inner clip isn't optimized away completely. The +# segments of the rounded corner clip don't have any intersection at +# all with the clip in area from the outer clip, so they shouldn't +# affect the rendering of the green square. +--- +root: + items: + - type: clip + bounds: [100, 100, 100, 100] + id: 2 + - + type: stacking-context + clip-and-scroll: 2 + transform: rotate(0.25) + items: + - type: clip + bounds: [0, 0, 2400, 900] + id: 3 + complex: + - rect: [ 0, 0, 2400, 900 ] + radius: 50 + - type: rect + color: [0, 255, 0, 1] + bounds: [0, 0, 2400, 900] + clip-and-scroll: 3 + diff --git a/gfx/wr/wrench/reftests/clip/segmentation-with-other-coordinate-system-clip-ref.yaml b/gfx/wr/wrench/reftests/clip/segmentation-with-other-coordinate-system-clip-ref.yaml new file mode 100644 index 0000000000..8627d2ed74 --- /dev/null +++ b/gfx/wr/wrench/reftests/clip/segmentation-with-other-coordinate-system-clip-ref.yaml @@ -0,0 +1,8 @@ +--- +root: + items: + - + type: rect + color: green + bounds: [0, 0, 100, 100] + "clip-rect": [0, 0, 100, 100] diff --git a/gfx/wr/wrench/reftests/clip/segmentation-with-other-coordinate-system-clip.png b/gfx/wr/wrench/reftests/clip/segmentation-with-other-coordinate-system-clip.png Binary files differnew file mode 100644 index 0000000000..67507a2573 --- /dev/null +++ b/gfx/wr/wrench/reftests/clip/segmentation-with-other-coordinate-system-clip.png diff --git a/gfx/wr/wrench/reftests/clip/segmentation-with-other-coordinate-system-clip.yaml b/gfx/wr/wrench/reftests/clip/segmentation-with-other-coordinate-system-clip.yaml new file mode 100644 index 0000000000..db98da3a3e --- /dev/null +++ b/gfx/wr/wrench/reftests/clip/segmentation-with-other-coordinate-system-clip.yaml @@ -0,0 +1,47 @@ +# This is testing whether a clip properly clips a primitive in another +# coordinate system that is segmented. +# See https://github.com/servo/webrender/issues/2294 +--- +root: + items: + - + type: "stacking-context" + items: + - + bounds: [0, 0, 100, 100] + "clip-rect": [0, 0, 100, 100] + type: clip + items: + - + type: "stacking-context" + transform: [0.98883086, 0.14904226, 0, 0, -0.14904226, 0.98883086, 0, 0, 0, 0, 1, 0, 1533.3134, 109.21605, 0, 1] + items: + - + type: "stacking-context" + transform: [0.7818315, 0.6234898, 0, 0, -0.6234898, 0.7818315, 0, 0, 0, 0, 1, 0, 132.98201, -64.04077, 0, 1] + items: + - + type: "stacking-context" + transform: [0.93087375, 0.36534107, 0, 0, -0.36534107, 0.93087375, 0, 0, 0, 0, 1, 0, 68.64584, -46.80194, 0, 1] + items: + - + type: "stacking-context" + transform: [0.8262389, 0.56332004, 0, 0, -0.56332004, 0.8262389, 0, 0, 0, 0, 1, 0, 116.458824, -61.550323, 0, 1] + items: + - + type: "stacking-context" + transform: [0.90096885, 0.43388373, 0, 0, -0.43388373, 0.90096885, 0, 0, 0, 0, 1, 0, 84.200554, -52.906708, 0, 1] + items: + - + type: "stacking-context" + transform: [0.98883086, 0.14904226, 0, 0, -0.14904226, 0.98883086, 0, 0, 0, 0, 1, 0, 25.3134, -21.78395, 0, 1] + items: + - + type: "stacking-context" + transform: [0.73305184, 0.68017274, 0, 0, -0.68017274, 0.73305184, 0, 0, 0, 0, 1, 0, 149.64511, -65.28949, 0, 1] + items: + - + bounds: [1000, 0, 1000, 1000] + "clip-rect": [1000, 0, 1000, 1000] + type: rect + color: green diff --git a/gfx/wr/wrench/reftests/clip/snapping-ref.yaml b/gfx/wr/wrench/reftests/clip/snapping-ref.yaml new file mode 100644 index 0000000000..7be527df93 --- /dev/null +++ b/gfx/wr/wrench/reftests/clip/snapping-ref.yaml @@ -0,0 +1,17 @@ +--- +root: + items: + - type: clip + bounds: [0, 0, 1000, 1000] + complex: + - rect: [50, 50, 100, 100] + radius: 16 + items: + - type: rect + bounds: 50 50 100 100 + color: red + + - type: rect + bounds: 200 50 100 100 + color: green + diff --git a/gfx/wr/wrench/reftests/clip/snapping.yaml b/gfx/wr/wrench/reftests/clip/snapping.yaml new file mode 100644 index 0000000000..d2ad449ea9 --- /dev/null +++ b/gfx/wr/wrench/reftests/clip/snapping.yaml @@ -0,0 +1,17 @@ +--- +root: + items: + - type: clip + bounds: [0, 0, 1000, 1000] + complex: + - rect: [50.3, 50.3, 100, 100] + radius: 16 + items: + - type: rect + bounds: 50.3 50.3 100 100 + color: red + + - type: rect + bounds: 200.3 50.3 100 100 + color: green + diff --git a/gfx/wr/wrench/reftests/clip/stacking-context-clip-ref.yaml b/gfx/wr/wrench/reftests/clip/stacking-context-clip-ref.yaml new file mode 100644 index 0000000000..50fb8facd4 --- /dev/null +++ b/gfx/wr/wrench/reftests/clip/stacking-context-clip-ref.yaml @@ -0,0 +1,32 @@ +--- +root: + items: + - type: clip + id: 2 + bounds: [0, 0, 100, 100] + complex: + - rect: [0, 0, 100, 100] + radius: { + top-left: 50, + top-right: 50, + bottom-left: 50, + bottom-right: 50, + } + - type: stacking-context + bounds: [0, 0, 100, 100] + items: + - type: rect + bounds: [ 0, 0, 100, 100 ] + color: [0, 255, 0] + clip-and-scroll: 2 + - type: clip + id: 3 + bounds: [120, 0, 50, 50] + - type: stacking-context + bounds: [100, 0, 100, 100] + filters: hue-rotate(90) + items: + - type: rect + bounds: [ 0, 0, 100, 100 ] + color: [0, 255, 0] + clip-and-scroll: 3 diff --git a/gfx/wr/wrench/reftests/clip/stacking-context-clip.yaml b/gfx/wr/wrench/reftests/clip/stacking-context-clip.yaml new file mode 100644 index 0000000000..5516b65539 --- /dev/null +++ b/gfx/wr/wrench/reftests/clip/stacking-context-clip.yaml @@ -0,0 +1,36 @@ +--- +root: + items: + - type: clip + id: 2 + bounds: [0, 0, 100, 100] + complex: + - rect: [0, 0, 100, 100] + radius: { + top-left: 50, + top-right: 50, + bottom-left: 50, + bottom-right: 50, + } + - type: stacking-context + bounds: [0, 0, 100, 100] + clip-node: 2 + items: + - type: rect + bounds: [ 0, 0, 100, 100 ] + color: [0, 255, 0] + # The same test, but this time with hue rotation, which means that the stacking + # context is rendered to an intermediate surface first. Unfortunately, we cannot + # use a rounded clip here because we want to avoid subpixel differences and avoid + # relying on a PNG reference image. + - type: clip + id: 3 + bounds: [120, 0, 50, 50] + - type: stacking-context + bounds: [100, 0, 100, 100] + filters: hue-rotate(90) + clip-node: 3 + items: + - type: rect + bounds: [ 0, 0, 100, 100 ] + color: [0, 255, 0] diff --git a/gfx/wr/wrench/reftests/filters/backdrop-filter-basic-ref.yaml b/gfx/wr/wrench/reftests/filters/backdrop-filter-basic-ref.yaml new file mode 100644 index 0000000000..aec471df21 --- /dev/null +++ b/gfx/wr/wrench/reftests/filters/backdrop-filter-basic-ref.yaml @@ -0,0 +1,11 @@ + +# Tests that a basic invert backdrop-filter works +--- +root: + items: + - type: stacking-context + bounds: 0 0 0 0 + items: + - type: rect + color: [0, 255, 255, 1] + bounds: 0 0 256 256 diff --git a/gfx/wr/wrench/reftests/filters/backdrop-filter-basic.yaml b/gfx/wr/wrench/reftests/filters/backdrop-filter-basic.yaml new file mode 100644 index 0000000000..837d403978 --- /dev/null +++ b/gfx/wr/wrench/reftests/filters/backdrop-filter-basic.yaml @@ -0,0 +1,22 @@ +# Tests that a basic invert backdrop-filter works +--- +root: + items: + - type: stacking-context + backdrop-root: true + bounds: 0 0 0 0 + items: + - type: rect + color: [255, 0, 0, 1] + bounds: 0 0 256 256 + - type: clip + id: 2 + bounds: 0 0 256 256 + clip-rect: 0 0 256 256 + - type: stacking-context + bounds: 0 0 0 0 + items: + - type: backdrop-filter + bounds: 0 0 256 256 + clip-node: 2 + filters: invert(1) diff --git a/gfx/wr/wrench/reftests/filters/backdrop-filter-perspective.png b/gfx/wr/wrench/reftests/filters/backdrop-filter-perspective.png Binary files differnew file mode 100644 index 0000000000..c49abf6b96 --- /dev/null +++ b/gfx/wr/wrench/reftests/filters/backdrop-filter-perspective.png diff --git a/gfx/wr/wrench/reftests/filters/backdrop-filter-perspective.yaml b/gfx/wr/wrench/reftests/filters/backdrop-filter-perspective.yaml new file mode 100644 index 0000000000..ca834e5ff7 --- /dev/null +++ b/gfx/wr/wrench/reftests/filters/backdrop-filter-perspective.yaml @@ -0,0 +1,29 @@ +# Tests that backdrop filter works with a perspective transform +--- +root: + items: + - type: stacking-context + bounds: 0 0 0 0 + backdrop-root: true + perspective: 500 + items: + - type: rect + color: [255, 255, 255, 1] + bounds: 0 0 1024 1024 + - image: "firefox.png" + bounds: 0 0 256 256 + - type: stacking-context + bounds: 50 50 0 0 + transform: ["rotate-y(-50)", "rotate-z(-45)"] + items: + - type: clip + id: 2 + bounds: 0 0 100 100 + clip-rect: 0 0 100 100 + - type: stacking-context + bounds: 0 0 0 0 + items: + - type: backdrop-filter + bounds: 0 0 100 100 + clip-and-scroll: 2 + filters: invert(1) diff --git a/gfx/wr/wrench/reftests/filters/blank.yaml b/gfx/wr/wrench/reftests/filters/blank.yaml new file mode 100644 index 0000000000..c4eb3ab673 --- /dev/null +++ b/gfx/wr/wrench/reftests/filters/blank.yaml @@ -0,0 +1,2 @@ +--- +root: diff --git a/gfx/wr/wrench/reftests/filters/blend-clipped.png b/gfx/wr/wrench/reftests/filters/blend-clipped.png Binary files differnew file mode 100644 index 0000000000..5d942f673a --- /dev/null +++ b/gfx/wr/wrench/reftests/filters/blend-clipped.png diff --git a/gfx/wr/wrench/reftests/filters/blend-clipped.yaml b/gfx/wr/wrench/reftests/filters/blend-clipped.yaml new file mode 100644 index 0000000000..2fdb4ad51c --- /dev/null +++ b/gfx/wr/wrench/reftests/filters/blend-clipped.yaml @@ -0,0 +1,105 @@ +--- +root: + items: + - + type: "stacking-context" + items: + - + bounds: [0, 0, 1887, 2081] + "clip-rect": [0, 0, 1887, 2081] + "backface-visible": true + type: clip + id: 2 + "content-size": [1887, 2081] + - + bounds: [0, 111, 1887, 1970] + "clip-rect": [0, 111, 1887, 1970] + "backface-visible": true + type: clip + id: 3 + "content-size": [1887, 1970] + - + bounds: [0, 111, 1887, 1971] + "clip-rect": [0, 111, 1887, 1971] + "clip-and-scroll": 3 + "backface-visible": true + type: iframe + id: [1, 3] + id: [1, 1] +pipelines: + - + id: [1, 3] + items: + - + type: "stacking-context" + items: + - + bounds: [0, 0, 1887, 1971] + "clip-rect": [0, 0, 1887, 1971] + type: clip + id: 10 + "content-size": [1887, 1971] + - + "clip-rect": [0, 0, 1887, 1971] + "clip-and-scroll": 10 + type: "scroll-frame" + id: 2 + "content-size": [1887, 1971] + bounds: [0, 0, 1887, 1971] + - + bounds: [0, 0, 1887, 1971] + "clip-rect": [0, 0, 1887, 1971] + "clip-and-scroll": 2 + type: clip + id: 3 + "content-size": [1887, 1971] + - + "clip-and-scroll": 3 + type: "stacking-context" + items: + - + bounds: [0, -186, 1887, 239] + "clip-rect": [0, -186, 1887, 239] + "clip-and-scroll": 3 + "backface-visible": true + type: clip + id: 4 + "content-size": [1887, 239] + - + bounds: [-660.45, -186, 0, 0] + "clip-rect": [-660.45, -186, 0, 0] + "clip-and-scroll": 4 + type: "stacking-context" + transform: [1, 0, 0, 0, -0.57735026, 1, 0, 0, 0, 0, 1, 0, 68.849, 0, 0, 1] + items: + - + type: "stacking-context" + filters: + - opacity(0.8) + items: + - + bounds: [0, 0, 1887, 239] + "clip-rect": [0, 0, 1887, 239] + type: clip + id: 5 + "content-size": [1887, 239] + - + bounds: [0, 0, 1887, 239] + "clip-rect": [0, 0, 1887, 239] + "clip-and-scroll": 5 + "backface-visible": true + type: gradient + start: [943.5, -0.00000000000005684342] + end: [943.5, 238.5] + "tile-size": [1887, 238.5] + "tile-spacing": [0, 0] + stops: + - 0 + - 0 153 204.00002 1.0000 + - 0.3 + - 0 153 204.00002 1.0000 + - 0.6 + - 7.0000005 137 194.00002 1.0000 + - 1 + - 0 91 137 1.0000 + repeat: false diff --git a/gfx/wr/wrench/reftests/filters/filter-blur-clamping-ref.yaml b/gfx/wr/wrench/reftests/filters/filter-blur-clamping-ref.yaml new file mode 100644 index 0000000000..a06489467a --- /dev/null +++ b/gfx/wr/wrench/reftests/filters/filter-blur-clamping-ref.yaml @@ -0,0 +1,18 @@ +# Ensures that blur clamping happens after scale factors are applied +--- +root: + items: + - type: stacking-context + bounds: [100, 100, 300, 300] + filters: blur(100, 100) + items: + - type: rect + bounds: [0, 0, 100, 100] + color: 0 255 0 1.0 + - type: stacking-context + bounds: [400, 100, 300, 300] + filters: blur(50, 50) + items: + - type: rect + bounds: [0, 0, 100, 100] + color: 255 0 0 1.0 diff --git a/gfx/wr/wrench/reftests/filters/filter-blur-clamping.yaml b/gfx/wr/wrench/reftests/filters/filter-blur-clamping.yaml new file mode 100644 index 0000000000..0d81a616ee --- /dev/null +++ b/gfx/wr/wrench/reftests/filters/filter-blur-clamping.yaml @@ -0,0 +1,30 @@ +# Ensures that blur clamping happens after scale factors are applied +--- +root: + items: + - type: stacking-context + bounds: [100, 100, 300, 300] + transform: scale(10) + items: + - type: stacking-context + bounds: [0, 0, 300, 300] + # Blur will be 20 * 10(scale) = 200 and it should then be clamped to 100 + filters: blur(20, 20) + items: + - type: rect + bounds: [0, 0, 10, 10] + color: 0 255 0 1.0 + - type: stacking-context + bounds: [400, 100, 300, 300] + transform: scale(0.1) + items: + - type: stacking-context + bounds: [0, 0, 300, 300] + # Blur should be 500 * 0.1(scale) = 50. This tests to make sure clamping + # does not occur before applying scale factors, otherwise 500 would be + # clamped to 100. + filters: blur(500, 500) + items: + - type: rect + bounds: [0, 0, 1000, 1000] + color: 255 0 0 1.0 diff --git a/gfx/wr/wrench/reftests/filters/filter-blur-huge.yaml b/gfx/wr/wrench/reftests/filters/filter-blur-huge.yaml new file mode 100644 index 0000000000..13a4c72fd8 --- /dev/null +++ b/gfx/wr/wrench/reftests/filters/filter-blur-huge.yaml @@ -0,0 +1,10 @@ +# Don't crash on very large blur radius! +--- +root: + items: + - type: stacking-context + bounds: [10, 10, 260, 260] + filters: blur(1000000, 1000000) + items: + - image: checkerboard(2, 16, 16) + bounds: [10, 10, 260, 260] diff --git a/gfx/wr/wrench/reftests/filters/filter-blur-scaled-ref.yaml b/gfx/wr/wrench/reftests/filters/filter-blur-scaled-ref.yaml new file mode 100644 index 0000000000..6a5f314df0 --- /dev/null +++ b/gfx/wr/wrench/reftests/filters/filter-blur-scaled-ref.yaml @@ -0,0 +1,11 @@ +# Ensure scales from enclosing SCs get applied to blurs +--- +root: + items: + - type: stacking-context + bounds: [0, 0, 500, 500] + filters: blur(10, 10) + items: + - type: rect + bounds: [50, 50, 250, 250] + color: 0 255 0 1.0 diff --git a/gfx/wr/wrench/reftests/filters/filter-blur-scaled-xonly.png b/gfx/wr/wrench/reftests/filters/filter-blur-scaled-xonly.png Binary files differnew file mode 100644 index 0000000000..48f8913752 --- /dev/null +++ b/gfx/wr/wrench/reftests/filters/filter-blur-scaled-xonly.png diff --git a/gfx/wr/wrench/reftests/filters/filter-blur-scaled-xonly.yaml b/gfx/wr/wrench/reftests/filters/filter-blur-scaled-xonly.yaml new file mode 100644 index 0000000000..18a897131d --- /dev/null +++ b/gfx/wr/wrench/reftests/filters/filter-blur-scaled-xonly.yaml @@ -0,0 +1,16 @@ +# Ensure scales from enclosing SCs get applied to blurs. This one +# applies a mixed-dimension scale by scaling the x-axis only. +--- +root: + items: + - type: reference-frame + bounds: [0, 0, 100, 100] + transform: [5, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1] + items: + - type: stacking-context + bounds: [0, 0, 100, 100] + filters: blur(2, 2) + items: + - type: rect + bounds: [10, 10, 50, 50] + color: 0 255 0 1.0 diff --git a/gfx/wr/wrench/reftests/filters/filter-blur-scaled.yaml b/gfx/wr/wrench/reftests/filters/filter-blur-scaled.yaml new file mode 100644 index 0000000000..0e8c9cbff9 --- /dev/null +++ b/gfx/wr/wrench/reftests/filters/filter-blur-scaled.yaml @@ -0,0 +1,15 @@ +# Ensure scales from enclosing SCs get applied to blurs +--- +root: + items: + - type: reference-frame + bounds: [0, 0, 100, 100] + transform: [5, 0, 0, 0, 0, 5, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1] + items: + - type: stacking-context + bounds: [0, 0, 100, 100] + filters: blur(2, 2) + items: + - type: rect + bounds: [10, 10, 50, 50] + color: 0 255 0 1.0 diff --git a/gfx/wr/wrench/reftests/filters/filter-blur.png b/gfx/wr/wrench/reftests/filters/filter-blur.png Binary files differnew file mode 100644 index 0000000000..996e79215e --- /dev/null +++ b/gfx/wr/wrench/reftests/filters/filter-blur.png diff --git a/gfx/wr/wrench/reftests/filters/filter-blur.yaml b/gfx/wr/wrench/reftests/filters/filter-blur.yaml new file mode 100644 index 0000000000..ee915d7bb1 --- /dev/null +++ b/gfx/wr/wrench/reftests/filters/filter-blur.yaml @@ -0,0 +1,9 @@ +--- +root: + items: + - type: stacking-context + bounds: [100, 100, 300, 300] + filters: blur(10, 10) + items: + - image: "firefox.png" + bounds: 20 20 256 256 diff --git a/gfx/wr/wrench/reftests/filters/filter-brightness-2-ref.yaml b/gfx/wr/wrench/reftests/filters/filter-brightness-2-ref.yaml new file mode 100644 index 0000000000..209dfb3cc3 --- /dev/null +++ b/gfx/wr/wrench/reftests/filters/filter-brightness-2-ref.yaml @@ -0,0 +1,9 @@ +--- +root: + items: + - type: stacking-context + bounds: [0, 0, 120, 120] + items: + - type: rect + bounds: [10, 10, 100, 100] + color: [0, 0, 0, 1] diff --git a/gfx/wr/wrench/reftests/filters/filter-brightness-2.yaml b/gfx/wr/wrench/reftests/filters/filter-brightness-2.yaml new file mode 100644 index 0000000000..2bdb20aa1a --- /dev/null +++ b/gfx/wr/wrench/reftests/filters/filter-brightness-2.yaml @@ -0,0 +1,13 @@ +--- +root: + items: + - type: stacking-context + bounds: [0, 0, 120, 120] + items: + - type: stacking-context + bounds: [10, 10, 100, 100] + filters: brightness(0) + items: + - type: rect + bounds: [0, 0, 100, 100] + color: [255, 0, 0, 1] diff --git a/gfx/wr/wrench/reftests/filters/filter-brightness-3-ref.yaml b/gfx/wr/wrench/reftests/filters/filter-brightness-3-ref.yaml new file mode 100644 index 0000000000..3201170182 --- /dev/null +++ b/gfx/wr/wrench/reftests/filters/filter-brightness-3-ref.yaml @@ -0,0 +1,9 @@ +--- +root: + items: + - type: stacking-context + bounds: [0, 0, 120, 120] + items: + - type: rect + bounds: [10, 10, 100, 100] + color: [0, 128, 0, 1] diff --git a/gfx/wr/wrench/reftests/filters/filter-brightness-3.yaml b/gfx/wr/wrench/reftests/filters/filter-brightness-3.yaml new file mode 100644 index 0000000000..8ea1eef5a8 --- /dev/null +++ b/gfx/wr/wrench/reftests/filters/filter-brightness-3.yaml @@ -0,0 +1,13 @@ +--- +root: + items: + - type: stacking-context + bounds: [0, 0, 120, 120] + items: + - type: stacking-context + bounds: [10, 10, 100, 100] + filters: brightness(4) + items: + - type: rect + bounds: [0, 0, 100, 100] + color: [0, 32, 0, 1] diff --git a/gfx/wr/wrench/reftests/filters/filter-brightness-4-ref.yaml b/gfx/wr/wrench/reftests/filters/filter-brightness-4-ref.yaml new file mode 100644 index 0000000000..b300d2a026 --- /dev/null +++ b/gfx/wr/wrench/reftests/filters/filter-brightness-4-ref.yaml @@ -0,0 +1,9 @@ +--- +root: + items: + - type: stacking-context + bounds: [0, 0, 120, 120] + items: + - type: rect + bounds: [10, 10, 100, 100] + color: [0, 64, 0, 1] diff --git a/gfx/wr/wrench/reftests/filters/filter-brightness-4.yaml b/gfx/wr/wrench/reftests/filters/filter-brightness-4.yaml new file mode 100644 index 0000000000..9a15b15895 --- /dev/null +++ b/gfx/wr/wrench/reftests/filters/filter-brightness-4.yaml @@ -0,0 +1,13 @@ +--- +root: + items: + - type: stacking-context + bounds: [0, 0, 120, 120] + items: + - type: stacking-context + bounds: [10, 10, 100, 100] + filters: brightness(0.25) + items: + - type: rect + bounds: [0, 0, 100, 100] + color: [0, 255, 0, 1] diff --git a/gfx/wr/wrench/reftests/filters/filter-brightness-ref.yaml b/gfx/wr/wrench/reftests/filters/filter-brightness-ref.yaml new file mode 100644 index 0000000000..98e1bf419a --- /dev/null +++ b/gfx/wr/wrench/reftests/filters/filter-brightness-ref.yaml @@ -0,0 +1,13 @@ +--- +root: + items: + - type: stacking-context + bounds: [0, 0, 120, 120] + items: + - type: rect + bounds: [0, 0, 120, 120] + color: [0, 0, 0, 1] + + - type: rect + bounds: [10, 10, 100, 100] + color: [64, 64, 64, 1] diff --git a/gfx/wr/wrench/reftests/filters/filter-brightness.yaml b/gfx/wr/wrench/reftests/filters/filter-brightness.yaml new file mode 100644 index 0000000000..65da0e0b25 --- /dev/null +++ b/gfx/wr/wrench/reftests/filters/filter-brightness.yaml @@ -0,0 +1,17 @@ +--- +root: + items: + - type: stacking-context + bounds: [0, 0, 120, 120] + items: + - type: rect + bounds: [0, 0, 120, 120] + color: [0, 0, 0, 1] + + - type: stacking-context + bounds: [10, 10, 100, 100] + filters: brightness(2) + items: + - type: rect + bounds: [0, 0, 100, 100] + color: [255, 255, 255, 0.25] diff --git a/gfx/wr/wrench/reftests/filters/filter-color-matrix-ref.yaml b/gfx/wr/wrench/reftests/filters/filter-color-matrix-ref.yaml new file mode 100644 index 0000000000..2d32e5307b --- /dev/null +++ b/gfx/wr/wrench/reftests/filters/filter-color-matrix-ref.yaml @@ -0,0 +1,21 @@ +--- +root: + items: + - type: stacking-context + bounds: [0, 0, 120, 170] + items: + - type: rect + bounds: [0, 0, 120, 170] + color: [0, 0, 0, 1] + - type: rect + bounds: [10, 10, 50, 50] + color: [100, 175, 136, 1] + - type: rect + bounds: [10, 60, 50, 50] + color: [255, 0, 255, 1] + - type: rect + bounds: [60, 10, 50, 50] + color: [255, 0, 0, 1] + - type: rect + bounds: [10, 110, 50, 50] + color: [0, 0, 128, 1] diff --git a/gfx/wr/wrench/reftests/filters/filter-color-matrix.yaml b/gfx/wr/wrench/reftests/filters/filter-color-matrix.yaml new file mode 100644 index 0000000000..4deb19b779 --- /dev/null +++ b/gfx/wr/wrench/reftests/filters/filter-color-matrix.yaml @@ -0,0 +1,53 @@ +--- +root: + items: + - type: stacking-context + bounds: [0, 0, 120, 170] + items: + - type: rect + bounds: [0, 0, 120, 170] + color: [0, 0, 0, 1] + - type: stacking-context + bounds: [10, 10, 50, 50] + filters: color-matrix( 0.393, 0.686, 0.534, 0, + 0.189, 0.168, 0.131, 0, + 0.349, 0.272, 0, 0, + 0, 0, 0, 1, + 0, 0, 0, 0 ) + items: + - type: rect + bounds: [0, 0, 50, 50] + color: [255, 0, 0, 1] + - type: stacking-context + bounds: [10, 60, 50, 50] + filters: color-matrix( -1, 0, 0, 0, + 0, -1, 0, 0, + 0, 0, -1, 0, + 0, 0, 0, 1, + 1, 1, 1, 0 ) + items: + - type: rect + bounds: [0, 0, 50, 50] + color: [0, 255, 0, 1] + - type: stacking-context + bounds: [60, 10, 50, 50] + filters: color-matrix( 0, 0, 1, 0, + 0, 1, 0, 0, + 1, 0, 0, 0, + 0, 0, 0, 1, + 0, 0, 0, 0 ) + items: + - type: rect + bounds: [0, 0, 50, 50] + color: [0, 0, 255, 1] + - type: stacking-context + bounds: [10, 110, 50, 50] + filters: color-matrix( 1, 0, 0, 0, + 0, 1, 0, 0, + 0, 0, 1, 0.5, + 0, 0, 0, 0, + 0, 0, 0, 0 ) + items: + - type: rect + bounds: [0, 0, 50, 50] + color: [0, 0, 255, 1] diff --git a/gfx/wr/wrench/reftests/filters/filter-component-transfer-ref.yaml b/gfx/wr/wrench/reftests/filters/filter-component-transfer-ref.yaml new file mode 100644 index 0000000000..e578f95b39 --- /dev/null +++ b/gfx/wr/wrench/reftests/filters/filter-component-transfer-ref.yaml @@ -0,0 +1,51 @@ +--- +root: + items: + - type: stacking-context + bounds: [0, 0, 170, 250] + items: + - type: rect + bounds: [0, 0, 50, 50] + color: [255, 0, 255, 1] + - type: rect + bounds: [0, 50, 50, 50] + color: [0, 255, 141, 1] + - type: rect + bounds: [0, 100, 50, 50] + color: [255, 255, 0, 1] + - type: rect + bounds: [0, 150, 50, 50] + color: [191, 128, 128, 1] + - type: rect + bounds: [0, 200, 50, 50] + color: [0, 255, 24, 1] + - type: rect + bounds: [60, 0, 50, 50] + color: [255, 0, 255, 1] + - type: rect + bounds: [60, 50, 50, 50] + color: [255, 255, 255, 1] + - type: rect + bounds: [60, 100, 50, 50] + color: [255, 255, 255, 1] + - type: rect + bounds: [60, 150, 50, 50] + color: [223, 191, 191, 1] + - type: rect + bounds: [60, 200, 50, 50] + color: [191, 255, 197, 1] + - type: rect + bounds: [120, 0, 50, 50] + color: [255, 127, 255, 1] + - type: rect + bounds: [120, 50, 50, 50] + color: [128, 255, 198, 1] + - type: rect + bounds: [120, 100, 50, 50] + color: [255, 255, 255, 1] + - type: rect + bounds: [120, 150, 50, 50] + color: [239, 223, 223, 1] + - type: rect + bounds: [120, 200, 50, 50] + color: [63, 255, 81, 1] diff --git a/gfx/wr/wrench/reftests/filters/filter-component-transfer.yaml b/gfx/wr/wrench/reftests/filters/filter-component-transfer.yaml new file mode 100644 index 0000000000..a573b5587e --- /dev/null +++ b/gfx/wr/wrench/reftests/filters/filter-component-transfer.yaml @@ -0,0 +1,352 @@ +--- +root: + items: + - type: stacking-context + bounds: [0, 0, 170, 250] + items: + - type: stacking-context + bounds: [0, 0, 50, 50] + filters: + - component-transfer + filter-datas: + - - - Identity + - Identity + - Identity + - Identity + - [] + - [] + - [] + - [] + items: + - type: rect + bounds: [0, 0, 50, 50] + color: [255, 0, 255, 1] + - type: stacking-context + bounds: [0, 50, 50, 50] + filters: + - component-transfer + filter-datas: + - - - Table + - Table + - Table + - Identity + - - "1" + - "1" + - "0" + - "0" + - - "0" + - "0" + - "1" + - "1" + - - "0" + - "1" + - "1" + - "0" + - [] + items: + - type: rect + bounds: [0, 0, 50, 50] + color: [173, 255, 47, 1] + - type: stacking-context + bounds: [0, 100, 50, 50] + filters: + - component-transfer + filter-datas: + - - - Discrete + - Discrete + - Discrete + - Identity + - - "1" + - "1" + - "0" + - "0" + - - "0" + - "0" + - "1" + - "1" + - - "0" + - "1" + - "1" + - "0" + - [] + items: + - type: rect + bounds: [0, 0, 50, 50] + color: [0, 255, 255, 1] + - type: stacking-context + bounds: [0, 150, 50, 50] + filters: + - component-transfer + filter-datas: + - - - Linear + - Linear + - Linear + - Identity + - - "0.5" + - "0.25" + - - "0.5" + - "0" + - - "0.5" + - "0.5" + - [] + items: + - type: rect + bounds: [0, 0, 50, 50] + color: [255, 255, 0, 1] + - type: stacking-context + bounds: [0, 200, 50, 50] + filters: + - component-transfer + filter-datas: + - - - Gamma + - Gamma + - Gamma + - Identity + - - "2" + - "5" + - "-1" + - - "2" + - "3" + - "0" + - - "2" + - "1" + - "-1.75" + - [] + items: + - type: rect + bounds: [0, 0, 50, 50] + color: [135, 206, 235, 1] + - type: stacking-context + bounds: [60, 0, 50, 50] + filters: + - component-transfer + filter-datas: + - - - Identity + - Identity + - Identity + - Identity + - [] + - [] + - [] + - [] + items: + - type: rect + bounds: [0, 0, 50, 50] + color: [255, 0, 255, 1] + - type: stacking-context + bounds: [60, 50, 50, 50] + filters: + - component-transfer + filter-datas: + - - - Table + - Table + - Table + - Table + - - "1" + - "1" + - "0" + - "0" + - - "0" + - "0" + - "1" + - "1" + - - "0" + - "1" + - "1" + - "0" + - - "1" + - "0" + items: + - type: rect + bounds: [0, 0, 50, 50] + color: [173, 255, 47, 1] + - type: stacking-context + bounds: [60, 100, 50, 50] + filters: + - component-transfer + filter-datas: + - - - Discrete + - Discrete + - Discrete + - Discrete + - - "1" + - "1" + - "0" + - "0" + - - "0" + - "0" + - "1" + - "1" + - - "0" + - "1" + - "1" + - "0" + - - "1" + - "0" + items: + - type: rect + bounds: [0, 0, 50, 50] + color: [0, 255, 255, 1] + - type: stacking-context + bounds: [60, 150, 50, 50] + filters: + - component-transfer + filter-datas: + - - - Linear + - Linear + - Linear + - Linear + - - "0.5" + - "0.25" + - - "0.5" + - "0" + - - "0.5" + - "0.5" + - - "0.5" + - "0" + items: + - type: rect + bounds: [0, 0, 50, 50] + color: [255, 255, 0, 1] + - type: stacking-context + bounds: [60, 200, 50, 50] + filters: + - component-transfer + filter-datas: + - - - Gamma + - Gamma + - Gamma + - Gamma + - - "2" + - "5" + - "-1" + - - "2" + - "3" + - "0" + - - "2" + - "1" + - "-1.75" + - - "2" + - "1" + - "-1.75" + items: + - type: rect + bounds: [0, 0, 50, 50] + color: [135, 206, 235, 1] + - type: stacking-context + bounds: [120, 0, 50, 50] + filters: + - component-transfer + filter-datas: + - - - Identity + - Identity + - Identity + - Identity + - [] + - [] + - [] + - [] + items: + - type: rect + bounds: [0, 0, 50, 50] + color: [255, 0, 255, 0.5] + - type: stacking-context + bounds: [120, 50, 50, 50] + filters: + - component-transfer + filter-datas: + - - - Table + - Table + - Table + - Table + - - "1" + - "1" + - "0" + - "0" + - - "0" + - "0" + - "1" + - "1" + - - "0" + - "1" + - "1" + - "0" + - - "1" + - "0" + items: + - type: rect + bounds: [0, 0, 50, 50] + color: [173, 255, 47, 0.5] + - type: stacking-context + bounds: [120, 100, 50, 50] + filters: + - component-transfer + filter-datas: + - - - Discrete + - Discrete + - Discrete + - Discrete + - - "1" + - "1" + - "0" + - "0" + - - "0" + - "0" + - "1" + - "1" + - - "0" + - "1" + - "1" + - "0" + - - "1" + - "0" + items: + - type: rect + bounds: [0, 0, 50, 50] + color: [0, 255, 255, 0.5] + - type: stacking-context + bounds: [120, 150, 50, 50] + filters: + - component-transfer + filter-datas: + - - - Linear + - Linear + - Linear + - Linear + - - "0.5" + - "0.25" + - - "0.5" + - "0" + - - "0.5" + - "0.5" + - - "0.5" + - "0" + items: + - type: rect + bounds: [0, 0, 50, 50] + color: [255, 255, 0, 0.5] + - type: stacking-context + bounds: [120, 200, 50, 50] + filters: + - component-transfer + filter-datas: + - - - Gamma + - Gamma + - Gamma + - Gamma + - - "2" + - "5" + - "-1" + - - "2" + - "3" + - "0" + - - "2" + - "1" + - "-1.75" + - - "2" + - "1" + - "-0.25" + items: + - type: rect + bounds: [0, 0, 50, 50] + color: [135, 206, 235, 0.5] diff --git a/gfx/wr/wrench/reftests/filters/filter-contrast-gray-alpha-1-ref.yaml b/gfx/wr/wrench/reftests/filters/filter-contrast-gray-alpha-1-ref.yaml new file mode 100644 index 0000000000..6b176d9570 --- /dev/null +++ b/gfx/wr/wrench/reftests/filters/filter-contrast-gray-alpha-1-ref.yaml @@ -0,0 +1,13 @@ +--- +root: + items: + - type: stacking-context + bounds: [0, 0, 120, 120] + items: + - type: rect + bounds: [0, 0, 120, 120] + color: [255, 255, 255, 1] + + - type: rect + bounds: [10, 10, 100, 100] + color: [223, 223, 223, 1] diff --git a/gfx/wr/wrench/reftests/filters/filter-contrast-gray-alpha-1.yaml b/gfx/wr/wrench/reftests/filters/filter-contrast-gray-alpha-1.yaml new file mode 100644 index 0000000000..87758d3f4a --- /dev/null +++ b/gfx/wr/wrench/reftests/filters/filter-contrast-gray-alpha-1.yaml @@ -0,0 +1,13 @@ +--- +root: + items: + - type: stacking-context + bounds: [0, 0, 120, 120] + items: + - type: stacking-context + bounds: [10, 10, 100, 100] + filters: contrast(0) + items: + - type: rect + bounds: [0, 0, 100, 100] + color: [128, 128, 128, 0.25] diff --git a/gfx/wr/wrench/reftests/filters/filter-drop-shadow-blur-clamping-ref.yaml b/gfx/wr/wrench/reftests/filters/filter-drop-shadow-blur-clamping-ref.yaml new file mode 100644 index 0000000000..6ffcde5f5b --- /dev/null +++ b/gfx/wr/wrench/reftests/filters/filter-drop-shadow-blur-clamping-ref.yaml @@ -0,0 +1,18 @@ +# Ensures that blur clamping happens after scale factors are applied +--- +root: + items: + - type: stacking-context + bounds: [100, 100, 300, 300] + filters: drop-shadow([0, 0], 100, blue) + items: + - type: rect + bounds: [0, 0, 100, 100] + color: 0 255 0 1.0 + - type: stacking-context + bounds: [400, 100, 300, 300] + filters: drop-shadow([0, 0], 50, green) + items: + - type: rect + bounds: [0, 0, 100, 100] + color: 255 0 0 1.0 diff --git a/gfx/wr/wrench/reftests/filters/filter-drop-shadow-blur-clamping.yaml b/gfx/wr/wrench/reftests/filters/filter-drop-shadow-blur-clamping.yaml new file mode 100644 index 0000000000..1d7157a8e6 --- /dev/null +++ b/gfx/wr/wrench/reftests/filters/filter-drop-shadow-blur-clamping.yaml @@ -0,0 +1,30 @@ +# Ensures that blur clamping happens after scale factors are applied +--- +root: + items: + - type: stacking-context + bounds: [100, 100, 300, 300] + transform: scale(10) + items: + - type: stacking-context + bounds: [0, 0, 300, 300] + # Blur will be 20 * 10(scale) = 200 and it should then be clamped to 100 + filters: drop-shadow([0, 0], 20, blue) + items: + - type: rect + bounds: [0, 0, 10, 10] + color: 0 255 0 1.0 + - type: stacking-context + bounds: [400, 100, 300, 300] + transform: scale(0.1) + items: + - type: stacking-context + bounds: [0, 0, 300, 300] + # Blur should be 500 * 0.1(scale) = 50. This tests to make sure clamping + # does not occur before applying scale factors, otherwise 500 would be + # clamped to 100. + filters: drop-shadow([0, 0], 500, green) + items: + - type: rect + bounds: [0, 0, 1000, 1000] + color: 255 0 0 1.0 diff --git a/gfx/wr/wrench/reftests/filters/filter-drop-shadow-clip-2.png b/gfx/wr/wrench/reftests/filters/filter-drop-shadow-clip-2.png Binary files differnew file mode 100644 index 0000000000..1d43dc942b --- /dev/null +++ b/gfx/wr/wrench/reftests/filters/filter-drop-shadow-clip-2.png diff --git a/gfx/wr/wrench/reftests/filters/filter-drop-shadow-clip-2.yaml b/gfx/wr/wrench/reftests/filters/filter-drop-shadow-clip-2.yaml new file mode 100644 index 0000000000..6aafa73137 --- /dev/null +++ b/gfx/wr/wrench/reftests/filters/filter-drop-shadow-clip-2.yaml @@ -0,0 +1,17 @@ +# Bug 1561447: If a clip task is created for a picture, it should take into account the rect of the drop shadow +--- +root: + items: + - type: clip + id: 2 + bounds: 10 0 300 300 + clip-rect: 10 0 300 300 + - type: stacking-context + bounds: 30 30 0 0 + transform: rotate-z(-45) + filters: drop-shadow([15, 0], 0, red) + clip-node: 2 + items: + - type: rect + bounds: 0 0 100 100 + color: blue diff --git a/gfx/wr/wrench/reftests/filters/filter-drop-shadow-clip-3.png b/gfx/wr/wrench/reftests/filters/filter-drop-shadow-clip-3.png Binary files differnew file mode 100644 index 0000000000..3e3dda9075 --- /dev/null +++ b/gfx/wr/wrench/reftests/filters/filter-drop-shadow-clip-3.png diff --git a/gfx/wr/wrench/reftests/filters/filter-drop-shadow-clip-3.yaml b/gfx/wr/wrench/reftests/filters/filter-drop-shadow-clip-3.yaml new file mode 100644 index 0000000000..4b9ad3d36e --- /dev/null +++ b/gfx/wr/wrench/reftests/filters/filter-drop-shadow-clip-3.yaml @@ -0,0 +1,37 @@ +--- +# WebRender internally clips the stacking context to avoid +# rendering parts that are off-screen. It has to take shadow +# offsets into account. +# This test introduces a 90 degrees rotation to ensure that +# the clip inflation isn't done in the wrong space. +root: + items: + # Rotation inside of the shadowed stacking context. + - type: stacking-context + bounds: [0, -10, 200, 100] + filters: drop-shadow([-10, 200], 5, red) + items: + - type: stacking-context + bounds: [50, -10, 200, 100] + transform: rotate-z(-90) + items: + - + bounds: [0, 0, 500, 150] + glyphs: [55, 75, 76, 86] + offsets: [0, 100, 75, 100, 150, 100, 180, 100] + size: 90 + color: blue + font: "../text/VeraBd.ttf" + # Rotation applied to the shadowed stacking context directly. + - type: stacking-context + bounds: [150, 35, 200, 100] + filters: drop-shadow([200, 10], 5, red) + transform: rotate-z(-90) + items: + - + bounds: [0, 0, 500, 150] + glyphs: [55, 75, 76, 86] + offsets: [0, 100, 75, 100, 150, 100, 180, 100] + size: 90 + color: blue + font: "../text/VeraBd.ttf" diff --git a/gfx/wr/wrench/reftests/filters/filter-drop-shadow-clip.png b/gfx/wr/wrench/reftests/filters/filter-drop-shadow-clip.png Binary files differnew file mode 100644 index 0000000000..197dc458da --- /dev/null +++ b/gfx/wr/wrench/reftests/filters/filter-drop-shadow-clip.png diff --git a/gfx/wr/wrench/reftests/filters/filter-drop-shadow-clip.yaml b/gfx/wr/wrench/reftests/filters/filter-drop-shadow-clip.yaml new file mode 100644 index 0000000000..c36a4c6847 --- /dev/null +++ b/gfx/wr/wrench/reftests/filters/filter-drop-shadow-clip.yaml @@ -0,0 +1,25 @@ +--- +root: + items: + - type: clip + id: 3 + bounds: [0, 0, 256, 256] + complex: + - rect: [0, 0, 256, 256] + radius: 16 + - type: clip-chain + id: 5 + clips: [3] + - type: clip + id: 4 + bounds: [100, 100, 2000, 2000] + items: + - type: stacking-context + bounds: [10, 10, 0, 0] + filters: drop-shadow([50, 50], 25, red) + clip-node: 4 + items: + - type: rect + bounds: 0 0 256 256 + color: green + clip-and-scroll: [root-scroll-node, 5] diff --git a/gfx/wr/wrench/reftests/filters/filter-drop-shadow-huge.yaml b/gfx/wr/wrench/reftests/filters/filter-drop-shadow-huge.yaml new file mode 100644 index 0000000000..dc971a7d3a --- /dev/null +++ b/gfx/wr/wrench/reftests/filters/filter-drop-shadow-huge.yaml @@ -0,0 +1,10 @@ +# Don't crash on very large blur radius! +--- +root: + items: + - type: stacking-context + bounds: [10, 10, 260, 260] + filters: drop-shadow([73, 73], 10000000, [255, 0, 0, 1]) + items: + - image: checkerboard(2, 16, 16) + bounds: [10, 10, 260, 260] diff --git a/gfx/wr/wrench/reftests/filters/filter-drop-shadow-on-viewport-edge.png b/gfx/wr/wrench/reftests/filters/filter-drop-shadow-on-viewport-edge.png Binary files differnew file mode 100644 index 0000000000..24de0898ea --- /dev/null +++ b/gfx/wr/wrench/reftests/filters/filter-drop-shadow-on-viewport-edge.png diff --git a/gfx/wr/wrench/reftests/filters/filter-drop-shadow-on-viewport-edge.yaml b/gfx/wr/wrench/reftests/filters/filter-drop-shadow-on-viewport-edge.yaml new file mode 100644 index 0000000000..663c03a0de --- /dev/null +++ b/gfx/wr/wrench/reftests/filters/filter-drop-shadow-on-viewport-edge.yaml @@ -0,0 +1,10 @@ +--- +root: + items: + - type: stacking-context + bounds: [10, 10, 400, 400] + filters: drop-shadow([10, 10], 20, [255, 0, 0, 1]) + items: + - type: rect + bounds: 0 0 256 256 + color: green diff --git a/gfx/wr/wrench/reftests/filters/filter-drop-shadow-scaled-ref.yaml b/gfx/wr/wrench/reftests/filters/filter-drop-shadow-scaled-ref.yaml new file mode 100644 index 0000000000..9173528be4 --- /dev/null +++ b/gfx/wr/wrench/reftests/filters/filter-drop-shadow-scaled-ref.yaml @@ -0,0 +1,11 @@ +# Ensure scales from enclosing SCs get applied to drop-shadows +--- +root: + items: + - type: stacking-context + bounds: [0, 0, 500, 500] + filters: drop-shadow([0, 0], 10, [255, 0, 0, 1]) + items: + - type: rect + bounds: [50, 50, 250, 250] + color: 0 255 0 1.0 diff --git a/gfx/wr/wrench/reftests/filters/filter-drop-shadow-scaled.yaml b/gfx/wr/wrench/reftests/filters/filter-drop-shadow-scaled.yaml new file mode 100644 index 0000000000..87fac1ee6d --- /dev/null +++ b/gfx/wr/wrench/reftests/filters/filter-drop-shadow-scaled.yaml @@ -0,0 +1,15 @@ +# Ensure scales from enclosing SCs get applied to drop-shadows +--- +root: + items: + - type: reference-frame + bounds: [0, 0, 100, 100] + transform: [5, 0, 0, 0, 0, 5, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1] + items: + - type: stacking-context + bounds: [0, 0, 400, 400] + filters: drop-shadow([0, 0], 2, [255, 0, 0, 1]) + items: + - type: rect + bounds: [10, 10, 50, 50] + color: 0 255 0 1.0 diff --git a/gfx/wr/wrench/reftests/filters/filter-drop-shadow-transform-huge.yaml b/gfx/wr/wrench/reftests/filters/filter-drop-shadow-transform-huge.yaml new file mode 100644 index 0000000000..e46af9dfa4 --- /dev/null +++ b/gfx/wr/wrench/reftests/filters/filter-drop-shadow-transform-huge.yaml @@ -0,0 +1,17 @@ +# Don't crash on large blur radius with large transform! +--- +root: + items: + - type: stacking-context + bounds: [0, 0, 1000, 1000] + items: + - type: stacking-context + bounds: [0, 0, 1000, 1000] + transform: scale-y(100) + items: + - type: stacking-context + bounds: [0, 0, 1000, 1000] + filters: drop-shadow([0, 0], 999999, [255, 0, 0, 1]) + items: + - image: checkerboard(2, 16, 16) + bounds: [0, 0, 1000, 1000] diff --git a/gfx/wr/wrench/reftests/filters/filter-drop-shadow.png b/gfx/wr/wrench/reftests/filters/filter-drop-shadow.png Binary files differnew file mode 100644 index 0000000000..dd81aa63ef --- /dev/null +++ b/gfx/wr/wrench/reftests/filters/filter-drop-shadow.png diff --git a/gfx/wr/wrench/reftests/filters/filter-drop-shadow.yaml b/gfx/wr/wrench/reftests/filters/filter-drop-shadow.yaml new file mode 100644 index 0000000000..59f90b42da --- /dev/null +++ b/gfx/wr/wrench/reftests/filters/filter-drop-shadow.yaml @@ -0,0 +1,9 @@ +--- +root: + items: + - type: stacking-context + bounds: [100, 100, 400, 400] + filters: drop-shadow([73, 73], 20, [255, 0, 0, 1]) + items: + - image: "firefox.png" + bounds: 0 0 256 256 diff --git a/gfx/wr/wrench/reftests/filters/filter-grayscale-ref.yaml b/gfx/wr/wrench/reftests/filters/filter-grayscale-ref.yaml new file mode 100644 index 0000000000..6a0baae7d9 --- /dev/null +++ b/gfx/wr/wrench/reftests/filters/filter-grayscale-ref.yaml @@ -0,0 +1,6 @@ +--- +root: + items: + - type: rect + bounds: [10, 10, 200, 200] + color: [182, 182, 182] diff --git a/gfx/wr/wrench/reftests/filters/filter-grayscale.yaml b/gfx/wr/wrench/reftests/filters/filter-grayscale.yaml new file mode 100644 index 0000000000..efa299cc07 --- /dev/null +++ b/gfx/wr/wrench/reftests/filters/filter-grayscale.yaml @@ -0,0 +1,10 @@ +--- +root: + items: + - type: stacking-context + bounds: [10, 10, 200, 200] + filters: grayscale(1) + items: + - type: rect + bounds: [0, 0, 200, 200] + color: [0, 255, 0] diff --git a/gfx/wr/wrench/reftests/filters/filter-hue-rotate-1-ref.yaml b/gfx/wr/wrench/reftests/filters/filter-hue-rotate-1-ref.yaml new file mode 100644 index 0000000000..a1c4039010 --- /dev/null +++ b/gfx/wr/wrench/reftests/filters/filter-hue-rotate-1-ref.yaml @@ -0,0 +1,21 @@ +--- +root: + items: + - type: stacking-context + bounds: [0, 0, 120, 120] + items: + - type: rect + bounds: [0, 0, 120, 120] + color: [0, 0, 0, 1] + - type: rect + bounds: [10, 10, 50, 50] + color: [0, 91, 0, 1] + - type: rect + bounds: [10, 60, 50, 50] + color: [0, 218, 255, 1] + - type: rect + bounds: [60, 10, 50, 50] + color: [255, 0, 37, 1] + - type: rect + bounds: [60, 60, 50, 50] + color: [128, 128, 128, 1]
\ No newline at end of file diff --git a/gfx/wr/wrench/reftests/filters/filter-hue-rotate-1.yaml b/gfx/wr/wrench/reftests/filters/filter-hue-rotate-1.yaml new file mode 100644 index 0000000000..9934661bbd --- /dev/null +++ b/gfx/wr/wrench/reftests/filters/filter-hue-rotate-1.yaml @@ -0,0 +1,37 @@ +--- +root: + items: + - type: stacking-context + bounds: [0, 0, 120, 120] + items: + - type: rect + bounds: [0, 0, 120, 120] + color: [0, 0, 0, 1] + - type: stacking-context + bounds: [10, 10, 50, 50] + filters: hue-rotate(90) + items: + - type: rect + bounds: [0, 0, 50, 50] + color: [255, 0, 0, 1] + - type: stacking-context + bounds: [10, 60, 50, 50] + filters: hue-rotate(90) + items: + - type: rect + bounds: [0, 0, 50, 50] + color: [0, 255, 0, 1] + - type: stacking-context + bounds: [60, 10, 50, 50] + filters: hue-rotate(90) + items: + - type: rect + bounds: [0, 0, 50, 50] + color: [0, 0, 255, 1] + - type: stacking-context + bounds: [60, 60, 50, 50] + filters: hue-rotate(90) + items: + - type: rect + bounds: [0, 0, 50, 50] + color: [128, 128, 128, 1]
\ No newline at end of file diff --git a/gfx/wr/wrench/reftests/filters/filter-hue-rotate-alpha-1-ref.yaml b/gfx/wr/wrench/reftests/filters/filter-hue-rotate-alpha-1-ref.yaml new file mode 100644 index 0000000000..436f30937a --- /dev/null +++ b/gfx/wr/wrench/reftests/filters/filter-hue-rotate-alpha-1-ref.yaml @@ -0,0 +1,21 @@ +--- +root: + items: + - type: stacking-context + bounds: [0, 0, 120, 120] + items: + - type: rect + bounds: [0, 0, 120, 120] + color: [0, 0, 0, 1] + - type: rect + bounds: [10, 10, 50, 50] + color: [0, 46, 0, 1] + - type: rect + bounds: [10, 60, 50, 50] + color: [0, 109, 128, 1] + - type: rect + bounds: [60, 10, 50, 50] + color: [128, 0, 18, 1] + - type: rect + bounds: [60, 60, 50, 50] + color: [64, 64, 64, 1] diff --git a/gfx/wr/wrench/reftests/filters/filter-hue-rotate-alpha-1.yaml b/gfx/wr/wrench/reftests/filters/filter-hue-rotate-alpha-1.yaml new file mode 100644 index 0000000000..b38cb218ff --- /dev/null +++ b/gfx/wr/wrench/reftests/filters/filter-hue-rotate-alpha-1.yaml @@ -0,0 +1,37 @@ +--- +root: + items: + - type: stacking-context + bounds: [0, 0, 120, 120] + items: + - type: rect + bounds: [0, 0, 120, 120] + color: [0, 0, 0, 1] + - type: stacking-context + bounds: [10, 10, 50, 50] + filters: hue-rotate(90) + items: + - type: rect + bounds: [0, 0, 50, 50] + color: [255, 0, 0, 0.5] + - type: stacking-context + bounds: [10, 60, 50, 50] + filters: hue-rotate(90) + items: + - type: rect + bounds: [0, 0, 50, 50] + color: [0, 255, 0, 0.5] + - type: stacking-context + bounds: [60, 10, 50, 50] + filters: hue-rotate(90) + items: + - type: rect + bounds: [0, 0, 50, 50] + color: [0, 0, 255, 0.5] + - type: stacking-context + bounds: [60, 60, 50, 50] + filters: hue-rotate(90) + items: + - type: rect + bounds: [0, 0, 50, 50] + color: [128, 128, 128, 0.5]
\ No newline at end of file diff --git a/gfx/wr/wrench/reftests/filters/filter-invert-2-ref.yaml b/gfx/wr/wrench/reftests/filters/filter-invert-2-ref.yaml new file mode 100644 index 0000000000..08aa94333d --- /dev/null +++ b/gfx/wr/wrench/reftests/filters/filter-invert-2-ref.yaml @@ -0,0 +1,9 @@ +--- +root: + items: + - type: stacking-context + bounds: [0, 0, 120, 120] + items: + - type: rect + bounds: [0, 0, 120, 120] + color: [0, 0, 255, 1] diff --git a/gfx/wr/wrench/reftests/filters/filter-invert-2.yaml b/gfx/wr/wrench/reftests/filters/filter-invert-2.yaml new file mode 100644 index 0000000000..f254816dc5 --- /dev/null +++ b/gfx/wr/wrench/reftests/filters/filter-invert-2.yaml @@ -0,0 +1,17 @@ +--- +root: + items: + - type: stacking-context + bounds: [0, 0, 120, 120] + items: + - type: rect + bounds: [0, 0, 120, 120] + color: [0, 0, 255, 1] + + - type: stacking-context + bounds: [10, 10, 100, 100] + filters: invert(1) + items: + - type: rect + bounds: [0, 0, 100, 100] + color: [255, 255, 0, 0.5] diff --git a/gfx/wr/wrench/reftests/filters/filter-invert-ref.yaml b/gfx/wr/wrench/reftests/filters/filter-invert-ref.yaml new file mode 100644 index 0000000000..674ecee969 --- /dev/null +++ b/gfx/wr/wrench/reftests/filters/filter-invert-ref.yaml @@ -0,0 +1,9 @@ +--- +root: + items: + - type: stacking-context + bounds: [0, 0, 120, 120] + items: + - type: rect + bounds: [10, 10, 100, 100] + color: [0, 0, 0, 0.25] diff --git a/gfx/wr/wrench/reftests/filters/filter-invert.yaml b/gfx/wr/wrench/reftests/filters/filter-invert.yaml new file mode 100644 index 0000000000..57ebcdb43c --- /dev/null +++ b/gfx/wr/wrench/reftests/filters/filter-invert.yaml @@ -0,0 +1,13 @@ +--- +root: + items: + - type: stacking-context + bounds: [0, 0, 120, 120] + items: + - type: stacking-context + bounds: [10, 10, 100, 100] + filters: invert(1) + items: + - type: rect + bounds: [0, 0, 100, 100] + color: [255, 255, 255, 0.25] diff --git a/gfx/wr/wrench/reftests/filters/filter-large-blur-radius.png b/gfx/wr/wrench/reftests/filters/filter-large-blur-radius.png Binary files differnew file mode 100644 index 0000000000..24db853d44 --- /dev/null +++ b/gfx/wr/wrench/reftests/filters/filter-large-blur-radius.png diff --git a/gfx/wr/wrench/reftests/filters/filter-large-blur-radius.yaml b/gfx/wr/wrench/reftests/filters/filter-large-blur-radius.yaml new file mode 100644 index 0000000000..6ce5f4cb22 --- /dev/null +++ b/gfx/wr/wrench/reftests/filters/filter-large-blur-radius.yaml @@ -0,0 +1,10 @@ +--- +root: + items: + - type: stacking-context + bounds: 100 100 512 512 + filters: blur(100, 100) + items: + - type: rect + bounds: 0 0 512 512 + color: red diff --git a/gfx/wr/wrench/reftests/filters/filter-long-chain.png b/gfx/wr/wrench/reftests/filters/filter-long-chain.png Binary files differnew file mode 100644 index 0000000000..6e58dd6300 --- /dev/null +++ b/gfx/wr/wrench/reftests/filters/filter-long-chain.png diff --git a/gfx/wr/wrench/reftests/filters/filter-long-chain.yaml b/gfx/wr/wrench/reftests/filters/filter-long-chain.yaml new file mode 100644 index 0000000000..a0f9d698bd --- /dev/null +++ b/gfx/wr/wrench/reftests/filters/filter-long-chain.yaml @@ -0,0 +1,19 @@ +--- +root: + items: + - type: stacking-context + bounds: [100, 100, 400, 400] + filters: [brightness(2), + contrast(0.4), + grayscale(0.2), + hue-rotate(270), + invert(0.6), + opacity(0.8), + saturate(10), + sepia(0.4), + "blur(3,3)", + "drop-shadow([73, 73], 3, [0, 255, 0, 1])"] + items: + - type: rect + color: red + bounds: 0 0 256 256 diff --git a/gfx/wr/wrench/reftests/filters/filter-mix-blend-mode-ref.yaml b/gfx/wr/wrench/reftests/filters/filter-mix-blend-mode-ref.yaml new file mode 100644 index 0000000000..0a43095403 --- /dev/null +++ b/gfx/wr/wrench/reftests/filters/filter-mix-blend-mode-ref.yaml @@ -0,0 +1,6 @@ +--- +root: + items: + - type: rect + color: [128, 128, 127, 1] + bounds: 100 100 100 100 diff --git a/gfx/wr/wrench/reftests/filters/filter-mix-blend-mode.yaml b/gfx/wr/wrench/reftests/filters/filter-mix-blend-mode.yaml new file mode 100644 index 0000000000..0b6e3eb468 --- /dev/null +++ b/gfx/wr/wrench/reftests/filters/filter-mix-blend-mode.yaml @@ -0,0 +1,17 @@ +--- +root: + items: + - type: stacking-context + blend-container: true + items: + - type: rect + color: [128, 128, 128, 1] + bounds: 100 100 100 100 + - type: stacking-context + bounds: [100, 100, 100, 100] + filters: [invert(1)] + mix-blend-mode: exclusion + items: + - type: rect + color: yellow + bounds: 0 0 100 100 diff --git a/gfx/wr/wrench/reftests/filters/filter-mix-blend-scaling-ref.yaml b/gfx/wr/wrench/reftests/filters/filter-mix-blend-scaling-ref.yaml new file mode 100644 index 0000000000..949da2b16b --- /dev/null +++ b/gfx/wr/wrench/reftests/filters/filter-mix-blend-scaling-ref.yaml @@ -0,0 +1,11 @@ + +# Tests that mix-blend mode content renders correctly when in a scaled surface. +# See bug 1642549 +--- +root: + items: + - type: stacking-context + bounds: 0 0 0 0 + items: + - rect: 0 0 150 150 + color: green diff --git a/gfx/wr/wrench/reftests/filters/filter-mix-blend-scaling.yaml b/gfx/wr/wrench/reftests/filters/filter-mix-blend-scaling.yaml new file mode 100644 index 0000000000..577f4edebf --- /dev/null +++ b/gfx/wr/wrench/reftests/filters/filter-mix-blend-scaling.yaml @@ -0,0 +1,23 @@ +# Tests that mix-blend mode content renders correctly when in a scaled surface. +# See bug 1642549 +--- +root: + items: + - type: stacking-context + bounds: 0 0 0 0 + # Force WebRender to form a raster root + transform: perspective(1000) + items: + - type: stacking-context + bounds: -50 -50 0 0 + # The raster root will have a 2x scaling factor + transform: scale(2) + blend-container: true + items: + - rect: 0 0 100 100 + color: green + - type: stacking-context + mix-blend-mode: multiply + items: + - rect: 0 0 100 100 + color: white diff --git a/gfx/wr/wrench/reftests/filters/filter-saturate-blue-1-ref.yaml b/gfx/wr/wrench/reftests/filters/filter-saturate-blue-1-ref.yaml new file mode 100644 index 0000000000..9b5a96e542 --- /dev/null +++ b/gfx/wr/wrench/reftests/filters/filter-saturate-blue-1-ref.yaml @@ -0,0 +1,13 @@ +--- +root: + items: + - type: stacking-context + bounds: [0, 0, 120, 120] + items: + - type: rect + bounds: [0, 0, 120, 120] + color: [0, 0, 0, 1] + + - type: rect + bounds: [10, 10, 100, 100] + color: [18, 18, 18, 1] diff --git a/gfx/wr/wrench/reftests/filters/filter-saturate-blue-1.yaml b/gfx/wr/wrench/reftests/filters/filter-saturate-blue-1.yaml new file mode 100644 index 0000000000..22d47f10e0 --- /dev/null +++ b/gfx/wr/wrench/reftests/filters/filter-saturate-blue-1.yaml @@ -0,0 +1,17 @@ +--- +root: + items: + - type: stacking-context + bounds: [0, 0, 120, 120] + items: + - type: rect + bounds: [0, 0, 120, 120] + color: [0, 0, 0, 1] + + - type: stacking-context + bounds: [10, 10, 100, 100] + filters: saturate(0) + items: + - type: rect + bounds: [0, 0, 100, 100] + color: [0, 0, 255, 1] diff --git a/gfx/wr/wrench/reftests/filters/filter-saturate-blue-2-ref.yaml b/gfx/wr/wrench/reftests/filters/filter-saturate-blue-2-ref.yaml new file mode 100644 index 0000000000..a83166358d --- /dev/null +++ b/gfx/wr/wrench/reftests/filters/filter-saturate-blue-2-ref.yaml @@ -0,0 +1,13 @@ +--- +root: + items: + - type: stacking-context + bounds: [0, 0, 120, 120] + items: + - type: rect + bounds: [0, 0, 120, 120] + color: [0, 0, 0, 1] + + - type: rect + bounds: [10, 10, 100, 100] + color: [9, 9, 137, 1] diff --git a/gfx/wr/wrench/reftests/filters/filter-saturate-blue-2.yaml b/gfx/wr/wrench/reftests/filters/filter-saturate-blue-2.yaml new file mode 100644 index 0000000000..0b8cac5609 --- /dev/null +++ b/gfx/wr/wrench/reftests/filters/filter-saturate-blue-2.yaml @@ -0,0 +1,17 @@ +--- +root: + items: + - type: stacking-context + bounds: [0, 0, 120, 120] + items: + - type: rect + bounds: [0, 0, 120, 120] + color: [0, 0, 0, 1] + + - type: stacking-context + bounds: [10, 10, 100, 100] + filters: saturate(0.5) + items: + - type: rect + bounds: [0, 0, 100, 100] + color: [0, 0, 255, 1] diff --git a/gfx/wr/wrench/reftests/filters/filter-saturate-blue-3-ref.yaml b/gfx/wr/wrench/reftests/filters/filter-saturate-blue-3-ref.yaml new file mode 100644 index 0000000000..ebb3450e02 --- /dev/null +++ b/gfx/wr/wrench/reftests/filters/filter-saturate-blue-3-ref.yaml @@ -0,0 +1,13 @@ +--- +root: + items: + - type: stacking-context + bounds: [0, 0, 120, 120] + items: + - type: rect + bounds: [0, 0, 120, 120] + color: [0, 0, 0, 1] + + - type: rect + bounds: [10, 10, 100, 100] + color: [0, 0, 255, 1] diff --git a/gfx/wr/wrench/reftests/filters/filter-saturate-blue-3.yaml b/gfx/wr/wrench/reftests/filters/filter-saturate-blue-3.yaml new file mode 100644 index 0000000000..060d0294ff --- /dev/null +++ b/gfx/wr/wrench/reftests/filters/filter-saturate-blue-3.yaml @@ -0,0 +1,17 @@ +--- +root: + items: + - type: stacking-context + bounds: [0, 0, 120, 120] + items: + - type: rect + bounds: [0, 0, 120, 120] + color: [0, 0, 0, 1] + + - type: stacking-context + bounds: [10, 10, 100, 100] + filters: saturate(1) + items: + - type: rect + bounds: [0, 0, 100, 100] + color: [0, 0, 255, 1] diff --git a/gfx/wr/wrench/reftests/filters/filter-saturate-blue-alpha-1-ref.yaml b/gfx/wr/wrench/reftests/filters/filter-saturate-blue-alpha-1-ref.yaml new file mode 100644 index 0000000000..321bea6876 --- /dev/null +++ b/gfx/wr/wrench/reftests/filters/filter-saturate-blue-alpha-1-ref.yaml @@ -0,0 +1,13 @@ +--- +root: + items: + - type: stacking-context + bounds: [0, 0, 120, 120] + items: + - type: rect + bounds: [0, 0, 120, 120] + color: [0, 0, 0, 1] + + - type: rect + bounds: [10, 10, 100, 100] + color: [5, 5, 69, 1] diff --git a/gfx/wr/wrench/reftests/filters/filter-saturate-blue-alpha-1.yaml b/gfx/wr/wrench/reftests/filters/filter-saturate-blue-alpha-1.yaml new file mode 100644 index 0000000000..1a264cc458 --- /dev/null +++ b/gfx/wr/wrench/reftests/filters/filter-saturate-blue-alpha-1.yaml @@ -0,0 +1,17 @@ +--- +root: + items: + - type: stacking-context + bounds: [0, 0, 120, 120] + items: + - type: rect + bounds: [0, 0, 120, 120] + color: [0, 0, 0, 1] + + - type: stacking-context + bounds: [10, 10, 100, 100] + filters: saturate(0.5) + items: + - type: rect + bounds: [0, 0, 100, 100] + color: [0, 0, 255, 0.5] diff --git a/gfx/wr/wrench/reftests/filters/filter-saturate-green-1-ref.yaml b/gfx/wr/wrench/reftests/filters/filter-saturate-green-1-ref.yaml new file mode 100644 index 0000000000..2a710fae15 --- /dev/null +++ b/gfx/wr/wrench/reftests/filters/filter-saturate-green-1-ref.yaml @@ -0,0 +1,13 @@ +--- +root: + items: + - type: stacking-context + bounds: [0, 0, 120, 120] + items: + - type: rect + bounds: [0, 0, 120, 120] + color: [0, 0, 0, 1] + + - type: rect + bounds: [10, 10, 100, 100] + color: [182, 182, 182, 1] diff --git a/gfx/wr/wrench/reftests/filters/filter-saturate-green-1.yaml b/gfx/wr/wrench/reftests/filters/filter-saturate-green-1.yaml new file mode 100644 index 0000000000..4fcfa8174b --- /dev/null +++ b/gfx/wr/wrench/reftests/filters/filter-saturate-green-1.yaml @@ -0,0 +1,17 @@ +--- +root: + items: + - type: stacking-context + bounds: [0, 0, 120, 120] + items: + - type: rect + bounds: [0, 0, 120, 120] + color: [0, 0, 0, 1] + + - type: stacking-context + bounds: [10, 10, 100, 100] + filters: saturate(0) + items: + - type: rect + bounds: [0, 0, 100, 100] + color: [0, 255, 0, 1] diff --git a/gfx/wr/wrench/reftests/filters/filter-saturate-green-2-ref.yaml b/gfx/wr/wrench/reftests/filters/filter-saturate-green-2-ref.yaml new file mode 100644 index 0000000000..f13c6e225d --- /dev/null +++ b/gfx/wr/wrench/reftests/filters/filter-saturate-green-2-ref.yaml @@ -0,0 +1,13 @@ +--- +root: + items: + - type: stacking-context + bounds: [0, 0, 120, 120] + items: + - type: rect + bounds: [0, 0, 120, 120] + color: [0, 0, 0, 1] + + - type: rect + bounds: [10, 10, 100, 100] + color: [91, 219, 91, 1] diff --git a/gfx/wr/wrench/reftests/filters/filter-saturate-green-2.yaml b/gfx/wr/wrench/reftests/filters/filter-saturate-green-2.yaml new file mode 100644 index 0000000000..98f033bb76 --- /dev/null +++ b/gfx/wr/wrench/reftests/filters/filter-saturate-green-2.yaml @@ -0,0 +1,17 @@ +--- +root: + items: + - type: stacking-context + bounds: [0, 0, 120, 120] + items: + - type: rect + bounds: [0, 0, 120, 120] + color: [0, 0, 0, 1] + + - type: stacking-context + bounds: [10, 10, 100, 100] + filters: saturate(0.5) + items: + - type: rect + bounds: [0, 0, 100, 100] + color: [0, 255, 0, 1] diff --git a/gfx/wr/wrench/reftests/filters/filter-saturate-green-3-ref.yaml b/gfx/wr/wrench/reftests/filters/filter-saturate-green-3-ref.yaml new file mode 100644 index 0000000000..00aae63bdc --- /dev/null +++ b/gfx/wr/wrench/reftests/filters/filter-saturate-green-3-ref.yaml @@ -0,0 +1,13 @@ +--- +root: + items: + - type: stacking-context + bounds: [0, 0, 120, 120] + items: + - type: rect + bounds: [0, 0, 120, 120] + color: [0, 0, 0, 1] + + - type: rect + bounds: [10, 10, 100, 100] + color: [0, 255, 0, 1] diff --git a/gfx/wr/wrench/reftests/filters/filter-saturate-green-3.yaml b/gfx/wr/wrench/reftests/filters/filter-saturate-green-3.yaml new file mode 100644 index 0000000000..c7f3561171 --- /dev/null +++ b/gfx/wr/wrench/reftests/filters/filter-saturate-green-3.yaml @@ -0,0 +1,17 @@ +--- +root: + items: + - type: stacking-context + bounds: [0, 0, 120, 120] + items: + - type: rect + bounds: [0, 0, 120, 120] + color: [0, 0, 0, 1] + + - type: stacking-context + bounds: [10, 10, 100, 100] + filters: saturate(1) + items: + - type: rect + bounds: [0, 0, 100, 100] + color: [0, 255, 0, 1] diff --git a/gfx/wr/wrench/reftests/filters/filter-saturate-green-alpha-1-ref.yaml b/gfx/wr/wrench/reftests/filters/filter-saturate-green-alpha-1-ref.yaml new file mode 100644 index 0000000000..e4c5643f29 --- /dev/null +++ b/gfx/wr/wrench/reftests/filters/filter-saturate-green-alpha-1-ref.yaml @@ -0,0 +1,12 @@ +--- +root: + items: + - type: stacking-context + bounds: [0, 0, 120, 120] + items: + - type: rect + bounds: [0, 0, 120, 120] + color: [0, 0, 0, 1] + - type: rect + bounds: [10, 10, 100, 100] + color: [46, 110, 46, 1] diff --git a/gfx/wr/wrench/reftests/filters/filter-saturate-green-alpha-1.yaml b/gfx/wr/wrench/reftests/filters/filter-saturate-green-alpha-1.yaml new file mode 100644 index 0000000000..042d19d6f5 --- /dev/null +++ b/gfx/wr/wrench/reftests/filters/filter-saturate-green-alpha-1.yaml @@ -0,0 +1,17 @@ +--- +root: + items: + - type: stacking-context + bounds: [0, 0, 120, 120] + items: + - type: rect + bounds: [0, 0, 120, 120] + color: [0, 0, 0, 1] + + - type: stacking-context + bounds: [10, 10, 100, 100] + filters: saturate(0.5) + items: + - type: rect + bounds: [0, 0, 100, 100] + color: [0, 255, 0, 0.5] diff --git a/gfx/wr/wrench/reftests/filters/filter-saturate-red-1-ref.yaml b/gfx/wr/wrench/reftests/filters/filter-saturate-red-1-ref.yaml new file mode 100644 index 0000000000..3b95adb53a --- /dev/null +++ b/gfx/wr/wrench/reftests/filters/filter-saturate-red-1-ref.yaml @@ -0,0 +1,13 @@ +--- +root: + items: + - type: stacking-context + bounds: [0, 0, 120, 120] + items: + - type: rect + bounds: [0, 0, 120, 120] + color: [0, 0, 0, 1] + + - type: rect + bounds: [10, 10, 100, 100] + color: [54, 54, 54, 1] diff --git a/gfx/wr/wrench/reftests/filters/filter-saturate-red-1.yaml b/gfx/wr/wrench/reftests/filters/filter-saturate-red-1.yaml new file mode 100644 index 0000000000..9dab61a552 --- /dev/null +++ b/gfx/wr/wrench/reftests/filters/filter-saturate-red-1.yaml @@ -0,0 +1,17 @@ +--- +root: + items: + - type: stacking-context + bounds: [0, 0, 120, 120] + items: + - type: rect + bounds: [0, 0, 120, 120] + color: [0, 0, 0, 1] + + - type: stacking-context + bounds: [10, 10, 100, 100] + filters: saturate(0) + items: + - type: rect + bounds: [0, 0, 100, 100] + color: [255, 0, 0, 1] diff --git a/gfx/wr/wrench/reftests/filters/filter-saturate-red-2-ref.yaml b/gfx/wr/wrench/reftests/filters/filter-saturate-red-2-ref.yaml new file mode 100644 index 0000000000..f6707424d0 --- /dev/null +++ b/gfx/wr/wrench/reftests/filters/filter-saturate-red-2-ref.yaml @@ -0,0 +1,13 @@ +--- +root: + items: + - type: stacking-context + bounds: [0, 0, 120, 120] + items: + - type: rect + bounds: [0, 0, 120, 120] + color: [0, 0, 0, 1] + + - type: rect + bounds: [10, 10, 100, 100] + color: [155, 27, 27, 1] diff --git a/gfx/wr/wrench/reftests/filters/filter-saturate-red-2.yaml b/gfx/wr/wrench/reftests/filters/filter-saturate-red-2.yaml new file mode 100644 index 0000000000..5810894a2c --- /dev/null +++ b/gfx/wr/wrench/reftests/filters/filter-saturate-red-2.yaml @@ -0,0 +1,17 @@ +--- +root: + items: + - type: stacking-context + bounds: [0, 0, 120, 120] + items: + - type: rect + bounds: [0, 0, 120, 120] + color: [0, 0, 0, 1] + + - type: stacking-context + bounds: [10, 10, 100, 100] + filters: saturate(0.5) + items: + - type: rect + bounds: [0, 0, 100, 100] + color: [255, 0, 0, 1] diff --git a/gfx/wr/wrench/reftests/filters/filter-saturate-red-3-ref.yaml b/gfx/wr/wrench/reftests/filters/filter-saturate-red-3-ref.yaml new file mode 100644 index 0000000000..0c9e4f4ac2 --- /dev/null +++ b/gfx/wr/wrench/reftests/filters/filter-saturate-red-3-ref.yaml @@ -0,0 +1,13 @@ +--- +root: + items: + - type: stacking-context + bounds: [0, 0, 120, 120] + items: + - type: rect + bounds: [0, 0, 120, 120] + color: [0, 0, 0, 1] + + - type: rect + bounds: [10, 10, 100, 100] + color: [255, 0, 0, 1] diff --git a/gfx/wr/wrench/reftests/filters/filter-saturate-red-3.yaml b/gfx/wr/wrench/reftests/filters/filter-saturate-red-3.yaml new file mode 100644 index 0000000000..ce9ed012d3 --- /dev/null +++ b/gfx/wr/wrench/reftests/filters/filter-saturate-red-3.yaml @@ -0,0 +1,17 @@ +--- +root: + items: + - type: stacking-context + bounds: [0, 0, 120, 120] + items: + - type: rect + bounds: [0, 0, 120, 120] + color: [0, 0, 0, 1] + + - type: stacking-context + bounds: [10, 10, 100, 100] + filters: saturate(1) + items: + - type: rect + bounds: [0, 0, 100, 100] + color: [255, 0, 0, 1] diff --git a/gfx/wr/wrench/reftests/filters/filter-saturate-red-alpha-1-ref.yaml b/gfx/wr/wrench/reftests/filters/filter-saturate-red-alpha-1-ref.yaml new file mode 100644 index 0000000000..bdcd52d339 --- /dev/null +++ b/gfx/wr/wrench/reftests/filters/filter-saturate-red-alpha-1-ref.yaml @@ -0,0 +1,12 @@ +--- +root: + items: + - type: stacking-context + bounds: [0, 0, 120, 120] + items: + - type: rect + bounds: [0, 0, 120, 120] + color: [0, 0, 0, 1] + - type: rect + bounds: [10, 10, 100, 100] + color: [78, 14, 14, 1] diff --git a/gfx/wr/wrench/reftests/filters/filter-saturate-red-alpha-1.yaml b/gfx/wr/wrench/reftests/filters/filter-saturate-red-alpha-1.yaml new file mode 100644 index 0000000000..11218fcf85 --- /dev/null +++ b/gfx/wr/wrench/reftests/filters/filter-saturate-red-alpha-1.yaml @@ -0,0 +1,17 @@ +--- +root: + items: + - type: stacking-context + bounds: [0, 0, 120, 120] + items: + - type: rect + bounds: [0, 0, 120, 120] + color: [0, 0, 0, 1] + + - type: stacking-context + bounds: [10, 10, 100, 100] + filters: saturate(0.5) + items: + - type: rect + bounds: [0, 0, 100, 100] + color: [255, 0, 0, 0.5] diff --git a/gfx/wr/wrench/reftests/filters/filter-segments-ref.yaml b/gfx/wr/wrench/reftests/filters/filter-segments-ref.yaml new file mode 100644 index 0000000000..22a5373e2a --- /dev/null +++ b/gfx/wr/wrench/reftests/filters/filter-segments-ref.yaml @@ -0,0 +1,18 @@ +--- +root: + items: + - type: clip + bounds: [10, 10, 256, 256] + complex: + - rect: [10, 10, 256, 256] + radius: 16 + items: + - type: rect + color: [54, 54, 54] + bounds: [10, 10, 512, 512] + - type: rect + color: red + bounds: [0, 0, 300, 32] + - type: rect + color: red + bounds: [0, 250, 300, 32] diff --git a/gfx/wr/wrench/reftests/filters/filter-segments.yaml b/gfx/wr/wrench/reftests/filters/filter-segments.yaml new file mode 100644 index 0000000000..4d42218430 --- /dev/null +++ b/gfx/wr/wrench/reftests/filters/filter-segments.yaml @@ -0,0 +1,24 @@ +# Ensure that picture / filter primitives draw the entire primitive +# when they are eligible to be segmented. The red rects are used to +# mask out the corners, since the AA varies between the tests. +--- +root: + items: + - type: clip + bounds: [10, 10, 256, 256] + complex: + - rect: [10, 10, 256, 256] + radius: 16 + items: + - type: stacking-context + filters: grayscale(1) + items: + - type: rect + color: red + bounds: [10, 10, 512, 512] + - type: rect + color: red + bounds: [0, 0, 300, 32] + - type: rect + color: red + bounds: [0, 250, 300, 32] diff --git a/gfx/wr/wrench/reftests/filters/filter-small-blur-radius.png b/gfx/wr/wrench/reftests/filters/filter-small-blur-radius.png Binary files differnew file mode 100644 index 0000000000..e755e2bb6c --- /dev/null +++ b/gfx/wr/wrench/reftests/filters/filter-small-blur-radius.png diff --git a/gfx/wr/wrench/reftests/filters/filter-small-blur-radius.yaml b/gfx/wr/wrench/reftests/filters/filter-small-blur-radius.yaml new file mode 100644 index 0000000000..d5b550d0ab --- /dev/null +++ b/gfx/wr/wrench/reftests/filters/filter-small-blur-radius.yaml @@ -0,0 +1,10 @@ +--- +root: + items: + - type: stacking-context + bounds: 100 100 512 512 + filters: blur(2, 2) + items: + - type: rect + bounds: 0 0 512 512 + color: red diff --git a/gfx/wr/wrench/reftests/filters/firefox.png b/gfx/wr/wrench/reftests/filters/firefox.png Binary files differnew file mode 100644 index 0000000000..696ba9c9b5 --- /dev/null +++ b/gfx/wr/wrench/reftests/filters/firefox.png diff --git a/gfx/wr/wrench/reftests/filters/iframe-dropshadow-ref.yaml b/gfx/wr/wrench/reftests/filters/iframe-dropshadow-ref.yaml new file mode 100644 index 0000000000..47c7140163 --- /dev/null +++ b/gfx/wr/wrench/reftests/filters/iframe-dropshadow-ref.yaml @@ -0,0 +1,22 @@ +# a drop-shadow in an iframe causes the content to not render +--- +root: + items: + - + type: "stacking-context" + bounds: [0, 148, 1920, 1606] + items: + - + type: "rect" + color: [255, 0, 0, 1] + bounds: [387, 12, 34, 38] + clip-rect: [386, 11, 36, 40] + - + type: "stacking-context" + filters: drop-shadow([0, 4], 2, [0, 0, 0, 0.3294117748737335]) + items: + - + type: "rect" + color: [255, 0, 0, 1] + bounds: [345, 12, 34, 38] + clip-rect: [344, 11, 36, 40] diff --git a/gfx/wr/wrench/reftests/filters/iframe-dropshadow.yaml b/gfx/wr/wrench/reftests/filters/iframe-dropshadow.yaml new file mode 100644 index 0000000000..440e757e04 --- /dev/null +++ b/gfx/wr/wrench/reftests/filters/iframe-dropshadow.yaml @@ -0,0 +1,34 @@ +# a drop-shadow in an iframe causes the content to not render +--- +root: + items: + - + type: "stacking-context" + items: + - + type: iframe + id: [1, 2] + bounds: [0, 148, 1920, 1606] + clip-rect: [0, 148, 1920, 1606] + +pipelines: + - + id: [1, 2] + items: + - + type: "stacking-context" + items: + - + type: "rect" + color: [255, 0, 0, 1] + bounds: [387, 12, 34, 38] + clip-rect: [386, 11, 36, 40] + - + type: "stacking-context" + filters: drop-shadow([0, 4], 2, [0, 0, 0, 0.3294117748737335]) + items: + - + type: "rect" + color: [255, 0, 0, 1] + bounds: [345, 12, 34, 38] + clip-rect: [344, 11, 36, 40] diff --git a/gfx/wr/wrench/reftests/filters/invisible-ref.yaml b/gfx/wr/wrench/reftests/filters/invisible-ref.yaml new file mode 100644 index 0000000000..ec31525d31 --- /dev/null +++ b/gfx/wr/wrench/reftests/filters/invisible-ref.yaml @@ -0,0 +1,6 @@ +--- +root: + items: + - type: rect + bounds: [10, 10, 50, 50] + color: green diff --git a/gfx/wr/wrench/reftests/filters/invisible.yaml b/gfx/wr/wrench/reftests/filters/invisible.yaml new file mode 100644 index 0000000000..c4a99e64a8 --- /dev/null +++ b/gfx/wr/wrench/reftests/filters/invisible.yaml @@ -0,0 +1,27 @@ +--- +root: + items: + - type: stacking-context + bounds: [0, 0, 100, 100] + filters: opacity(0.0), + items: + - type: stacking-context + bounds: [0, 0, 100, 100] + items: + - type: stacking-context + bounds: [0, 0, 100, 100] + items: + - type: stacking-context + bounds: [0, 0, 100, 100] + items: + - type: stacking-context + bounds: [0, 0, 100, 100] + items: + - type: rect + bounds: [70, 70, 50, 50] + color: green + # This display item ensures that the stacking context is skipped, but + # later items are not. + - type: rect + bounds: [10, 10, 50, 50] + color: green diff --git a/gfx/wr/wrench/reftests/filters/isolated-ref.yaml b/gfx/wr/wrench/reftests/filters/isolated-ref.yaml new file mode 100644 index 0000000000..28c6912a97 --- /dev/null +++ b/gfx/wr/wrench/reftests/filters/isolated-ref.yaml @@ -0,0 +1,13 @@ +--- +root: + items: + - type: rect + bounds: [0, 0, 100, 100] + color: [0, 0, 0] + - type: stacking-context + bounds: [0, 0, 100, 100] + filters: opacity(0.5) + items: + - type: rect + bounds: [0, 0, 100, 100] + color: [0, 255, 0] diff --git a/gfx/wr/wrench/reftests/filters/isolated.yaml b/gfx/wr/wrench/reftests/filters/isolated.yaml new file mode 100644 index 0000000000..5f61ba2dfa --- /dev/null +++ b/gfx/wr/wrench/reftests/filters/isolated.yaml @@ -0,0 +1,17 @@ +# this tests that filters don't create isolated groups +--- +root: + items: + - type: rect + bounds: [0, 0, 100, 100] + color: [0, 0, 0] + - type: stacking-context + bounds: [0, 0, 100, 100] + items: + - type: stacking-context + bounds: [0, 0, 100, 100] + filters: opacity(0.5) + items: + - type: rect + bounds: [0, 0, 100, 100] + color: [0, 255, 0] diff --git a/gfx/wr/wrench/reftests/filters/opacity-combined-ref.yaml b/gfx/wr/wrench/reftests/filters/opacity-combined-ref.yaml new file mode 100644 index 0000000000..2b008f0a2f --- /dev/null +++ b/gfx/wr/wrench/reftests/filters/opacity-combined-ref.yaml @@ -0,0 +1,10 @@ +# this tests that opacity combination respets pre-multiplied alpha +root: + items: + - type: stacking-context + bounds: [10, 10, 500, 500] + filters: [opacity(0.25)] + items: + - type: rect + bounds: [10, 10, 100, 100] + color: green diff --git a/gfx/wr/wrench/reftests/filters/opacity-combined.yaml b/gfx/wr/wrench/reftests/filters/opacity-combined.yaml new file mode 100644 index 0000000000..7d9bfa4ac5 --- /dev/null +++ b/gfx/wr/wrench/reftests/filters/opacity-combined.yaml @@ -0,0 +1,10 @@ +# this tests that opacity combination respects pre-multiplied alpha +root: + items: + - type: stacking-context + bounds: [10, 10, 500, 500] + filters: [opacity(0.50), opacity(0.50)] + items: + - type: rect + bounds: [10, 10, 100, 100] + color: green diff --git a/gfx/wr/wrench/reftests/filters/opacity-overlap-ref.yaml b/gfx/wr/wrench/reftests/filters/opacity-overlap-ref.yaml new file mode 100644 index 0000000000..d3ad75812e --- /dev/null +++ b/gfx/wr/wrench/reftests/filters/opacity-overlap-ref.yaml @@ -0,0 +1,9 @@ +# this tests opacity rectangle overlapping with opaque one +root: + items: + - type: stacking-context + bounds: [10, 10, 500, 500] + items: + - type: rect + bounds: [10, 10, 100, 100] + color: [32, 0, 96] diff --git a/gfx/wr/wrench/reftests/filters/opacity-overlap.yaml b/gfx/wr/wrench/reftests/filters/opacity-overlap.yaml new file mode 100644 index 0000000000..94832004a3 --- /dev/null +++ b/gfx/wr/wrench/reftests/filters/opacity-overlap.yaml @@ -0,0 +1,16 @@ +# this tests opacity rectangle overlapping with opaque one +root: + items: + - type: stacking-context + bounds: [10, 10, 500, 500] + items: + - type: rect + bounds: [10, 10, 100, 100] + color: [128, 0, 0] + - type: stacking-context + bounds: [10, 10, 500, 500] + filters: [opacity(0.75)] + items: + - type: rect + bounds: [10, 10, 100, 100] + color: [0, 0, 128] diff --git a/gfx/wr/wrench/reftests/filters/opacity-ref.yaml b/gfx/wr/wrench/reftests/filters/opacity-ref.yaml new file mode 100644 index 0000000000..ffe06bc5fd --- /dev/null +++ b/gfx/wr/wrench/reftests/filters/opacity-ref.yaml @@ -0,0 +1,8 @@ +root: + items: + - type: stacking-context + bounds: [10, 10, 500, 500] + items: + - type: rect + bounds: [10, 10, 100, 100] + color: [255, 255, 209, 1.0] diff --git a/gfx/wr/wrench/reftests/filters/opacity.yaml b/gfx/wr/wrench/reftests/filters/opacity.yaml new file mode 100644 index 0000000000..838937de2a --- /dev/null +++ b/gfx/wr/wrench/reftests/filters/opacity.yaml @@ -0,0 +1,10 @@ +# this tests opacity pre-multiplied color +root: + items: + - type: stacking-context + bounds: [10, 10, 500, 500] + filters: [opacity(0.9)] + items: + - type: rect + bounds: [10, 10, 100, 100] + color: [255, 255, 0, 0.2] diff --git a/gfx/wr/wrench/reftests/filters/reftest.list b/gfx/wr/wrench/reftests/filters/reftest.list new file mode 100644 index 0000000000..fd45a09e3f --- /dev/null +++ b/gfx/wr/wrench/reftests/filters/reftest.list @@ -0,0 +1,68 @@ +== filter-grayscale.yaml filter-grayscale-ref.yaml +platform(linux,mac) == draw_calls(7) color_targets(7) alpha_targets(0) filter-blur.yaml filter-blur.png +== isolated.yaml isolated-ref.yaml +== invisible.yaml invisible-ref.yaml +fuzzy-if(platform(swgl),1,10000) == opacity.yaml opacity-ref.yaml +fuzzy-range(<=1,*10000) == opacity-combined.yaml opacity-combined-ref.yaml +== opacity-overlap.yaml opacity-overlap-ref.yaml +== filter-brightness.yaml filter-brightness-ref.yaml +== filter-brightness-2.yaml filter-brightness-2-ref.yaml +== filter-brightness-3.yaml filter-brightness-3-ref.yaml +== filter-brightness-4.yaml filter-brightness-4-ref.yaml +== filter-component-transfer.yaml filter-component-transfer-ref.yaml +skip_on(android,device) == filter-color-matrix.yaml filter-color-matrix-ref.yaml # fails on Pixel2 +== filter-contrast-gray-alpha-1.yaml filter-contrast-gray-alpha-1-ref.yaml +== filter-invert.yaml filter-invert-ref.yaml +== filter-invert-2.yaml filter-invert-2-ref.yaml +platform(linux,mac) fuzzy(1,133) == filter-large-blur-radius.yaml filter-large-blur-radius.png +skip_on(android,device) fuzzy(1,12) fuzzy-if(platform(swgl),2,12276) == draw_calls(7) color_targets(6) alpha_targets(0) filter-small-blur-radius.yaml filter-small-blur-radius.png # fails on Pixel2 +== filter-saturate-red-1.yaml filter-saturate-red-1-ref.yaml +== filter-saturate-red-2.yaml filter-saturate-red-2-ref.yaml +== filter-saturate-red-3.yaml filter-saturate-red-3-ref.yaml +== filter-saturate-green-1.yaml filter-saturate-green-1-ref.yaml +== filter-saturate-green-2.yaml filter-saturate-green-2-ref.yaml +== filter-saturate-green-3.yaml filter-saturate-green-3-ref.yaml +== filter-saturate-blue-1.yaml filter-saturate-blue-1-ref.yaml +== filter-saturate-blue-2.yaml filter-saturate-blue-2-ref.yaml +== filter-saturate-blue-3.yaml filter-saturate-blue-3-ref.yaml +== filter-saturate-red-alpha-1.yaml filter-saturate-red-alpha-1-ref.yaml +== filter-saturate-green-alpha-1.yaml filter-saturate-green-alpha-1-ref.yaml +== filter-saturate-blue-alpha-1.yaml filter-saturate-blue-alpha-1-ref.yaml +fuzzy(1,14) == filter-hue-rotate-1.yaml filter-hue-rotate-1-ref.yaml +skip_on(android,device) == filter-hue-rotate-alpha-1.yaml filter-hue-rotate-alpha-1-ref.yaml # Fails on Pixel2 +skip_on(android,device) fuzzy(2,9072) fuzzy-if(platform(swgl),9,109897) == filter-long-chain.yaml filter-long-chain.png # fails on Pixel2 +platform(linux,mac) == filter-drop-shadow.yaml filter-drop-shadow.png +platform(linux,mac) == filter-drop-shadow-on-viewport-edge.yaml filter-drop-shadow-on-viewport-edge.png +platform(linux,mac) == blend-clipped.yaml blend-clipped.png +platform(linux,mac) == filter-drop-shadow-clip.yaml filter-drop-shadow-clip.png +fuzzy(2,10) platform(linux,mac) == filter-drop-shadow-clip-2.yaml filter-drop-shadow-clip-2.png +fuzzy(1,23) platform(linux) == filter-drop-shadow-clip-3.yaml filter-drop-shadow-clip-3.png +fuzzy(5,100000) == filter-drop-shadow-scaled.yaml filter-drop-shadow-scaled-ref.yaml +== filter-segments.yaml filter-segments-ref.yaml +== iframe-dropshadow.yaml iframe-dropshadow-ref.yaml +skip_on(android,device) == filter-mix-blend-mode.yaml filter-mix-blend-mode-ref.yaml # fails on Pixel2 +== fuzzy(3,20000) srgb-to-linear.yaml srgb-to-linear-ref.yaml +!= srgb-to-linear-2.yaml srgb-to-linear-ref.yaml +!= filter-blur-huge.yaml blank.yaml +!= filter-drop-shadow-huge.yaml blank.yaml +!= filter-drop-shadow-transform-huge.yaml blank.yaml +fuzzy(3,79400) == filter-drop-shadow-blur-clamping.yaml filter-drop-shadow-blur-clamping-ref.yaml +== filter-blur-scaled.yaml filter-blur-scaled-ref.yaml +== filter-blur-clamping.yaml filter-blur-clamping-ref.yaml +skip_on(android,device) fuzzy(1,104) fuzzy-if(platform(swgl),4,18484) == filter-blur-scaled-xonly.yaml filter-blur-scaled-xonly.png # fails on Pixel2 +== svg-filter-component-transfer.yaml filter-component-transfer-ref.yaml +== svg-filter-flood.yaml svg-filter-flood-ref.yaml +skip_on(android,device) == svg-filter-blend.yaml svg-filter-blend-ref.yaml +skip_on(android,device) == svg-filter-color-matrix.yaml filter-color-matrix-ref.yaml # fails on Pixel2 +platform(linux,mac) == draw_calls(8) color_targets(8) alpha_targets(0) svg-filter-blur.yaml filter-blur.png # Extra draw call is due to render task graph workaround +platform(linux,mac) == svg-filter-drop-shadow.yaml svg-filter-drop-shadow.png +== fuzzy(1,10000) svg-srgb-to-linear.yaml srgb-to-linear-ref.yaml +platform(linux,mac) == fuzzy(5,35250) svg-filter-drop-shadow-rotate.yaml svg-filter-drop-shadow-rotate-ref.yaml +platform(linux,mac) fuzzy(3,3184) == svg-filter-blur-transforms.yaml svg-filter-blur-transforms.png +platform(linux,mac) == svg-filter-drop-shadow-on-viewport-edge.yaml svg-filter-drop-shadow-on-viewport-edge.png +fuzzy(1,1) platform(linux,mac) == svg-filter-drop-shadow-perspective.yaml svg-filter-drop-shadow-perspective.png +== backdrop-filter-basic.yaml backdrop-filter-basic-ref.yaml +platform(linux,mac) == backdrop-filter-perspective.yaml backdrop-filter-perspective.png +platform(linux,max) == svg-filter-offset.yaml svg-filter-offset-ref.yaml +skip_on(android,device) == fuzzy(1,100) svg-filter-composite.yaml svg-filter-composite-ref.yaml +skip_on(android,device) == filter-mix-blend-scaling.yaml filter-mix-blend-scaling-ref.yaml diff --git a/gfx/wr/wrench/reftests/filters/srgb-to-linear-2.yaml b/gfx/wr/wrench/reftests/filters/srgb-to-linear-2.yaml new file mode 100644 index 0000000000..333ef502ae --- /dev/null +++ b/gfx/wr/wrench/reftests/filters/srgb-to-linear-2.yaml @@ -0,0 +1,16 @@ +--- +root: + items: + - type: stacking-context + bounds: [0, 0, 300, 100] + filters: [srgb-to-linear] + items: + - type: rect + bounds: [100, 0, 100, 100] + color: [200, 200, 200, 1.0] + - type: rect + bounds: [100, 0, 100, 100] + color: [100, 100, 100, 1.0] + - type: rect + bounds: [200, 0, 100, 100] + color: [50, 50, 50, 1.0] diff --git a/gfx/wr/wrench/reftests/filters/srgb-to-linear-ref.yaml b/gfx/wr/wrench/reftests/filters/srgb-to-linear-ref.yaml new file mode 100644 index 0000000000..d984523da6 --- /dev/null +++ b/gfx/wr/wrench/reftests/filters/srgb-to-linear-ref.yaml @@ -0,0 +1,15 @@ +--- +root: + items: + - type: stacking-context + bounds: [0, 0, 300, 100] + items: + - type: rect + bounds: [100, 0, 100, 100] + color: [200, 200, 200, 1.0] + - type: rect + bounds: [100, 0, 100, 100] + color: [100, 100, 100, 1.0] + - type: rect + bounds: [200, 0, 100, 100] + color: [50, 50, 50, 1.0] diff --git a/gfx/wr/wrench/reftests/filters/srgb-to-linear.yaml b/gfx/wr/wrench/reftests/filters/srgb-to-linear.yaml new file mode 100644 index 0000000000..67eb35119f --- /dev/null +++ b/gfx/wr/wrench/reftests/filters/srgb-to-linear.yaml @@ -0,0 +1,16 @@ +--- +root: + items: + - type: stacking-context + bounds: [0, 0, 300, 100] + filters: [srgb-to-linear, linear-to-srgb] + items: + - type: rect + bounds: [100, 0, 100, 100] + color: [200, 200, 200, 1.0] + - type: rect + bounds: [100, 0, 100, 100] + color: [100, 100, 100, 1.0] + - type: rect + bounds: [200, 0, 100, 100] + color: [50, 50, 50, 1.0] diff --git a/gfx/wr/wrench/reftests/filters/svg-filter-blend-ref.yaml b/gfx/wr/wrench/reftests/filters/svg-filter-blend-ref.yaml new file mode 100644 index 0000000000..d796f0b85e --- /dev/null +++ b/gfx/wr/wrench/reftests/filters/svg-filter-blend-ref.yaml @@ -0,0 +1,21 @@ +--- +root: + items: + - type: stacking-context + bounds: [0, 0, 50, 250] + items: + - type: rect + bounds: [0, 0, 50, 50] + color: [0, 255, 0, 1] + - type: rect + bounds: [0, 50, 50, 50] + color: [40, 20, 2, 1] + - type: rect + bounds: [0, 100, 50, 50] + color: [20, 10, 155, 1] + - type: rect + bounds: [0, 150, 50, 50] + color: [255, 222, 156, 1] + - type: rect + bounds: [0, 200, 50, 50] + color: [255, 245, 151, 1] diff --git a/gfx/wr/wrench/reftests/filters/svg-filter-blend.yaml b/gfx/wr/wrench/reftests/filters/svg-filter-blend.yaml new file mode 100644 index 0000000000..2167013d3c --- /dev/null +++ b/gfx/wr/wrench/reftests/filters/svg-filter-blend.yaml @@ -0,0 +1,83 @@ +# Tests various blend modes using the blend filter primitive. +--- +root: + items: + - type: stacking-context + bounds: [0, 0, 50, 250] + filter-primitives: + - type: flood + color: [255, 255, 255, 1] + color-space: srgb + - type: blend + in1: original + in2: 0 + color-space: srgb + blend-mode: difference + items: + - type: rect + bounds: [0, 0, 50, 50] + color: [255, 0, 255, 1] + + - type: stacking-context + bounds: [0, 0, 50, 250] + filter-primitives: + - type: flood + color: [51, 51, 51, 1] + color-space: srgb + - type: blend + in1: original + in2: 0 + color-space: srgb + blend-mode: multiply + items: + - type: rect + bounds: [0, 50, 50, 50] + color: [200, 100, 10, 1] + + - type: stacking-context + bounds: [0, 0, 50, 250] + filter-primitives: + - type: flood + color: [255, 10, 156, 1] + color-space: srgb + - type: blend + in1: original + in2: 0 + color-space: srgb + blend-mode: darken + items: + - type: rect + bounds: [0, 100, 50, 50] + color: [20, 222, 155, 1] + + - type: stacking-context + bounds: [0, 0, 50, 250] + filter-primitives: + - type: flood + color: [255, 10, 156, 1] + color-space: srgb + - type: blend + in1: original + in2: 0 + color-space: srgb + blend-mode: lighten + items: + - type: rect + bounds: [0, 150, 50, 50] + color: [20, 222, 155, 1] + + - type: stacking-context + bounds: [0, 0, 50, 250] + filter-primitives: + - type: flood + color: [255, 10, 156, 1] + color-space: srgb + - type: blend + in1: original + in2: 0 + color-space: srgb + blend-mode: exclusion + items: + - type: rect + bounds: [0, 200, 50, 50] + color: [0, 255, 24, 1] diff --git a/gfx/wr/wrench/reftests/filters/svg-filter-blur-transforms.png b/gfx/wr/wrench/reftests/filters/svg-filter-blur-transforms.png Binary files differnew file mode 100644 index 0000000000..890c815bef --- /dev/null +++ b/gfx/wr/wrench/reftests/filters/svg-filter-blur-transforms.png diff --git a/gfx/wr/wrench/reftests/filters/svg-filter-blur-transforms.yaml b/gfx/wr/wrench/reftests/filters/svg-filter-blur-transforms.yaml new file mode 100644 index 0000000000..d78f3ae806 --- /dev/null +++ b/gfx/wr/wrench/reftests/filters/svg-filter-blur-transforms.yaml @@ -0,0 +1,16 @@ +--- +root: + items: + - type: stacking-context + bounds: [0, 100, 300, 300] + transform: scale-x(0.1) rotate-z(-45) + filter-primitives: + - type: blur + width: 10 + height: 10 + in: previous + color-space: srgb + items: + - type: rect + color: red + bounds: 0 0 256 256 diff --git a/gfx/wr/wrench/reftests/filters/svg-filter-blur.yaml b/gfx/wr/wrench/reftests/filters/svg-filter-blur.yaml new file mode 100644 index 0000000000..5554688500 --- /dev/null +++ b/gfx/wr/wrench/reftests/filters/svg-filter-blur.yaml @@ -0,0 +1,14 @@ +--- +root: + items: + - type: stacking-context + bounds: [100, 100, 300, 300] + filter-primitives: + - type: blur + width: 10 + height: 10 + in: previous + color-space: srgb + items: + - image: "firefox.png" + bounds: 20 20 256 256 diff --git a/gfx/wr/wrench/reftests/filters/svg-filter-color-matrix.yaml b/gfx/wr/wrench/reftests/filters/svg-filter-color-matrix.yaml new file mode 100644 index 0000000000..60166b7514 --- /dev/null +++ b/gfx/wr/wrench/reftests/filters/svg-filter-color-matrix.yaml @@ -0,0 +1,69 @@ +--- +root: + items: + - type: stacking-context + bounds: [0, 0, 120, 170] + items: + - type: rect + bounds: [0, 0, 120, 170] + color: [0, 0, 0, 1] + - type: stacking-context + bounds: [10, 10, 50, 50] + filter-primitives: + - type: color-matrix + in: previous + color-space: srgb + matrix: [0.393, 0.686, 0.534, 0, + 0.189, 0.168, 0.131, 0, + 0.349, 0.272, 0, 0, + 0, 0, 0, 1, + 0, 0, 0, 0] + items: + - type: rect + bounds: [0, 0, 50, 50] + color: [255, 0, 0, 1] + - type: stacking-context + bounds: [10, 60, 50, 50] + filter-primitives: + - type: color-matrix + in: previous + color-space: srgb + matrix: [-1, 0, 0, 0, + 0, -1, 0, 0, + 0, 0, -1, 0, + 0, 0, 0, 1, + 1, 1, 1, 0] + items: + - type: rect + bounds: [0, 0, 50, 50] + color: [0, 255, 0, 1] + - type: stacking-context + bounds: [60, 10, 50, 50] + filter-primitives: + - type: color-matrix + in: previous + color-space: srgb + matrix: [0, 0, 1, 0, + 0, 1, 0, 0, + 1, 0, 0, 0, + 0, 0, 0, 1, + 0, 0, 0, 0] + items: + - type: rect + bounds: [0, 0, 50, 50] + color: [0, 0, 255, 1] + - type: stacking-context + bounds: [10, 110, 50, 50] + filter-primitives: + - type: color-matrix + in: previous + color-space: srgb + matrix: [1, 0, 0, 0, + 0, 1, 0, 0, + 0, 0, 1, 0.5, + 0, 0, 0, 0, + 0, 0, 0, 0] + items: + - type: rect + bounds: [0, 0, 50, 50] + color: [0, 0, 255, 1] diff --git a/gfx/wr/wrench/reftests/filters/svg-filter-component-transfer.yaml b/gfx/wr/wrench/reftests/filters/svg-filter-component-transfer.yaml new file mode 100644 index 0000000000..88b56a4a25 --- /dev/null +++ b/gfx/wr/wrench/reftests/filters/svg-filter-component-transfer.yaml @@ -0,0 +1,382 @@ +--- +root: + items: + - type: stacking-context + bounds: [0, 0, 50, 250] + items: + - type: stacking-context + bounds: [0, 0, 50, 50] + filter-primitives: + - type: component-transfer + color-space: srgb + in: previous + filter-datas: + - - - Identity + - Identity + - Identity + - Identity + - [] + - [] + - [] + - [] + items: + - type: rect + bounds: [0, 0, 50, 50] + color: [255, 0, 255, 1] + - type: stacking-context + bounds: [0, 50, 50, 50] + filter-primitives: + - type: component-transfer + color-space: srgb + in: previous + filter-datas: + - - - Table + - Table + - Table + - Identity + - - "1" + - "1" + - "0" + - "0" + - - "0" + - "0" + - "1" + - "1" + - - "0" + - "1" + - "1" + - "0" + - [] + items: + - type: rect + bounds: [0, 0, 50, 50] + color: [173, 255, 47, 1] + - type: stacking-context + bounds: [0, 100, 50, 50] + filter-primitives: + - type: component-transfer + color-space: srgb + in: previous + filter-datas: + - - - Discrete + - Discrete + - Discrete + - Identity + - - "1" + - "1" + - "0" + - "0" + - - "0" + - "0" + - "1" + - "1" + - - "0" + - "1" + - "1" + - "0" + - [] + items: + - type: rect + bounds: [0, 0, 50, 50] + color: [0, 255, 255, 1] + - type: stacking-context + bounds: [0, 150, 50, 50] + filter-primitives: + - type: component-transfer + color-space: srgb + in: previous + filter-datas: + - - - Linear + - Linear + - Linear + - Identity + - - "0.5" + - "0.25" + - - "0.5" + - "0" + - - "0.5" + - "0.5" + - [] + items: + - type: rect + bounds: [0, 0, 50, 50] + color: [255, 255, 0, 1] + - type: stacking-context + bounds: [0, 200, 50, 50] + filter-primitives: + - type: component-transfer + color-space: srgb + in: previous + filter-datas: + - - - Gamma + - Gamma + - Gamma + - Identity + - - "2" + - "5" + - "-1" + - - "2" + - "3" + - "0" + - - "2" + - "1" + - "-1.75" + - [] + items: + - type: rect + bounds: [0, 0, 50, 50] + color: [135, 206, 235, 1] + - type: stacking-context + bounds: [60, 0, 50, 50] + filter-primitives: + - type: component-transfer + color-space: srgb + in: previous + filter-datas: + - - - Identity + - Identity + - Identity + - Identity + - [] + - [] + - [] + - [] + items: + - type: rect + bounds: [0, 0, 50, 50] + color: [255, 0, 255, 1] + - type: stacking-context + bounds: [60, 50, 50, 50] + filter-primitives: + - type: component-transfer + color-space: srgb + in: previous + filter-datas: + - - - Table + - Table + - Table + - Table + - - "1" + - "1" + - "0" + - "0" + - - "0" + - "0" + - "1" + - "1" + - - "0" + - "1" + - "1" + - "0" + - - "1" + - "0" + items: + - type: rect + bounds: [0, 0, 50, 50] + color: [173, 255, 47, 1] + - type: stacking-context + bounds: [60, 100, 50, 50] + filter-primitives: + - type: component-transfer + color-space: srgb + in: previous + filter-datas: + - - - Discrete + - Discrete + - Discrete + - Discrete + - - "1" + - "1" + - "0" + - "0" + - - "0" + - "0" + - "1" + - "1" + - - "0" + - "1" + - "1" + - "0" + - - "1" + - "0" + items: + - type: rect + bounds: [0, 0, 50, 50] + color: [0, 255, 255, 1] + - type: stacking-context + bounds: [60, 150, 50, 50] + filter-primitives: + - type: component-transfer + color-space: srgb + in: previous + filter-datas: + - - - Linear + - Linear + - Linear + - Linear + - - "0.5" + - "0.25" + - - "0.5" + - "0" + - - "0.5" + - "0.5" + - - "0.5" + - "0" + items: + - type: rect + bounds: [0, 0, 50, 50] + color: [255, 255, 0, 1] + - type: stacking-context + bounds: [60, 200, 50, 50] + filter-primitives: + - type: component-transfer + color-space: srgb + in: previous + filter-datas: + - - - Gamma + - Gamma + - Gamma + - Gamma + - - "2" + - "5" + - "-1" + - - "2" + - "3" + - "0" + - - "2" + - "1" + - "-1.75" + - - "2" + - "1" + - "-1.75" + items: + - type: rect + bounds: [0, 0, 50, 50] + color: [135, 206, 235, 1] + - type: stacking-context + bounds: [120, 0, 50, 50] + filter-primitives: + - type: component-transfer + color-space: srgb + in: previous + filter-datas: + - - - Identity + - Identity + - Identity + - Identity + - [] + - [] + - [] + - [] + items: + - type: rect + bounds: [0, 0, 50, 50] + color: [255, 0, 255, 0.5] + - type: stacking-context + bounds: [120, 50, 50, 50] + filter-primitives: + - type: component-transfer + color-space: srgb + in: previous + filter-datas: + - - - Table + - Table + - Table + - Table + - - "1" + - "1" + - "0" + - "0" + - - "0" + - "0" + - "1" + - "1" + - - "0" + - "1" + - "1" + - "0" + - - "1" + - "0" + items: + - type: rect + bounds: [0, 0, 50, 50] + color: [173, 255, 47, 0.5] + - type: stacking-context + bounds: [120, 100, 50, 50] + filter-primitives: + - type: component-transfer + color-space: srgb + in: previous + filter-datas: + - - - Discrete + - Discrete + - Discrete + - Discrete + - - "1" + - "1" + - "0" + - "0" + - - "0" + - "0" + - "1" + - "1" + - - "0" + - "1" + - "1" + - "0" + - - "1" + - "0" + items: + - type: rect + bounds: [0, 0, 50, 50] + color: [0, 255, 255, 0.5] + - type: stacking-context + bounds: [120, 150, 50, 50] + filter-primitives: + - type: component-transfer + color-space: srgb + in: previous + filter-datas: + - - - Linear + - Linear + - Linear + - Linear + - - "0.5" + - "0.25" + - - "0.5" + - "0" + - - "0.5" + - "0.5" + - - "0.5" + - "0" + items: + - type: rect + bounds: [0, 0, 50, 50] + color: [255, 255, 0, 0.5] + - type: stacking-context + bounds: [120, 200, 50, 50] + filter-primitives: + - type: component-transfer + color-space: srgb + in: previous + filter-datas: + - - - Gamma + - Gamma + - Gamma + - Gamma + - - "2" + - "5" + - "-1" + - - "2" + - "3" + - "0" + - - "2" + - "1" + - "-1.75" + - - "2" + - "1" + - "-0.25" + items: + - type: rect + bounds: [0, 0, 50, 50] + color: [135, 206, 235, 0.5] diff --git a/gfx/wr/wrench/reftests/filters/svg-filter-composite-ref.yaml b/gfx/wr/wrench/reftests/filters/svg-filter-composite-ref.yaml new file mode 100644 index 0000000000..25d9e7db6a --- /dev/null +++ b/gfx/wr/wrench/reftests/filters/svg-filter-composite-ref.yaml @@ -0,0 +1,73 @@ +# Tests the composite SVG filter primitive +--- +root: + items: + - type: stacking-context + bounds: 0 0 0 0 + items: + - type: rect + color: yellow + bounds: 10 10 100 100 + - type: rect + color: blue + bounds: 60 60 100 100 + - type: stacking-context + bounds: 200 0 0 0 + items: + - type: rect + color: blue + bounds: 60 60 50 50 + - type: stacking-context + bounds: 400 0 0 0 + items: + - type: rect + color: yellow + bounds: 10 10 100 100 + - type: rect + color: blue + bounds: 60 60 50 50 + - type: stacking-context + bounds: 600 0 0 0 + items: + - type: rect + color: blue + bounds: 60 60 100 100 + - type: rect + color: white + bounds: 60 60 50 50 + - type: stacking-context + bounds: 0 200 0 0 + items: + - type: rect + color: yellow + bounds: 10 10 100 100 + - type: rect + color: blue + bounds: 60 60 100 100 + - type: rect + color: white + bounds: 60 60 50 50 + - type: stacking-context + bounds: 200 200 0 0 + items: + - type: rect + color: [255, 0, 0, 1.0] + bounds: 10 10 100 100 + - type: rect + color: [0, 0, 255, 1.0] + bounds: 60 60 100 100 + - type: rect + color: [255, 0, 255, 1.0] + bounds: 60 60 50 50 + - type: stacking-context + bounds: 400 200 0 0 + items: + - type: rect + color: [255, 255, 127, 1.0] + bounds: 10 10 100 100 + - type: rect + color: [127, 127, 255, 1.0] + bounds: 60 60 100 100 + - type: rect + color: [188, 188, 188, 1.0] + bounds: 60 60 50 50 diff --git a/gfx/wr/wrench/reftests/filters/svg-filter-composite.yaml b/gfx/wr/wrench/reftests/filters/svg-filter-composite.yaml new file mode 100644 index 0000000000..68f3cc0744 --- /dev/null +++ b/gfx/wr/wrench/reftests/filters/svg-filter-composite.yaml @@ -0,0 +1,124 @@ +# Tests the composite SVG filter primitive +--- +root: + items: + - type: stacking-context + bounds: 0 0 0 0 + filter-primitives: + - type: flood + color: yellow + in: previous + - type: offset + offset: -50 -50 + in: previous + - type: composite + in1: original + in2: 1 + operator: over + items: + - type: rect + color: blue + bounds: 60 60 100 100 + - type: stacking-context + bounds: 200 0 0 0 + filter-primitives: + - type: flood + color: yellow + in: previous + - type: offset + offset: -50 -50 + in: previous + - type: composite + in1: original + in2: 1 + operator: in + items: + - type: rect + color: blue + bounds: 60 60 100 100 + - type: stacking-context + bounds: 400 0 0 0 + filter-primitives: + - type: flood + color: yellow + in: previous + - type: offset + offset: -50 -50 + in: previous + - type: composite + in1: original + in2: 1 + operator: atop + items: + - type: rect + color: blue + bounds: 60 60 100 100 + - type: stacking-context + bounds: 600 0 0 0 + filter-primitives: + - type: flood + color: yellow + in: previous + - type: offset + offset: -50 -50 + in: previous + - type: composite + in1: original + in2: 1 + operator: out + items: + - type: rect + color: blue + bounds: 60 60 100 100 + - type: stacking-context + bounds: 0 200 0 0 + filter-primitives: + - type: flood + color: yellow + in: previous + - type: offset + offset: -50 -50 + in: previous + - type: composite + in1: original + in2: 1 + operator: xor + items: + - type: rect + color: blue + bounds: 60 60 100 100 + - type: stacking-context + bounds: 200 200 0 0 + filter-primitives: + - type: flood + color: [255, 0, 0, 1.0] + in: previous + - type: offset + offset: -50 -50 + in: previous + - type: composite + in1: original + in2: 1 + operator: lighter + items: + - type: rect + color: [0, 0, 255, 1.0] + bounds: 60 60 100 100 + - type: stacking-context + bounds: 400 200 0 0 + filter-primitives: + - type: flood + color: yellow + in: previous + - type: offset + offset: -50 -50 + in: previous + - type: composite + in1: original + in2: 1 + operator: arithmetic + k-values: [0.5, 0.5, 0.5, 0] + items: + - type: rect + color: blue + bounds: 60 60 100 100 diff --git a/gfx/wr/wrench/reftests/filters/svg-filter-drop-shadow-on-viewport-edge.png b/gfx/wr/wrench/reftests/filters/svg-filter-drop-shadow-on-viewport-edge.png Binary files differnew file mode 100644 index 0000000000..dcc09c53cb --- /dev/null +++ b/gfx/wr/wrench/reftests/filters/svg-filter-drop-shadow-on-viewport-edge.png diff --git a/gfx/wr/wrench/reftests/filters/svg-filter-drop-shadow-on-viewport-edge.yaml b/gfx/wr/wrench/reftests/filters/svg-filter-drop-shadow-on-viewport-edge.yaml new file mode 100644 index 0000000000..3b1a4da213 --- /dev/null +++ b/gfx/wr/wrench/reftests/filters/svg-filter-drop-shadow-on-viewport-edge.yaml @@ -0,0 +1,16 @@ +--- +root: + items: + - type: stacking-context + bounds: [10, 10, 400, 400] + filter-primitives: + - type: drop-shadow + offset: [10, 10] + radius: 20 + color: [255, 0, 0, 1] + in: previous + color-space: srgb + items: + - type: rect + bounds: 0 0 256 256 + color: green diff --git a/gfx/wr/wrench/reftests/filters/svg-filter-drop-shadow-perspective.png b/gfx/wr/wrench/reftests/filters/svg-filter-drop-shadow-perspective.png Binary files differnew file mode 100644 index 0000000000..035c5d46e0 --- /dev/null +++ b/gfx/wr/wrench/reftests/filters/svg-filter-drop-shadow-perspective.png diff --git a/gfx/wr/wrench/reftests/filters/svg-filter-drop-shadow-perspective.yaml b/gfx/wr/wrench/reftests/filters/svg-filter-drop-shadow-perspective.yaml new file mode 100644 index 0000000000..744e2f655e --- /dev/null +++ b/gfx/wr/wrench/reftests/filters/svg-filter-drop-shadow-perspective.yaml @@ -0,0 +1,22 @@ +# Tests SVG drop shadows with perspective transforms +--- +root: + items: + - type: stacking-context + perspective: 100 + perspective-origin: 100 50 + items: + - type: "stacking-context" + transform-origin: 0 250 + transform: rotate-x(-15) + filter-primitives: + - type: drop-shadow + color: red + offset: [20, 20] + radius: 10 + in: previous + color-space: srgb + items: + - type: rect + color: blue + bounds: 0 0 200 200 diff --git a/gfx/wr/wrench/reftests/filters/svg-filter-drop-shadow-rotate-ref.yaml b/gfx/wr/wrench/reftests/filters/svg-filter-drop-shadow-rotate-ref.yaml new file mode 100644 index 0000000000..69501250a0 --- /dev/null +++ b/gfx/wr/wrench/reftests/filters/svg-filter-drop-shadow-rotate-ref.yaml @@ -0,0 +1,11 @@ +# Tests SVG drop shadows with transforms +--- +root: + items: + - type: stacking-context + bounds: [100, 100, 400, 400] + filters: drop-shadow([73, 73], 20, [255, 0, 0, 1]) + transform: rotate-z(45) + items: + - image: "firefox.png" + bounds: 0 0 256 256 diff --git a/gfx/wr/wrench/reftests/filters/svg-filter-drop-shadow-rotate.yaml b/gfx/wr/wrench/reftests/filters/svg-filter-drop-shadow-rotate.yaml new file mode 100644 index 0000000000..71acca0f52 --- /dev/null +++ b/gfx/wr/wrench/reftests/filters/svg-filter-drop-shadow-rotate.yaml @@ -0,0 +1,17 @@ +# Tests SVG drop shadows with transforms +--- +root: + items: + - type: stacking-context + bounds: [100, 100, 400, 400] + transform: rotate-z(45) + filter-primitives: + - type: drop-shadow + in: previous + offset: [73, 73] + radius: 20 + color: [255, 0, 0, 1] + color-space: srgb + items: + - image: "firefox.png" + bounds: 0 0 256 256 diff --git a/gfx/wr/wrench/reftests/filters/svg-filter-drop-shadow.png b/gfx/wr/wrench/reftests/filters/svg-filter-drop-shadow.png Binary files differnew file mode 100644 index 0000000000..eee62c79d2 --- /dev/null +++ b/gfx/wr/wrench/reftests/filters/svg-filter-drop-shadow.png diff --git a/gfx/wr/wrench/reftests/filters/svg-filter-drop-shadow.yaml b/gfx/wr/wrench/reftests/filters/svg-filter-drop-shadow.yaml new file mode 100644 index 0000000000..25cdfaf61e --- /dev/null +++ b/gfx/wr/wrench/reftests/filters/svg-filter-drop-shadow.yaml @@ -0,0 +1,16 @@ +# Tests that SVG drop shadows are working properly +--- +root: + items: + - type: stacking-context + bounds: [100, 100, 400, 400] + filter-primitives: + - type: drop-shadow + in: previous + offset: [73, 73] + radius: 20 + color: [255, 0, 0, 1] + color-space: srgb + items: + - image: "firefox.png" + bounds: 0 0 256 256 diff --git a/gfx/wr/wrench/reftests/filters/svg-filter-flood-ref.yaml b/gfx/wr/wrench/reftests/filters/svg-filter-flood-ref.yaml new file mode 100644 index 0000000000..ae4eb6a0d1 --- /dev/null +++ b/gfx/wr/wrench/reftests/filters/svg-filter-flood-ref.yaml @@ -0,0 +1,10 @@ +# Test that flood filter is equivalent to drawing a rect with the same size and color +--- +root: + items: + - type: stacking-context + bounds: [100, 100, 400, 400] + items: + - type: rect + bounds: [20, 20, 256, 256] + color: [0, 255.0, 0, 0.4] diff --git a/gfx/wr/wrench/reftests/filters/svg-filter-flood.yaml b/gfx/wr/wrench/reftests/filters/svg-filter-flood.yaml new file mode 100644 index 0000000000..bf896e266f --- /dev/null +++ b/gfx/wr/wrench/reftests/filters/svg-filter-flood.yaml @@ -0,0 +1,10 @@ +# Test that flood filter is equivalent to drawing a rect with the same size and color +--- +root: + items: + - type: stacking-context + bounds: [100, 100, 400, 400] + filters: flood([0, 255.0, 0, 0.4]) + items: + - image: "firefox.png" + bounds: 20 20 256 256 diff --git a/gfx/wr/wrench/reftests/filters/svg-filter-offset-ref.yaml b/gfx/wr/wrench/reftests/filters/svg-filter-offset-ref.yaml new file mode 100644 index 0000000000..f6326b5134 --- /dev/null +++ b/gfx/wr/wrench/reftests/filters/svg-filter-offset-ref.yaml @@ -0,0 +1,11 @@ +# Tests the SVG offset filter primitive +# An offset filter should have the same effect as changing the origin of the rectangle. +--- +root: + items: + - type: stacking-context + bounds: 0 0 0 0 + items: + - type: rect + bounds: 20 20 100 100 + color: red diff --git a/gfx/wr/wrench/reftests/filters/svg-filter-offset.yaml b/gfx/wr/wrench/reftests/filters/svg-filter-offset.yaml new file mode 100644 index 0000000000..f48fb5104e --- /dev/null +++ b/gfx/wr/wrench/reftests/filters/svg-filter-offset.yaml @@ -0,0 +1,15 @@ +# Tests the SVG offset filter primitive +# An offset filter should have the same effect as changing the origin of the rectangle. +--- +root: + items: + - type: stacking-context + bounds: 0 0 0 0 + filter-primitives: + - type: offset + offset: 10 10 + in: original + items: + - type: rect + bounds: 10 10 100 100 + color: red diff --git a/gfx/wr/wrench/reftests/filters/svg-srgb-to-linear.yaml b/gfx/wr/wrench/reftests/filters/svg-srgb-to-linear.yaml new file mode 100644 index 0000000000..f7f33165f5 --- /dev/null +++ b/gfx/wr/wrench/reftests/filters/svg-srgb-to-linear.yaml @@ -0,0 +1,20 @@ +# this test ensures that a sRGB -> linear-RGB -> sRGB results in no change (with exception to rounding error) +--- +root: + items: + - type: stacking-context + bounds: [0, 0, 300, 100] + filter-primitives: + - type: identity + in: previous + color-space: linear-rgb + items: + - type: rect + bounds: [100, 0, 100, 100] + color: [200, 200, 200, 1.0] + - type: rect + bounds: [100, 0, 100, 100] + color: [100, 100, 100, 1.0] + - type: rect + bounds: [200, 0, 100, 100] + color: [50, 50, 50, 1.0] diff --git a/gfx/wr/wrench/reftests/gradient/conic-angle-wraparound-negative.yaml b/gfx/wr/wrench/reftests/gradient/conic-angle-wraparound-negative.yaml new file mode 100644 index 0000000000..f2053c42b6 --- /dev/null +++ b/gfx/wr/wrench/reftests/gradient/conic-angle-wraparound-negative.yaml @@ -0,0 +1,8 @@ +--- +root: + items: + - type: conic-gradient + bounds: 50 50 300 300 + center: 150 150 + angle: -5.497787143782138 + stops: [0.0, red, 1.0, yellow]
\ No newline at end of file diff --git a/gfx/wr/wrench/reftests/gradient/conic-angle-wraparound.yaml b/gfx/wr/wrench/reftests/gradient/conic-angle-wraparound.yaml new file mode 100644 index 0000000000..67a1370eac --- /dev/null +++ b/gfx/wr/wrench/reftests/gradient/conic-angle-wraparound.yaml @@ -0,0 +1,8 @@ +--- +root: + items: + - type: conic-gradient + bounds: 50 50 300 300 + center: 150 150 + angle: 7.0685834705770345 + stops: [0.0, red, 1.0, yellow]
\ No newline at end of file diff --git a/gfx/wr/wrench/reftests/gradient/conic-angle.png b/gfx/wr/wrench/reftests/gradient/conic-angle.png Binary files differnew file mode 100644 index 0000000000..81ec931cec --- /dev/null +++ b/gfx/wr/wrench/reftests/gradient/conic-angle.png diff --git a/gfx/wr/wrench/reftests/gradient/conic-angle.yaml b/gfx/wr/wrench/reftests/gradient/conic-angle.yaml new file mode 100644 index 0000000000..11a068c9e6 --- /dev/null +++ b/gfx/wr/wrench/reftests/gradient/conic-angle.yaml @@ -0,0 +1,8 @@ +--- +root: + items: + - type: conic-gradient + bounds: 50 50 300 300 + center: 150 150 + angle: 0.7853981633974483 + stops: [0.0, red, 1.0, yellow]
\ No newline at end of file diff --git a/gfx/wr/wrench/reftests/gradient/conic-backdrop-ref.yaml b/gfx/wr/wrench/reftests/gradient/conic-backdrop-ref.yaml new file mode 100644 index 0000000000..e4d55171d3 --- /dev/null +++ b/gfx/wr/wrench/reftests/gradient/conic-backdrop-ref.yaml @@ -0,0 +1,11 @@ +--- +root: + items: + - type: rect + bounds: 0 0 800 450 + color: red + - type: conic-gradient + bounds: 0 0 800 450 + center: 400 225 + angle: 0.0 + stops: [ 0.0, [255, 255, 255, 1], 1.0, [0,0,0,1] ] diff --git a/gfx/wr/wrench/reftests/gradient/conic-backdrop-with-spacing-ref.yaml b/gfx/wr/wrench/reftests/gradient/conic-backdrop-with-spacing-ref.yaml new file mode 100644 index 0000000000..2f9bd2225b --- /dev/null +++ b/gfx/wr/wrench/reftests/gradient/conic-backdrop-with-spacing-ref.yaml @@ -0,0 +1,13 @@ +--- +root: + items: + - type: rect + bounds: 0 0 800 450 + color: red + - type: conic-gradient + bounds: 0 0 800 450 + center: 100 100 + angle: 0.0 + stops: [ 0.0, [255, 255, 255, 1], 1.0, [0,0,0,1] ] + tile-size: 100 100 + tile-spacing: 20 20 diff --git a/gfx/wr/wrench/reftests/gradient/conic-backdrop-with-spacing.yaml b/gfx/wr/wrench/reftests/gradient/conic-backdrop-with-spacing.yaml new file mode 100644 index 0000000000..063492ec95 --- /dev/null +++ b/gfx/wr/wrench/reftests/gradient/conic-backdrop-with-spacing.yaml @@ -0,0 +1,18 @@ +--- +root: + items: + - type: rect + bounds: 0 0 800 450 + color: red + - type: "scroll-frame" + bounds: 0 0 800 450 + clip-rect: 0 0 800 450 + id: 2 + - type: conic-gradient + bounds: 0 0 800 450 + "clip-and-scroll": 2 + center: 100 100 + angle: 0.0 + stops: [ 0.0, [255, 255, 255, 1], 1.0, [0,0,0,1] ] + tile-size: 100 100 + tile-spacing: 20 20 diff --git a/gfx/wr/wrench/reftests/gradient/conic-backdrop.yaml b/gfx/wr/wrench/reftests/gradient/conic-backdrop.yaml new file mode 100644 index 0000000000..fafaacd4fa --- /dev/null +++ b/gfx/wr/wrench/reftests/gradient/conic-backdrop.yaml @@ -0,0 +1,16 @@ +--- +root: + items: + - type: rect + bounds: 0 0 800 450 + color: red + - type: "scroll-frame" + bounds: 0 0 800 450 + clip-rect: 0 0 800 450 + id: 2 + - type: conic-gradient + bounds: 0 0 800 450 + "clip-and-scroll": 2 + center: 400 225 + angle: 0.0 + stops: [ 0.0, [255, 255, 255, 1], 1.0, [0,0,0,1] ] diff --git a/gfx/wr/wrench/reftests/gradient/conic-center.png b/gfx/wr/wrench/reftests/gradient/conic-center.png Binary files differnew file mode 100644 index 0000000000..9843a2efb5 --- /dev/null +++ b/gfx/wr/wrench/reftests/gradient/conic-center.png diff --git a/gfx/wr/wrench/reftests/gradient/conic-center.yaml b/gfx/wr/wrench/reftests/gradient/conic-center.yaml new file mode 100644 index 0000000000..d01ebc9c8e --- /dev/null +++ b/gfx/wr/wrench/reftests/gradient/conic-center.yaml @@ -0,0 +1,11 @@ +--- +root: + items: + - type: conic-gradient + bounds: 50 50 200 200 + center: 50 50 + angle: 0.0 + stops: [0.0, red, 0.25, red, + 0.25, green, 0.5, green, + 0.5, blue, 0.75, blue, + 0.75, black, 1.0, black]
\ No newline at end of file diff --git a/gfx/wr/wrench/reftests/gradient/conic-color-wheel.png b/gfx/wr/wrench/reftests/gradient/conic-color-wheel.png Binary files differnew file mode 100644 index 0000000000..c4e0dfeda6 --- /dev/null +++ b/gfx/wr/wrench/reftests/gradient/conic-color-wheel.png diff --git a/gfx/wr/wrench/reftests/gradient/conic-color-wheel.yaml b/gfx/wr/wrench/reftests/gradient/conic-color-wheel.yaml new file mode 100644 index 0000000000..5414529572 --- /dev/null +++ b/gfx/wr/wrench/reftests/gradient/conic-color-wheel.yaml @@ -0,0 +1,14 @@ +--- +root: + items: + - type: clip + bounds: [50, 50, 300, 300] + complex: + - rect: [50, 50, 300, 300] + radius: 300 + items: + - type: conic-gradient + bounds: 50 50 300 300 + center: 150 150 + angle: 0.0 + stops: [0.0, red, 0.16666, yellow, 0.33333, green, 0.5, [0,255,255,1], 0.66666, blue, 0.83333, [255,0,255,1], 1.0, red] diff --git a/gfx/wr/wrench/reftests/gradient/conic-ref.yaml b/gfx/wr/wrench/reftests/gradient/conic-ref.yaml new file mode 100644 index 0000000000..c29484ae9c --- /dev/null +++ b/gfx/wr/wrench/reftests/gradient/conic-ref.yaml @@ -0,0 +1,18 @@ +--- +root: + items: + - type: stacking-context + bounds: 50 50 100 100 + items: + - type: rect + bounds: 0 0 100 100 + color: black + - type: rect + bounds: 100 0 100 100 + color: red + - type: rect + bounds: 100 100 100 100 + color: green + - type: rect + bounds: 0 100 100 100 + color: blue diff --git a/gfx/wr/wrench/reftests/gradient/conic-simple.png b/gfx/wr/wrench/reftests/gradient/conic-simple.png Binary files differnew file mode 100644 index 0000000000..79d0885c40 --- /dev/null +++ b/gfx/wr/wrench/reftests/gradient/conic-simple.png diff --git a/gfx/wr/wrench/reftests/gradient/conic-simple.yaml b/gfx/wr/wrench/reftests/gradient/conic-simple.yaml new file mode 100644 index 0000000000..c40c878403 --- /dev/null +++ b/gfx/wr/wrench/reftests/gradient/conic-simple.yaml @@ -0,0 +1,8 @@ +--- +root: + items: + - type: conic-gradient + bounds: 50 50 300 300 + center: 150 150 + angle: 0.0 + stops: [0.0, red, 1.0, yellow]
\ No newline at end of file diff --git a/gfx/wr/wrench/reftests/gradient/conic.yaml b/gfx/wr/wrench/reftests/gradient/conic.yaml new file mode 100644 index 0000000000..ad034d6a9b --- /dev/null +++ b/gfx/wr/wrench/reftests/gradient/conic.yaml @@ -0,0 +1,11 @@ +--- +root: + items: + - type: conic-gradient + bounds: 50 50 200 200 + center: 100 100 + angle: 0.0 + stops: [0.0, red, 0.25, red, + 0.25, green, 0.5, green, + 0.5, blue, 0.75, blue, + 0.75, black, 1.0, black]
\ No newline at end of file diff --git a/gfx/wr/wrench/reftests/gradient/gradient_cache_5stops.yaml b/gfx/wr/wrench/reftests/gradient/gradient_cache_5stops.yaml new file mode 100644 index 0000000000..d448723002 --- /dev/null +++ b/gfx/wr/wrench/reftests/gradient/gradient_cache_5stops.yaml @@ -0,0 +1,13 @@ +---
+root:
+ items:
+ - type: gradient
+ bounds: 0 0 960 540
+ start: 0 0
+ end: 960 0
+ stops: [0.0, red,
+ 0.25, green,
+ 0.5, blue,
+ 0.75, [40,40,40,1],
+ 1.0, [100,200,50,1]]
+
diff --git a/gfx/wr/wrench/reftests/gradient/gradient_cache_5stops_ref.yaml b/gfx/wr/wrench/reftests/gradient/gradient_cache_5stops_ref.yaml new file mode 100644 index 0000000000..34b6b0e01c --- /dev/null +++ b/gfx/wr/wrench/reftests/gradient/gradient_cache_5stops_ref.yaml @@ -0,0 +1,18 @@ +---
+root:
+ items:
+ - type: gradient
+ bounds: 0 0 480 540
+ start: 0 0
+ end: 480 0
+ stops: [0.0, red,
+ 0.5, green,
+ 1.0, blue]
+ - type: gradient
+ bounds: 480 0 480 540
+ start: 0 0
+ end: 480 0
+ stops: [ 0.0, blue,
+ 0.5, [40,40,40,1],
+ 1.0, [100,200,50,1]]
+
diff --git a/gfx/wr/wrench/reftests/gradient/gradient_cache_5stops_vertical.yaml b/gfx/wr/wrench/reftests/gradient/gradient_cache_5stops_vertical.yaml new file mode 100644 index 0000000000..dd2c8b7c9d --- /dev/null +++ b/gfx/wr/wrench/reftests/gradient/gradient_cache_5stops_vertical.yaml @@ -0,0 +1,13 @@ +---
+root:
+ items:
+ - type: gradient
+ bounds: 0 0 960 540
+ start: 0 0
+ end: 0 540
+ stops: [0.0, red,
+ 0.25, green,
+ 0.5, blue,
+ 0.75, [40,40,40,1],
+ 1.0, [100,200,50,1]]
+
diff --git a/gfx/wr/wrench/reftests/gradient/gradient_cache_5stops_vertical_ref.yaml b/gfx/wr/wrench/reftests/gradient/gradient_cache_5stops_vertical_ref.yaml new file mode 100644 index 0000000000..704b5be2f6 --- /dev/null +++ b/gfx/wr/wrench/reftests/gradient/gradient_cache_5stops_vertical_ref.yaml @@ -0,0 +1,18 @@ +---
+root:
+ items:
+ - type: gradient
+ bounds: 0 0 960 270
+ start: 0 0
+ end: 0 270
+ stops: [0.0, red,
+ 0.5, green,
+ 1.0, blue]
+ - type: gradient
+ bounds: 0 270 960 270
+ start: 0 0
+ end: 0 270
+ stops: [ 0.0, blue,
+ 0.5, [40,40,40,1],
+ 1.0, [100,200,50,1]]
+
diff --git a/gfx/wr/wrench/reftests/gradient/gradient_cache_clamp.yaml b/gfx/wr/wrench/reftests/gradient/gradient_cache_clamp.yaml new file mode 100644 index 0000000000..1c55a269a1 --- /dev/null +++ b/gfx/wr/wrench/reftests/gradient/gradient_cache_clamp.yaml @@ -0,0 +1,20 @@ +---
+root:
+ items:
+ - type: gradient
+ bounds: 0 0 400 200
+ start: 0 100
+ end: 100 100
+ stops: [0.0, blue, 1.0, blue, 1.0, red]
+ - type: gradient
+ bounds: 0 300 400 200
+ start: 100 100
+ end: 200 100
+ stops: [0.0, blue, 1.0, blue, 1.0, red]
+ - type: gradient
+ bounds: 0 600 200 400
+ start: 0 100
+ end: 0 300
+ stops: [
+ 0.0, blue,
+ 1.0, red]
diff --git a/gfx/wr/wrench/reftests/gradient/gradient_cache_clamp_ref.yaml b/gfx/wr/wrench/reftests/gradient/gradient_cache_clamp_ref.yaml new file mode 100644 index 0000000000..4631192cd8 --- /dev/null +++ b/gfx/wr/wrench/reftests/gradient/gradient_cache_clamp_ref.yaml @@ -0,0 +1,30 @@ +---
+root:
+ items:
+ - type: gradient
+ bounds: 0 0 400 200
+ start: 0 100
+ end: 400 100
+ stops: [
+ 0.0, blue,
+ 0.25, blue,
+ 0.25, red,
+ 1.0, red]
+ - type: gradient
+ bounds: 0 300 400 200
+ start: 0 100
+ end: 400 100
+ stops: [
+ 0.0, blue,
+ 0.5, blue,
+ 0.5, red,
+ 1.0, red]
+ - type: gradient
+ bounds: 0 600 200 400
+ start: 0 0
+ end: 0 400
+ stops: [
+ 0.0, blue,
+ 0.25, blue,
+ 0.75, red,
+ 1.0, red]
diff --git a/gfx/wr/wrench/reftests/gradient/gradient_cache_hardstop.yaml b/gfx/wr/wrench/reftests/gradient/gradient_cache_hardstop.yaml new file mode 100644 index 0000000000..53c908fb22 --- /dev/null +++ b/gfx/wr/wrench/reftests/gradient/gradient_cache_hardstop.yaml @@ -0,0 +1,19 @@ +---
+root:
+ items:
+ - type: gradient
+ bounds: 0 0 960 540
+ start: 0 0
+ end: 960 0
+ stops: [0.0, red,
+ 0.125, yellow,
+ 0.25, red,
+ 0.25, green,
+ 0.375, yellow,
+ 0.5, green,
+ 0.5, blue,
+ 0.625, yellow,
+ 0.75, blue,
+ 0.75, white,
+ 1.0, [100,200,50,1]]
+
diff --git a/gfx/wr/wrench/reftests/gradient/gradient_cache_hardstop_clip.yaml b/gfx/wr/wrench/reftests/gradient/gradient_cache_hardstop_clip.yaml new file mode 100644 index 0000000000..3e7a2e946f --- /dev/null +++ b/gfx/wr/wrench/reftests/gradient/gradient_cache_hardstop_clip.yaml @@ -0,0 +1,21 @@ +---
+root:
+ items:
+ - type: gradient
+ bounds: 0 0 960 540
+ start: 0 0
+ end: 960 0
+ stops: [0.0, red,
+ 0.125, yellow,
+ 0.25, red,
+ 0.25, green,
+ 0.375, yellow,
+ 0.5, green,
+ 0.5, blue,
+ 0.625, yellow,
+ 0.75, blue,
+ 0.75, white,
+ 1.0, [100,200,50,1]]
+ complex-clip:
+ rect: [100, 100, 760, 340]
+ radius: [32, 32]
diff --git a/gfx/wr/wrench/reftests/gradient/gradient_cache_hardstop_clip_ref.yaml b/gfx/wr/wrench/reftests/gradient/gradient_cache_hardstop_clip_ref.yaml new file mode 100644 index 0000000000..2b27c5649c --- /dev/null +++ b/gfx/wr/wrench/reftests/gradient/gradient_cache_hardstop_clip_ref.yaml @@ -0,0 +1,28 @@ +---
+root:
+ items:
+ - type: gradient
+ bounds: 0 0 480 540
+ start: 0 0
+ end: 480 0
+ stops: [0.0, red,
+ 0.25, yellow,
+ 0.5, red,
+ 0.5, green,
+ 0.75, yellow,
+ 1.0, green]
+ complex-clip:
+ rect: [100, 100, 760, 340]
+ radius: [32, 32]
+ - type: gradient
+ bounds: 480 0 480 540
+ start: 0 0
+ end: 480 0
+ stops: [0.0, blue,
+ 0.25, yellow,
+ 0.5, blue,
+ 0.5, white,
+ 1.0, [100,200,50,1]]
+ complex-clip:
+ rect: [100, 100, 760, 340]
+ radius: [32, 32]
diff --git a/gfx/wr/wrench/reftests/gradient/gradient_cache_hardstop_ref.yaml b/gfx/wr/wrench/reftests/gradient/gradient_cache_hardstop_ref.yaml new file mode 100644 index 0000000000..e4b3928046 --- /dev/null +++ b/gfx/wr/wrench/reftests/gradient/gradient_cache_hardstop_ref.yaml @@ -0,0 +1,24 @@ +---
+root:
+ items:
+ - type: gradient
+ bounds: 0 0 480 540
+ start: 0 0
+ end: 480 0
+ stops: [0.0, red,
+ 0.25, yellow,
+ 0.5, red,
+ 0.5, green,
+ 0.75, yellow,
+ 1.0, green]
+ - type: gradient
+ bounds: 480 0 480 540
+ start: 0 0
+ end: 480 0
+ stops: [0.0, blue,
+ 0.25, yellow,
+ 0.5, blue,
+ 0.5, white,
+ 1.0, [100,200,50,1]]
+
+
diff --git a/gfx/wr/wrench/reftests/gradient/gradient_cache_repeat.yaml b/gfx/wr/wrench/reftests/gradient/gradient_cache_repeat.yaml new file mode 100644 index 0000000000..20a07a72a6 --- /dev/null +++ b/gfx/wr/wrench/reftests/gradient/gradient_cache_repeat.yaml @@ -0,0 +1,119 @@ +---
+root:
+ items:
+ # non-repeating
+ - type: gradient
+ bounds: 100 50 500 10
+ start: 100 0
+ end: 200 0
+ repeat: false
+ stops: [0.0, green,
+ 0.5, green,
+ 0.5, blue,
+ 1.0, blue ]
+
+ # repeat 4 times
+ - type: gradient
+ bounds: 100 100 500 10
+ start: 100 0
+ end: 200 0
+ repeat: true
+ stops: [0.0, green,
+ 0.5, green,
+ 0.5, blue,
+ 1.0, blue ]
+
+ # same but start doesn't line up with 0
+ - type: gradient
+ bounds: 100 150 500 10
+ start: 125 0
+ end: 225 0
+ repeat: true
+ stops: [0.0, green,
+ 0.5, green,
+ 0.5, blue,
+ 1.0, blue ]
+
+ # more hard stops, non-uniform distribution
+ - type: gradient
+ bounds: 100 250 500 10
+ start: 200 0
+ end: 300 0
+ repeat: false
+ stops: [0.0, green,
+ 0.25, green,
+ 0.25, red,
+ 0.75, red,
+ 0.75, blue,
+ 1.0, blue ]
+
+ # repeat the hard stops
+ - type: gradient
+ bounds: 100 300 500 10
+ start: 200 0
+ end: 300 0
+ repeat: true
+ stops: [0.0, green,
+ 0.25, green,
+ 0.25, red,
+ 0.75, red,
+ 0.75, blue,
+ 1.0, blue ]
+
+ # same but start doesn't line up with 0
+ - type: gradient
+ bounds: 100 350 500 10
+ start: 175 0
+ end: 275 0
+ repeat: true
+ stops: [0.0, green,
+ 0.25, green,
+ 0.25, red,
+ 0.75, red,
+ 0.75, blue,
+ 1.0, blue ]
+
+ # the entire gradient from 0 to 1 is
+ # "offscreen", we're only seeing its
+ # repeats. the gradient is 100 wide
+ # and ends at -75, so the first
+ # three-quarters of it would be hidden,
+ # that is, it should start with blue.
+ - type: gradient
+ bounds: 100 400 500 10
+ start: -175 0
+ end: -75 0
+ repeat: true
+ stops: [0.0, green,
+ 0.25, green,
+ 0.25, red,
+ 0.75, red,
+ 0.75, blue,
+ 1.0, blue ]
+
+ # same but over on the right
+ - type: gradient
+ bounds: 100 450 500 10
+ start: 575 0
+ end: 675 0
+ repeat: true
+ stops: [0.0, green,
+ 0.25, green,
+ 0.25, red,
+ 0.75, red,
+ 0.75, blue,
+ 1.0, blue ]
+
+ # a repeat, but not really because only part
+ # of the gradient is visible
+ - type: gradient
+ bounds: 100 500 500 10
+ start: -50 0
+ end: 550 0
+ repeat: true
+ stops: [0.0, green,
+ 0.25, green,
+ 0.25, red,
+ 0.75, red,
+ 0.75, blue,
+ 1.0, blue ]
diff --git a/gfx/wr/wrench/reftests/gradient/gradient_cache_repeat_ref.yaml b/gfx/wr/wrench/reftests/gradient/gradient_cache_repeat_ref.yaml new file mode 100644 index 0000000000..e1682622f8 --- /dev/null +++ b/gfx/wr/wrench/reftests/gradient/gradient_cache_repeat_ref.yaml @@ -0,0 +1,119 @@ +---
+root:
+ items:
+ # non-repeating
+ - type: gradient
+ bounds: 100 50 500 10
+ start: 100 0
+ end: 200 0.001
+ repeat: false
+ stops: [0.0, green,
+ 0.5, green,
+ 0.5, blue,
+ 1.0, blue ]
+
+ # repeat 4 times
+ - type: gradient
+ bounds: 100 100 500 10
+ start: 100 0
+ end: 200 0.001
+ repeat: true
+ stops: [0.0, green,
+ 0.5, green,
+ 0.5, blue,
+ 1.0, blue ]
+
+ # same but start doesn't line up with 0
+ - type: gradient
+ bounds: 100 150 500 10
+ start: 125 0
+ end: 225 0.001
+ repeat: true
+ stops: [0.0, green,
+ 0.5, green,
+ 0.5, blue,
+ 1.0, blue ]
+
+ # more hard stops, non-uniform distribution
+ - type: gradient
+ bounds: 100 250 500 10
+ start: 200 0
+ end: 300 0.001
+ repeat: false
+ stops: [0.0, green,
+ 0.25, green,
+ 0.25, red,
+ 0.75, red,
+ 0.75, blue,
+ 1.0, blue ]
+
+ # repeat the hard stops
+ - type: gradient
+ bounds: 100 300 500 10
+ start: 200 0
+ end: 300 0.001
+ repeat: true
+ stops: [0.0, green,
+ 0.25, green,
+ 0.25, red,
+ 0.75, red,
+ 0.75, blue,
+ 1.0, blue ]
+
+ # same but start doesn't line up with 0
+ - type: gradient
+ bounds: 100 350 500 10
+ start: 175 0
+ end: 275 0.001
+ repeat: true
+ stops: [0.0, green,
+ 0.25, green,
+ 0.25, red,
+ 0.75, red,
+ 0.75, blue,
+ 1.0, blue ]
+
+ # the entire gradient from 0 to 1 is
+ # "offscreen", we're only seeing its
+ # repeats. the gradient is 100 wide
+ # and ends at -75, so the first
+ # three-quarters of it would be hidden,
+ # that is, it should start with blue.
+ - type: gradient
+ bounds: 100 400 500 10
+ start: -175 0
+ end: -75 0.001
+ repeat: true
+ stops: [0.0, green,
+ 0.25, green,
+ 0.25, red,
+ 0.75, red,
+ 0.75, blue,
+ 1.0, blue ]
+
+ # same but over on the right
+ - type: gradient
+ bounds: 100 450 500 10
+ start: 575 0
+ end: 675 0.001
+ repeat: true
+ stops: [0.0, green,
+ 0.25, green,
+ 0.25, red,
+ 0.75, red,
+ 0.75, blue,
+ 1.0, blue ]
+
+ # a repeat, but not really because only part
+ # of the gradient is visible
+ - type: gradient
+ bounds: 100 500 500 10
+ start: -50 0
+ end: 550 0.001
+ repeat: true
+ stops: [0.0, green,
+ 0.25, green,
+ 0.25, red,
+ 0.75, red,
+ 0.75, blue,
+ 1.0, blue ]
diff --git a/gfx/wr/wrench/reftests/gradient/linear-adjust-tile-size-ref.yaml b/gfx/wr/wrench/reftests/gradient/linear-adjust-tile-size-ref.yaml new file mode 100644 index 0000000000..c9145fc5e6 --- /dev/null +++ b/gfx/wr/wrench/reftests/gradient/linear-adjust-tile-size-ref.yaml @@ -0,0 +1,9 @@ +--- +root: + items: + - type: gradient + bounds: 15.47998046875 18 684.39990234375 643.199951171875 + start: 10.286011695861816 653.47998046875 + end: 143.13165283203125 520.7279663085938 + stops: [0.0, red, 1.0, blue] + repeat: true diff --git a/gfx/wr/wrench/reftests/gradient/linear-adjust-tile-size.yaml b/gfx/wr/wrench/reftests/gradient/linear-adjust-tile-size.yaml new file mode 100644 index 0000000000..4d78b9b99e --- /dev/null +++ b/gfx/wr/wrench/reftests/gradient/linear-adjust-tile-size.yaml @@ -0,0 +1,10 @@ +--- +root: + items: + - type: gradient + bounds: 15.47998046875 18 684.39990234375 643.199951171875 + tile-size: 684.4000244140625 643.2000122070313 + start: 10.286011695861816 653.47998046875 + end: 143.13165283203125 520.7279663085938 + stops: [0.0, red, 1.0, blue] + repeat: true diff --git a/gfx/wr/wrench/reftests/gradient/linear-aligned-border-radius.png b/gfx/wr/wrench/reftests/gradient/linear-aligned-border-radius.png Binary files differnew file mode 100644 index 0000000000..2f9c3d2700 --- /dev/null +++ b/gfx/wr/wrench/reftests/gradient/linear-aligned-border-radius.png diff --git a/gfx/wr/wrench/reftests/gradient/linear-aligned-border-radius.yaml b/gfx/wr/wrench/reftests/gradient/linear-aligned-border-radius.yaml new file mode 100644 index 0000000000..a79b4423c3 --- /dev/null +++ b/gfx/wr/wrench/reftests/gradient/linear-aligned-border-radius.yaml @@ -0,0 +1,46 @@ +--- +root: + items: + - type: clip + bounds: [20, 20, 100, 100] + complex: + - rect: [20, 20, 100, 100] + radius: 32 + items: + - type: gradient + bounds: 20 20 100 100 + start: 50 0 + end: 50 100 + stops: [0.0, red, 1.0, yellow] + + - type: rect + bounds: [130, 10, 120, 120] + color: blue + + - type: clip + bounds: [140, 20, 100, 100] + complex: + - rect: [140, 20, 100, 100] + radius: 32 + items: + - type: gradient + bounds: 140 20 100 100 + start: 50 0 + end: 50 100 + stops: [0.0, red, 1.0, yellow] + + - type: rect + bounds: [260, 10, 120, 120] + color: black + + - type: clip + bounds: [270, 20, 100, 100] + complex: + - rect: [270, 20, 100, 100] + radius: 32 + items: + - type: gradient + bounds: 270 20 100 100 + start: 50 0 + end: 50 100 + stops: [0.0, red, 1.0, yellow] diff --git a/gfx/wr/wrench/reftests/gradient/linear-aligned-clip-ref.yaml b/gfx/wr/wrench/reftests/gradient/linear-aligned-clip-ref.yaml new file mode 100644 index 0000000000..08a395dc71 --- /dev/null +++ b/gfx/wr/wrench/reftests/gradient/linear-aligned-clip-ref.yaml @@ -0,0 +1,16 @@ +--- +root: + items: + # an aligned gradient from [0, 400] + - type: gradient + bounds: 0 0 200 400 + start: 100 0 + end: 100 400 + stops: [0.0, green, 1.0, blue] + # manual clipping + - type: rect + bounds: 0 0 200 100 + color: white + - type: rect + bounds: 0 300 200 100 + color: white diff --git a/gfx/wr/wrench/reftests/gradient/linear-aligned-clip.yaml b/gfx/wr/wrench/reftests/gradient/linear-aligned-clip.yaml new file mode 100644 index 0000000000..fad030724f --- /dev/null +++ b/gfx/wr/wrench/reftests/gradient/linear-aligned-clip.yaml @@ -0,0 +1,9 @@ +--- +root: + items: + # an aligned gradient from [0, 400] and clipped to [100, 300] + - type: gradient + bounds: 0 100 200 200 + start: 100 -100 + end: 100 300 + stops: [0.0, green, 1.0, blue] diff --git a/gfx/wr/wrench/reftests/gradient/linear-backdrop-ref.yaml b/gfx/wr/wrench/reftests/gradient/linear-backdrop-ref.yaml new file mode 100644 index 0000000000..7cc02b573c --- /dev/null +++ b/gfx/wr/wrench/reftests/gradient/linear-backdrop-ref.yaml @@ -0,0 +1,11 @@ +--- +root: + items: + - type: rect + bounds: 0 0 800 450 + color: red + - type: gradient + bounds: 0 0 800 450 + start: 100 100 + end: 700 350 + stops: [ 0.0, [255, 255, 255, 1], 1.0, [0,0,0,1] ] diff --git a/gfx/wr/wrench/reftests/gradient/linear-backdrop-with-spacing-ref.yaml b/gfx/wr/wrench/reftests/gradient/linear-backdrop-with-spacing-ref.yaml new file mode 100644 index 0000000000..e72d156433 --- /dev/null +++ b/gfx/wr/wrench/reftests/gradient/linear-backdrop-with-spacing-ref.yaml @@ -0,0 +1,14 @@ +--- +root: + items: + - type: rect + bounds: 0 0 800 450 + color: red + - type: gradient + bounds: 0 0 800 450 + start: 20 20 + end: 80 50 + stops: [ 0.0, [255, 255, 255, 1], 1.0, [0,0,0,1] ] + tile-size: 100 100 + tile-spacing: 20 20 + diff --git a/gfx/wr/wrench/reftests/gradient/linear-backdrop-with-spacing.yaml b/gfx/wr/wrench/reftests/gradient/linear-backdrop-with-spacing.yaml new file mode 100644 index 0000000000..083222b6ac --- /dev/null +++ b/gfx/wr/wrench/reftests/gradient/linear-backdrop-with-spacing.yaml @@ -0,0 +1,18 @@ +--- +root: + items: + - type: rect + bounds: 0 0 800 450 + color: red + - type: "scroll-frame" + bounds: 0 0 800 450 + clip-rect: 0 0 800 450 + id: 2 + - type: gradient + bounds: 0 0 800 450 + "clip-and-scroll": 2 + start: 20 20 + end: 80 50 + stops: [ 0.0, [255, 255, 255, 1], 1.0, [0,0,0,1] ] + tile-size: 100 100 + tile-spacing: 20 20 diff --git a/gfx/wr/wrench/reftests/gradient/linear-backdrop.yaml b/gfx/wr/wrench/reftests/gradient/linear-backdrop.yaml new file mode 100644 index 0000000000..4a4eea5b66 --- /dev/null +++ b/gfx/wr/wrench/reftests/gradient/linear-backdrop.yaml @@ -0,0 +1,16 @@ +--- +root: + items: + - type: rect + bounds: 0 0 800 450 + color: red + - type: "scroll-frame" + bounds: 0 0 800 450 + clip-rect: 0 0 800 450 + id: 2 + - type: gradient + bounds: 0 0 800 450 + "clip-and-scroll": 2 + start: 100 100 + end: 700 350 + stops: [ 0.0, [255, 255, 255, 1], 1.0, [0,0,0,1] ] diff --git a/gfx/wr/wrench/reftests/gradient/linear-clamp-1-ref.yaml b/gfx/wr/wrench/reftests/gradient/linear-clamp-1-ref.yaml new file mode 100644 index 0000000000..81c366d858 --- /dev/null +++ b/gfx/wr/wrench/reftests/gradient/linear-clamp-1-ref.yaml @@ -0,0 +1,8 @@ +--- +root: + items: + - type: gradient + bounds: 50 50 200 200 + start: 0 100 + end: 200 100 + stops: [0.0, blue, 0.5, blue, 0.5, red, 1.0, red] diff --git a/gfx/wr/wrench/reftests/gradient/linear-clamp-1a.yaml b/gfx/wr/wrench/reftests/gradient/linear-clamp-1a.yaml new file mode 100644 index 0000000000..b83963a37a --- /dev/null +++ b/gfx/wr/wrench/reftests/gradient/linear-clamp-1a.yaml @@ -0,0 +1,8 @@ +--- +root: + items: + - type: gradient + bounds: 50 50 200 200 + start: 0 100 + end: 100 100 + stops: [0.0, blue, 1.0, blue, 1.0, red] diff --git a/gfx/wr/wrench/reftests/gradient/linear-clamp-1b.yaml b/gfx/wr/wrench/reftests/gradient/linear-clamp-1b.yaml new file mode 100644 index 0000000000..ffe3391999 --- /dev/null +++ b/gfx/wr/wrench/reftests/gradient/linear-clamp-1b.yaml @@ -0,0 +1,8 @@ +--- +root: + items: + - type: gradient + bounds: 50 50 200 200 + start: 100 100 + end: 200 100 + stops: [0.0, blue, 0.0, red, 1.0, red] diff --git a/gfx/wr/wrench/reftests/gradient/linear-clamp-2-ref.yaml b/gfx/wr/wrench/reftests/gradient/linear-clamp-2-ref.yaml new file mode 100644 index 0000000000..8eb475d0a5 --- /dev/null +++ b/gfx/wr/wrench/reftests/gradient/linear-clamp-2-ref.yaml @@ -0,0 +1,8 @@ +--- +root: + items: + - type: gradient + bounds: 50 50 200 200 + start: 0 100 + end: 200 100 + stops: [0.0, blue, 0.25, blue, 0.25, green, 0.75, green, 0.75, red, 1.0, red] diff --git a/gfx/wr/wrench/reftests/gradient/linear-clamp-2.yaml b/gfx/wr/wrench/reftests/gradient/linear-clamp-2.yaml new file mode 100644 index 0000000000..48428b974a --- /dev/null +++ b/gfx/wr/wrench/reftests/gradient/linear-clamp-2.yaml @@ -0,0 +1,8 @@ +--- +root: + items: + - type: gradient + bounds: 50 50 200 200 + start: 50 100 + end: 150 100 + stops: [0.0, blue, 0.0, green, 1.0, green, 1.0, red] diff --git a/gfx/wr/wrench/reftests/gradient/linear-double.yaml b/gfx/wr/wrench/reftests/gradient/linear-double.yaml new file mode 100644 index 0000000000..c9e4a44d84 --- /dev/null +++ b/gfx/wr/wrench/reftests/gradient/linear-double.yaml @@ -0,0 +1,13 @@ +--- +root: + items: + - type: gradient + bounds: 300 50 200 200 + start: 0 100 + end: 200 100 + stops: [0.0, blue, 1.0, red] + - type: gradient + bounds: 50 50 200 200 + start: 0 100 + end: 200 100 + stops: [0.0, green, 1.0, blue] diff --git a/gfx/wr/wrench/reftests/gradient/linear-hard-stop-ref.png b/gfx/wr/wrench/reftests/gradient/linear-hard-stop-ref.png Binary files differnew file mode 100644 index 0000000000..4feb5e4993 --- /dev/null +++ b/gfx/wr/wrench/reftests/gradient/linear-hard-stop-ref.png diff --git a/gfx/wr/wrench/reftests/gradient/linear-hard-stop.yaml b/gfx/wr/wrench/reftests/gradient/linear-hard-stop.yaml new file mode 100644 index 0000000000..b9249e7f2a --- /dev/null +++ b/gfx/wr/wrench/reftests/gradient/linear-hard-stop.yaml @@ -0,0 +1,8 @@ +--- +root: + items: + - type: gradient + bounds: 50 50 200 200 + start: 0 0 + end: 0 100 + stops: [0.0, blue, 0.5 , red, 0.5, green] diff --git a/gfx/wr/wrench/reftests/gradient/linear-ref.png b/gfx/wr/wrench/reftests/gradient/linear-ref.png Binary files differnew file mode 100644 index 0000000000..b157ee4bef --- /dev/null +++ b/gfx/wr/wrench/reftests/gradient/linear-ref.png diff --git a/gfx/wr/wrench/reftests/gradient/linear-ref.yaml b/gfx/wr/wrench/reftests/gradient/linear-ref.yaml new file mode 100644 index 0000000000..83d7248166 --- /dev/null +++ b/gfx/wr/wrench/reftests/gradient/linear-ref.yaml @@ -0,0 +1,18 @@ +--- +root: + items: + - type: stacking-context + bounds: 50 50 200 200 + items: + - type: rect + bounds: 0 0 50 200 + color: red + - type: rect + bounds: 50 0 50 200 + color: green + - type: rect + bounds: 100 0 50 200 + color: blue + - type: rect + bounds: 150 0 50 200 + color: black diff --git a/gfx/wr/wrench/reftests/gradient/linear-reverse.yaml b/gfx/wr/wrench/reftests/gradient/linear-reverse.yaml new file mode 100644 index 0000000000..ecae199e88 --- /dev/null +++ b/gfx/wr/wrench/reftests/gradient/linear-reverse.yaml @@ -0,0 +1,11 @@ +--- +root: + items: + - type: gradient + bounds: 50 50 200 200 + start: 200 100 + end: 000 100 + stops: [0.0, black, 0.25, black, + 0.25, blue, 0.5, blue, + 0.5, green, 0.75, green, + 0.75, red, 1.0, red] diff --git a/gfx/wr/wrench/reftests/gradient/linear-stops-ref.png b/gfx/wr/wrench/reftests/gradient/linear-stops-ref.png Binary files differnew file mode 100644 index 0000000000..dca38ed429 --- /dev/null +++ b/gfx/wr/wrench/reftests/gradient/linear-stops-ref.png diff --git a/gfx/wr/wrench/reftests/gradient/linear-stops.yaml b/gfx/wr/wrench/reftests/gradient/linear-stops.yaml new file mode 100644 index 0000000000..f5b8bfbc99 --- /dev/null +++ b/gfx/wr/wrench/reftests/gradient/linear-stops.yaml @@ -0,0 +1,7 @@ +root: + items: + - type: gradient + bounds: [0, 0, 200, 200] + start: 0 100 + end: 200 100 + stops: [0.0, red, 0.5, green, 1.0, blue] diff --git a/gfx/wr/wrench/reftests/gradient/linear.yaml b/gfx/wr/wrench/reftests/gradient/linear.yaml new file mode 100644 index 0000000000..53d8d512cd --- /dev/null +++ b/gfx/wr/wrench/reftests/gradient/linear.yaml @@ -0,0 +1,11 @@ +--- +root: + items: + - type: gradient + bounds: 50 50 200 200 + start: 0 100 + end: 200 100 + stops: [0.0, red, 0.25, red, + 0.25, green, 0.5, green, + 0.5, blue, 0.75, blue, + 0.75, black, 1.0, black] diff --git a/gfx/wr/wrench/reftests/gradient/norm-conic-1-ref.yaml b/gfx/wr/wrench/reftests/gradient/norm-conic-1-ref.yaml new file mode 100644 index 0000000000..a3bb761463 --- /dev/null +++ b/gfx/wr/wrench/reftests/gradient/norm-conic-1-ref.yaml @@ -0,0 +1,9 @@ +--- +root: + items: + - type: conic-gradient + bounds: 50 50 200 200 + angle: 0.0 + center: 100 100 + stops: [0.0, green, 0.5, green, + 0.5, blue, 1.0, blue] diff --git a/gfx/wr/wrench/reftests/gradient/norm-conic-1.yaml b/gfx/wr/wrench/reftests/gradient/norm-conic-1.yaml new file mode 100644 index 0000000000..8bf6b734c2 --- /dev/null +++ b/gfx/wr/wrench/reftests/gradient/norm-conic-1.yaml @@ -0,0 +1,9 @@ +--- +root: + items: + - type: conic-gradient + bounds: 50 50 200 200 + angle: 0.0 + center: 100 100 + stops: [0.25, green, 0.5, green, + 0.5, blue, 0.75, blue] diff --git a/gfx/wr/wrench/reftests/gradient/norm-conic-2-ref.yaml b/gfx/wr/wrench/reftests/gradient/norm-conic-2-ref.yaml new file mode 100644 index 0000000000..a3bb761463 --- /dev/null +++ b/gfx/wr/wrench/reftests/gradient/norm-conic-2-ref.yaml @@ -0,0 +1,9 @@ +--- +root: + items: + - type: conic-gradient + bounds: 50 50 200 200 + angle: 0.0 + center: 100 100 + stops: [0.0, green, 0.5, green, + 0.5, blue, 1.0, blue] diff --git a/gfx/wr/wrench/reftests/gradient/norm-conic-2.yaml b/gfx/wr/wrench/reftests/gradient/norm-conic-2.yaml new file mode 100644 index 0000000000..ba9b174b51 --- /dev/null +++ b/gfx/wr/wrench/reftests/gradient/norm-conic-2.yaml @@ -0,0 +1,9 @@ +--- +root: + items: + - type: conic-gradient + bounds: 50 50 200 200 + angle: 0.0 + center: 100 100 + stops: [0.5, green, + 0.5, blue] diff --git a/gfx/wr/wrench/reftests/gradient/norm-conic-3-ref.yaml b/gfx/wr/wrench/reftests/gradient/norm-conic-3-ref.yaml new file mode 100644 index 0000000000..d5403c498f --- /dev/null +++ b/gfx/wr/wrench/reftests/gradient/norm-conic-3-ref.yaml @@ -0,0 +1,8 @@ +--- +root: + items: + - type: conic-gradient + bounds: 50 50 200 200 + angle: 0.0 + center: 100 100 + stops: [0.0, blue, 1.0, blue] diff --git a/gfx/wr/wrench/reftests/gradient/norm-conic-3.yaml b/gfx/wr/wrench/reftests/gradient/norm-conic-3.yaml new file mode 100644 index 0000000000..962ff4e7aa --- /dev/null +++ b/gfx/wr/wrench/reftests/gradient/norm-conic-3.yaml @@ -0,0 +1,9 @@ +--- +root: + items: + - type: conic-gradient + bounds: 50 50 200 200 + angle: 0.0 + center: 100 100 + stops: [-0.5, green, + -0.5, blue] diff --git a/gfx/wr/wrench/reftests/gradient/norm-conic-4-ref.yaml b/gfx/wr/wrench/reftests/gradient/norm-conic-4-ref.yaml new file mode 100644 index 0000000000..6c0b6e508f --- /dev/null +++ b/gfx/wr/wrench/reftests/gradient/norm-conic-4-ref.yaml @@ -0,0 +1,8 @@ +--- +root: + items: + - type: conic-gradient + bounds: 50 50 200 200 + angle: 0.0 + center: 100 100 + stops: [0.0, green, 1.0, green] diff --git a/gfx/wr/wrench/reftests/gradient/norm-conic-4.yaml b/gfx/wr/wrench/reftests/gradient/norm-conic-4.yaml new file mode 100644 index 0000000000..6564d84721 --- /dev/null +++ b/gfx/wr/wrench/reftests/gradient/norm-conic-4.yaml @@ -0,0 +1,9 @@ +--- +root: + items: + - type: conic-gradient + bounds: 50 50 200 200 + angle: 0.0 + center: 100 100 + stops: [1.5, green, + 1.5, blue] diff --git a/gfx/wr/wrench/reftests/gradient/norm-conic-degenerate-ref.yaml b/gfx/wr/wrench/reftests/gradient/norm-conic-degenerate-ref.yaml new file mode 100644 index 0000000000..1ba6bd2f9e --- /dev/null +++ b/gfx/wr/wrench/reftests/gradient/norm-conic-degenerate-ref.yaml @@ -0,0 +1,8 @@ +--- +root: + items: + - type: conic-gradient + bounds: 50 50 300 300 + angle: 0.0 + center: 150 150 + stops: [0.0, red, 1.0, red] diff --git a/gfx/wr/wrench/reftests/gradient/norm-conic-degenerate.yaml b/gfx/wr/wrench/reftests/gradient/norm-conic-degenerate.yaml new file mode 100644 index 0000000000..be96200722 --- /dev/null +++ b/gfx/wr/wrench/reftests/gradient/norm-conic-degenerate.yaml @@ -0,0 +1,14 @@ +# see: https://www.w3.org/TR/2012/CR-css3-images-20120417/#repeating-gradients +# the spec says that repeating gradients with color stops in the same offset +# must render as a solid rect with color equal to the average color of the +# gradient. Gecko and Blink seem to draw it with color equal to the last stop +# so that is the behavior tested here +--- +root: + items: + - type: conic-gradient + bounds: 50 50 300 300 + angle: 0.0 + center: 150 150 + stops: [0.5, blue, 0.5, red] + repeat: true diff --git a/gfx/wr/wrench/reftests/gradient/norm-linear-1-ref.yaml b/gfx/wr/wrench/reftests/gradient/norm-linear-1-ref.yaml new file mode 100644 index 0000000000..5b8a0b317a --- /dev/null +++ b/gfx/wr/wrench/reftests/gradient/norm-linear-1-ref.yaml @@ -0,0 +1,9 @@ +--- +root: + items: + - type: gradient + bounds: 50 50 200 200 + start: 0 100 + end: 200 100 + stops: [0.0, green, 0.5, green, + 0.5, blue, 1.0, blue] diff --git a/gfx/wr/wrench/reftests/gradient/norm-linear-1.yaml b/gfx/wr/wrench/reftests/gradient/norm-linear-1.yaml new file mode 100644 index 0000000000..d79b8608b1 --- /dev/null +++ b/gfx/wr/wrench/reftests/gradient/norm-linear-1.yaml @@ -0,0 +1,9 @@ +--- +root: + items: + - type: gradient + bounds: 50 50 200 200 + start: 0 100 + end: 200 100 + stops: [0.25, green, 0.5, green, + 0.5, blue, 0.75, blue] diff --git a/gfx/wr/wrench/reftests/gradient/norm-linear-2-ref.yaml b/gfx/wr/wrench/reftests/gradient/norm-linear-2-ref.yaml new file mode 100644 index 0000000000..5b8a0b317a --- /dev/null +++ b/gfx/wr/wrench/reftests/gradient/norm-linear-2-ref.yaml @@ -0,0 +1,9 @@ +--- +root: + items: + - type: gradient + bounds: 50 50 200 200 + start: 0 100 + end: 200 100 + stops: [0.0, green, 0.5, green, + 0.5, blue, 1.0, blue] diff --git a/gfx/wr/wrench/reftests/gradient/norm-linear-2.yaml b/gfx/wr/wrench/reftests/gradient/norm-linear-2.yaml new file mode 100644 index 0000000000..aa3aa2afe1 --- /dev/null +++ b/gfx/wr/wrench/reftests/gradient/norm-linear-2.yaml @@ -0,0 +1,9 @@ +--- +root: + items: + - type: gradient + bounds: 50 50 200 200 + start: 0 100 + end: 200 100 + stops: [0.5, green, + 0.5, blue] diff --git a/gfx/wr/wrench/reftests/gradient/norm-linear-3-ref.yaml b/gfx/wr/wrench/reftests/gradient/norm-linear-3-ref.yaml new file mode 100644 index 0000000000..62bfda97e6 --- /dev/null +++ b/gfx/wr/wrench/reftests/gradient/norm-linear-3-ref.yaml @@ -0,0 +1,8 @@ +--- +root: + items: + - type: gradient + bounds: 50 50 200 200 + start: 0 100 + end: 200 100 + stops: [0.0, blue, 1.0, blue] diff --git a/gfx/wr/wrench/reftests/gradient/norm-linear-3.yaml b/gfx/wr/wrench/reftests/gradient/norm-linear-3.yaml new file mode 100644 index 0000000000..cc18371592 --- /dev/null +++ b/gfx/wr/wrench/reftests/gradient/norm-linear-3.yaml @@ -0,0 +1,9 @@ +--- +root: + items: + - type: gradient + bounds: 50 50 200 200 + start: 0 100 + end: 200 100 + stops: [-0.5, green, + -0.5, blue] diff --git a/gfx/wr/wrench/reftests/gradient/norm-linear-4-ref.yaml b/gfx/wr/wrench/reftests/gradient/norm-linear-4-ref.yaml new file mode 100644 index 0000000000..bcd84d8294 --- /dev/null +++ b/gfx/wr/wrench/reftests/gradient/norm-linear-4-ref.yaml @@ -0,0 +1,8 @@ +--- +root: + items: + - type: gradient + bounds: 50 50 200 200 + start: 0 100 + end: 200 100 + stops: [0.0, green, 1.0, green] diff --git a/gfx/wr/wrench/reftests/gradient/norm-linear-4.yaml b/gfx/wr/wrench/reftests/gradient/norm-linear-4.yaml new file mode 100644 index 0000000000..df622bf299 --- /dev/null +++ b/gfx/wr/wrench/reftests/gradient/norm-linear-4.yaml @@ -0,0 +1,9 @@ +--- +root: + items: + - type: gradient + bounds: 50 50 200 200 + start: 0 100 + end: 200 100 + stops: [1.5, green, + 1.5, blue] diff --git a/gfx/wr/wrench/reftests/gradient/norm-linear-degenerate-ref.yaml b/gfx/wr/wrench/reftests/gradient/norm-linear-degenerate-ref.yaml new file mode 100644 index 0000000000..ae61c486cb --- /dev/null +++ b/gfx/wr/wrench/reftests/gradient/norm-linear-degenerate-ref.yaml @@ -0,0 +1,8 @@ +--- +root: + items: + - type: gradient + bounds: 50 50 300 300 + start: 0 150 + end: 300 150 + stops: [0.0, red, 1.0, red] diff --git a/gfx/wr/wrench/reftests/gradient/norm-linear-degenerate.yaml b/gfx/wr/wrench/reftests/gradient/norm-linear-degenerate.yaml new file mode 100644 index 0000000000..89b431df32 --- /dev/null +++ b/gfx/wr/wrench/reftests/gradient/norm-linear-degenerate.yaml @@ -0,0 +1,14 @@ +# see: https://www.w3.org/TR/2012/CR-css3-images-20120417/#repeating-gradients +# the spec says that repeating gradients with color stops in the same offset +# must render as a solid rect with color equal to the average color of the +# gradient. Gecko and Blink seem to draw it with color equal to the last stop +# so that is the behavior tested here +--- +root: + items: + - type: gradient + bounds: 50 50 300 300 + start: 0 150 + end: 300 150 + stops: [0.5, blue, 0.5, red] + repeat: true diff --git a/gfx/wr/wrench/reftests/gradient/norm-radial-1-ref.yaml b/gfx/wr/wrench/reftests/gradient/norm-radial-1-ref.yaml new file mode 100644 index 0000000000..a67b51ecf8 --- /dev/null +++ b/gfx/wr/wrench/reftests/gradient/norm-radial-1-ref.yaml @@ -0,0 +1,8 @@ +--- +root: + items: + - type: radial-gradient + bounds: 50 50 300 300 + center: 150 150 + radius: 200 200 + stops: [0.0, red, 0.5, red, 0.5, blue, 1.0, blue] diff --git a/gfx/wr/wrench/reftests/gradient/norm-radial-1.yaml b/gfx/wr/wrench/reftests/gradient/norm-radial-1.yaml new file mode 100644 index 0000000000..7ee6caeafa --- /dev/null +++ b/gfx/wr/wrench/reftests/gradient/norm-radial-1.yaml @@ -0,0 +1,8 @@ +--- +root: + items: + - type: radial-gradient + bounds: 50 50 300 300 + center: 150 150 + radius: 200 200 + stops: [0.5, red, 0.5, blue] diff --git a/gfx/wr/wrench/reftests/gradient/norm-radial-2-ref.yaml b/gfx/wr/wrench/reftests/gradient/norm-radial-2-ref.yaml new file mode 100644 index 0000000000..adfc8d70d4 --- /dev/null +++ b/gfx/wr/wrench/reftests/gradient/norm-radial-2-ref.yaml @@ -0,0 +1,8 @@ +--- +root: + items: + - type: radial-gradient + bounds: 50 50 300 300 + center: 150 150 + radius: 200 200 + stops: [0.0, blue, 1.0, blue] diff --git a/gfx/wr/wrench/reftests/gradient/norm-radial-2.yaml b/gfx/wr/wrench/reftests/gradient/norm-radial-2.yaml new file mode 100644 index 0000000000..dac1b78361 --- /dev/null +++ b/gfx/wr/wrench/reftests/gradient/norm-radial-2.yaml @@ -0,0 +1,8 @@ +--- +root: + items: + - type: radial-gradient + bounds: 50 50 300 300 + center: 150 150 + radius: 200 200 + stops: [-0.5, red, -0.5, blue] diff --git a/gfx/wr/wrench/reftests/gradient/norm-radial-3-ref.yaml b/gfx/wr/wrench/reftests/gradient/norm-radial-3-ref.yaml new file mode 100644 index 0000000000..d90d1ee4f8 --- /dev/null +++ b/gfx/wr/wrench/reftests/gradient/norm-radial-3-ref.yaml @@ -0,0 +1,8 @@ +--- +root: + items: + - type: radial-gradient + bounds: 50 50 300 300 + center: 150 150 + radius: 200 200 + stops: [0.0, red, 1.0, red] diff --git a/gfx/wr/wrench/reftests/gradient/norm-radial-3.yaml b/gfx/wr/wrench/reftests/gradient/norm-radial-3.yaml new file mode 100644 index 0000000000..fbd5dc929f --- /dev/null +++ b/gfx/wr/wrench/reftests/gradient/norm-radial-3.yaml @@ -0,0 +1,8 @@ +--- +root: + items: + - type: radial-gradient + bounds: 50 50 300 300 + center: 150 150 + radius: 200 200 + stops: [1.5, red, 1.5, blue] diff --git a/gfx/wr/wrench/reftests/gradient/norm-radial-degenerate-ref.yaml b/gfx/wr/wrench/reftests/gradient/norm-radial-degenerate-ref.yaml new file mode 100644 index 0000000000..afe59a770b --- /dev/null +++ b/gfx/wr/wrench/reftests/gradient/norm-radial-degenerate-ref.yaml @@ -0,0 +1,8 @@ +--- +root: + items: + - type: radial-gradient + bounds: 50 50 300 300 + center: 150 150 + radius: 150 150 + stops: [0.0, red, 1.0, red] diff --git a/gfx/wr/wrench/reftests/gradient/norm-radial-degenerate.yaml b/gfx/wr/wrench/reftests/gradient/norm-radial-degenerate.yaml new file mode 100644 index 0000000000..26d9935475 --- /dev/null +++ b/gfx/wr/wrench/reftests/gradient/norm-radial-degenerate.yaml @@ -0,0 +1,14 @@ +# see: https://www.w3.org/TR/2012/CR-css3-images-20120417/#repeating-gradients +# the spec says that repeating gradients with color stops in the same offset +# must render as a solid rect with color equal to the average color of the +# gradient. Gecko and Blink seem to draw it with color equal to the last stop +# so that is the behavior tested here +--- +root: + items: + - type: radial-gradient + bounds: 50 50 300 300 + center: 150 150 + radius: 150 150 + stops: [0.5, blue, 0.5, red] + repeat: true diff --git a/gfx/wr/wrench/reftests/gradient/premultiplied-aligned-2.png b/gfx/wr/wrench/reftests/gradient/premultiplied-aligned-2.png Binary files differnew file mode 100644 index 0000000000..4285b642c6 --- /dev/null +++ b/gfx/wr/wrench/reftests/gradient/premultiplied-aligned-2.png diff --git a/gfx/wr/wrench/reftests/gradient/premultiplied-aligned-2.yaml b/gfx/wr/wrench/reftests/gradient/premultiplied-aligned-2.yaml new file mode 100644 index 0000000000..ea8acd5f26 --- /dev/null +++ b/gfx/wr/wrench/reftests/gradient/premultiplied-aligned-2.yaml @@ -0,0 +1,8 @@ +--- +root: + items: + - type: gradient + bounds: 50 50 200 200 + start: 0 100 + end: 200 100 + stops: [0.0, [255.0, 0.0, 0.0, 0.5], 0.5, [0.0, 255.0, 0.0, 0.5], 1.0, [0.0, 0.0, 255.0, 0.5]] diff --git a/gfx/wr/wrench/reftests/gradient/premultiplied-aligned.png b/gfx/wr/wrench/reftests/gradient/premultiplied-aligned.png Binary files differnew file mode 100644 index 0000000000..e75f3405e4 --- /dev/null +++ b/gfx/wr/wrench/reftests/gradient/premultiplied-aligned.png diff --git a/gfx/wr/wrench/reftests/gradient/premultiplied-aligned.yaml b/gfx/wr/wrench/reftests/gradient/premultiplied-aligned.yaml new file mode 100644 index 0000000000..a709f845ea --- /dev/null +++ b/gfx/wr/wrench/reftests/gradient/premultiplied-aligned.yaml @@ -0,0 +1,8 @@ +--- +root: + items: + - type: gradient + bounds: 50 50 200 200 + start: 0 100 + end: 200 100 + stops: [0.0, red, 0.5, [0.0, 0.0, 0.0, 0.0], 1.0, green] diff --git a/gfx/wr/wrench/reftests/gradient/premultiplied-angle-2.png b/gfx/wr/wrench/reftests/gradient/premultiplied-angle-2.png Binary files differnew file mode 100644 index 0000000000..ea7a5cf7ef --- /dev/null +++ b/gfx/wr/wrench/reftests/gradient/premultiplied-angle-2.png diff --git a/gfx/wr/wrench/reftests/gradient/premultiplied-angle-2.yaml b/gfx/wr/wrench/reftests/gradient/premultiplied-angle-2.yaml new file mode 100644 index 0000000000..35546b0cd2 --- /dev/null +++ b/gfx/wr/wrench/reftests/gradient/premultiplied-angle-2.yaml @@ -0,0 +1,8 @@ +--- +root: + items: + - type: gradient + bounds: 50 50 200 200 + start: 0 0 + end: 200 200 + stops: [0.0, [255.0, 0.0, 0.0, 0.5], 0.5, [0.0, 255.0, 0.0, 0.5], 1.0, [0.0, 0.0, 255.0, 0.5]] diff --git a/gfx/wr/wrench/reftests/gradient/premultiplied-angle.png b/gfx/wr/wrench/reftests/gradient/premultiplied-angle.png Binary files differnew file mode 100644 index 0000000000..a37120ad7e --- /dev/null +++ b/gfx/wr/wrench/reftests/gradient/premultiplied-angle.png diff --git a/gfx/wr/wrench/reftests/gradient/premultiplied-angle.yaml b/gfx/wr/wrench/reftests/gradient/premultiplied-angle.yaml new file mode 100644 index 0000000000..b665e47150 --- /dev/null +++ b/gfx/wr/wrench/reftests/gradient/premultiplied-angle.yaml @@ -0,0 +1,8 @@ +--- +root: + items: + - type: gradient + bounds: 50 50 200 200 + start: 0 0 + end: 200 200 + stops: [0.0, red, 0.5, [0.0, 0.0, 0.0, 0.0], 1.0, green] diff --git a/gfx/wr/wrench/reftests/gradient/premultiplied-conic-2.png b/gfx/wr/wrench/reftests/gradient/premultiplied-conic-2.png Binary files differnew file mode 100644 index 0000000000..e589168621 --- /dev/null +++ b/gfx/wr/wrench/reftests/gradient/premultiplied-conic-2.png diff --git a/gfx/wr/wrench/reftests/gradient/premultiplied-conic-2.yaml b/gfx/wr/wrench/reftests/gradient/premultiplied-conic-2.yaml new file mode 100644 index 0000000000..dee4cec03b --- /dev/null +++ b/gfx/wr/wrench/reftests/gradient/premultiplied-conic-2.yaml @@ -0,0 +1,8 @@ +--- +root: + items: + - type: conic-gradient + bounds: 50 50 200 200 + angle: 0.0 + center: 100 100 + stops: [0.0, [255.0, 0.0, 0.0, 0.5], 0.5, [0.0, 255.0, 0.0, 0.5], 1.0, [0.0, 0.0, 255.0, 0.5]] diff --git a/gfx/wr/wrench/reftests/gradient/premultiplied-conic.png b/gfx/wr/wrench/reftests/gradient/premultiplied-conic.png Binary files differnew file mode 100644 index 0000000000..678dc9c87f --- /dev/null +++ b/gfx/wr/wrench/reftests/gradient/premultiplied-conic.png diff --git a/gfx/wr/wrench/reftests/gradient/premultiplied-conic.yaml b/gfx/wr/wrench/reftests/gradient/premultiplied-conic.yaml new file mode 100644 index 0000000000..d4b442bca7 --- /dev/null +++ b/gfx/wr/wrench/reftests/gradient/premultiplied-conic.yaml @@ -0,0 +1,8 @@ +--- +root: + items: + - type: conic-gradient + bounds: 50 50 200 200 + angle: 0.0 + center: 100 100 + stops: [0.0, red, 0.5, [0.0, 0.0, 0.0, 0.0], 1.0, green] diff --git a/gfx/wr/wrench/reftests/gradient/premultiplied-radial-2.png b/gfx/wr/wrench/reftests/gradient/premultiplied-radial-2.png Binary files differnew file mode 100644 index 0000000000..cfd7ca2aaa --- /dev/null +++ b/gfx/wr/wrench/reftests/gradient/premultiplied-radial-2.png diff --git a/gfx/wr/wrench/reftests/gradient/premultiplied-radial-2.yaml b/gfx/wr/wrench/reftests/gradient/premultiplied-radial-2.yaml new file mode 100644 index 0000000000..3e682328d1 --- /dev/null +++ b/gfx/wr/wrench/reftests/gradient/premultiplied-radial-2.yaml @@ -0,0 +1,8 @@ +--- +root: + items: + - type: radial-gradient + bounds: 50 50 200 200 + center: 100 100 + radius: 100 100 + stops: [0.0, [255.0, 0.0, 0.0, 0.5], 0.5, [0.0, 255.0, 0.0, 0.5], 1.0, [0.0, 0.0, 255.0, 0.5]] diff --git a/gfx/wr/wrench/reftests/gradient/premultiplied-radial.png b/gfx/wr/wrench/reftests/gradient/premultiplied-radial.png Binary files differnew file mode 100644 index 0000000000..0b2b2c2f21 --- /dev/null +++ b/gfx/wr/wrench/reftests/gradient/premultiplied-radial.png diff --git a/gfx/wr/wrench/reftests/gradient/premultiplied-radial.yaml b/gfx/wr/wrench/reftests/gradient/premultiplied-radial.yaml new file mode 100644 index 0000000000..dc3750abd4 --- /dev/null +++ b/gfx/wr/wrench/reftests/gradient/premultiplied-radial.yaml @@ -0,0 +1,8 @@ +--- +root: + items: + - type: radial-gradient + bounds: 50 50 200 200 + center: 100 100 + radius: 100 100 + stops: [0.0, red, 0.5, [0.0, 0.0, 0.0, 0.0], 1.0, green] diff --git a/gfx/wr/wrench/reftests/gradient/radial-backdrop-ref.yaml b/gfx/wr/wrench/reftests/gradient/radial-backdrop-ref.yaml new file mode 100644 index 0000000000..a878e2ac0a --- /dev/null +++ b/gfx/wr/wrench/reftests/gradient/radial-backdrop-ref.yaml @@ -0,0 +1,11 @@ +--- +root: + items: + - type: rect + bounds: 0 0 800 450 + color: red + - type: radial-gradient + bounds: 0 0 800 450 + center: 400 225 + radius: 200 200 + stops: [ 0.0, [255, 255, 255, 1], 1.0, [0,0,0,1] ] diff --git a/gfx/wr/wrench/reftests/gradient/radial-backdrop-with-spacing-ref.yaml b/gfx/wr/wrench/reftests/gradient/radial-backdrop-with-spacing-ref.yaml new file mode 100644 index 0000000000..2aea254d3a --- /dev/null +++ b/gfx/wr/wrench/reftests/gradient/radial-backdrop-with-spacing-ref.yaml @@ -0,0 +1,13 @@ +--- +root: + items: + - type: rect + bounds: 0 0 800 450 + color: red + - type: radial-gradient + bounds: 0 0 800 450 + center: 50 50 + radius: 60 60 + stops: [ 0.0, [255, 255, 255, 1], 1.0, [0,0,0,1] ] + tile-size: 100 100 + tile-spacing: 20 20 diff --git a/gfx/wr/wrench/reftests/gradient/radial-backdrop-with-spacing.yaml b/gfx/wr/wrench/reftests/gradient/radial-backdrop-with-spacing.yaml new file mode 100644 index 0000000000..795c65d070 --- /dev/null +++ b/gfx/wr/wrench/reftests/gradient/radial-backdrop-with-spacing.yaml @@ -0,0 +1,18 @@ +--- +root: + items: + - type: rect + bounds: 0 0 800 450 + color: red + - type: "scroll-frame" + bounds: 0 0 800 450 + clip-rect: 0 0 800 450 + id: 2 + - type: radial-gradient + bounds: 0 0 800 450 + "clip-and-scroll": 2 + center: 50 50 + radius: 60 60 + stops: [ 0.0, [255, 255, 255, 1], 1.0, [0,0,0,1] ] + tile-size: 100 100 + tile-spacing: 20 20 diff --git a/gfx/wr/wrench/reftests/gradient/radial-backdrop.yaml b/gfx/wr/wrench/reftests/gradient/radial-backdrop.yaml new file mode 100644 index 0000000000..22e360bf01 --- /dev/null +++ b/gfx/wr/wrench/reftests/gradient/radial-backdrop.yaml @@ -0,0 +1,16 @@ +--- +root: + items: + - type: rect + bounds: 0 0 800 450 + color: red + - type: "scroll-frame" + bounds: 0 0 800 450 + clip-rect: 0 0 800 450 + id: 2 + - type: radial-gradient + bounds: 0 0 800 450 + "clip-and-scroll": 2 + center: 400 225 + radius: 200 200 + stops: [ 0.0, [255, 255, 255, 1], 1.0, [0,0,0,1] ] diff --git a/gfx/wr/wrench/reftests/gradient/radial-circle-ref.png b/gfx/wr/wrench/reftests/gradient/radial-circle-ref.png Binary files differnew file mode 100644 index 0000000000..3f9a748a7e --- /dev/null +++ b/gfx/wr/wrench/reftests/gradient/radial-circle-ref.png diff --git a/gfx/wr/wrench/reftests/gradient/radial-circle.yaml b/gfx/wr/wrench/reftests/gradient/radial-circle.yaml new file mode 100644 index 0000000000..037da7eddc --- /dev/null +++ b/gfx/wr/wrench/reftests/gradient/radial-circle.yaml @@ -0,0 +1,8 @@ +--- +root: + items: + - type: radial-gradient + bounds: 50 50 300 300 + center: 150 150 + radius: 200 200 + stops: [0, red, 1, blue] diff --git a/gfx/wr/wrench/reftests/gradient/radial-ellipse-ref.png b/gfx/wr/wrench/reftests/gradient/radial-ellipse-ref.png Binary files differnew file mode 100644 index 0000000000..b4786cd387 --- /dev/null +++ b/gfx/wr/wrench/reftests/gradient/radial-ellipse-ref.png diff --git a/gfx/wr/wrench/reftests/gradient/radial-ellipse.yaml b/gfx/wr/wrench/reftests/gradient/radial-ellipse.yaml new file mode 100644 index 0000000000..7c733f7223 --- /dev/null +++ b/gfx/wr/wrench/reftests/gradient/radial-ellipse.yaml @@ -0,0 +1,8 @@ +--- +root: + items: + - type: radial-gradient + bounds: 50 50 300 300 + center: 150 150 + radius: 100 200 + stops: [0, red, 1, blue] diff --git a/gfx/wr/wrench/reftests/gradient/radial-zero-size-1.yaml b/gfx/wr/wrench/reftests/gradient/radial-zero-size-1.yaml new file mode 100644 index 0000000000..43e4ef323d --- /dev/null +++ b/gfx/wr/wrench/reftests/gradient/radial-zero-size-1.yaml @@ -0,0 +1,8 @@ +--- +root: + items: + - type: radial-gradient + bounds: 50 50 200 200 + center: 100 100 + radius: 100 0 + stops: [0.0, blue, 1.0, red] diff --git a/gfx/wr/wrench/reftests/gradient/radial-zero-size-2.yaml b/gfx/wr/wrench/reftests/gradient/radial-zero-size-2.yaml new file mode 100644 index 0000000000..94bf6eae73 --- /dev/null +++ b/gfx/wr/wrench/reftests/gradient/radial-zero-size-2.yaml @@ -0,0 +1,8 @@ +--- +root: + items: + - type: radial-gradient + bounds: 50 50 200 200 + center: 100 100 + radius: 0 100 + stops: [0.0, blue, 1.0, red] diff --git a/gfx/wr/wrench/reftests/gradient/radial-zero-size-3.yaml b/gfx/wr/wrench/reftests/gradient/radial-zero-size-3.yaml new file mode 100644 index 0000000000..3efa1ec307 --- /dev/null +++ b/gfx/wr/wrench/reftests/gradient/radial-zero-size-3.yaml @@ -0,0 +1,6 @@ +--- +root: + items: + - type: rect + bounds: 50 50 200 200 + color: red diff --git a/gfx/wr/wrench/reftests/gradient/radial-zero-size-ref.yaml b/gfx/wr/wrench/reftests/gradient/radial-zero-size-ref.yaml new file mode 100644 index 0000000000..b3770b752e --- /dev/null +++ b/gfx/wr/wrench/reftests/gradient/radial-zero-size-ref.yaml @@ -0,0 +1,8 @@ +--- +root: + items: + - type: radial-gradient + bounds: 50 50 200 200 + center: 100 100 + radius: 100 100 + stops: [0.0, red, 1.0, red] diff --git a/gfx/wr/wrench/reftests/gradient/reftest.list b/gfx/wr/wrench/reftests/gradient/reftest.list new file mode 100644 index 0000000000..0441182ece --- /dev/null +++ b/gfx/wr/wrench/reftests/gradient/reftest.list @@ -0,0 +1,106 @@ +platform(linux,mac) == premultiplied-aligned.yaml premultiplied-aligned.png +fuzzy(1,500) platform(linux,mac) == premultiplied-angle.yaml premultiplied-angle.png +platform(linux,mac) == premultiplied-radial.yaml premultiplied-radial.png +platform(linux,mac) == premultiplied-conic.yaml premultiplied-conic.png + +platform(linux,mac) == premultiplied-aligned-2.yaml premultiplied-aligned-2.png +platform(linux,mac) == premultiplied-angle-2.yaml premultiplied-angle-2.png +platform(linux,mac) == premultiplied-radial-2.yaml premultiplied-radial-2.png +platform(linux,mac) == premultiplied-conic-2.yaml premultiplied-conic-2.png + +== linear.yaml linear-ref.png +== linear-reverse.yaml linear-ref.png +platform(linux,mac) fuzzy(1,35000) == linear-stops.yaml linear-stops-ref.png + +== linear-clamp-1a.yaml linear-clamp-1-ref.yaml +== linear-clamp-1b.yaml linear-clamp-1-ref.yaml +== linear-clamp-2.yaml linear-clamp-2-ref.yaml + +fuzzy-range(<=1,*4800) == linear-hard-stop.yaml linear-hard-stop-ref.png + +# dithering requires us to fuzz here +fuzzy(1,20000) == linear.yaml linear-ref.yaml +fuzzy(1,20000) == linear-reverse.yaml linear-ref.yaml + +fuzzy(1,15200) == linear-aligned-clip.yaml linear-aligned-clip-ref.yaml + +platform(linux,mac) fuzzy(1,80000) == radial-circle.yaml radial-circle-ref.png +platform(linux,mac) fuzzy(1,80000) == radial-ellipse.yaml radial-ellipse-ref.png + +!= radial-circle.yaml radial-ellipse.yaml + +== norm-linear-1.yaml norm-linear-1-ref.yaml +== norm-linear-2.yaml norm-linear-2-ref.yaml +== norm-linear-3.yaml norm-linear-3-ref.yaml +== norm-linear-4.yaml norm-linear-4-ref.yaml +== norm-linear-degenerate.yaml norm-radial-degenerate-ref.yaml + +== norm-radial-1.yaml norm-radial-1-ref.yaml +== norm-radial-2.yaml norm-radial-2-ref.yaml +== norm-radial-3.yaml norm-radial-3-ref.yaml +== norm-radial-degenerate.yaml norm-radial-degenerate-ref.yaml + +== norm-conic-1.yaml norm-conic-1-ref.yaml +== norm-conic-2.yaml norm-conic-2-ref.yaml +== norm-conic-3.yaml norm-conic-3-ref.yaml +== norm-conic-4.yaml norm-conic-4-ref.yaml +== norm-conic-degenerate.yaml norm-conic-degenerate-ref.yaml + +# fuzzy because of differences from normalization +# this might be able to be improved +fuzzy(255,1200) == repeat-linear.yaml repeat-linear-ref.yaml +fuzzy(255,1200) == repeat-linear-reverse.yaml repeat-linear-ref.yaml +fuzzy(255,2664) == repeat-radial.yaml repeat-radial-ref.yaml +fuzzy(255,2664) == repeat-radial-negative.yaml repeat-radial-ref.yaml +fuzzy(255,1652) == repeat-conic.yaml repeat-conic-ref.yaml +fuzzy(255,1652) == repeat-conic-negative.yaml repeat-conic-ref.yaml + +# fuzzy because of thin spaced out column of pixels that are 1 off +fuzzy(1,83164) == tiling-linear-1.yaml tiling-linear-1-ref.yaml +fuzzy(1,46293) == tiling-linear-2.yaml tiling-linear-2-ref.yaml +fuzzy(1,62154) == tiling-linear-3.yaml tiling-linear-3-ref.yaml + +fuzzy(1,17) == tiling-radial-1.yaml tiling-radial-1-ref.yaml +fuzzy(1,1) == tiling-radial-2.yaml tiling-radial-2-ref.yaml +fuzzy(1,3) == tiling-radial-3.yaml tiling-radial-3-ref.yaml +fuzzy(1,17) == tiling-radial-4.yaml tiling-radial-4-ref.yaml + +fuzzy(1,17) == tiling-conic-1.yaml tiling-conic-1-ref.yaml +fuzzy(1,1) == tiling-conic-2.yaml tiling-conic-2-ref.yaml +fuzzy(1,7) == tiling-conic-3.yaml tiling-conic-3-ref.yaml + +== radial-zero-size-1.yaml radial-zero-size-ref.yaml +== radial-zero-size-2.yaml radial-zero-size-ref.yaml +== radial-zero-size-3.yaml radial-zero-size-ref.yaml + +== linear-adjust-tile-size.yaml linear-adjust-tile-size-ref.yaml + +platform(linux,mac) == linear-aligned-border-radius.yaml linear-aligned-border-radius.png +# interpolation fuzz from sampling texture-baked gradient ramps +platform(linux,mac) fuzzy-range(<=1,*1404) == repeat-border-radius.yaml repeat-border-radius.png + +== conic.yaml conic-ref.yaml +fuzzy(1,57) == conic-simple.yaml conic-simple.png +fuzzy(255,302) == conic-angle.yaml conic-angle.png +== conic-center.yaml conic-center.png +fuzzy(1,2) == conic-angle-wraparound.yaml conic-angle.yaml +fuzzy(1,1) == conic-angle-wraparound-negative.yaml conic-angle.yaml +fuzzy(1,333) == conic-color-wheel.yaml conic-color-wheel.png + +# gradient caching tests +# replaces a computed gradient by a sampled texture, so a lot of off-by-one +# variation from interpolation, which is fine: +fuzzy-range(<=1,*195000) == gradient_cache_5stops.yaml gradient_cache_5stops_ref.yaml +fuzzy-range(<=1,*171840) == gradient_cache_5stops_vertical.yaml gradient_cache_5stops_vertical_ref.yaml +== gradient_cache_hardstop.yaml gradient_cache_hardstop_ref.yaml +fuzzy-range(<=1,1) == gradient_cache_hardstop_clip.yaml gradient_cache_hardstop_clip_ref.yaml +== gradient_cache_clamp.yaml gradient_cache_clamp_ref.yaml +== gradient_cache_repeat.yaml gradient_cache_repeat_ref.yaml + +# Recognize opaque tiles with gradient backgrounds +== conic-backdrop-with-spacing.yaml conic-backdrop-with-spacing-ref.yaml +== conic-backdrop.yaml conic-backdrop-ref.yaml +== linear-backdrop-with-spacing.yaml linear-backdrop-with-spacing-ref.yaml +== linear-backdrop.yaml linear-backdrop-ref.yaml +== radial-backdrop-with-spacing.yaml radial-backdrop-with-spacing-ref.yaml +== radial-backdrop.yaml radial-backdrop-ref.yaml diff --git a/gfx/wr/wrench/reftests/gradient/repeat-border-radius.png b/gfx/wr/wrench/reftests/gradient/repeat-border-radius.png Binary files differnew file mode 100644 index 0000000000..ec05b3a55b --- /dev/null +++ b/gfx/wr/wrench/reftests/gradient/repeat-border-radius.png diff --git a/gfx/wr/wrench/reftests/gradient/repeat-border-radius.yaml b/gfx/wr/wrench/reftests/gradient/repeat-border-radius.yaml new file mode 100644 index 0000000000..b578f80b5d --- /dev/null +++ b/gfx/wr/wrench/reftests/gradient/repeat-border-radius.yaml @@ -0,0 +1,137 @@ +--- +root: + items: + - type: clip + bounds: [20, 20, 100, 100] + complex: + - rect: [20, 20, 100, 100] + radius: 32 + items: + - type: gradient + bounds: 20 20 100 100 + start: 50 0 + end: 50 100 + stops: [0.0, red, 1.0, yellow] + repeat: true + + - type: rect + bounds: [130, 10, 120, 120] + color: blue + + - type: clip + bounds: [140, 20, 100, 100] + complex: + - rect: [140, 20, 100, 100] + radius: 32 + items: + - type: gradient + bounds: 140 20 100 100 + start: 50 0 + end: 50 100 + stops: [0.2, red, 1.0, yellow] + + - type: rect + bounds: [260, 10, 120, 120] + color: black + + - type: clip + bounds: [270, 20, 100, 100] + complex: + - rect: [270, 20, 100, 100] + radius: 32 + items: + - type: gradient + bounds: 270 20 100 100 + start: 50 0 + end: 51 100 + stops: [0.0, red, 1.0, yellow] + + - type: clip + bounds: [20, 160, 100, 100] + complex: + - rect: [20, 160, 100, 100] + radius: 32 + items: + - type: radial-gradient + bounds: 20 160 100 100 + center: 50 50 + radius: 25 25 + stops: [0.0, red, 1.0, yellow] + + - type: rect + bounds: [130, 150, 120, 120] + color: blue + + - type: clip + bounds: [140, 160, 100, 100] + complex: + - rect: [140, 160, 100, 100] + radius: 32 + items: + - type: radial-gradient + bounds: 140 160 100 100 + center: 50 50 + radius: 25 25 + stops: [0.0, red, 1.0, yellow] + + - type: rect + bounds: [260, 150, 120, 120] + color: black + + - type: clip + bounds: [270, 160, 100, 100] + complex: + - rect: [270, 160, 100, 100] + radius: 32 + items: + - type: radial-gradient + bounds: 270 160 100 100 + center: 50 50 + radius: 25 25 + stops: [0.0, red, 1.0, yellow] + + - type: clip + bounds: [20, 300, 100, 100] + complex: + - rect: [20, 300, 100, 100] + radius: 32 + items: + - type: conic-gradient + bounds: 20 300 100 100 + angle: 0.0 + center: 50 50 + stops: [0.0, red, 1.0, yellow] + repeat: true + + - type: rect + bounds: [130, 290, 120, 120] + color: blue + + - type: clip + bounds: [140, 300, 100, 100] + complex: + - rect: [140, 300, 100, 100] + radius: 32 + items: + - type: conic-gradient + bounds: 140 300 100 100 + angle: 0.0 + center: 50 50 + stops: [0.0, red, 1.0, yellow] + + - type: rect + bounds: [260, 290, 120, 120] + color: black + + - type: clip + bounds: [270, 300, 100, 100] + complex: + - rect: [270, 300, 100, 100] + radius: 32 + items: + - type: conic-gradient + bounds: 270 300 100 100 + angle: 0.0 + center: 50 50 + stops: [0.0, red, 1.0, yellow] + diff --git a/gfx/wr/wrench/reftests/gradient/repeat-conic-negative.yaml b/gfx/wr/wrench/reftests/gradient/repeat-conic-negative.yaml new file mode 100644 index 0000000000..e1043562da --- /dev/null +++ b/gfx/wr/wrench/reftests/gradient/repeat-conic-negative.yaml @@ -0,0 +1,9 @@ +--- +root: + items: + - type: conic-gradient + bounds: 50 50 300 300 + angle: -0.62831853 + center: 150 150 + stops: [0.1, red, 0.2, red, 0.2, blue, 0.3, blue] + repeat: true diff --git a/gfx/wr/wrench/reftests/gradient/repeat-conic-ref.yaml b/gfx/wr/wrench/reftests/gradient/repeat-conic-ref.yaml new file mode 100644 index 0000000000..b98cc378a7 --- /dev/null +++ b/gfx/wr/wrench/reftests/gradient/repeat-conic-ref.yaml @@ -0,0 +1,27 @@ +--- +root: + items: + - type: conic-gradient + bounds: 50 50 300 300 + angle: 0.0 + center: 150 150 + stops: [0.0, red, + 0.1, red, + 0.1, blue, + 0.2, blue, + 0.2, red, + 0.3, red, + 0.3, blue, + 0.4, blue, + 0.4, red, + 0.5, red, + 0.5, blue, + 0.6, blue, + 0.6, red, + 0.7, red, + 0.7, blue, + 0.8, blue, + 0.8, red, + 0.9, red, + 0.9, blue, + 1.0, blue] diff --git a/gfx/wr/wrench/reftests/gradient/repeat-conic.yaml b/gfx/wr/wrench/reftests/gradient/repeat-conic.yaml new file mode 100644 index 0000000000..bbc4202aec --- /dev/null +++ b/gfx/wr/wrench/reftests/gradient/repeat-conic.yaml @@ -0,0 +1,9 @@ +--- +root: + items: + - type: conic-gradient + bounds: 50 50 300 300 + angle: 0.0 + center: 150 150 + stops: [0.1, blue, 0.2, blue, 0.2, red, 0.3, red] + repeat: true diff --git a/gfx/wr/wrench/reftests/gradient/repeat-linear-ref.yaml b/gfx/wr/wrench/reftests/gradient/repeat-linear-ref.yaml new file mode 100644 index 0000000000..420a08db01 --- /dev/null +++ b/gfx/wr/wrench/reftests/gradient/repeat-linear-ref.yaml @@ -0,0 +1,27 @@ +--- +root: + items: + - type: gradient + bounds: 50 50 300 300 + start: 0 150 + end: 300 150 + stops: [0.0, red, + 0.1, red, + 0.1, blue, + 0.2, blue, + 0.2, red, + 0.3, red, + 0.3, blue, + 0.4, blue, + 0.4, red, + 0.5, red, + 0.5, blue, + 0.6, blue, + 0.6, red, + 0.7, red, + 0.7, blue, + 0.8, blue, + 0.8, red, + 0.9, red, + 0.9, blue, + 1.0, blue] diff --git a/gfx/wr/wrench/reftests/gradient/repeat-linear-reverse.yaml b/gfx/wr/wrench/reftests/gradient/repeat-linear-reverse.yaml new file mode 100644 index 0000000000..a81bafe1bd --- /dev/null +++ b/gfx/wr/wrench/reftests/gradient/repeat-linear-reverse.yaml @@ -0,0 +1,9 @@ +--- +root: + items: + - type: gradient + bounds: 50 50 300 300 + start: 300 150 + end: 0 150 + stops: [0.1, red, 0.2, red, 0.2, blue, 0.3, blue] + repeat: true diff --git a/gfx/wr/wrench/reftests/gradient/repeat-linear.yaml b/gfx/wr/wrench/reftests/gradient/repeat-linear.yaml new file mode 100644 index 0000000000..63e136bc8e --- /dev/null +++ b/gfx/wr/wrench/reftests/gradient/repeat-linear.yaml @@ -0,0 +1,9 @@ +--- +root: + items: + - type: gradient + bounds: 50 50 300 300 + start: 0 150 + end: 300 150 + stops: [0.1, blue, 0.2, blue, 0.2, red, 0.3, red] + repeat: true diff --git a/gfx/wr/wrench/reftests/gradient/repeat-radial-negative.yaml b/gfx/wr/wrench/reftests/gradient/repeat-radial-negative.yaml new file mode 100644 index 0000000000..949455f893 --- /dev/null +++ b/gfx/wr/wrench/reftests/gradient/repeat-radial-negative.yaml @@ -0,0 +1,9 @@ +--- +root: + items: + - type: radial-gradient + bounds: 50 50 300 300 + center: 150 150 + radius: 150 150 + stops: [-0.3, blue, -0.2, blue, -0.2, red, -0.1, red] + repeat: true diff --git a/gfx/wr/wrench/reftests/gradient/repeat-radial-ref.yaml b/gfx/wr/wrench/reftests/gradient/repeat-radial-ref.yaml new file mode 100644 index 0000000000..d2c0292e6e --- /dev/null +++ b/gfx/wr/wrench/reftests/gradient/repeat-radial-ref.yaml @@ -0,0 +1,38 @@ +--- +root: + items: + - type: radial-gradient + bounds: 50 50 300 300 + center: 150 150 + radius: 150 150 + # note: we need stops up to 1.4 because a repeating radial gradient + # will fill the whole rect beyond 1.0. So the furthest radius we have + # to fill in is the diagonal of the unit square + stops: [0.0, red, + 0.1, red, + 0.1, blue, + 0.2, blue, + 0.2, red, + 0.3, red, + 0.3, blue, + 0.4, blue, + 0.4, red, + 0.5, red, + 0.5, blue, + 0.6, blue, + 0.6, red, + 0.7, red, + 0.7, blue, + 0.8, blue, + 0.8, red, + 0.9, red, + 0.9, blue, + 1.0, blue, + 1.0, red, + 1.1, red, + 1.1, blue, + 1.2, blue, + 1.2, red, + 1.3, red, + 1.3, blue, + 1.4, blue] diff --git a/gfx/wr/wrench/reftests/gradient/repeat-radial.yaml b/gfx/wr/wrench/reftests/gradient/repeat-radial.yaml new file mode 100644 index 0000000000..04c676c25b --- /dev/null +++ b/gfx/wr/wrench/reftests/gradient/repeat-radial.yaml @@ -0,0 +1,9 @@ +--- +root: + items: + - type: radial-gradient + bounds: 50 50 300 300 + center: 150 150 + radius: 150 150 + stops: [0.1, blue, 0.2, blue, 0.2, red, 0.3, red] + repeat: true diff --git a/gfx/wr/wrench/reftests/gradient/tiling-conic-1-ref.yaml b/gfx/wr/wrench/reftests/gradient/tiling-conic-1-ref.yaml new file mode 100644 index 0000000000..6b93e28fa1 --- /dev/null +++ b/gfx/wr/wrench/reftests/gradient/tiling-conic-1-ref.yaml @@ -0,0 +1,27 @@ +--- +root: + items: + # top left + - type: conic-gradient + bounds: 50 50 200 200 + angle: 0.0 + center: 100 100 + stops: [0, red, 1, blue] + # top right + - type: conic-gradient + bounds: 350 50 200 200 + angle: 0.0 + center: 100 100 + stops: [0, red, 1, blue] + # bottom left + - type: conic-gradient + bounds: 50 350 200 200 + angle: 0.0 + center: 100 100 + stops: [0, red, 1, blue] + # bottom right + - type: conic-gradient + bounds: 350 350 200 200 + angle: 0.0 + center: 100 100 + stops: [0, red, 1, blue] diff --git a/gfx/wr/wrench/reftests/gradient/tiling-conic-1.yaml b/gfx/wr/wrench/reftests/gradient/tiling-conic-1.yaml new file mode 100644 index 0000000000..71ffe80b22 --- /dev/null +++ b/gfx/wr/wrench/reftests/gradient/tiling-conic-1.yaml @@ -0,0 +1,11 @@ +--- +root: + items: + # basic - 4 tiles spaced out with no clipping + - type: conic-gradient + bounds: 50 50 500 500 + angle: 0.0 + center: 100 100 + stops: [0, red, 1, blue] + tile-size: 200 200 + tile-spacing: 100 100 diff --git a/gfx/wr/wrench/reftests/gradient/tiling-conic-2-ref.yaml b/gfx/wr/wrench/reftests/gradient/tiling-conic-2-ref.yaml new file mode 100644 index 0000000000..4360aa204c --- /dev/null +++ b/gfx/wr/wrench/reftests/gradient/tiling-conic-2-ref.yaml @@ -0,0 +1,27 @@ +--- +root: + items: + # top left + - type: conic-gradient + bounds: 50 50 200 200 + angle: 0.0 + center: 100 100 + stops: [0, red, 1, blue] + # top right + - type: conic-gradient + bounds: 350 50 100 200 + angle: 0.0 + center: 100 100 + stops: [0, red, 1, blue] + # bottom left + - type: conic-gradient + bounds: 50 350 200 100 + angle: 0.0 + center: 100 100 + stops: [0, red, 1, blue] + # bottom right + - type: conic-gradient + bounds: 350 350 100 100 + angle: 0.0 + center: 100 100 + stops: [0, red, 1, blue] diff --git a/gfx/wr/wrench/reftests/gradient/tiling-conic-2.yaml b/gfx/wr/wrench/reftests/gradient/tiling-conic-2.yaml new file mode 100644 index 0000000000..ba9522a68c --- /dev/null +++ b/gfx/wr/wrench/reftests/gradient/tiling-conic-2.yaml @@ -0,0 +1,11 @@ +--- +root: + items: + # slightly clip the last tile + - type: conic-gradient + bounds: 50 50 400 400 + angle: 0.0 + center: 100 100 + stops: [0, red, 1, blue] + tile-size: 200 200 + tile-spacing: 100 100 diff --git a/gfx/wr/wrench/reftests/gradient/tiling-conic-3-ref.yaml b/gfx/wr/wrench/reftests/gradient/tiling-conic-3-ref.yaml new file mode 100644 index 0000000000..d7b9541ef4 --- /dev/null +++ b/gfx/wr/wrench/reftests/gradient/tiling-conic-3-ref.yaml @@ -0,0 +1,27 @@ +--- +root: + items: + # top left + - type: conic-gradient + bounds: 50 50 200 200 + angle: 0.0 + center: 100 100 + stops: [0, red, 1, blue] + # top right + - type: conic-gradient + bounds: 250 50 200 200 + angle: 0.0 + center: 100 100 + stops: [0, red, 1, blue] + # bottom left + - type: conic-gradient + bounds: 50 250 200 100 + angle: 0.0 + center: 100 100 + stops: [0, red, 1, blue] + # bottom right + - type: conic-gradient + bounds: 250 250 200 100 + angle: 0.0 + center: 100 100 + stops: [0, red, 1, blue] diff --git a/gfx/wr/wrench/reftests/gradient/tiling-conic-3.yaml b/gfx/wr/wrench/reftests/gradient/tiling-conic-3.yaml new file mode 100644 index 0000000000..77b28a9e22 --- /dev/null +++ b/gfx/wr/wrench/reftests/gradient/tiling-conic-3.yaml @@ -0,0 +1,11 @@ +--- +root: + items: + # no spacing with a clip + - type: conic-gradient + bounds: 50 50 400 300 + angle: 0.0 + center: 100 100 + stops: [0, red, 1, blue] + tile-size: 200 200 + tile-spacing: 0 0 diff --git a/gfx/wr/wrench/reftests/gradient/tiling-linear-1-ref.yaml b/gfx/wr/wrench/reftests/gradient/tiling-linear-1-ref.yaml new file mode 100644 index 0000000000..c06e05fb53 --- /dev/null +++ b/gfx/wr/wrench/reftests/gradient/tiling-linear-1-ref.yaml @@ -0,0 +1,27 @@ +--- +root: + items: + # top left + - type: gradient + bounds: 50 50 200 200 + start: 0 100 + end: 200 100 + stops: [0, red, 1, blue] + # top right + - type: gradient + bounds: 350 50 200 200 + start: 0 100 + end: 200 100 + stops: [0, red, 1, blue] + # bottom left + - type: gradient + bounds: 50 350 200 200 + start: 0 100 + end: 200 100 + stops: [0, red, 1, blue] + # bottom right + - type: gradient + bounds: 350 350 200 200 + start: 0 100 + end: 200 100 + stops: [0, red, 1, blue] diff --git a/gfx/wr/wrench/reftests/gradient/tiling-linear-1.yaml b/gfx/wr/wrench/reftests/gradient/tiling-linear-1.yaml new file mode 100644 index 0000000000..f388e7c593 --- /dev/null +++ b/gfx/wr/wrench/reftests/gradient/tiling-linear-1.yaml @@ -0,0 +1,11 @@ +--- +root: + items: + # basic - 4 tiles spaced out with no clipping + - type: gradient + bounds: 50 50 500 500 + start: 0 100 + end: 200 100 + stops: [0, red, 1, blue] + tile-size: 200 200 + tile-spacing: 100 100 diff --git a/gfx/wr/wrench/reftests/gradient/tiling-linear-2-ref.yaml b/gfx/wr/wrench/reftests/gradient/tiling-linear-2-ref.yaml new file mode 100644 index 0000000000..be7dc77463 --- /dev/null +++ b/gfx/wr/wrench/reftests/gradient/tiling-linear-2-ref.yaml @@ -0,0 +1,27 @@ +--- +root: + items: + # top left + - type: gradient + bounds: 50 50 200 200 + start: 0 100 + end: 200 100 + stops: [0, red, 1, blue] + # top right + - type: gradient + bounds: 350 50 100 200 + start: 0 100 + end: 200 100 + stops: [0, red, 1, blue] + # bottom left + - type: gradient + bounds: 50 350 200 100 + start: 0 100 + end: 200 100 + stops: [0, red, 1, blue] + # bottom right + - type: gradient + bounds: 350 350 100 100 + start: 0 100 + end: 200 100 + stops: [0, red, 1, blue] diff --git a/gfx/wr/wrench/reftests/gradient/tiling-linear-2.yaml b/gfx/wr/wrench/reftests/gradient/tiling-linear-2.yaml new file mode 100644 index 0000000000..7a01c062d1 --- /dev/null +++ b/gfx/wr/wrench/reftests/gradient/tiling-linear-2.yaml @@ -0,0 +1,11 @@ +--- +root: + items: + # slightly clip the last tile + - type: gradient + bounds: 50 50 400 400 + start: 0 100 + end: 200 100 + stops: [0, red, 1, blue] + tile-size: 200 200 + tile-spacing: 100 100 diff --git a/gfx/wr/wrench/reftests/gradient/tiling-linear-3-ref.yaml b/gfx/wr/wrench/reftests/gradient/tiling-linear-3-ref.yaml new file mode 100644 index 0000000000..90b110c8d0 --- /dev/null +++ b/gfx/wr/wrench/reftests/gradient/tiling-linear-3-ref.yaml @@ -0,0 +1,15 @@ +--- +root: + items: + # top left and bottom left + - type: gradient + bounds: 50 50 200 300 + start: 0 100 + end: 200 100 + stops: [0, red, 1, blue] + # top right and bottom right + - type: gradient + bounds: 250 50 200 300 + start: 0 100 + end: 200 100 + stops: [0, red, 1, blue] diff --git a/gfx/wr/wrench/reftests/gradient/tiling-linear-3.yaml b/gfx/wr/wrench/reftests/gradient/tiling-linear-3.yaml new file mode 100644 index 0000000000..a595f3572f --- /dev/null +++ b/gfx/wr/wrench/reftests/gradient/tiling-linear-3.yaml @@ -0,0 +1,11 @@ +--- +root: + items: + # no spacing with a clip + - type: gradient + bounds: 50 50 400 300 + start: 0 100 + end: 200 100 + stops: [0, red, 1, blue] + tile-size: 200 200 + tile-spacing: 0 0 diff --git a/gfx/wr/wrench/reftests/gradient/tiling-radial-1-ref.yaml b/gfx/wr/wrench/reftests/gradient/tiling-radial-1-ref.yaml new file mode 100644 index 0000000000..66f8c03592 --- /dev/null +++ b/gfx/wr/wrench/reftests/gradient/tiling-radial-1-ref.yaml @@ -0,0 +1,27 @@ +--- +root: + items: + # top left + - type: radial-gradient + bounds: 50 50 200 200 + center: 100 100 + radius: 100 100 + stops: [0, red, 1, blue] + # top right + - type: radial-gradient + bounds: 350 50 200 200 + center: 100 100 + radius: 100 100 + stops: [0, red, 1, blue] + # bottom left + - type: radial-gradient + bounds: 50 350 200 200 + center: 100 100 + radius: 100 100 + stops: [0, red, 1, blue] + # bottom right + - type: radial-gradient + bounds: 350 350 200 200 + center: 100 100 + radius: 100 100 + stops: [0, red, 1, blue] diff --git a/gfx/wr/wrench/reftests/gradient/tiling-radial-1.yaml b/gfx/wr/wrench/reftests/gradient/tiling-radial-1.yaml new file mode 100644 index 0000000000..b832a72f96 --- /dev/null +++ b/gfx/wr/wrench/reftests/gradient/tiling-radial-1.yaml @@ -0,0 +1,11 @@ +--- +root: + items: + # basic - 4 tiles spaced out with no clipping + - type: radial-gradient + bounds: 50 50 500 500 + center: 100 100 + radius: 100 100 + stops: [0, red, 1, blue] + tile-size: 200 200 + tile-spacing: 100 100 diff --git a/gfx/wr/wrench/reftests/gradient/tiling-radial-2-ref.yaml b/gfx/wr/wrench/reftests/gradient/tiling-radial-2-ref.yaml new file mode 100644 index 0000000000..da9bcd1bff --- /dev/null +++ b/gfx/wr/wrench/reftests/gradient/tiling-radial-2-ref.yaml @@ -0,0 +1,27 @@ +--- +root: + items: + # top left + - type: radial-gradient + bounds: 50 50 200 200 + center: 100 100 + radius: 100 100 + stops: [0, red, 1, blue] + # top right + - type: radial-gradient + bounds: 350 50 100 200 + center: 100 100 + radius: 100 100 + stops: [0, red, 1, blue] + # bottom left + - type: radial-gradient + bounds: 50 350 200 100 + center: 100 100 + radius: 100 100 + stops: [0, red, 1, blue] + # bottom right + - type: radial-gradient + bounds: 350 350 100 100 + center: 100 100 + radius: 100 100 + stops: [0, red, 1, blue] diff --git a/gfx/wr/wrench/reftests/gradient/tiling-radial-2.yaml b/gfx/wr/wrench/reftests/gradient/tiling-radial-2.yaml new file mode 100644 index 0000000000..8b7feb205e --- /dev/null +++ b/gfx/wr/wrench/reftests/gradient/tiling-radial-2.yaml @@ -0,0 +1,11 @@ +--- +root: + items: + # slightly clip the last tile + - type: radial-gradient + bounds: 50 50 400 400 + center: 100 100 + radius: 100 100 + stops: [0, red, 1, blue] + tile-size: 200 200 + tile-spacing: 100 100 diff --git a/gfx/wr/wrench/reftests/gradient/tiling-radial-3-ref.yaml b/gfx/wr/wrench/reftests/gradient/tiling-radial-3-ref.yaml new file mode 100644 index 0000000000..d8564eed64 --- /dev/null +++ b/gfx/wr/wrench/reftests/gradient/tiling-radial-3-ref.yaml @@ -0,0 +1,27 @@ +--- +root: + items: + # top left + - type: radial-gradient + bounds: 50 50 200 200 + center: 100 100 + radius: 200 100 + stops: [0, red, 1, blue] + # top right + - type: radial-gradient + bounds: 250 50 200 200 + center: 100 100 + radius: 200 100 + stops: [0, red, 1, blue] + # bottom left + - type: radial-gradient + bounds: 50 250 200 100 + center: 100 100 + radius: 200 100 + stops: [0, red, 1, blue] + # bottom right + - type: radial-gradient + bounds: 250 250 200 100 + center: 100 100 + radius: 200 100 + stops: [0, red, 1, blue] diff --git a/gfx/wr/wrench/reftests/gradient/tiling-radial-3.yaml b/gfx/wr/wrench/reftests/gradient/tiling-radial-3.yaml new file mode 100644 index 0000000000..4ca0886a0d --- /dev/null +++ b/gfx/wr/wrench/reftests/gradient/tiling-radial-3.yaml @@ -0,0 +1,11 @@ +--- +root: + items: + # no spacing with a clip + - type: radial-gradient + bounds: 50 50 400 300 + center: 100 100 + radius: 200 100 + stops: [0, red, 1, blue] + tile-size: 200 200 + tile-spacing: 0 0 diff --git a/gfx/wr/wrench/reftests/gradient/tiling-radial-4-ref.yaml b/gfx/wr/wrench/reftests/gradient/tiling-radial-4-ref.yaml new file mode 100644 index 0000000000..2ba2a96322 --- /dev/null +++ b/gfx/wr/wrench/reftests/gradient/tiling-radial-4-ref.yaml @@ -0,0 +1,27 @@ +--- +root: + items: + # top left + - type: radial-gradient + bounds: 50 50 200 200 + center: 100 100 + radius: 200 100 + stops: [0, red, 1, blue] + # top right + - type: radial-gradient + bounds: 350 50 200 200 + center: 100 100 + radius: 200 100 + stops: [0, red, 1, blue] + # bottom left + - type: radial-gradient + bounds: 50 350 200 200 + center: 100 100 + radius: 200 100 + stops: [0, red, 1, blue] + # bottom right + - type: radial-gradient + bounds: 350 350 200 200 + center: 100 100 + radius: 200 100 + stops: [0, red, 1, blue] diff --git a/gfx/wr/wrench/reftests/gradient/tiling-radial-4.yaml b/gfx/wr/wrench/reftests/gradient/tiling-radial-4.yaml new file mode 100644 index 0000000000..724019441f --- /dev/null +++ b/gfx/wr/wrench/reftests/gradient/tiling-radial-4.yaml @@ -0,0 +1,11 @@ +--- +root: + items: + # make sure the ellipse transformation retains square tiles + - type: radial-gradient + bounds: 50 50 500 500 + center: 100 100 + radius: 200 100 + stops: [0, red, 1, blue] + tile-size: 200 200 + tile-spacing: 100 100 diff --git a/gfx/wr/wrench/reftests/image/colorrect.png b/gfx/wr/wrench/reftests/image/colorrect.png Binary files differnew file mode 100644 index 0000000000..75283ee1f1 --- /dev/null +++ b/gfx/wr/wrench/reftests/image/colorrect.png diff --git a/gfx/wr/wrench/reftests/image/downscale.png b/gfx/wr/wrench/reftests/image/downscale.png Binary files differnew file mode 100644 index 0000000000..460a29df19 --- /dev/null +++ b/gfx/wr/wrench/reftests/image/downscale.png diff --git a/gfx/wr/wrench/reftests/image/downscale.yaml b/gfx/wr/wrench/reftests/image/downscale.yaml new file mode 100644 index 0000000000..fcaac883c2 --- /dev/null +++ b/gfx/wr/wrench/reftests/image/downscale.yaml @@ -0,0 +1,15 @@ +# Tests the image quality of using a very large A8 image +# as a clip mask. It's currently not very good! +# https://github.com/servo/webrender/issues/2023 +root: + items: + - type: clip + bounds: [0, 0, 350, 90] + image-mask: + image: "firefox.png" + rect: [0, 0, 350, 90] + repeat: false + items: + - type: rect + bounds: [0, 0, 350, 90] + color: blue diff --git a/gfx/wr/wrench/reftests/image/firefox.png b/gfx/wr/wrench/reftests/image/firefox.png Binary files differnew file mode 100644 index 0000000000..f00696789a --- /dev/null +++ b/gfx/wr/wrench/reftests/image/firefox.png diff --git a/gfx/wr/wrench/reftests/image/occlusion.png b/gfx/wr/wrench/reftests/image/occlusion.png Binary files differnew file mode 100644 index 0000000000..56332f2ef5 --- /dev/null +++ b/gfx/wr/wrench/reftests/image/occlusion.png diff --git a/gfx/wr/wrench/reftests/image/occlusion.yaml b/gfx/wr/wrench/reftests/image/occlusion.yaml new file mode 100644 index 0000000000..4e89a7765b --- /dev/null +++ b/gfx/wr/wrench/reftests/image/occlusion.yaml @@ -0,0 +1,15 @@ +# Ensure that the clip rect of a primitive that is promoted to a compositor +# surface is correctly applied when registering it as an occlusion plane. + +root: + items: + - type: rect + color: red + bounds: [50, 50, 200, 200] + + - type: yuv-image + format: interleaved + src: spacex-yuv.png + bounds: [50, 50, 200, 200] + prefer-compositor-surface: true + clip-rect: [75, 75, 150, 150] diff --git a/gfx/wr/wrench/reftests/image/reftest.list b/gfx/wr/wrench/reftests/image/reftest.list new file mode 100644 index 0000000000..c1581d2e89 --- /dev/null +++ b/gfx/wr/wrench/reftests/image/reftest.list @@ -0,0 +1,15 @@ +== tile-size.yaml tile-size-ref.yaml +== very-big.yaml very-big-ref.yaml +== very-big-tile-size.yaml very-big-tile-size-ref.yaml +== tile-with-spacing.yaml tile-with-spacing-ref.yaml +skip_on(android,device) fuzzy(1,331264) == tile-repeat-prim-or-decompose.yaml tile-repeat-prim-or-decompose-ref.yaml +platform(linux,mac) options(allow-mipmaps) == downscale.yaml downscale.png +skip_on(android,device) fuzzy-if(platform(swgl),1,20) == segments.yaml segments.png +platform(linux,mac) == yuv.yaml yuv.png +platform(linux,mac) fuzzy(1,6000) fuzzy-if(platform(swgl),1,205000) == yuv-clip.yaml yuv.png +skip_on(android,device) == tiled-clip-chain.yaml tiled-clip-chain-ref.yaml +skip_on(android,device) == tiled-complex-clip.yaml tiled-complex-clip-ref.yaml +platform(linux,mac) == texture-rect.yaml texture-rect-ref.yaml +platform(linux) == occlusion.yaml occlusion.png +# allow slight lerp change where the squares meet, but catch lerping problems on the boundary (should clamp) +fuzzy-range(<=2,*450) == rgb_composite.yaml rgb_composite_ref.yaml diff --git a/gfx/wr/wrench/reftests/image/rgb_composite.yaml b/gfx/wr/wrench/reftests/image/rgb_composite.yaml new file mode 100644 index 0000000000..74db512eed --- /dev/null +++ b/gfx/wr/wrench/reftests/image/rgb_composite.yaml @@ -0,0 +1,10 @@ +--- +root: + items: + - type: stacking-context + bounds: [50, 50, 100, 100] + transform: scale(1.5) + items: + - image: colorrect.png + bounds: [0, 0, 100, 100] + prefer-compositor-surface: true diff --git a/gfx/wr/wrench/reftests/image/rgb_composite_ref.yaml b/gfx/wr/wrench/reftests/image/rgb_composite_ref.yaml new file mode 100644 index 0000000000..0bc4a6e436 --- /dev/null +++ b/gfx/wr/wrench/reftests/image/rgb_composite_ref.yaml @@ -0,0 +1,9 @@ +--- +root: + items: + - type: stacking-context + bounds: [50, 50, 100, 100] + transform: scale(1.5) + items: + - image: colorrect.png + bounds: [0, 0, 100, 100] diff --git a/gfx/wr/wrench/reftests/image/segments.png b/gfx/wr/wrench/reftests/image/segments.png Binary files differnew file mode 100644 index 0000000000..168e9348ea --- /dev/null +++ b/gfx/wr/wrench/reftests/image/segments.png diff --git a/gfx/wr/wrench/reftests/image/segments.yaml b/gfx/wr/wrench/reftests/image/segments.yaml new file mode 100644 index 0000000000..5c4d42825c --- /dev/null +++ b/gfx/wr/wrench/reftests/image/segments.yaml @@ -0,0 +1,12 @@ +root: + items: + - type: clip + bounds: [10, 10, 260, 260] + complex: + - rect: [10, 10, 260, 260] + radius: 32 + items: + - image: checkerboard(2, 16, 16) + bounds: [10, 10, 260, 260] + - image: checkerboard(2, 16, 16) + bounds: [10, 290, 260, 260] diff --git a/gfx/wr/wrench/reftests/image/spacex-u.png b/gfx/wr/wrench/reftests/image/spacex-u.png Binary files differnew file mode 100644 index 0000000000..1de9b6ff66 --- /dev/null +++ b/gfx/wr/wrench/reftests/image/spacex-u.png diff --git a/gfx/wr/wrench/reftests/image/spacex-uv.png b/gfx/wr/wrench/reftests/image/spacex-uv.png Binary files differnew file mode 100644 index 0000000000..4b0259900e --- /dev/null +++ b/gfx/wr/wrench/reftests/image/spacex-uv.png diff --git a/gfx/wr/wrench/reftests/image/spacex-v.png b/gfx/wr/wrench/reftests/image/spacex-v.png Binary files differnew file mode 100644 index 0000000000..1d1a1c0118 --- /dev/null +++ b/gfx/wr/wrench/reftests/image/spacex-v.png diff --git a/gfx/wr/wrench/reftests/image/spacex-y.png b/gfx/wr/wrench/reftests/image/spacex-y.png Binary files differnew file mode 100644 index 0000000000..2256fabecd --- /dev/null +++ b/gfx/wr/wrench/reftests/image/spacex-y.png diff --git a/gfx/wr/wrench/reftests/image/spacex-yuv.png b/gfx/wr/wrench/reftests/image/spacex-yuv.png Binary files differnew file mode 100644 index 0000000000..6073e71735 --- /dev/null +++ b/gfx/wr/wrench/reftests/image/spacex-yuv.png diff --git a/gfx/wr/wrench/reftests/image/texture-rect-ref.yaml b/gfx/wr/wrench/reftests/image/texture-rect-ref.yaml new file mode 100644 index 0000000000..42d8907434 --- /dev/null +++ b/gfx/wr/wrench/reftests/image/texture-rect-ref.yaml @@ -0,0 +1,15 @@ +# Reference for test to ensure external images using the textureRect sampler mode work correctly. +root: + items: + - type: rect + bounds: [0, 0, 50, 50] + color: red + - type: rect + bounds: [50, 0, 50, 50] + color: blue + - type: rect + bounds: [0, 50, 50, 50] + color: green + - type: rect + bounds: [50, 50, 50, 50] + color: white
\ No newline at end of file diff --git a/gfx/wr/wrench/reftests/image/texture-rect.yaml b/gfx/wr/wrench/reftests/image/texture-rect.yaml new file mode 100644 index 0000000000..78e7ce6e86 --- /dev/null +++ b/gfx/wr/wrench/reftests/image/texture-rect.yaml @@ -0,0 +1,7 @@ +# Test to ensure external images using the textureRect sampler mode work correctly. +root: + items: + - image: colorrect.png + bounds: [0, 0, 100, 100] + external: true + external-target: rect
\ No newline at end of file diff --git a/gfx/wr/wrench/reftests/image/tile-repeat-prim-or-decompose-ref.yaml b/gfx/wr/wrench/reftests/image/tile-repeat-prim-or-decompose-ref.yaml new file mode 100644 index 0000000000..8b7e801d56 --- /dev/null +++ b/gfx/wr/wrench/reftests/image/tile-repeat-prim-or-decompose-ref.yaml @@ -0,0 +1,8 @@ +root: + items: + - image: xy-gradient(500, 50) + bounds: 0 0 800 800 + stretch-size: 50 50 + - image: xy-gradient(50, 500) + bounds: 800 0 800 800 + stretch-size: 50 50 diff --git a/gfx/wr/wrench/reftests/image/tile-repeat-prim-or-decompose.yaml b/gfx/wr/wrench/reftests/image/tile-repeat-prim-or-decompose.yaml new file mode 100644 index 0000000000..43b12bbd94 --- /dev/null +++ b/gfx/wr/wrench/reftests/image/tile-repeat-prim-or-decompose.yaml @@ -0,0 +1,17 @@ +# This test aims at exercising the different ways we handle repetition of tiled images. +root: + items: + # This should cause the primitive repetition to be decomposed on the cpu along the x axis + # but perform the repetition along the y axis on the image shader because the image width + # fits within the tile size. + - image: xy-gradient(500, 50) + bounds: 0 0 800 800 + stretch-size: 50 50 + tile-size: 50 + # This should cause the primitive repetition to be decomposed on the cpu along the y axis + # but perform the repetition along the x axis in the image shader because the image height + # fits within the tile size. + - image: xy-gradient(50, 500) + bounds: 800 0 800 800 + stretch-size: 50 50 + tile-size: 50 diff --git a/gfx/wr/wrench/reftests/image/tile-size-ref.yaml b/gfx/wr/wrench/reftests/image/tile-size-ref.yaml new file mode 100644 index 0000000000..c90ea8a341 --- /dev/null +++ b/gfx/wr/wrench/reftests/image/tile-size-ref.yaml @@ -0,0 +1,14 @@ +root: + items: + - image: xy-gradient(512, 512) + bounds: 0 0 512 512 + stretch-size: 512 512 + - image: xy-gradient(512, 512) + bounds: 512 0 512 512 + stretch-size: 512 512 + - image: xy-gradient(512, 512) + bounds: 0 512 512 512 + stretch-size: 512 512 + - image: xy-gradient(512, 512) + bounds: 512 512 512 512 + stretch-size: 512 512 diff --git a/gfx/wr/wrench/reftests/image/tile-size.yaml b/gfx/wr/wrench/reftests/image/tile-size.yaml new file mode 100644 index 0000000000..e17a7b53a4 --- /dev/null +++ b/gfx/wr/wrench/reftests/image/tile-size.yaml @@ -0,0 +1,19 @@ +root: + items: + - image: xy-gradient(512, 512) + bounds: 0 0 512 512 + stretch-size: 512 512 + tile-size: 64 + - image: xy-gradient(512, 512) + bounds: 512 0 512 512 + stretch-size: 512 512 + tile-size: 128 + - image: xy-gradient(512, 512) + bounds: 0 512 512 512 + stretch-size: 512 512 + tile-size: 256 + # tile size bigger than the image itself + - image: xy-gradient(512, 512) + bounds: 512 512 512 512 + stretch-size: 512 512 + tile-size: 4096 diff --git a/gfx/wr/wrench/reftests/image/tile-with-spacing-ref.yaml b/gfx/wr/wrench/reftests/image/tile-with-spacing-ref.yaml new file mode 100644 index 0000000000..63e1315f0b --- /dev/null +++ b/gfx/wr/wrench/reftests/image/tile-with-spacing-ref.yaml @@ -0,0 +1,6 @@ +root: + items: + - image: solid-color(255, 0, 0, 255, 300, 300) + bounds: 0 0 800 800 + stretch-size: 200 200 + tile-spacing: 10 10 diff --git a/gfx/wr/wrench/reftests/image/tile-with-spacing.yaml b/gfx/wr/wrench/reftests/image/tile-with-spacing.yaml new file mode 100644 index 0000000000..40bc5802d4 --- /dev/null +++ b/gfx/wr/wrench/reftests/image/tile-with-spacing.yaml @@ -0,0 +1,12 @@ +root: + items: + # TODO: This test would be more useful if we used an image with variations instead + # of a solid color. To do this we first need to change the way pixel snapping is + # applied so that when an image is split into several primitives, so that the latter + # all get snapped the same way rather than independently. + #- image: xy-gradient(300, 300) + - image: solid-color(255, 0, 0, 255, 300, 300) + bounds: 0 0 800 800 + stretch-size: 200 200 + tile-spacing: 10 10 + tile-size: 64 diff --git a/gfx/wr/wrench/reftests/image/tiled-clip-chain-ref.yaml b/gfx/wr/wrench/reftests/image/tiled-clip-chain-ref.yaml new file mode 100644 index 0000000000..83b4494269 --- /dev/null +++ b/gfx/wr/wrench/reftests/image/tiled-clip-chain-ref.yaml @@ -0,0 +1,10 @@ +root: + items: + - image: checkerboard(2, 16, 16) + bounds: [10, 10, 260, 260] + - type: rect + bounds: [10, 110, 200, 200] + color: white + - type: rect + bounds: [110, 10, 200, 270] + color: white
\ No newline at end of file diff --git a/gfx/wr/wrench/reftests/image/tiled-clip-chain.yaml b/gfx/wr/wrench/reftests/image/tiled-clip-chain.yaml new file mode 100644 index 0000000000..fdc7157753 --- /dev/null +++ b/gfx/wr/wrench/reftests/image/tiled-clip-chain.yaml @@ -0,0 +1,10 @@ +# Test that local clip rects from clip-chains are correctly +# propagated into the local clip rect for tiled images. +root: + items: + - type: clip + bounds: [10, 10, 100, 100] + items: + - image: checkerboard(2, 16, 16) + bounds: [10, 10, 260, 260] + tile-size: 64
\ No newline at end of file diff --git a/gfx/wr/wrench/reftests/image/tiled-complex-clip-ref.yaml b/gfx/wr/wrench/reftests/image/tiled-complex-clip-ref.yaml new file mode 100644 index 0000000000..9350da2372 --- /dev/null +++ b/gfx/wr/wrench/reftests/image/tiled-complex-clip-ref.yaml @@ -0,0 +1,10 @@ +root: + items: + - type: clip + bounds: [10, 10, 100, 100] + complex: + - rect: [10, 10, 100, 100] + radius: 32 + items: + - image: checkerboard(2, 16, 16) + bounds: [10, 10, 260, 260] diff --git a/gfx/wr/wrench/reftests/image/tiled-complex-clip.yaml b/gfx/wr/wrench/reftests/image/tiled-complex-clip.yaml new file mode 100644 index 0000000000..83ad3f1a8f --- /dev/null +++ b/gfx/wr/wrench/reftests/image/tiled-complex-clip.yaml @@ -0,0 +1,13 @@ +# Test that complex clips from clip-chains are correctly +# taken into account for tiled images. +root: + items: + - type: clip + bounds: [10, 10, 100, 100] + complex: + - rect: [10, 10, 100, 100] + radius: 32 + items: + - image: checkerboard(2, 16, 16) + bounds: [10, 10, 260, 260] + tile-size: 64 diff --git a/gfx/wr/wrench/reftests/image/very-big-ref.yaml b/gfx/wr/wrench/reftests/image/very-big-ref.yaml new file mode 100644 index 0000000000..6d7ea1b4b1 --- /dev/null +++ b/gfx/wr/wrench/reftests/image/very-big-ref.yaml @@ -0,0 +1,5 @@ +root: + items: + - type: rect + bounds: 0 0 500 500 + color: red diff --git a/gfx/wr/wrench/reftests/image/very-big-tile-size-ref.yaml b/gfx/wr/wrench/reftests/image/very-big-tile-size-ref.yaml new file mode 100644 index 0000000000..5001c2812c --- /dev/null +++ b/gfx/wr/wrench/reftests/image/very-big-tile-size-ref.yaml @@ -0,0 +1,5 @@ +root: + items: + - type: rect + bounds: 0 0 500 500 + color: green diff --git a/gfx/wr/wrench/reftests/image/very-big-tile-size.yaml b/gfx/wr/wrench/reftests/image/very-big-tile-size.yaml new file mode 100644 index 0000000000..d3bb3b8ec7 --- /dev/null +++ b/gfx/wr/wrench/reftests/image/very-big-tile-size.yaml @@ -0,0 +1,9 @@ +root: + items: + - type: rect + bounds: 0 0 500 500 + color: green + - image: solid-color(255, 0, 0, 255, 100000, 1000) + bounds: 0 0 500 500 + stretch-size: 1000000 1000 + tile-size: 60000 diff --git a/gfx/wr/wrench/reftests/image/very-big.yaml b/gfx/wr/wrench/reftests/image/very-big.yaml new file mode 100644 index 0000000000..dc0981d3a4 --- /dev/null +++ b/gfx/wr/wrench/reftests/image/very-big.yaml @@ -0,0 +1,5 @@ +root: + items: + - image: solid-color(255, 0, 0, 255, 100000, 1000) + bounds: 0 0 500 500 + stretch-size: 1000000 1000 diff --git a/gfx/wr/wrench/reftests/image/yuv-clip.yaml b/gfx/wr/wrench/reftests/image/yuv-clip.yaml new file mode 100644 index 0000000000..6ceb7b6940 --- /dev/null +++ b/gfx/wr/wrench/reftests/image/yuv-clip.yaml @@ -0,0 +1,24 @@ +root: + items: + - type: clip + bounds: [0, 0, 1314, 650] + complex: + - rect: [0, 0, 1314, 650] + items: + - type: yuv-image + format: planar + src-y: spacex-y.png + src-u: spacex-u.png + src-v: spacex-v.png + bounds: [10, 10, 427, 640] + + - type: yuv-image + format: interleaved + src: spacex-yuv.png + bounds: [447, 10, 427, 640] + + - type: yuv-image + format: nv12 + src-y: spacex-y.png + src-uv: spacex-uv.png + bounds: [887, 10, 427, 640] diff --git a/gfx/wr/wrench/reftests/image/yuv.png b/gfx/wr/wrench/reftests/image/yuv.png Binary files differnew file mode 100644 index 0000000000..66519bea8f --- /dev/null +++ b/gfx/wr/wrench/reftests/image/yuv.png diff --git a/gfx/wr/wrench/reftests/image/yuv.yaml b/gfx/wr/wrench/reftests/image/yuv.yaml new file mode 100644 index 0000000000..8120d93f8c --- /dev/null +++ b/gfx/wr/wrench/reftests/image/yuv.yaml @@ -0,0 +1,19 @@ +root: + items: + - type: yuv-image + format: planar + src-y: spacex-y.png + src-u: spacex-u.png + src-v: spacex-v.png + bounds: [10, 10, 427, 640] + + - type: yuv-image + format: interleaved + src: spacex-yuv.png + bounds: [447, 10, 427, 640] + + - type: yuv-image + format: nv12 + src-y: spacex-y.png + src-uv: spacex-uv.png + bounds: [887, 10, 427, 640] diff --git a/gfx/wr/wrench/reftests/mask/aligned-layer-rect-ref.yaml b/gfx/wr/wrench/reftests/mask/aligned-layer-rect-ref.yaml new file mode 100644 index 0000000000..d4ef946d7c --- /dev/null +++ b/gfx/wr/wrench/reftests/mask/aligned-layer-rect-ref.yaml @@ -0,0 +1,8 @@ +--- +root: + items: + - type: stacking-context + items: + - type: rect + bounds: [9, 9, 10, 10] + color: blue diff --git a/gfx/wr/wrench/reftests/mask/aligned-layer-rect.yaml b/gfx/wr/wrench/reftests/mask/aligned-layer-rect.yaml new file mode 100644 index 0000000000..a1c6e2f17e --- /dev/null +++ b/gfx/wr/wrench/reftests/mask/aligned-layer-rect.yaml @@ -0,0 +1,13 @@ +--- +root: + items: + - type: scroll-frame + bounds: [9, 9, 10, 10] + content-size: [95, 88] + items: + - type: scroll-frame + bounds: [0, 0, 100, 100] + items: + - type: rect + bounds: [0, 0, 100, 100] + color: blue diff --git a/gfx/wr/wrench/reftests/mask/checkerboard-tiling.yaml b/gfx/wr/wrench/reftests/mask/checkerboard-tiling.yaml new file mode 100644 index 0000000000..782babbef6 --- /dev/null +++ b/gfx/wr/wrench/reftests/mask/checkerboard-tiling.yaml @@ -0,0 +1,16 @@ +# Tests a tiled image mask with leftover tile offsets. +--- +root: + items: + - type: clip + bounds: [0, 0, 200, 200] + image-mask: + image: transparent-checkerboard(2, 16, 16) + rect: [0, 0, 200, 200] + repeat: false + # This is the point of the test, can't be a divisor of 200. + tile-size: 37 + items: + - type: rect + bounds: [0, 0, 200, 200] + color: blue diff --git a/gfx/wr/wrench/reftests/mask/checkerboard.png b/gfx/wr/wrench/reftests/mask/checkerboard.png Binary files differnew file mode 100644 index 0000000000..f2c45c3194 --- /dev/null +++ b/gfx/wr/wrench/reftests/mask/checkerboard.png diff --git a/gfx/wr/wrench/reftests/mask/checkerboard.yaml b/gfx/wr/wrench/reftests/mask/checkerboard.yaml new file mode 100644 index 0000000000..980bdb13fe --- /dev/null +++ b/gfx/wr/wrench/reftests/mask/checkerboard.yaml @@ -0,0 +1,13 @@ +--- +root: + items: + - type: clip + bounds: [0, 0, 200, 200] + image-mask: + image: transparent-checkerboard(2, 16, 16) + rect: [0, 0, 200, 200] + repeat: false + items: + - type: rect + bounds: [0, 0, 200, 200] + color: blue diff --git a/gfx/wr/wrench/reftests/mask/green.yaml b/gfx/wr/wrench/reftests/mask/green.yaml new file mode 100644 index 0000000000..0d3df60582 --- /dev/null +++ b/gfx/wr/wrench/reftests/mask/green.yaml @@ -0,0 +1,6 @@ +--- +root: + items: + - type: rect + bounds: [0, 0, 95, 88] + color: green diff --git a/gfx/wr/wrench/reftests/mask/mask-atomicity-ref.yaml b/gfx/wr/wrench/reftests/mask/mask-atomicity-ref.yaml new file mode 100644 index 0000000000..81480856c0 --- /dev/null +++ b/gfx/wr/wrench/reftests/mask/mask-atomicity-ref.yaml @@ -0,0 +1,17 @@ +--- +root: + items: + - type: rect + bounds: [25, 25, 100, 100] + color: red + - type: stacking-context + bounds: [0, 0, 200, 200] + filters: + - "opacity(0.5)" + items: + - type: rect + bounds: [0, 0, 100, 100] + color: blue + - type: rect + bounds: [50, 50, 100, 100] + color: green diff --git a/gfx/wr/wrench/reftests/mask/mask-atomicity-tiling.yaml b/gfx/wr/wrench/reftests/mask/mask-atomicity-tiling.yaml new file mode 100644 index 0000000000..f44b4ab3ce --- /dev/null +++ b/gfx/wr/wrench/reftests/mask/mask-atomicity-tiling.yaml @@ -0,0 +1,25 @@ +--- +root: + items: + - type: rect + bounds: [25, 25, 100, 100] + color: red + - type: clip + bounds: [0, 0, 200, 200] + id: 2 + image-mask: + # premultiplied 0.5 alpha white(??) + image: solid-color(127,127,127,127,200,200) + rect: [0, 0, 200, 200] + tile-size: 10 + repeat: false + - type: stacking-context + bounds: [0, 0, 200, 200] + clip-node: 2 + items: + - type: rect + bounds: [0, 0, 100, 100] + color: blue + - type: rect + bounds: [50, 50, 100, 100] + color: green diff --git a/gfx/wr/wrench/reftests/mask/mask-atomicity.yaml b/gfx/wr/wrench/reftests/mask/mask-atomicity.yaml new file mode 100644 index 0000000000..269030e361 --- /dev/null +++ b/gfx/wr/wrench/reftests/mask/mask-atomicity.yaml @@ -0,0 +1,24 @@ +--- +root: + items: + - type: rect + bounds: [25, 25, 100, 100] + color: red + - type: clip + bounds: [0, 0, 200, 200] + id: 2 + image-mask: + # premultiplied 0.5 alpha white(??) + image: solid-color(127,127,127,127,200,200) + rect: [0, 0, 200, 200] + repeat: false + - type: stacking-context + bounds: [0, 0, 200, 200] + clip-node: 2 + items: + - type: rect + bounds: [0, 0, 100, 100] + color: blue + - type: rect + bounds: [50, 50, 100, 100] + color: green diff --git a/gfx/wr/wrench/reftests/mask/mask-perspective-tiling.yaml b/gfx/wr/wrench/reftests/mask/mask-perspective-tiling.yaml new file mode 100644 index 0000000000..bd0fad7af9 --- /dev/null +++ b/gfx/wr/wrench/reftests/mask/mask-perspective-tiling.yaml @@ -0,0 +1,23 @@ +--- +root: + items: + - + type: stacking-context + perspective: 1 + perspective-origin: 0 0 + items: + - + type: stacking-context + transform: 10 0 0 0 0 10 0 0 0 0 10 0 0 0 -9 1 + items: + - type: clip + bounds: [0, 0, 95, 88] + image-mask: + image: "mask.png" + rect: [0, 0, 35, 35] + repeat: false + tile-size: 5 + items: + - type: rect + bounds: [0, 0, 95, 88] + color: blue diff --git a/gfx/wr/wrench/reftests/mask/mask-perspective.png b/gfx/wr/wrench/reftests/mask/mask-perspective.png Binary files differnew file mode 100644 index 0000000000..edec10eae3 --- /dev/null +++ b/gfx/wr/wrench/reftests/mask/mask-perspective.png diff --git a/gfx/wr/wrench/reftests/mask/mask-perspective.yaml b/gfx/wr/wrench/reftests/mask/mask-perspective.yaml new file mode 100644 index 0000000000..e8d8e4d5d4 --- /dev/null +++ b/gfx/wr/wrench/reftests/mask/mask-perspective.yaml @@ -0,0 +1,22 @@ +--- +root: + items: + - + type: stacking-context + perspective: 1 + perspective-origin: 0 0 + items: + - + type: stacking-context + transform: 10 0 0 0 0 10 0 0 0 0 10 0 0 0 -9 1 + items: + - type: clip + bounds: [0, 0, 95, 88] + image-mask: + image: "mask.png" + rect: [0, 0, 35, 35] + repeat: false + items: + - type: rect + bounds: [0, 0, 95, 88] + color: blue diff --git a/gfx/wr/wrench/reftests/mask/mask-ref.yaml b/gfx/wr/wrench/reftests/mask/mask-ref.yaml new file mode 100644 index 0000000000..01c4e60946 --- /dev/null +++ b/gfx/wr/wrench/reftests/mask/mask-ref.yaml @@ -0,0 +1,9 @@ +--- +root: + items: + - type: stacking-context + bounds: [0, 0, 95, 88] + items: + - type: rect + bounds: [9, 9, 10, 10] + color: blue diff --git a/gfx/wr/wrench/reftests/mask/mask-tiling.yaml b/gfx/wr/wrench/reftests/mask/mask-tiling.yaml new file mode 100644 index 0000000000..021ec9fa28 --- /dev/null +++ b/gfx/wr/wrench/reftests/mask/mask-tiling.yaml @@ -0,0 +1,14 @@ +--- +root: + items: + - type: clip + bounds: [0, 0, 95, 88] + image-mask: + image: "mask.png" + rect: [0, 0, 35, 35] + repeat: false + tile-size: 5 + items: + - type: rect + bounds: [0, 0, 95, 88] + color: blue diff --git a/gfx/wr/wrench/reftests/mask/mask-transformed-to-empty-rect-ref.yaml b/gfx/wr/wrench/reftests/mask/mask-transformed-to-empty-rect-ref.yaml new file mode 100644 index 0000000000..1df66453d6 --- /dev/null +++ b/gfx/wr/wrench/reftests/mask/mask-transformed-to-empty-rect-ref.yaml @@ -0,0 +1,6 @@ +--- +root: + items: + - type: rect + bounds: [0, 0, 100, 100] + color: 0 255 0 1.0 diff --git a/gfx/wr/wrench/reftests/mask/mask-transformed-to-empty-rect.yaml b/gfx/wr/wrench/reftests/mask/mask-transformed-to-empty-rect.yaml new file mode 100644 index 0000000000..a291c1fb96 --- /dev/null +++ b/gfx/wr/wrench/reftests/mask/mask-transformed-to-empty-rect.yaml @@ -0,0 +1,26 @@ +--- +root: + items: + - type: stacking-context + bounds: [0, 0, 300, 300] + "scroll-policy": scrollable + z-index: 4 + transform: [1, 0, 0, 0, 0, 0, 1, 0, 0, -1, 0, 0, 0, 150, -150, 1] + items: + - type: clip + bounds: [0, 0, 300, 300] + # This image mask here assures that we will be forced to try to + # mask instead of skipping it due to the mask rect becoming a + # zero rect. + image-mask: + image: "tiny-check-mask.png" + rect: [0, 0, 300, 300] + repeat: false + id: 2 + items: + - type: rect + bounds: [0, 0, 300, 300] + color: 0 128 0 1.0000 + - type: rect + bounds: [0, 0, 100, 100] + color: 0 255 0 1.0 diff --git a/gfx/wr/wrench/reftests/mask/mask.png b/gfx/wr/wrench/reftests/mask/mask.png Binary files differnew file mode 100644 index 0000000000..ab1bdb9b50 --- /dev/null +++ b/gfx/wr/wrench/reftests/mask/mask.png diff --git a/gfx/wr/wrench/reftests/mask/mask.yaml b/gfx/wr/wrench/reftests/mask/mask.yaml new file mode 100644 index 0000000000..b7432f5827 --- /dev/null +++ b/gfx/wr/wrench/reftests/mask/mask.yaml @@ -0,0 +1,13 @@ +--- +root: + items: + - type: clip + bounds: [0, 0, 95, 88] + image-mask: + image: "mask.png" + rect: [0, 0, 35, 35] + repeat: false + items: + - type: rect + bounds: [0, 0, 95, 88] + color: blue diff --git a/gfx/wr/wrench/reftests/mask/missing-mask-ref.yaml b/gfx/wr/wrench/reftests/mask/missing-mask-ref.yaml new file mode 100644 index 0000000000..112da9c9d1 --- /dev/null +++ b/gfx/wr/wrench/reftests/mask/missing-mask-ref.yaml @@ -0,0 +1,7 @@ +# Don't crash when supplied an invalid image key for the mask! +--- +root: + items: + - type: rect + bounds: [0, 0, 35, 35] + color: blue diff --git a/gfx/wr/wrench/reftests/mask/missing-mask.yaml b/gfx/wr/wrench/reftests/mask/missing-mask.yaml new file mode 100644 index 0000000000..124c2cd893 --- /dev/null +++ b/gfx/wr/wrench/reftests/mask/missing-mask.yaml @@ -0,0 +1,14 @@ +# Don't crash when supplied an invalid image key for the mask! +--- +root: + items: + - type: clip + bounds: [0, 0, 95, 88] + image-mask: + image: invalid + rect: [0, 0, 35, 35] + repeat: false + items: + - type: rect + bounds: [0, 0, 95, 88] + color: blue diff --git a/gfx/wr/wrench/reftests/mask/nested-mask-ref.yaml b/gfx/wr/wrench/reftests/mask/nested-mask-ref.yaml new file mode 100644 index 0000000000..c16df79e4c --- /dev/null +++ b/gfx/wr/wrench/reftests/mask/nested-mask-ref.yaml @@ -0,0 +1,9 @@ +--- +root: + items: + - type: stacking-context + bounds: [0, 0, 95, 88] + items: + - type: rect + bounds: [13, 13, 6, 6] + color: blue diff --git a/gfx/wr/wrench/reftests/mask/nested-mask-tiling.yaml b/gfx/wr/wrench/reftests/mask/nested-mask-tiling.yaml new file mode 100644 index 0000000000..0e70758f58 --- /dev/null +++ b/gfx/wr/wrench/reftests/mask/nested-mask-tiling.yaml @@ -0,0 +1,22 @@ +--- +root: + items: + - type: clip + bounds: [0, 0, 95, 88] + image-mask: + image: "mask.png" + rect: [0, 0, 35, 35] + repeat: false + tile-size: 5 + items: + - type: clip + bounds: [0, 0, 95, 88] + image-mask: + image: "mask.png" + rect: [4, 4, 35, 35] + repeat: false + tile-size: 5 + items: + - type: rect + bounds: [0, 0, 95, 88] + color: blue diff --git a/gfx/wr/wrench/reftests/mask/nested-mask.yaml b/gfx/wr/wrench/reftests/mask/nested-mask.yaml new file mode 100644 index 0000000000..cacbb63434 --- /dev/null +++ b/gfx/wr/wrench/reftests/mask/nested-mask.yaml @@ -0,0 +1,20 @@ +--- +root: + items: + - type: clip + bounds: [0, 0, 95, 88] + image-mask: + image: "mask.png" + rect: [0, 0, 35, 35] + repeat: false + items: + - type: clip + bounds: [0, 0, 95, 88] + image-mask: + image: "mask.png" + rect: [4, 4, 35, 35] + repeat: false + items: + - type: rect + bounds: [0, 0, 95, 88] + color: blue diff --git a/gfx/wr/wrench/reftests/mask/out-of-bounds.yaml b/gfx/wr/wrench/reftests/mask/out-of-bounds.yaml new file mode 100644 index 0000000000..8e0eed09e0 --- /dev/null +++ b/gfx/wr/wrench/reftests/mask/out-of-bounds.yaml @@ -0,0 +1,16 @@ +--- +root: + items: + - type: clip + bounds: [0, 0, 10000, 10000] + complex: + - rect: [0, 0, 10000, 10000] + radius: + top-left: [30, 30] + top-right: [30, 30] + bottom-right: [30, 30] + bottom-left: [30, 30] + items: + - type: rect + bounds: [0, 0, 10000, 10000] + color: green diff --git a/gfx/wr/wrench/reftests/mask/reftest.list b/gfx/wr/wrench/reftests/mask/reftest.list new file mode 100644 index 0000000000..eb3bb3641d --- /dev/null +++ b/gfx/wr/wrench/reftests/mask/reftest.list @@ -0,0 +1,16 @@ +fuzzy(1,10) == mask.yaml mask-ref.yaml +fuzzy(1,10) == mask-tiling.yaml mask-ref.yaml +fuzzy(1,10) == nested-mask.yaml nested-mask-ref.yaml +== nested-mask-tiling.yaml nested-mask-ref.yaml +!= mask.yaml green.yaml +== aligned-layer-rect.yaml aligned-layer-rect-ref.yaml +== mask-transformed-to-empty-rect.yaml mask-transformed-to-empty-rect-ref.yaml +platform(linux,mac) == rounded-corners.yaml rounded-corners.png +!= mask.yaml out-of-bounds.yaml +platform(linux,mac) fuzzy(1,17500) color_targets(3) alpha_targets(1) == mask-atomicity.yaml mask-atomicity-ref.yaml +platform(linux,mac) fuzzy(1,17500) == mask-atomicity-tiling.yaml mask-atomicity-ref.yaml +platform(linux,mac) == mask-perspective.yaml mask-perspective.png +== fuzzy(1,11) mask-perspective-tiling.yaml mask-perspective.yaml +platform(linux,mac) == checkerboard.yaml checkerboard.png +skip_on(android,device) == checkerboard.yaml checkerboard-tiling.yaml # Fails on a Pixel2 +== missing-mask.yaml missing-mask-ref.yaml diff --git a/gfx/wr/wrench/reftests/mask/rounded-corners.png b/gfx/wr/wrench/reftests/mask/rounded-corners.png Binary files differnew file mode 100644 index 0000000000..19adfe02ec --- /dev/null +++ b/gfx/wr/wrench/reftests/mask/rounded-corners.png diff --git a/gfx/wr/wrench/reftests/mask/rounded-corners.yaml b/gfx/wr/wrench/reftests/mask/rounded-corners.yaml new file mode 100644 index 0000000000..e26a656cc0 --- /dev/null +++ b/gfx/wr/wrench/reftests/mask/rounded-corners.yaml @@ -0,0 +1,24 @@ +--- +root: + items: + - type: clip + bounds: [0, 0, 100, 100] + complex: + - rect: [0, 0, 100, 100] + radius: + top-left: [30, 30] + top-right: [30, 30] + bottom-right: [30, 30] + bottom-left: [30, 30] + items: + - type: border + bounds: [0, 0, 100, 100] + width: [5, 5, 5, 5] + border-type: normal + style: [solid, solid, solid, solid] + color: [blue, blue, blue, blue] + radius: + top-left: [30, 30] + top-right: [30, 30] + bottom-right: [0, 0] + bottom-left: [0, 0] diff --git a/gfx/wr/wrench/reftests/mask/tiny-check-mask.png b/gfx/wr/wrench/reftests/mask/tiny-check-mask.png Binary files differnew file mode 100644 index 0000000000..d6f6e3548d --- /dev/null +++ b/gfx/wr/wrench/reftests/mask/tiny-check-mask.png diff --git a/gfx/wr/wrench/reftests/performance/compositor-surface-opaque-slice-ref.yaml b/gfx/wr/wrench/reftests/performance/compositor-surface-opaque-slice-ref.yaml new file mode 100644 index 0000000000..7c538488bc --- /dev/null +++ b/gfx/wr/wrench/reftests/performance/compositor-surface-opaque-slice-ref.yaml @@ -0,0 +1,9 @@ +root: + items: + - + bounds: [0, 0, 200, 200] + image: checkerboard(2, 16, 12) + stretch-size: 200 200 + - type: rect + bounds: [0, 0, 200, 200] + color: [255, 0, 0, 0.5] diff --git a/gfx/wr/wrench/reftests/performance/compositor-surface-opaque-slice.yaml b/gfx/wr/wrench/reftests/performance/compositor-surface-opaque-slice.yaml new file mode 100644 index 0000000000..a5821973e9 --- /dev/null +++ b/gfx/wr/wrench/reftests/performance/compositor-surface-opaque-slice.yaml @@ -0,0 +1,10 @@ +root: + items: + - + bounds: [0, 0, 200, 200] + image: checkerboard(2, 16, 12) + stretch-size: 200 200 + prefer-compositor-surface: true + - type: rect + bounds: [0, 0, 200, 200] + color: [255, 0, 0, 0.5] diff --git a/gfx/wr/wrench/reftests/performance/no-clip-mask.png b/gfx/wr/wrench/reftests/performance/no-clip-mask.png Binary files differnew file mode 100644 index 0000000000..0b1bfca755 --- /dev/null +++ b/gfx/wr/wrench/reftests/performance/no-clip-mask.png diff --git a/gfx/wr/wrench/reftests/performance/no-clip-mask.yaml b/gfx/wr/wrench/reftests/performance/no-clip-mask.yaml new file mode 100644 index 0000000000..51d981e2a0 --- /dev/null +++ b/gfx/wr/wrench/reftests/performance/no-clip-mask.yaml @@ -0,0 +1,24 @@ +# In this case, there is no incompatible transform. +# Therefore, the clip condition should be handled +# by the vertex shader via the local_clip_rect, and +# there should be no clip mask generated. +--- +root: + items: + - + type: "stacking-context" + items: + - + bounds: [0, 111, 1087, 565] + "clip-rect": [0, 111, 1087, 565] + type: iframe + id: [1, 2] +pipelines: + - + id: [1, 2] + items: + - + bounds: [1075, -1, 12, 199] + "clip-rect": [1075, -1, 12, 199] + image: checkerboard(4, 8, 8) + stretch-size: 72 72 diff --git a/gfx/wr/wrench/reftests/performance/reftest.list b/gfx/wr/wrench/reftests/performance/reftest.list new file mode 100644 index 0000000000..5ca69146dc --- /dev/null +++ b/gfx/wr/wrench/reftests/performance/reftest.list @@ -0,0 +1,2 @@ +skip_on(android) == color_targets(2) alpha_targets(0) no-clip-mask.yaml no-clip-mask.png # Too wide for Android +platform(linux,mac) == compositor-surface-opaque-slice.yaml compositor-surface-opaque-slice-ref.yaml diff --git a/gfx/wr/wrench/reftests/reftest.list b/gfx/wr/wrench/reftests/reftest.list new file mode 100644 index 0000000000..de0ed5cba6 --- /dev/null +++ b/gfx/wr/wrench/reftests/reftest.list @@ -0,0 +1,17 @@ +include aa/reftest.list +include backface/reftest.list +include blend/reftest.list +include border/reftest.list +include boxshadow/reftest.list +include clip/reftest.list +include filters/reftest.list +include gradient/reftest.list +include image/reftest.list +include mask/reftest.list +include performance/reftest.list +include scrolling/reftest.list +include snap/reftest.list +include split/reftest.list +include text/reftest.list +include transforms/reftest.list +include tiles/reftest.list diff --git a/gfx/wr/wrench/reftests/scrolling/clip-and-scroll-property-ref.yaml b/gfx/wr/wrench/reftests/scrolling/clip-and-scroll-property-ref.yaml new file mode 100644 index 0000000000..a465f412df --- /dev/null +++ b/gfx/wr/wrench/reftests/scrolling/clip-and-scroll-property-ref.yaml @@ -0,0 +1,5 @@ +root: + items: + - type: rect + bounds: [0, 0, 200, 200] + color: green diff --git a/gfx/wr/wrench/reftests/scrolling/clip-and-scroll-property.yaml b/gfx/wr/wrench/reftests/scrolling/clip-and-scroll-property.yaml new file mode 100644 index 0000000000..ed72c23fce --- /dev/null +++ b/gfx/wr/wrench/reftests/scrolling/clip-and-scroll-property.yaml @@ -0,0 +1,30 @@ +--- +root: + items: + - + bounds: [0, 0, 200, 200] + type: "stacking-context" + "scroll-policy": scrollable + items: + - + bounds: [0, 0, 200, 200] + type: clip + id: 2 + # Here we are testing that the clip-and-scroll property applies to + # both stacking contexts and items. + - + bounds: [0, 0, 0, 0] + content-size: [200, 200] + clip-and-scroll: 2 + type: "stacking-context" + "scroll-policy": scrollable + transform: [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, -100, 0, 0, 1] + "transform-style": flat + items: + - + bounds: [100, 0, 200, 200] + clip: [-8947849, -8947849, 17895698, 17895698] + type: rect + color: green + id: [0, 0] +pipelines: [] diff --git a/gfx/wr/wrench/reftests/scrolling/empty-mask-ref.yaml b/gfx/wr/wrench/reftests/scrolling/empty-mask-ref.yaml new file mode 100644 index 0000000000..aca8ccd66c --- /dev/null +++ b/gfx/wr/wrench/reftests/scrolling/empty-mask-ref.yaml @@ -0,0 +1,5 @@ +root: + items: + - type: rect + bounds: [0, 0, 100, 100] + color: green diff --git a/gfx/wr/wrench/reftests/scrolling/empty-mask.yaml b/gfx/wr/wrench/reftests/scrolling/empty-mask.yaml new file mode 100644 index 0000000000..69378dd5ad --- /dev/null +++ b/gfx/wr/wrench/reftests/scrolling/empty-mask.yaml @@ -0,0 +1,18 @@ +root: + items: + - type: rect + bounds: [0, 0, 100, 100] + color: green + - type: scroll-frame + bounds: [0, 0, 100, 100] + items: + - type: clip + bounds: [0, 0, 0, 0] + content-size: [100, 100] + complex: + - rect: [0, 0, 100, 100] + radius: 20 + items: + - type: rect + bounds: [0, 0, 500, 500] + color: red diff --git a/gfx/wr/wrench/reftests/scrolling/ext-scroll-offset-1-ref.yaml b/gfx/wr/wrench/reftests/scrolling/ext-scroll-offset-1-ref.yaml new file mode 100644 index 0000000000..3b8d47e94c --- /dev/null +++ b/gfx/wr/wrench/reftests/scrolling/ext-scroll-offset-1-ref.yaml @@ -0,0 +1,10 @@ +root: + items: + - type: scroll-frame + bounds: [0, 0, 100, 100] + content-size: [100, 1000] + scroll-offset: [0, -50] + items: + - type: rect + color: green + bounds: [0, 0, 100, 100] diff --git a/gfx/wr/wrench/reftests/scrolling/ext-scroll-offset-1.yaml b/gfx/wr/wrench/reftests/scrolling/ext-scroll-offset-1.yaml new file mode 100644 index 0000000000..7803574bed --- /dev/null +++ b/gfx/wr/wrench/reftests/scrolling/ext-scroll-offset-1.yaml @@ -0,0 +1,14 @@ +# Test that items with an external scroll offset in both the +# scroll node and primitive match up with items that have +# been scrolled without an external scroll offset. +root: + items: + - type: scroll-frame + bounds: [0, 0, 100, 100] + content-size: [100, 1000] + scroll-offset: [0, 0] + external-scroll-offset: [0, 50] + items: + - type: rect + color: green + bounds: [0, 50, 100, 100] diff --git a/gfx/wr/wrench/reftests/scrolling/fixed-position-ref.yaml b/gfx/wr/wrench/reftests/scrolling/fixed-position-ref.yaml new file mode 100644 index 0000000000..aa26387828 --- /dev/null +++ b/gfx/wr/wrench/reftests/scrolling/fixed-position-ref.yaml @@ -0,0 +1,14 @@ +root: + items: + - type: rect + bounds: [0, 0, 50, 50] + color: green + - type: rect + bounds: [60, 0, 50, 50] + color: green + - type: rect + bounds: [120, 0, 50, 50] + color: green + - type: rect + bounds: [180, 0, 50, 50] + color: green diff --git a/gfx/wr/wrench/reftests/scrolling/fixed-position-scrolling-clip-ref.yaml b/gfx/wr/wrench/reftests/scrolling/fixed-position-scrolling-clip-ref.yaml new file mode 100644 index 0000000000..eb50353314 --- /dev/null +++ b/gfx/wr/wrench/reftests/scrolling/fixed-position-scrolling-clip-ref.yaml @@ -0,0 +1,5 @@ +root: + items: + - type: rect + bounds: [10, 10, 50, 50] + color: green diff --git a/gfx/wr/wrench/reftests/scrolling/fixed-position-scrolling-clip.yaml b/gfx/wr/wrench/reftests/scrolling/fixed-position-scrolling-clip.yaml new file mode 100644 index 0000000000..63573e5742 --- /dev/null +++ b/gfx/wr/wrench/reftests/scrolling/fixed-position-scrolling-clip.yaml @@ -0,0 +1,28 @@ +root: + items: + - type: scroll-frame + bounds: [10, 10, 100, 300] + content-size: [100, 700] + id: 41 + scroll-offset: [0, 50] + items: + # The rectangles below should stay in place even when the parent scroll area scrolls, + # because they use the root reference frame as their scroll node (fixed position). + # On the other hand, the clip item here will scroll with its parent scroll area. Normally + # fixed position items would only be clipped by their reference frame (in this case the + # root), but since these items specify an auxiliary clip, they will be clipped by their + # sibling clip (42). + - type: clip + bounds: [10, 60, 50, 50] + id: 42 + - type: stacking-context + bounds: [10, 10, 100, 100] + items: + - type: rect + bounds: [0, 0, 100, 50] + color: green + clip-and-scroll: [root-reference-frame, 42] + - type: rect + bounds: [0, 50, 100, 50] + color: red + clip-and-scroll: [root-reference-frame, 42] diff --git a/gfx/wr/wrench/reftests/scrolling/fixed-position.yaml b/gfx/wr/wrench/reftests/scrolling/fixed-position.yaml new file mode 100644 index 0000000000..6fa099b5e3 --- /dev/null +++ b/gfx/wr/wrench/reftests/scrolling/fixed-position.yaml @@ -0,0 +1,55 @@ +root: + bounds: [0, 0, 1024, 10000] + scroll-offset: [0, 100] + items: + - type: stacking-context + bounds: [0, 0, 50, 50] + items: + # This item should not scroll out of view because it is fixed position. + - type: rect + bounds: [0, 0, 50, 50] + color: green + clip-and-scroll: root-reference-frame + - type: stacking-context + bounds: [0, 0, 50, 50] + transform: translate(60, 100) + id: 100 + items: + - type: stacking-context + bounds: [0, 0, 50, 50] + items: + # Even though there is a custom clip-scroll ID, it should scroll, + # because it is fixed relative to its reference frame. The reference frame + # of this stacking context is the stacking context parent because it has + # a transformation. + - type: rect + bounds: [0, 0, 50, 50] + color: green + clip-and-scroll: 100 + - type: stacking-context + bounds: [120, 0, 50, 200] + transform: translate(0, 0) + id: 101 + items: + # This is similar to the previous case, but ensures that this still works + # even with an identity transform. + - type: stacking-context + bounds: [0, 0, 50, 200] + items: + - type: rect + bounds: [0, 100, 50, 50] + color: green + clip-and-scroll: 101 + - type: stacking-context + bounds: [180, 0, 50, 200] + perspective: 1 + id: 102 + items: + # This is similar to the previous case, but for perspective. + - type: stacking-context + bounds: [0, 0, 50, 200] + items: + - type: rect + bounds: [0, 100, 50, 50] + color: green + clip-and-scroll: 102 diff --git a/gfx/wr/wrench/reftests/scrolling/mask.png b/gfx/wr/wrench/reftests/scrolling/mask.png Binary files differnew file mode 100644 index 0000000000..d3cbfe6a63 --- /dev/null +++ b/gfx/wr/wrench/reftests/scrolling/mask.png diff --git a/gfx/wr/wrench/reftests/scrolling/nested-scroll-offset-ref.yaml b/gfx/wr/wrench/reftests/scrolling/nested-scroll-offset-ref.yaml new file mode 100644 index 0000000000..c2f0a30710 --- /dev/null +++ b/gfx/wr/wrench/reftests/scrolling/nested-scroll-offset-ref.yaml @@ -0,0 +1,5 @@ +root: + items: + - type: rect + bounds: [0, 0, 50, 50] + color: green diff --git a/gfx/wr/wrench/reftests/scrolling/nested-scroll-offset.yaml b/gfx/wr/wrench/reftests/scrolling/nested-scroll-offset.yaml new file mode 100644 index 0000000000..850468f180 --- /dev/null +++ b/gfx/wr/wrench/reftests/scrolling/nested-scroll-offset.yaml @@ -0,0 +1,16 @@ +root: + items: + - type: scroll-frame + bounds: [0, 0, 500, 500] + content-size: [1000, 1000] + scroll-offset: [0, 300] + items: + - type: scroll-frame + bounds: [0, 300, 50, 50] + items: + - type: scroll-frame + bounds: [0, 300, 50, 50] + items: + - type: rect + bounds: [0, 300, 50, 50] + color: green diff --git a/gfx/wr/wrench/reftests/scrolling/nested-stickys-ref.yaml b/gfx/wr/wrench/reftests/scrolling/nested-stickys-ref.yaml new file mode 100644 index 0000000000..869ad7e9e1 --- /dev/null +++ b/gfx/wr/wrench/reftests/scrolling/nested-stickys-ref.yaml @@ -0,0 +1,11 @@ +root: + items: + # This is a scroll frame with an out-of-viewport rect that should be pushed into the + # viewport by its "bottom" sticky constraint. + - type: scroll-frame + bounds: [10, 10, 50, 50] + content-size: [200, 200] + items: + - type: rect + bounds: [10, 20, 50, 50] + color: green diff --git a/gfx/wr/wrench/reftests/scrolling/nested-stickys.yaml b/gfx/wr/wrench/reftests/scrolling/nested-stickys.yaml new file mode 100644 index 0000000000..2082bb2576 --- /dev/null +++ b/gfx/wr/wrench/reftests/scrolling/nested-stickys.yaml @@ -0,0 +1,20 @@ +root: + items: + - type: scroll-frame + bounds: [10, 10, 50, 50] + content-size: [200, 200] + scroll-offset: [0, 30] + items: + - type: sticky-frame + bounds: [10, 30, 50, 50] + margin-top: 5 + vertical-offset-bounds: [0, 500] + items: + - type: sticky-frame + bounds: [10, 30, 50, 50] + margin-top: 10 + vertical-offset-bounds: [0, 500] + items: + - type: rect + bounds: [10, 30, 50, 50] + color: green diff --git a/gfx/wr/wrench/reftests/scrolling/out-of-bounds-scroll-ref.yaml b/gfx/wr/wrench/reftests/scrolling/out-of-bounds-scroll-ref.yaml new file mode 100644 index 0000000000..eb50353314 --- /dev/null +++ b/gfx/wr/wrench/reftests/scrolling/out-of-bounds-scroll-ref.yaml @@ -0,0 +1,5 @@ +root: + items: + - type: rect + bounds: [10, 10, 50, 50] + color: green diff --git a/gfx/wr/wrench/reftests/scrolling/out-of-bounds-scroll.yaml b/gfx/wr/wrench/reftests/scrolling/out-of-bounds-scroll.yaml new file mode 100644 index 0000000000..8c87bd6f5c --- /dev/null +++ b/gfx/wr/wrench/reftests/scrolling/out-of-bounds-scroll.yaml @@ -0,0 +1,10 @@ +root: + items: + - type: scroll-frame + bounds: [10, 10, 50, 100] + content-size: [50, 200] + scroll-offset: [0, 50] + items: + - type: rect + bounds: [10, 60, 50, 50] + color: green diff --git a/gfx/wr/wrench/reftests/scrolling/reftest.list b/gfx/wr/wrench/reftests/scrolling/reftest.list new file mode 100644 index 0000000000..58638d277c --- /dev/null +++ b/gfx/wr/wrench/reftests/scrolling/reftest.list @@ -0,0 +1,21 @@ +== empty-mask.yaml empty-mask-ref.yaml +== fixed-position-scrolling-clip.yaml fixed-position-scrolling-clip-ref.yaml +== fixed-position.yaml fixed-position-ref.yaml +== nested-scroll-offset.yaml nested-scroll-offset-ref.yaml +== out-of-bounds-scroll.yaml out-of-bounds-scroll-ref.yaml +== root-scroll.yaml root-scroll-ref.yaml +== scroll-layer.yaml scroll-layer-ref.yaml +== simple.yaml simple-ref.yaml +== clip-and-scroll-property.yaml clip-and-scroll-property-ref.yaml +== translate-nested.yaml translate-nested-ref.yaml +== sticky.yaml sticky-ref.yaml +== sticky-nested.yaml sticky-ref.yaml +== sticky-applied.yaml sticky-applied-ref.yaml +== sticky-transformed.yaml sticky-transformed-ref.yaml +== sibling-hidden-clip.yaml sibling-hidden-clip-ref.yaml +== scale-offsets.yaml scale-offsets-ref.yaml +== nested-stickys.yaml nested-stickys-ref.yaml +== viewport-offset.yaml viewport-offset-ref.yaml +== ext-scroll-offset-1.yaml ext-scroll-offset-1-ref.yaml +== scroll-frame-order.yaml scroll-frame-order-ref.yaml + diff --git a/gfx/wr/wrench/reftests/scrolling/root-scroll-ref.yaml b/gfx/wr/wrench/reftests/scrolling/root-scroll-ref.yaml new file mode 100644 index 0000000000..d49f063d3a --- /dev/null +++ b/gfx/wr/wrench/reftests/scrolling/root-scroll-ref.yaml @@ -0,0 +1,6 @@ +root: + bounds: [0, 0, 1024, 10000] + items: + - type: rect + bounds: [10, 10, 50, 50] + color: green diff --git a/gfx/wr/wrench/reftests/scrolling/root-scroll.yaml b/gfx/wr/wrench/reftests/scrolling/root-scroll.yaml new file mode 100644 index 0000000000..d95c7debe1 --- /dev/null +++ b/gfx/wr/wrench/reftests/scrolling/root-scroll.yaml @@ -0,0 +1,7 @@ +root: + bounds: [0, 0, 1024, 10000] + scroll-offset: [0, 100] + items: + - type: rect + bounds: [10, 110, 50, 50] + color: green diff --git a/gfx/wr/wrench/reftests/scrolling/scale-offsets-ref.yaml b/gfx/wr/wrench/reftests/scrolling/scale-offsets-ref.yaml new file mode 100644 index 0000000000..9276ded8f8 --- /dev/null +++ b/gfx/wr/wrench/reftests/scrolling/scale-offsets-ref.yaml @@ -0,0 +1,5 @@ +root: + items: + - type: rect + color: green + bounds: [50, 50, 50, 50] diff --git a/gfx/wr/wrench/reftests/scrolling/scale-offsets.yaml b/gfx/wr/wrench/reftests/scrolling/scale-offsets.yaml new file mode 100644 index 0000000000..fe4cf74131 --- /dev/null +++ b/gfx/wr/wrench/reftests/scrolling/scale-offsets.yaml @@ -0,0 +1,15 @@ +# Test that a scroll-frame nested within a scale +# transform correctly calculates local offsets. +root: + items: + - type: stacking-context + transform: scale(0.5) + items: + - type: scroll-frame + bounds: [100, 100, 100, 100] + content-size: [260, 260] + scroll-offset: [0, 60] + items: + - type: rect + color: green + bounds: [100, 100, 260, 260] diff --git a/gfx/wr/wrench/reftests/scrolling/scroll-frame-order-ref.yaml b/gfx/wr/wrench/reftests/scrolling/scroll-frame-order-ref.yaml new file mode 100644 index 0000000000..5429d052db --- /dev/null +++ b/gfx/wr/wrench/reftests/scrolling/scroll-frame-order-ref.yaml @@ -0,0 +1,34 @@ +# Tests that scroll frames can be defined and used in any order. + +--- +root: + items: + - type: scroll-frame + bounds: [0, 0, 50, 50] + content-size: [50, 50] + clip-rect: [0, 0, 50, 50] + id: 123 + - type: scroll-frame + bounds: [50, 0, 50, 50] + content-size: [50, 50] + clip-rect: [50, 0, 50, 50] + scroll-offset: [0, -25] + id: 456 + - type: scroll-frame + bounds: [100, 0, 50, 50] + content-size: [50, 50] + clip-rect: [100, 0, 50, 50] + scroll-offset: [0, -15] + id: 789 + - type: rect + bounds: [0, 0, 50, 50] + color: red + clip-and-scroll: 123 + - type: rect + bounds: [50, 0, 50, 50] + color: green + clip-and-scroll: 456 + - type: rect + bounds: [100, 0, 50, 50] + color: blue + clip-and-scroll: 789 diff --git a/gfx/wr/wrench/reftests/scrolling/scroll-frame-order.yaml b/gfx/wr/wrench/reftests/scrolling/scroll-frame-order.yaml new file mode 100644 index 0000000000..1801dbb08a --- /dev/null +++ b/gfx/wr/wrench/reftests/scrolling/scroll-frame-order.yaml @@ -0,0 +1,35 @@ +# Tests that scroll frames can be defined and used in any order. + +--- +root: + items: + - type: scroll-frame + bounds: [0, 0, 50, 50] + content-size: [50, 50] + clip-rect: [0, 0, 50, 50] + id: 123 + - type: rect + bounds: [0, 0, 50, 50] + color: red + clip-and-scroll: 123 + - type: scroll-frame + bounds: [50, 0, 50, 50] + content-size: [50, 50] + clip-rect: [50, 0, 50, 50] + scroll-offset: [0, -25] + id: 456 + - type: rect + bounds: [50, 0, 50, 50] + color: green + clip-and-scroll: 456 + - type: scroll-frame + bounds: [100, 0, 50, 50] + content-size: [50, 50] + clip-rect: [100, 0, 50, 50] + scroll-offset: [0, -15] + id: 789 + - type: rect + bounds: [100, 0, 50, 50] + color: blue + clip-and-scroll: 789 + diff --git a/gfx/wr/wrench/reftests/scrolling/scroll-layer-ref.yaml b/gfx/wr/wrench/reftests/scrolling/scroll-layer-ref.yaml new file mode 100644 index 0000000000..c2f0a30710 --- /dev/null +++ b/gfx/wr/wrench/reftests/scrolling/scroll-layer-ref.yaml @@ -0,0 +1,5 @@ +root: + items: + - type: rect + bounds: [0, 0, 50, 50] + color: green diff --git a/gfx/wr/wrench/reftests/scrolling/scroll-layer.yaml b/gfx/wr/wrench/reftests/scrolling/scroll-layer.yaml new file mode 100644 index 0000000000..4956672a77 --- /dev/null +++ b/gfx/wr/wrench/reftests/scrolling/scroll-layer.yaml @@ -0,0 +1,10 @@ +root: + items: + - type: scroll-frame + bounds: [0, 0, 100, 100] + content-size: [1000, 1000] + scroll-offset: [50, 50] + items: + - type: rect + bounds: [50, 50, 50, 50] + color: green diff --git a/gfx/wr/wrench/reftests/scrolling/sibling-hidden-clip-ref.yaml b/gfx/wr/wrench/reftests/scrolling/sibling-hidden-clip-ref.yaml new file mode 100644 index 0000000000..f722f6f815 --- /dev/null +++ b/gfx/wr/wrench/reftests/scrolling/sibling-hidden-clip-ref.yaml @@ -0,0 +1,8 @@ +--- +root: + items: + - type: rect + bounds: [10, 10, 40, 70] + color: red + id: [0, 0] +pipelines: [] diff --git a/gfx/wr/wrench/reftests/scrolling/sibling-hidden-clip.yaml b/gfx/wr/wrench/reftests/scrolling/sibling-hidden-clip.yaml new file mode 100644 index 0000000000..74b735d32a --- /dev/null +++ b/gfx/wr/wrench/reftests/scrolling/sibling-hidden-clip.yaml @@ -0,0 +1,20 @@ +--- +root: + items: + - + bounds: [0, 0, 200, 200] + type: "stacking-context" + "scroll-policy": scrollable + filters: [opacity(0.0)] + items: + - + bounds: [0, 0, 50, 80] + type: clip + id: 2 + - type: rect + bounds: [10, 10, 100, 100] + color: red + clip-and-scroll: 2 + + id: [0, 0] +pipelines: [] diff --git a/gfx/wr/wrench/reftests/scrolling/simple-ref.yaml b/gfx/wr/wrench/reftests/scrolling/simple-ref.yaml new file mode 100644 index 0000000000..cb9ddda07f --- /dev/null +++ b/gfx/wr/wrench/reftests/scrolling/simple-ref.yaml @@ -0,0 +1,8 @@ +root: + items: + - type: rect + bounds: [10, 10, 50, 50] + color: green + - type: rect + bounds: [70, 10, 50, 50] + color: green diff --git a/gfx/wr/wrench/reftests/scrolling/simple.yaml b/gfx/wr/wrench/reftests/scrolling/simple.yaml new file mode 100644 index 0000000000..b8061dfca9 --- /dev/null +++ b/gfx/wr/wrench/reftests/scrolling/simple.yaml @@ -0,0 +1,16 @@ +root: + items: + - type: scroll-frame + bounds: [10, 10, 50, 50] + content-size: [100, 100] + items: + - type: rect + bounds: [10, 10, 500, 500] + color: green + - type: scroll-frame + bounds: [70, 10, 50, 50] + content-size: [100, 100] + items: + - type: rect + bounds: [70, 10, 100, 100] + color: green diff --git a/gfx/wr/wrench/reftests/scrolling/sticky-applied-ref.yaml b/gfx/wr/wrench/reftests/scrolling/sticky-applied-ref.yaml new file mode 100644 index 0000000000..1dd3973c31 --- /dev/null +++ b/gfx/wr/wrench/reftests/scrolling/sticky-applied-ref.yaml @@ -0,0 +1,70 @@ +root: + items: + # Reference images are listed in the same order as the test images - + # all the "bottom-sticky" ones are first, grouped together. + - type: rect + bounds: [10, 10, 50, 50] + color: green + - type: rect + bounds: [10, 70, 50, 40] + color: green + - type: rect + bounds: [10, 130, 50, 50] + color: green + - type: rect + bounds: [10, 190, 50, 50] + color: green + - type: rect + bounds: [10, 255, 50, 45] + color: green + + # Top sticky + - type: rect + bounds: [70, 10, 50, 50] + color: green + - type: rect + bounds: [70, 80, 50, 40] + color: green + - type: rect + bounds: [70, 130, 50, 50] + color: green + - type: rect + bounds: [70, 190, 50, 50] + color: green + - type: rect + bounds: [70, 250, 50, 45] + color: green + + # Right sticky + - type: rect + bounds: [130, 10, 50, 50] + color: green + - type: rect + bounds: [130, 70, 40, 50] + color: green + - type: rect + bounds: [130, 130, 50, 50] + color: green + - type: rect + bounds: [130, 190, 50, 50] + color: green + - type: rect + bounds: [135, 250, 45, 50] + color: green + + # Left sticky + - type: rect + bounds: [190, 10, 50, 50] + color: green + - type: rect + bounds: [200, 70, 40, 50] + color: green + - type: rect + bounds: [190, 130, 50, 50] + color: green + - type: rect + bounds: [190, 190, 50, 50] + color: green + - type: rect + bounds: [190, 250, 45, 50] + color: green diff --git a/gfx/wr/wrench/reftests/scrolling/sticky-applied.yaml b/gfx/wr/wrench/reftests/scrolling/sticky-applied.yaml new file mode 100644 index 0000000000..c5ca4ad3c7 --- /dev/null +++ b/gfx/wr/wrench/reftests/scrolling/sticky-applied.yaml @@ -0,0 +1,307 @@ +root: + items: + # Tests sticky-positioned items with previously-applied-offsets. + + # This item is bottom-sticky; we indicate to WR that it already has had + # a sticky offset of y=-50 applied, and then scroll down by 50 pixels. WR + # should unapply the entire 50px that was applied, and leave the rect + # visually in the same spot. + - type: scroll-frame + bounds: [10, 10, 50, 50] + content-size: [200, 200] + scroll-offset: [0, 50] + items: + - type: sticky-frame + bounds: [10, 10, 50, 50] + margin-bottom: 0 + vertical-offset-bounds: [-500, 0] + previously-applied-offset: [0, -50] + items: + - type: rect + bounds: [10, 10, 50, 50] + color: green + # Same as above, but this time we only indicate a previous-applied-offset + # of 40 pixels, so that's the maximum WR will unapply + - type: scroll-frame + bounds: [10, 70, 50, 50] + content-size: [200, 200] + scroll-offset: [0, 50] + items: + - type: sticky-frame + bounds: [10, 70, 50, 50] + margin-bottom: 0 + vertical-offset-bounds: [-500, 0] + previously-applied-offset: [0, -40] + items: + - type: rect + bounds: [10, 70, 50, 50] + color: green + # This time we indicate a previously-applied-offset of 50 pixels, but only + # scroll by 40 pixels. In this case 40 of the 50 applied-offset pixels will + # be unapplied + - type: scroll-frame + bounds: [10, 130, 50, 50] + content-size: [200, 200] + scroll-offset: [0, 40] + items: + - type: sticky-frame + bounds: [10, 130, 50, 50] + margin-bottom: 0 + vertical-offset-bounds: [-500, 0] + previously-applied-offset: [0, -50] + items: + - type: rect + bounds: [10, 130, 50, 50] + color: green + # Here we indicate a previously-applied-offset of 50 pixels, but continue + # scrolling in WR in the same direction by another 10 pixels. This effectively + # increases the applied offset to 60 pixels. + - type: scroll-frame + bounds: [10, 190, 50, 50] + content-size: [200, 200] + scroll-offset: [0, -10] + items: + - type: sticky-frame + bounds: [10, 190, 50, 50] + margin-bottom: 0 + vertical-offset-bounds: [-500, 0] + previously-applied-offset: [0, -50] + items: + - type: rect + bounds: [10, 190, 50, 50] + color: green + # Same as previous case, but this time with the vertical-offset-bounds + # adjusted to limit the applied offset to only 55 pixels. + - type: scroll-frame + bounds: [10, 250, 50, 50] + content-size: [200, 200] + scroll-offset: [0, -10] + items: + - type: sticky-frame + bounds: [10, 250, 50, 50] + margin-bottom: 0 + vertical-offset-bounds: [-55, 0] + previously-applied-offset: [0, -50] + items: + - type: rect + bounds: [10, 250, 50, 50] + color: green + + # Repeat all the above cases, for top-sticky + + - type: scroll-frame + bounds: [70, 10, 50, 50] + content-size: [200, 200] + scroll-offset: [0, -50] + items: + - type: sticky-frame + bounds: [70, 10, 50, 50] + margin-top: 0 + vertical-offset-bounds: [0, 500] + previously-applied-offset: [0, 50] + items: + - type: rect + bounds: [70, 10, 50, 50] + color: green + - type: scroll-frame + bounds: [70, 70, 50, 50] + content-size: [200, 200] + scroll-offset: [0, -50] + items: + - type: sticky-frame + bounds: [70, 70, 50, 50] + margin-top: 0 + vertical-offset-bounds: [0, 500] + previously-applied-offset: [0, 40] + items: + - type: rect + bounds: [70, 70, 50, 50] + color: green + - type: scroll-frame + bounds: [70, 130, 50, 50] + content-size: [200, 200] + scroll-offset: [0, -40] + items: + - type: sticky-frame + bounds: [70, 130, 50, 50] + margin-top: 0 + vertical-offset-bounds: [0, 500] + previously-applied-offset: [0, 50] + items: + - type: rect + bounds: [70, 130, 50, 50] + color: green + - type: scroll-frame + bounds: [70, 190, 50, 50] + content-size: [200, 200] + scroll-offset: [0, 10] + items: + - type: sticky-frame + bounds: [70, 190, 50, 50] + margin-top: 0 + vertical-offset-bounds: [0, 500] + previously-applied-offset: [0, 50] + items: + - type: rect + bounds: [70, 190, 50, 50] + color: green + - type: scroll-frame + bounds: [70, 250, 50, 50] + content-size: [200, 200] + scroll-offset: [0, 10] + items: + - type: sticky-frame + bounds: [70, 250, 50, 50] + margin-top: 0 + vertical-offset-bounds: [0, 55] + previously-applied-offset: [0, 50] + items: + - type: rect + bounds: [70, 250, 50, 50] + color: green + + # Repeat all the above cases, for right-sticky + + - type: scroll-frame + bounds: [130, 10, 50, 50] + content-size: [200, 200] + scroll-offset: [50, 0] + items: + - type: sticky-frame + bounds: [130, 10, 50, 50] + margin-right: 0 + horizontal-offset-bounds: [-500, 0] + previously-applied-offset: [-50, 0] + items: + - type: rect + bounds: [130, 10, 50, 50] + color: green + - type: scroll-frame + bounds: [130, 70, 50, 50] + content-size: [200, 200] + scroll-offset: [50, 0] + items: + - type: sticky-frame + bounds: [130, 70, 50, 50] + margin-right: 0 + horizontal-offset-bounds: [-500, 0] + previously-applied-offset: [-40, 0] + items: + - type: rect + bounds: [130, 70, 50, 50] + color: green + - type: scroll-frame + bounds: [130, 130, 50, 50] + content-size: [200, 200] + scroll-offset: [40, 0] + items: + - type: sticky-frame + bounds: [130, 130, 50, 50] + margin-right: 0 + horizontal-offset-bounds: [-500, 0] + previously-applied-offset: [-50, 0] + items: + - type: rect + bounds: [130, 130, 50, 50] + color: green + - type: scroll-frame + bounds: [130, 190, 50, 50] + content-size: [200, 200] + scroll-offset: [-10, 0] + items: + - type: sticky-frame + bounds: [130, 190, 50, 50] + margin-right: 0 + horizontal-offset-bounds: [-500, 0] + previously-applied-offset: [-50, 0] + items: + - type: rect + bounds: [130, 190, 50, 50] + color: green + - type: scroll-frame + bounds: [130, 250, 50, 50] + content-size: [200, 200] + scroll-offset: [-10, 0] + items: + - type: sticky-frame + bounds: [130, 250, 50, 50] + margin-right: 0 + horizontal-offset-bounds: [-55, 0] + previously-applied-offset: [-50, 0] + items: + - type: rect + bounds: [130, 250, 50, 50] + color: green + + # Repeat all the above cases, for left-sticky + + - type: scroll-frame + bounds: [190, 10, 50, 50] + content-size: [200, 200] + scroll-offset: [-50, 0] + items: + - type: sticky-frame + bounds: [190, 10, 50, 50] + margin-left: 0 + horizontal-offset-bounds: [0, 500] + previously-applied-offset: [50, 0] + items: + - type: rect + bounds: [190, 10, 50, 50] + color: green + - type: scroll-frame + bounds: [190, 70, 50, 50] + content-size: [200, 200] + scroll-offset: [-50, 0] + items: + - type: sticky-frame + bounds: [190, 70, 50, 50] + margin-left: 0 + horizontal-offset-bounds: [0, 500] + previously-applied-offset: [40, 0] + items: + - type: rect + bounds: [190, 70, 50, 50] + color: green + - type: scroll-frame + bounds: [190, 130, 50, 50] + content-size: [200, 200] + scroll-offset: [-40, 0] + items: + - type: sticky-frame + bounds: [190, 130, 50, 50] + margin-left: 0 + horizontal-offset-bounds: [0, 500] + previously-applied-offset: [50, 0] + items: + - type: rect + bounds: [190, 130, 50, 50] + color: green + - type: scroll-frame + bounds: [190, 190, 50, 50] + content-size: [200, 200] + scroll-offset: [10, 0] + items: + - type: sticky-frame + bounds: [190, 190, 50, 50] + margin-left: 0 + horizontal-offset-bounds: [0, 500] + previously-applied-offset: [50, 0] + items: + - type: rect + bounds: [190, 190, 50, 50] + color: green + - type: scroll-frame + bounds: [190, 250, 50, 50] + content-size: [200, 200] + scroll-offset: [10, 0] + items: + - type: sticky-frame + bounds: [190, 250, 50, 50] + margin-left: 0 + horizontal-offset-bounds: [0, 55] + previously-applied-offset: [50, 0] + items: + - type: rect + bounds: [190, 250, 50, 50] + color: green diff --git a/gfx/wr/wrench/reftests/scrolling/sticky-nested.yaml b/gfx/wr/wrench/reftests/scrolling/sticky-nested.yaml new file mode 100644 index 0000000000..d52821efeb --- /dev/null +++ b/gfx/wr/wrench/reftests/scrolling/sticky-nested.yaml @@ -0,0 +1,215 @@ +root: + items: + # This is a scroll frame with an out-of-viewport rect that should be pushed into the + # viewport by its "bottom" sticky constraint. + - type: scroll-frame + bounds: [10, 10, 50, 50] + content-size: [200, 200] + items: + - type: sticky-frame + bounds: [10, 60, 50, 50] + margin-bottom: 0 + vertical-offset-bounds: [-500, 0] + items: + - type: clip + bounds: [10, 60, 50, 50] + content-size: [100, 100] + items: + - type: rect + bounds: [10, 60, 50, 50] + color: green + # Do the same thing, but now for the "top" constraint. + - type: scroll-frame + bounds: [70, 10, 50, 50] + content-size: [200, 200] + scroll-offset: [0, 50] + items: + - type: sticky-frame + bounds: [70, 10, 50, 50] + margin-top: 0 + vertical-offset-bounds: [0, 500] + items: + - type: clip + bounds: [70, 10, 50, 50] + content-size: [100, 100] + items: + - type: rect + bounds: [70, 10, 50, 50] + color: green + # Do the same thing, but now for the "right" constraint. + - type: scroll-frame + bounds: [10, 70, 50, 50] + content-size: [200, 200] + items: + - type: sticky-frame + bounds: [60, 70, 50, 50] + margin-right: 0 + horizontal-offset-bounds: [-500, 0] + items: + - type: clip + bounds: [60, 70, 50, 50] + content-size: [100, 100] + items: + - type: rect + bounds: [60, 70, 50, 50] + color: green + # Do the same thing, but now for the "left" constraint. + - type: scroll-frame + bounds: [70, 70, 50, 50] + content-size: [200, 200] + scroll-offset: [50, 0] + items: + - type: sticky-frame + bounds: [70, 70, 50, 50] + margin-left: 0 + horizontal-offset-bounds: [0, 500] + items: + - type: clip + bounds: [70, 70, 50, 50] + content-size: [100, 100] + items: + - type: rect + bounds: [70, 70, 50, 50] + color: green + + # The same tests, but this time with a margin. + - type: scroll-frame + bounds: [130, 10, 50, 50] + content-size: [200, 200] + items: + - type: sticky-frame + bounds: [130, 60, 50, 50] + margin-bottom: 10 + vertical-offset-bounds: [-500, 0] + items: + - type: clip + bounds: [130, 60, 50, 50] + content-size: [100, 100] + items: + - type: rect + bounds: [130, 60, 50, 50] + color: green + # Do the same thing, but now for the "top" constraint. + - type: scroll-frame + bounds: [190, 10, 50, 50] + content-size: [200, 200] + scroll-offset: [0, 50] + items: + - type: sticky-frame + bounds: [190, 10, 50, 50] + margin-top: 10 + vertical-offset-bounds: [0, 500] + items: + - type: clip + bounds: [190, 10, 50, 50] + content-size: [100, 100] + items: + - type: rect + bounds: [190, 10, 50, 50] + color: green + # Do the same thing, but now for the "right" constraint. + - type: scroll-frame + bounds: [130, 70, 50, 50] + content-size: [200, 200] + items: + - type: sticky-frame + bounds: [180, 70, 50, 50] + margin-right: 10 + horizontal-offset-bounds: [-500, 0] + items: + - type: clip + bounds: [180, 70, 50, 50] + content-size: [100, 100] + items: + - type: rect + bounds: [180, 70, 50, 50] + color: green + # Do the same thing, but now for the "left" constraint. + - type: scroll-frame + bounds: [190, 70, 50, 50] + content-size: [200, 200] + scroll-offset: [50, 0] + items: + - type: sticky-frame + bounds: [190, 70, 50, 50] + margin-left: 10 + horizontal-offset-bounds: [0, 500] + items: + - type: clip + bounds: [190, 70, 50, 50] + content-size: [100, 100] + items: + - type: rect + bounds: [190, 70, 50, 50] + color: green + + # The same tests, but this time with a limit. + - type: scroll-frame + bounds: [250, 10, 50, 50] + content-size: [200, 200] + items: + - type: sticky-frame + bounds: [250, 60, 50, 50] + margin-bottom: 0 + vertical-offset-bounds: [-25, 0] + items: + - type: clip + bounds: [250, 60, 50, 50] + content-size: [100, 100] + items: + - type: rect + bounds: [250, 60, 50, 50] + color: green + # Do the same thing, but now for the "top" constraint. + - type: scroll-frame + bounds: [310, 10, 50, 50] + content-size: [200, 200] + scroll-offset: [0, 50] + items: + - type: sticky-frame + bounds: [310, 10, 50, 50] + margin-top: 0 + vertical-offset-bounds: [0, 25] + items: + - type: clip + bounds: [310, 10, 50, 50] + content-size: [100, 100] + items: + - type: rect + bounds: [310, 10, 50, 50] + color: green + # Do the same thing, but now for the "right" constraint. + - type: scroll-frame + bounds: [250, 70, 50, 50] + content-size: [200, 200] + items: + - type: sticky-frame + bounds: [300, 70, 50, 50] + margin-right: 0 + horizontal-offset-bounds: [-25, 0] + items: + - type: clip + bounds: [300, 70, 50, 50] + content-size: [100, 100] + items: + - type: rect + bounds: [300, 70, 50, 50] + color: green + # Do the same thing, but now for the "left" constraint. + - type: scroll-frame + bounds: [310, 70, 50, 50] + content-size: [200, 200] + scroll-offset: [50, 0] + items: + - type: sticky-frame + bounds: [310, 70, 50, 50] + margin-left: 0 + horizontal-offset-bounds: [0, 25] + items: + - type: clip + bounds: [310, 70, 50, 50] + content-size: [100, 100] + items: + - type: rect + bounds: [310, 70, 50, 50] + color: green diff --git a/gfx/wr/wrench/reftests/scrolling/sticky-ref.yaml b/gfx/wr/wrench/reftests/scrolling/sticky-ref.yaml new file mode 100644 index 0000000000..0f7b7b79a6 --- /dev/null +++ b/gfx/wr/wrench/reftests/scrolling/sticky-ref.yaml @@ -0,0 +1,40 @@ +root: + items: + - type: rect + bounds: [10, 10, 50, 50] + color: green + - type: rect + bounds: [10, 70, 50, 50] + color: green + - type: rect + bounds: [70, 10, 50, 50] + color: green + - type: rect + bounds: [70, 70, 50, 50] + color: green + + - type: rect + bounds: [130, 10, 50, 40] + color: green + - type: rect + bounds: [130, 70, 40, 50] + color: green + - type: rect + bounds: [190, 20, 50, 40] + color: green + - type: rect + bounds: [200, 70, 40, 50] + color: green + + - type: rect + bounds: [250, 35, 50, 25] + color: green + - type: rect + bounds: [275, 70, 25, 50] + color: green + - type: rect + bounds: [310, 10, 50, 25] + color: green + - type: rect + bounds: [310, 70, 25, 50] + color: green diff --git a/gfx/wr/wrench/reftests/scrolling/sticky-transformed-ref.yaml b/gfx/wr/wrench/reftests/scrolling/sticky-transformed-ref.yaml new file mode 100644 index 0000000000..9849a3f3d8 --- /dev/null +++ b/gfx/wr/wrench/reftests/scrolling/sticky-transformed-ref.yaml @@ -0,0 +1,5 @@ +root: + items: + - type: rect + bounds: [10, 30, 10, 10] + color: green diff --git a/gfx/wr/wrench/reftests/scrolling/sticky-transformed.yaml b/gfx/wr/wrench/reftests/scrolling/sticky-transformed.yaml new file mode 100644 index 0000000000..0144a7c1c3 --- /dev/null +++ b/gfx/wr/wrench/reftests/scrolling/sticky-transformed.yaml @@ -0,0 +1,21 @@ +root: + items: + # There is a new reference frame introduced between the scrollframe and + # the sticky item. This tests that the sticky item is still positioned + # correctly. + - type: scroll-frame + bounds: [10, 10, 50, 50] + content-size: [200, 200] + items: + - type: stacking-context + bounds: [10, 20, 10, 10] + transform: translate(0, 10) + items: + - type: sticky-frame + bounds: [0, 0, 10, 10] + margin-top: 10 + vertical-offset-bounds: [0, 200] + items: + - type: rect + bounds: [0, 0, 10, 10] + color: green diff --git a/gfx/wr/wrench/reftests/scrolling/sticky.yaml b/gfx/wr/wrench/reftests/scrolling/sticky.yaml new file mode 100644 index 0000000000..cdc0a7a124 --- /dev/null +++ b/gfx/wr/wrench/reftests/scrolling/sticky.yaml @@ -0,0 +1,167 @@ +root: + items: + # This is a scroll frame with an out-of-viewport rect that should be pushed into the + # viewport by its "bottom" sticky constraint. + - type: scroll-frame + bounds: [10, 10, 50, 50] + content-size: [200, 200] + items: + - type: sticky-frame + bounds: [10, 60, 50, 50] + margin-bottom: 0 + vertical-offset-bounds: [-500, 0] + items: + - type: rect + bounds: [10, 60, 50, 50] + color: green + # Do the same thing, but now for the "top" constraint. + - type: scroll-frame + bounds: [70, 10, 50, 50] + content-size: [200, 200] + scroll-offset: [0, 50] + items: + - type: sticky-frame + bounds: [70, 10, 50, 50] + margin-top: 0 + vertical-offset-bounds: [0, 500] + items: + - type: rect + bounds: [70, 10, 50, 50] + color: green + # Do the same thing, but now for the "right" constraint. + - type: scroll-frame + bounds: [10, 70, 50, 50] + content-size: [200, 200] + items: + - type: sticky-frame + bounds: [60, 70, 50, 50] + margin-right: 0 + horizontal-offset-bounds: [-500, 0] + items: + - type: rect + bounds: [60, 70, 50, 50] + color: green + # Do the same thing, but now for the "left" constraint. + - type: scroll-frame + bounds: [70, 70, 50, 50] + content-size: [200, 200] + scroll-offset: [50, 0] + items: + - type: sticky-frame + bounds: [70, 70, 50, 50] + margin-left: 0 + horizontal-offset-bounds: [0, 500] + items: + - type: rect + bounds: [70, 70, 50, 50] + color: green + + # The same tests, but this time with a margin. + - type: scroll-frame + bounds: [130, 10, 50, 50] + content-size: [200, 200] + items: + - type: sticky-frame + bounds: [130, 60, 50, 50] + margin-bottom: 10 + vertical-offset-bounds: [-500, 0] + items: + - type: rect + bounds: [130, 60, 50, 50] + color: green + # Do the same thing, but now for the "top" constraint. + - type: scroll-frame + bounds: [190, 10, 50, 50] + content-size: [200, 200] + scroll-offset: [0, 50] + items: + - type: sticky-frame + bounds: [190, 10, 50, 50] + margin-top: 10 + vertical-offset-bounds: [0, 500] + items: + - type: rect + bounds: [190, 10, 50, 50] + color: green + # Do the same thing, but now for the "right" constraint. + - type: scroll-frame + bounds: [130, 70, 50, 50] + content-size: [200, 200] + items: + - type: sticky-frame + bounds: [180, 70, 50, 50] + margin-right: 10 + horizontal-offset-bounds: [-500, 0] + items: + - type: rect + bounds: [180, 70, 50, 50] + color: green + # Do the same thing, but now for the "left" constraint. + - type: scroll-frame + bounds: [190, 70, 50, 50] + content-size: [200, 200] + scroll-offset: [50, 0] + items: + - type: sticky-frame + bounds: [190, 70, 50, 50] + margin-left: 10 + horizontal-offset-bounds: [0, 500] + items: + - type: rect + bounds: [190, 70, 50, 50] + color: green + + # The same tests, but this time with a limit. + - type: scroll-frame + bounds: [250, 10, 50, 50] + content-size: [200, 200] + items: + - type: sticky-frame + bounds: [250, 60, 50, 50] + margin-bottom: 0 + vertical-offset-bounds: [-25, 0] + items: + - type: rect + bounds: [250, 60, 50, 50] + color: green + # Do the same thing, but now for the "top" constraint. + - type: scroll-frame + bounds: [310, 10, 50, 50] + content-size: [200, 200] + scroll-offset: [0, 50] + items: + - type: sticky-frame + bounds: [310, 10, 50, 50] + margin-top: 0 + vertical-offset-bounds: [0, 25] + items: + - type: rect + bounds: [310, 10, 50, 50] + color: green + # Do the same thing, but now for the "right" constraint. + - type: scroll-frame + bounds: [250, 70, 50, 50] + content-size: [200, 200] + items: + - type: sticky-frame + bounds: [300, 70, 50, 50] + margin-right: 0 + horizontal-offset-bounds: [-25, 0] + items: + - type: rect + bounds: [300, 70, 50, 50] + color: green + # Do the same thing, but now for the "left" constraint. + - type: scroll-frame + bounds: [310, 70, 50, 50] + content-size: [200, 200] + scroll-offset: [50, 0] + items: + - type: sticky-frame + bounds: [310, 70, 50, 50] + margin-left: 0 + horizontal-offset-bounds: [0, 25] + items: + - type: rect + bounds: [310, 70, 50, 50] + color: green diff --git a/gfx/wr/wrench/reftests/scrolling/translate-nested-ref.yaml b/gfx/wr/wrench/reftests/scrolling/translate-nested-ref.yaml new file mode 100644 index 0000000000..f9f6c68209 --- /dev/null +++ b/gfx/wr/wrench/reftests/scrolling/translate-nested-ref.yaml @@ -0,0 +1,14 @@ +--- +root: + items: + - + bounds: [8, 8, 500, 500] + clip: [0, 0, 0, 0] + type: "stacking-context" + items: + - + bounds: [0, 0, 200, 200] + type: rect + color: green + id: [0, 0] +pipelines: [] diff --git a/gfx/wr/wrench/reftests/scrolling/translate-nested.yaml b/gfx/wr/wrench/reftests/scrolling/translate-nested.yaml new file mode 100644 index 0000000000..74bd647aa7 --- /dev/null +++ b/gfx/wr/wrench/reftests/scrolling/translate-nested.yaml @@ -0,0 +1,28 @@ +--- +root: + items: + - + bounds: [8, 8, 500, 500] + type: "stacking-context" + items: + - + bounds: [0, 0, 200, 200] + type: clip + id: 2 + items: + - + bounds: [0, 0, 200, 200] + type: rect + color: red + - + bounds: [0, 0, 200, 200] + type: "stacking-context" + transform: translate(100, 0) + items: + - + bounds: [-100, 0, 200, 200] + clip-rect: [-300, -300, 900, 900] + type: rect + color: green + id: [0, 0] +pipelines: [] diff --git a/gfx/wr/wrench/reftests/scrolling/viewport-offset-ref.yaml b/gfx/wr/wrench/reftests/scrolling/viewport-offset-ref.yaml new file mode 100644 index 0000000000..b7d697e4e0 --- /dev/null +++ b/gfx/wr/wrench/reftests/scrolling/viewport-offset-ref.yaml @@ -0,0 +1,9 @@ +--- +root: + items: + - type: stacking-context + bounds: 0 0 0 0 + items: + - type: rect + color: red + bounds: 0 100 1000 50 diff --git a/gfx/wr/wrench/reftests/scrolling/viewport-offset.yaml b/gfx/wr/wrench/reftests/scrolling/viewport-offset.yaml new file mode 100644 index 0000000000..9e807fd5f9 --- /dev/null +++ b/gfx/wr/wrench/reftests/scrolling/viewport-offset.yaml @@ -0,0 +1,20 @@ +# The test assures that the viewport offset is correctly getting +# the reference_frame_relative_offset applied when flattening +# a scroll frame. +--- +root: + items: + - type: stacking-context + bounds: 0 100 0 0 + items: + - type: scroll-frame + bounds: 0 0 1000 1000 + items: + - type: sticky-frame + bounds: 0 -50 1000 50 + margin-top: -50 + vertical-offset-bounds: [0, 2000] + items: + - type: rect + bounds: 0 -50 1000 100 + color: red diff --git a/gfx/wr/wrench/reftests/snap/preserve-3d.png b/gfx/wr/wrench/reftests/snap/preserve-3d.png Binary files differnew file mode 100644 index 0000000000..6af9bc1516 --- /dev/null +++ b/gfx/wr/wrench/reftests/snap/preserve-3d.png diff --git a/gfx/wr/wrench/reftests/snap/preserve-3d.yaml b/gfx/wr/wrench/reftests/snap/preserve-3d.yaml new file mode 100644 index 0000000000..346e881d83 --- /dev/null +++ b/gfx/wr/wrench/reftests/snap/preserve-3d.yaml @@ -0,0 +1,55 @@ +--- +root: + items: + - + bounds: [293, 139, 500, 500] + type: reference-frame + transform: scale(0.7) + items: + - + bounds: [0, 0, 500, 500] + type: stacking-context + perspective: [1, 0, 0, 0, 0, 1, 0, 0, -0.25416666, -0.23866667, 1, -0.00083333335, 0, 0, 0, 1] + "transform-style": preserve-3d + items: + - + bounds: [0, 0, 0, 0] + type: stacking-context + transform: [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, -110, 0, 0, 1] + items: + - + bounds: [24, 539, 24, 24] + type: clip + complex: + - + rect: [24, 539, 24, 24] + radius: [12, 12] + items: + - + bounds: [24, 539, 24, 24] + type: rect + color: black + - + bounds: [24, 770, 24, 24] + type: clip + complex: + - + rect: [24, 770, 24, 24] + radius: [12, 12] + items: + - + bounds: [24, 770, 24, 24] + type: rect + color: black + - + bounds: [24, 847, 24, 24] + type: clip + complex: + - + rect: [24, 847, 24, 24] + radius: [12, 12] + items: + - + bounds: [24, 847, 24, 24] + type: rect + color: black diff --git a/gfx/wr/wrench/reftests/snap/reftest.list b/gfx/wr/wrench/reftests/snap/reftest.list new file mode 100644 index 0000000000..84fe6c4979 --- /dev/null +++ b/gfx/wr/wrench/reftests/snap/reftest.list @@ -0,0 +1,3 @@ +platform(linux,mac) == snap.yaml snap.png +== transform.yaml transform.png +platform(linux,mac) == preserve-3d.yaml preserve-3d.png diff --git a/gfx/wr/wrench/reftests/snap/snap.png b/gfx/wr/wrench/reftests/snap/snap.png Binary files differnew file mode 100644 index 0000000000..38f7cf33e5 --- /dev/null +++ b/gfx/wr/wrench/reftests/snap/snap.png diff --git a/gfx/wr/wrench/reftests/snap/snap.yaml b/gfx/wr/wrench/reftests/snap/snap.yaml new file mode 100644 index 0000000000..f292a728a9 --- /dev/null +++ b/gfx/wr/wrench/reftests/snap/snap.yaml @@ -0,0 +1,15 @@ +--- +root: + items: + - type: rect + bounds: [ 1, 1, 5, 5 ] + color: green + - type: rect + bounds: [ 10.4, 1.8, 5, 5 ] + color: green + - type: rect + bounds: [ 21.5, 1.5, 5, 5 ] + color: green + - type: rect + bounds: [ 31.2, 1.6, 4.3, 5.5 ] + color: green diff --git a/gfx/wr/wrench/reftests/snap/transform.png b/gfx/wr/wrench/reftests/snap/transform.png Binary files differnew file mode 100644 index 0000000000..73c8feacdf --- /dev/null +++ b/gfx/wr/wrench/reftests/snap/transform.png diff --git a/gfx/wr/wrench/reftests/snap/transform.yaml b/gfx/wr/wrench/reftests/snap/transform.yaml new file mode 100644 index 0000000000..d1b0579eda --- /dev/null +++ b/gfx/wr/wrench/reftests/snap/transform.yaml @@ -0,0 +1,19 @@ +--- +root: + items: + # 45 degrees result in middle -+ 14.142, rounded to 14 + - type: stacking-context + bounds: [0, 0, 60, 60] + transform: rotate-y(45) + items: + - type: rect + bounds: [ 10, 10, 40, 40 ] + color: blue + # 50 degrees result in middle -+ 12.856, rounded to 13 + - type: stacking-context + bounds: [50, 0, 60, 60] + transform: rotate-x(50) + items: + - type: rect + bounds: [ 10, 10, 40, 40 ] + color: blue diff --git a/gfx/wr/wrench/reftests/split/cross-ref.yaml b/gfx/wr/wrench/reftests/split/cross-ref.yaml new file mode 100644 index 0000000000..c784e62fce --- /dev/null +++ b/gfx/wr/wrench/reftests/split/cross-ref.yaml @@ -0,0 +1,36 @@ +--- +root: + items: + - type: stacking-context + bounds: [0, 0, 100, 200] + items: + - type: stacking-context + bounds: [0, 0, 100, 200] + transform: rotate-y(-45) rotate-x(45) + items: + - type: rect + bounds: [0, 0, 50, 100] + color: green + - type: stacking-context + bounds: [0, 0, 100, 200] + transform: rotate-y(45) rotate-x(45) + items: + - type: rect + bounds: [0, 0, 50, 100] + color: red + - type: stacking-context + bounds: [0, 0, 100, 200] + transform: rotate-y(45) rotate-x(45) + items: + - type: rect + bounds: [50, 0, 50, 100] + color: red + - type: stacking-context + bounds: [0, 0, 100, 200] + transform: rotate-y(-45) rotate-x(45) + items: + - type: rect + bounds: [50, 0, 50, 100] + color: green + + diff --git a/gfx/wr/wrench/reftests/split/cross.yaml b/gfx/wr/wrench/reftests/split/cross.yaml new file mode 100644 index 0000000000..e306dbad33 --- /dev/null +++ b/gfx/wr/wrench/reftests/split/cross.yaml @@ -0,0 +1,24 @@ +# Crossed planes test. Similar to "simple" but has more complex transformations, +# which puts higher requirements on the precision of arithmetics, +# and all 4 pieces are visible on screen. +--- +root: + items: + - type: stacking-context + bounds: [0, 0, 100, 200] + transform-style: preserve-3d + items: + - type: stacking-context + bounds: [0, 0, 100, 200] + transform: rotate-y(45) rotate-x(45) + items: + - type: rect + bounds: [0, 0, 100, 100] + color: red + - type: stacking-context + bounds: [0, 0, 100, 200] + transform: rotate-y(-45) rotate-x(45) + items: + - type: rect + bounds: [0, 0, 100, 100] + color: green diff --git a/gfx/wr/wrench/reftests/split/filter-ref.yaml b/gfx/wr/wrench/reftests/split/filter-ref.yaml new file mode 100644 index 0000000000..01e16b6e8f --- /dev/null +++ b/gfx/wr/wrench/reftests/split/filter-ref.yaml @@ -0,0 +1,10 @@ +--- +root: + items: + - type: stacking-context + bounds: [0, 0, 200, 200] + transform-style: preserve-3d + items: + - type: rect + bounds: [0, 0, 200, 200] + color: [255, 0, 0, 0.5] diff --git a/gfx/wr/wrench/reftests/split/filter.yaml b/gfx/wr/wrench/reftests/split/filter.yaml new file mode 100644 index 0000000000..54667c0652 --- /dev/null +++ b/gfx/wr/wrench/reftests/split/filter.yaml @@ -0,0 +1,21 @@ +# This test ensures that an opacity filter forces the flattening of preserve-3D context. +# The innermost rectangle has backface visibility disabled. If the parent stacking context +# is a part of preserve-3D hierarchy, then the item would be backward-facing, thus invisible. +# With the opacity filter, it's no longer a part of the preserve-3D, thus visible. +--- +root: + items: + - type: stacking-context + bounds: [0, 0, 200, 200] + transform-style: preserve-3d + transform: rotate-y(180) + items: + - type: stacking-context + bounds: [0, 0, 200, 200] + transform-style: preserve-3d + filters: [opacity(0.5)] + items: + - type: rect + bounds: [0, 0, 200, 200] + color: red + backface-visible: false diff --git a/gfx/wr/wrench/reftests/split/gradient-ref.yaml b/gfx/wr/wrench/reftests/split/gradient-ref.yaml new file mode 100644 index 0000000000..5a461c737d --- /dev/null +++ b/gfx/wr/wrench/reftests/split/gradient-ref.yaml @@ -0,0 +1,39 @@ +# Checks the UV interpolation of a preserved 3d stacking context matches +# a flat stacking context. There are four black rectangles that overlap +# the edges of the transformed gradient to minimize fuzz. +--- +root: + items: + - type: "reference-frame" + bounds: [0, 0, 2746, 1408] + transform-style: flat + perspective: [1, 0, 0, 0, 0, 1, 0, 0, -0.4699999988079071, -0.44999998807907104, 1, -0.0012499999720603228, 176, 160, 0, 1] + items: + - type: "reference-frame" + bounds: [0, 0, 2746, 1408] + transform-style: flat + transform: rotate-y(-53) + items: + - type: "stacking-context" + transform-style: flat + items: + - type: rect + bounds: [0, 0, 300, 300] + color: 255 255 255 1.0000 + - type: gradient + bounds: [0, 0, 300, 150] + start: [150, 0] + end: [150, 150] + stops: [0.0, [255, 0, 0, 1], 1.0, [254, 0, 0, 1]] + - type: rect + bounds: [520, 260, 120, 20] + color: 0 0 0 1.0000 + - type: rect + bounds: [520, 336, 120, 3] + color: 0 0 0 1.0000 + - type: rect + bounds: [520, 260, 10, 80] + color: 0 0 0 1.0000 + - type: rect + bounds: [622, 260, 10, 80] + color: 0 0 0 1.0000 diff --git a/gfx/wr/wrench/reftests/split/gradient.yaml b/gfx/wr/wrench/reftests/split/gradient.yaml new file mode 100644 index 0000000000..8da777df03 --- /dev/null +++ b/gfx/wr/wrench/reftests/split/gradient.yaml @@ -0,0 +1,42 @@ +# Checks the UV interpolation of a preserved 3d stacking context matches +# a flat stacking context. There are four black rectangles that overlap +# the edges of the transformed gradient to minimize fuzz. +--- +root: + items: + - type: "reference-frame" + bounds: [0, 0, 2746, 1408] + transform-style: preserve-3d + perspective: [1, 0, 0, 0, 0, 1, 0, 0, -0.4699999988079071, -0.44999998807907104, 1, -0.0012499999720603228, 176, 160, 0, 1] + items: + - type: "reference-frame" + bounds: [0, 0, 2746, 1408] + transform-style: preserve-3d + transform: rotate-y(-53) + items: + - type: "stacking-context" + transform-style: preserve-3d + items: + - type: "stacking-context" + transform-style: flat + items: + - type: rect + bounds: [0, 0, 300, 300] + color: 255 255 255 1.0000 + - type: gradient + bounds: [0, 0, 300, 150] + start: [150, 0] + end: [150, 150] + stops: [0.0, [255, 0, 0, 1], 1.0, [254, 0, 0, 1]] + - type: rect + bounds: [520, 260, 120, 20] + color: 0 0 0 1.0000 + - type: rect + bounds: [520, 336, 120, 3] + color: 0 0 0 1.0000 + - type: rect + bounds: [520, 260, 10, 80] + color: 0 0 0 1.0000 + - type: rect + bounds: [622, 260, 10, 80] + color: 0 0 0 1.0000 diff --git a/gfx/wr/wrench/reftests/split/intermediate-1-ref.yaml b/gfx/wr/wrench/reftests/split/intermediate-1-ref.yaml new file mode 100644 index 0000000000..2d67df4ead --- /dev/null +++ b/gfx/wr/wrench/reftests/split/intermediate-1-ref.yaml @@ -0,0 +1,12 @@ +--- +root: + items: + - type: rect + bounds: 8 36 100 100 + color: green + - type: rect + bounds: 108 36 100 100 + color: blue + - type: rect + bounds: 208 36 100 100 + color: yellow diff --git a/gfx/wr/wrench/reftests/split/intermediate-1.yaml b/gfx/wr/wrench/reftests/split/intermediate-1.yaml new file mode 100644 index 0000000000..0c02fe8e3c --- /dev/null +++ b/gfx/wr/wrench/reftests/split/intermediate-1.yaml @@ -0,0 +1,38 @@ +--- +root: + items: + - type: rect + bounds: 8 36 300 100 + color: red + - type: stacking-context + transform-style: preserve-3d + transform: translate(8, 36, 0) + items: + - type: stacking-context + transform-style: preserve-3d + items: + - type: rect + bounds: 0 0 100 100 + color: green + - type: stacking-context # flat, intermediate surface + items: + - type: stacking-context + transform: translate(100, 0, 0) + transform-style: preserve-3d + items: + - type: stacking-context + transform-style: preserve-3d + items: + - type: rect + bounds: 0 0 100 100 + color: blue + - type: stacking-context + transform: translate(100, 0, 0) + transform-style: preserve-3d + items: + - type: stacking-context + transform-style: preserve-3d + items: + - type: rect + bounds: 0 0 100 100 + color: yellow diff --git a/gfx/wr/wrench/reftests/split/intermediate-2.yaml b/gfx/wr/wrench/reftests/split/intermediate-2.yaml new file mode 100644 index 0000000000..7d926ade4a --- /dev/null +++ b/gfx/wr/wrench/reftests/split/intermediate-2.yaml @@ -0,0 +1,34 @@ +--- +root: + items: + - type: rect + bounds: 8 36 300 100 + color: red + - type: stacking-context + transform-style: preserve-3d + transform: translate(8, 36, 0) + items: + - type: stacking-context + transform-style: preserve-3d + items: + - type: rect + bounds: 0 0 100 100 + color: green + - type: stacking-context + items: + - type: stacking-context + transform: translate(100, 0, 0) + items: + - type: rect + bounds: 0 0 100 100 + color: blue + - type: stacking-context + transform: translate(100, 0, 0) + transform-style: preserve-3d + items: + - type: stacking-context + transform-style: preserve-3d + items: + - type: rect + bounds: 0 0 100 100 + color: yellow diff --git a/gfx/wr/wrench/reftests/split/mixed-order-ref.yaml b/gfx/wr/wrench/reftests/split/mixed-order-ref.yaml new file mode 100644 index 0000000000..e3632665c0 --- /dev/null +++ b/gfx/wr/wrench/reftests/split/mixed-order-ref.yaml @@ -0,0 +1,22 @@ +# The result should be matching the flat ordering, since there +# is no variation in Z of the preserve-3D children. +--- +root: + items: + - type: stacking-context + bounds: [0, 0, 200, 200] + transform: rotate-x(30) + items: + - type: rect + bounds: [0, 0, 100, 100] + color: green + - type: stacking-context + bounds: [25, 25, 100, 100] + #transform: rotate-z(45) + items: + - type: rect + bounds: [0, 0, 100, 100] + color: red + - type: rect + bounds: [100, 0, 100, 100] + color: blue diff --git a/gfx/wr/wrench/reftests/split/mixed-order.yaml b/gfx/wr/wrench/reftests/split/mixed-order.yaml new file mode 100644 index 0000000000..789621dc5b --- /dev/null +++ b/gfx/wr/wrench/reftests/split/mixed-order.yaml @@ -0,0 +1,25 @@ +# The "preserve-3d" context has a mix of children being other stacking contexts and +# just primitives. The other stacking contexts are also "preserve-3d" but on the same plane, +# so the result ordering should be exactly matching the way we specify the children. +--- +root: + items: + - type: stacking-context + bounds: [0, 0, 200, 200] + transform-style: preserve-3d + transform: rotate-x(30) + items: + - type: rect + bounds: [0, 0, 100, 100] + color: green + - type: stacking-context + bounds: [25, 25, 100, 100] + #TODO: https://github.com/servo/webrender/issues/2946 + #transform: rotate-z(45) + items: + - type: rect + bounds: [0, 0, 100, 100] + color: red + - type: rect + bounds: [100, 0, 100, 100] + color: blue diff --git a/gfx/wr/wrench/reftests/split/near-plane.png b/gfx/wr/wrench/reftests/split/near-plane.png Binary files differnew file mode 100644 index 0000000000..c6e81c9983 --- /dev/null +++ b/gfx/wr/wrench/reftests/split/near-plane.png diff --git a/gfx/wr/wrench/reftests/split/near-plane.yaml b/gfx/wr/wrench/reftests/split/near-plane.yaml new file mode 100644 index 0000000000..f1911674ca --- /dev/null +++ b/gfx/wr/wrench/reftests/split/near-plane.yaml @@ -0,0 +1,16 @@ +# In this test, there is a single polygon intersecting the near plane. +--- +root: + items: + - type: stacking-context + bounds: [0, 0, 600, 600] + transform-style: preserve-3d + perspective: 200 + items: + - type: stacking-context + bounds: [0, 0, 600, 600] + transform: rotate-x(-60.0) + items: + - type: rect + bounds: [000, 0, 600, 600] + color: [255, 0, 0, 0.5] diff --git a/gfx/wr/wrench/reftests/split/nested-coord-systems-ref.yaml b/gfx/wr/wrench/reftests/split/nested-coord-systems-ref.yaml new file mode 100644 index 0000000000..97e2e82fc5 --- /dev/null +++ b/gfx/wr/wrench/reftests/split/nested-coord-systems-ref.yaml @@ -0,0 +1,6 @@ +--- +root: + items: + - type: rect + bounds: 0 0 150 200 + color: green diff --git a/gfx/wr/wrench/reftests/split/nested-coord-systems.yaml b/gfx/wr/wrench/reftests/split/nested-coord-systems.yaml new file mode 100644 index 0000000000..5cdc4ab634 --- /dev/null +++ b/gfx/wr/wrench/reftests/split/nested-coord-systems.yaml @@ -0,0 +1,28 @@ +# This test checks our ability to have the plane splitting root itself to be rasterized +# in some local space. Perspective transform forces WR to use the local space. +--- +root: + items: + - type: stacking-context + bounds: 0 0 400 400 + transform-style: preserve-3d + items: + - type: stacking-context + bounds: 0 0 400 400 + transform-style: flat + transform: perspective(100) rotate-y(30) + transform-origin: 0 0 + items: + - type: stacking-context + bounds: 0 0 400 400 + transform-style: preserve-3d + items: + - type: stacking-context + bounds: 0 0 400 400 + transform-style: flat + transform: perspective(100) rotate-y(30) + transform-origin: 0 0 + items: + - type: rect + bounds: 0 0 200 200 + color: green diff --git a/gfx/wr/wrench/reftests/split/nested-preserve3d-crash.yaml b/gfx/wr/wrench/reftests/split/nested-preserve3d-crash.yaml new file mode 100644 index 0000000000..68a01ebeb1 --- /dev/null +++ b/gfx/wr/wrench/reftests/split/nested-preserve3d-crash.yaml @@ -0,0 +1,37 @@ +--- +root: + items: + - type: stacking-context + bounds: 0 0 1024 768 + items: + - type: stacking-context + bounds: 0 0 1024 768 + transform-style: preserve-3d + transform: rotate-x(180) + items: + - type: stacking-context + bounds: 0 0 1024 768 + items: + - type: rect + bounds: 0 0 200 200 + color: green + - type: stacking-context + bounds: 0 0 1024 768 + items: + - type: rect + bounds: 0 0 200 200 + color: green + - type: stacking-context + bounds: 0 0 1024 768 + transform-style: preserve-3d + transform: rotate-x(180) + items: + - type: rect + bounds: 0 0 200 200 + color: green + - type: stacking-context + bounds: 0 0 1024 768 + items: + - type: rect + bounds: 0 0 200 200 + color: green diff --git a/gfx/wr/wrench/reftests/split/nested-ref.yaml b/gfx/wr/wrench/reftests/split/nested-ref.yaml new file mode 100644 index 0000000000..798b624356 --- /dev/null +++ b/gfx/wr/wrench/reftests/split/nested-ref.yaml @@ -0,0 +1,12 @@ +--- +root: + items: + - type: stacking-context + bounds: [0, 0, 1024, 1024] + items: + - type: rect + bounds: [150, 0, 300, 600] + color: red + - type: rect + bounds: [150, 0, 300, 200] + color: green diff --git a/gfx/wr/wrench/reftests/split/nested.yaml b/gfx/wr/wrench/reftests/split/nested.yaml new file mode 100644 index 0000000000..5b93224fda --- /dev/null +++ b/gfx/wr/wrench/reftests/split/nested.yaml @@ -0,0 +1,25 @@ +# This tests have a non-preserve3d stacking context nested within +# preserve-3d sub-tree. This nested context is still getting baked in +# and participates (as a whole) in plane splitting. +# It is layed out in the same plane as the parent, so should be ordered +# last, given that it's coming later than the parent. +--- +root: + items: + - type: stacking-context + bounds: [0, 0, 1024, 1024] + items: + - type: stacking-context + bounds: [0, 0, 600, 600] + transform-style: preserve-3d + transform: rotate-y(60.0) + items: + - type: rect + bounds: [0, 0, 600, 600] + color: red + - type: stacking-context + bounds: [0, 0, 100, 100] + items: + - type: rect + bounds: [0, 0, 600, 200] + color: green diff --git a/gfx/wr/wrench/reftests/split/order-1-ref.yaml b/gfx/wr/wrench/reftests/split/order-1-ref.yaml new file mode 100644 index 0000000000..930ac5c8b9 --- /dev/null +++ b/gfx/wr/wrench/reftests/split/order-1-ref.yaml @@ -0,0 +1,8 @@ +root: + items: + - type: stacking-context + bounds: [0, 0, 100, 100] + items: + - type: rect + bounds: [0, 0, 100, 100] + color: green diff --git a/gfx/wr/wrench/reftests/split/order-1.yaml b/gfx/wr/wrench/reftests/split/order-1.yaml new file mode 100644 index 0000000000..7b5613f6d3 --- /dev/null +++ b/gfx/wr/wrench/reftests/split/order-1.yaml @@ -0,0 +1,20 @@ +# The "preserve-3d" context has a "flat" child. Rotation by 180 degrees and positive Z offset +# should compensate each other, resulting in a green rectangle. +--- +root: + items: + - type: stacking-context + bounds: [0, 0, 100, 100] + transform-style: preserve-3d + transform: rotate-x(180) + items: + - type: rect + bounds: [0, 0, 100, 100] + color: green + - type: stacking-context + bounds: [0, 0, 100, 100] + transform: translate(0, 0, 10) + items: + - type: rect + bounds: [0, 0, 100, 100] + color: red diff --git a/gfx/wr/wrench/reftests/split/order-2-ref.yaml b/gfx/wr/wrench/reftests/split/order-2-ref.yaml new file mode 100644 index 0000000000..930ac5c8b9 --- /dev/null +++ b/gfx/wr/wrench/reftests/split/order-2-ref.yaml @@ -0,0 +1,8 @@ +root: + items: + - type: stacking-context + bounds: [0, 0, 100, 100] + items: + - type: rect + bounds: [0, 0, 100, 100] + color: green diff --git a/gfx/wr/wrench/reftests/split/order-2.yaml b/gfx/wr/wrench/reftests/split/order-2.yaml new file mode 100644 index 0000000000..a94d25b8f1 --- /dev/null +++ b/gfx/wr/wrench/reftests/split/order-2.yaml @@ -0,0 +1,27 @@ +# The "preserve-3d" context has a "flat" child, which contains two other stacking contexts +# that have their Z modified. The Z should not affect their drawing order, since they +# are hidden from the 3D hierarchy by the flat parent. +--- +root: + items: + - type: stacking-context + bounds: [0, 0, 100, 100] + transform-style: preserve-3d + items: + - type: stacking-context + bounds: [0, 0, 100, 100] + items: + - type: stacking-context + bounds: [0, 0, 100, 100] + transform: translate(0, 0, 10) + items: + - type: rect + bounds: [0, 0, 100, 100] + color: red + - type: stacking-context + bounds: [0, 0, 100, 100] + transform: translate(0, 0, -10) + items: + - type: rect + bounds: [0, 0, 100, 100] + color: green diff --git a/gfx/wr/wrench/reftests/split/order-3-ref.yaml b/gfx/wr/wrench/reftests/split/order-3-ref.yaml new file mode 100644 index 0000000000..9d896d9699 --- /dev/null +++ b/gfx/wr/wrench/reftests/split/order-3-ref.yaml @@ -0,0 +1,15 @@ +--- +root: + items: + - + type: rect + bounds: [8, 8, 200, 200] + color: blue + - + type: rect + bounds: [8, 208, 200, 200] + color: blue + - + type: rect + bounds: [8, 408, 200, 200] + color: blue diff --git a/gfx/wr/wrench/reftests/split/order-3.yaml b/gfx/wr/wrench/reftests/split/order-3.yaml new file mode 100644 index 0000000000..7f80652af6 --- /dev/null +++ b/gfx/wr/wrench/reftests/split/order-3.yaml @@ -0,0 +1,31 @@ +# Ensure that preserve-3d items are correctly batched with transparent siblings. +--- +root: + items: + - + type: stacking-context + transform-style: "preserve-3d" + items: + - + type: rect + bounds: [8, 8, 200, 200] + color: blue + - + type: stacking-context + transform-style: "preserve-3d" + items: + - + type: rect + bounds: [8, 208, 200, 200] + color: blue + - type: rect + color: [255, 0, 0, 0.5] + bounds: [8, 408, 200, 200] + - + type: stacking-context + transform-style: "preserve-3d" + items: + - + type: rect + bounds: [8, 408, 200, 200] + color: blue diff --git a/gfx/wr/wrench/reftests/split/ordering-ref.yaml b/gfx/wr/wrench/reftests/split/ordering-ref.yaml new file mode 100644 index 0000000000..33ad571660 --- /dev/null +++ b/gfx/wr/wrench/reftests/split/ordering-ref.yaml @@ -0,0 +1,15 @@ +--- +root: + items: + - + bounds: [15, 15, 150, 300] + type: rect + color: 255 0 0 1.0000 + - + bounds: [203, 15, 150, 300] + type: rect + color: 255 0 0 1.0000 + - + bounds: [0, 0, 450, 150] + type: rect + color: 0 0 0 0.6667 diff --git a/gfx/wr/wrench/reftests/split/ordering.yaml b/gfx/wr/wrench/reftests/split/ordering.yaml new file mode 100644 index 0000000000..2809166454 --- /dev/null +++ b/gfx/wr/wrench/reftests/split/ordering.yaml @@ -0,0 +1,25 @@ +--- +root: + items: + - + type: "stacking-context" + transform: [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 15, 15, 0, 1] + "transform-style": "preserve-3d" + items: + - + perspective: [1, 0, 0, 0, 0, 1, 0, 0, -0.05, -0.1, 1, -0.00066666666, 0, 0, 0, 1] + type: "stacking-context" + "transform-style": "preserve-3d" + items: + - + bounds: [0, 0, 150, 300] + type: rect + color: 255 0 0 1.0000 + - + bounds: [203, 15, 150, 300] + type: rect + color: 255 0 0 1.0000 + - + bounds: [0, 0, 450, 150] + type: rect + color: 0 0 0 0.6667 diff --git a/gfx/wr/wrench/reftests/split/perspective-clipping-ref.yaml b/gfx/wr/wrench/reftests/split/perspective-clipping-ref.yaml new file mode 100644 index 0000000000..8f6d4a1566 --- /dev/null +++ b/gfx/wr/wrench/reftests/split/perspective-clipping-ref.yaml @@ -0,0 +1,9 @@ +--- +root: + items: + - type: stacking-context + bounds: 0 0 1024 768 + items: + - type: rect + bounds: 0 0 1024 768 + color: green diff --git a/gfx/wr/wrench/reftests/split/perspective-clipping.yaml b/gfx/wr/wrench/reftests/split/perspective-clipping.yaml new file mode 100644 index 0000000000..7135f27c37 --- /dev/null +++ b/gfx/wr/wrench/reftests/split/perspective-clipping.yaml @@ -0,0 +1,23 @@ +--- +root: + items: + - type: stacking-context + bounds: 0 0 1024 768 + items: + - type: rect + bounds: 0 0 1024 768 + color: red + - type: stacking-context + bounds: 0 0 1024 768 + transform-style: preserve-3d + perspective: 300 + perspective-origin: 0 0 + items: + - type: stacking-context + bounds: 0 0 1024 768 + # translate-Z(-300) scale(2) + transform: 2 0 0 0 0 2 0 0 0 0 2 0 0 0 -300 1 + items: + - type: rect + bounds: 0 0 1024 768 + color: green diff --git a/gfx/wr/wrench/reftests/split/reftest.list b/gfx/wr/wrench/reftests/split/reftest.list new file mode 100644 index 0000000000..cd9b33c02b --- /dev/null +++ b/gfx/wr/wrench/reftests/split/reftest.list @@ -0,0 +1,22 @@ +fuzzy-if(platform(swgl),1,180000) == simple.yaml simple-ref.yaml +== order-1.yaml order-1-ref.yaml +== order-2.yaml order-2-ref.yaml +== nested.yaml nested-ref.yaml +# fuzziness is needed due to perspective for the edge +fuzzy(35,200) == nested-coord-systems.yaml nested-coord-systems-ref.yaml +== nested-preserve3d-crash.yaml nested-preserve3d-crash.yaml +== perspective-clipping.yaml perspective-clipping-ref.yaml +== intermediate-1.yaml intermediate-1-ref.yaml +== intermediate-2.yaml intermediate-1-ref.yaml +== split-intersect1.yaml split-intersect1-ref.yaml +== ordering.yaml ordering-ref.yaml +fuzzy(1,20) fuzzy-if(platform(swgl),128,39) == near-plane.yaml near-plane.png +# Note: on windows the image is rendered at a slightly different spot. +# similarly, a lot of tests in "transform" are non-windows. TODO: investigate +platform(linux,mac) fuzzy(1,20) == same-plane.yaml same-plane.png +#TODO: https://github.com/servo/webrender/issues/2946 +#== cross.yaml cross-ref.yaml +== mixed-order.yaml mixed-order-ref.yaml +fuzzy(1,40000) == filter.yaml filter-ref.yaml +fuzzy(1,10000) == gradient.yaml gradient-ref.yaml +== order-3.yaml order-3-ref.yaml diff --git a/gfx/wr/wrench/reftests/split/same-plane.png b/gfx/wr/wrench/reftests/split/same-plane.png Binary files differnew file mode 100644 index 0000000000..cfcd475488 --- /dev/null +++ b/gfx/wr/wrench/reftests/split/same-plane.png diff --git a/gfx/wr/wrench/reftests/split/same-plane.yaml b/gfx/wr/wrench/reftests/split/same-plane.yaml new file mode 100644 index 0000000000..277709bad1 --- /dev/null +++ b/gfx/wr/wrench/reftests/split/same-plane.yaml @@ -0,0 +1,33 @@ +# This test has a number of rectangles placed on the same transformed preserve3d plane. +# The expected result is that the rectangles are rendered in the order they are listed. +# This can fail if the primitives are considered outside of the main plane due +# to floating point precision issues in plane-splitting and transformation. +--- +root: + items: + - type: "stacking-context" + transform-style: preserve-3d + transform: rotate-y(-30) rotate-x(-75) translate(-100, 100, 0) + items: + - type: "stacking-context" + perspective: 400 + transform-style: preserve-3d + items: + - type: rect + bounds: [0, 0, 450, 300] + color: 0 255 0 1.0000 + - type: stacking-context + bounds: [0, 0, 600, 600] + transform: translate(200, 0, 0) + items: + - type: rect + bounds: [-200, 0, 150, 300] + color: 255 0 0 1.0000 + - type: stacking-context + bounds: [0, 0, 600, 600] + transform: rotate-z(-90) + items: + - + bounds: [0, 200, 150, 200] + type: rect + color: 0 0 255 1.0000 diff --git a/gfx/wr/wrench/reftests/split/simple-ref.yaml b/gfx/wr/wrench/reftests/split/simple-ref.yaml new file mode 100644 index 0000000000..de1fad9440 --- /dev/null +++ b/gfx/wr/wrench/reftests/split/simple-ref.yaml @@ -0,0 +1,12 @@ +--- +root: + items: + - type: stacking-context + bounds: [0, 0, 1024, 1024] + items: + - type: rect + bounds: [150, 0, 150, 600] + color: [191, 127, 63] + - type: rect + bounds: [300, 0, 150, 600] + color: [127, 191, 63] diff --git a/gfx/wr/wrench/reftests/split/simple.yaml b/gfx/wr/wrench/reftests/split/simple.yaml new file mode 100644 index 0000000000..b6445780f5 --- /dev/null +++ b/gfx/wr/wrench/reftests/split/simple.yaml @@ -0,0 +1,24 @@ +# This tests a simple intersection of 2 rotated planes to split properly. +# If the split doesn't happen, we see a single-colored rectangle. +# If it does, the rectangle gets split vertically in 2 parts of different colors. +--- +root: + items: + - type: stacking-context + bounds: [0, 0, 1024, 1024] + transform-style: preserve-3d + items: + - type: stacking-context + bounds: [0, 0, 600, 600] + transform: rotate-y(-60.0) + items: + - type: rect + bounds: [0, 0, 600, 600] + color: [255, 0, 0, 0.5] + - type: stacking-context + bounds: [0, 0, 600, 600] + transform: rotate-y(60.0) + items: + - type: rect + bounds: [0, 0, 600, 600] + color: [0, 255, 0, 0.5] diff --git a/gfx/wr/wrench/reftests/split/split-intersect1-ref.yaml b/gfx/wr/wrench/reftests/split/split-intersect1-ref.yaml new file mode 100644 index 0000000000..134698571c --- /dev/null +++ b/gfx/wr/wrench/reftests/split/split-intersect1-ref.yaml @@ -0,0 +1,15 @@ +--- +root: + items: + - type: stacking-context + items: + - type: stacking-context + items: + - type: rect + bounds: 50 0 50 100 + color: red + - type: stacking-context + items: + - type: rect + bounds: 0 0 50 100 + color: green diff --git a/gfx/wr/wrench/reftests/split/split-intersect1.yaml b/gfx/wr/wrench/reftests/split/split-intersect1.yaml new file mode 100644 index 0000000000..dff7638707 --- /dev/null +++ b/gfx/wr/wrench/reftests/split/split-intersect1.yaml @@ -0,0 +1,18 @@ +--- +root: + items: + - type: stacking-context + transform-style: preserve-3d + items: + - type: stacking-context + items: + - type: rect + bounds: 0 0 100 100 + color: red + - type: stacking-context + transform: rotate-y(-0.1) + bounds: 0 0 100 100 + items: + - type: rect + bounds: 0 0 100 100 + color: green diff --git a/gfx/wr/wrench/reftests/text/1658-ref.yaml b/gfx/wr/wrench/reftests/text/1658-ref.yaml new file mode 100644 index 0000000000..4f5fbe15c5 --- /dev/null +++ b/gfx/wr/wrench/reftests/text/1658-ref.yaml @@ -0,0 +1,26 @@ +--- +root: + items: + - + type: "shadow" + blur-radius: 5 + bounds: [14, 18, 205, 35] + offset: [0, 0] + color: black + - + bounds: [14, 18, 205, 35] + glyphs: [55] + offsets: [16, 43] + size: 18 + color: [0, 0, 0, 0.0] + font: "VeraBd.ttf" + - + type: "pop-all-shadows" + - + type: text + bounds: [14, 18, 205, 35] + glyphs: [55] + offsets: [16, 43] + size: 18 + color: [0, 0, 0, 1.0] + font: "VeraBd.ttf" diff --git a/gfx/wr/wrench/reftests/text/1658.yaml b/gfx/wr/wrench/reftests/text/1658.yaml new file mode 100644 index 0000000000..523e7b1143 --- /dev/null +++ b/gfx/wr/wrench/reftests/text/1658.yaml @@ -0,0 +1,19 @@ +--- +root: + items: + - + type: "shadow" + blur-radius: 5 + bounds: [14, 18, 205, 35] + offset: [0, 0] + color: black + - + bounds: [14, 18, 205, 35] + glyphs: [55] + offsets: [16, 43] + size: 18 + color: [0, 0, 0, 1.0] + font: "VeraBd.ttf" + - + type: "pop-all-shadows" + diff --git a/gfx/wr/wrench/reftests/text/Ahem.ttf b/gfx/wr/wrench/reftests/text/Ahem.ttf Binary files differnew file mode 100644 index 0000000000..4d4785a412 --- /dev/null +++ b/gfx/wr/wrench/reftests/text/Ahem.ttf diff --git a/gfx/wr/wrench/reftests/text/FreeSans.ttf b/gfx/wr/wrench/reftests/text/FreeSans.ttf Binary files differnew file mode 100644 index 0000000000..9db958532c --- /dev/null +++ b/gfx/wr/wrench/reftests/text/FreeSans.ttf diff --git a/gfx/wr/wrench/reftests/text/Proggy-License.txt b/gfx/wr/wrench/reftests/text/Proggy-License.txt new file mode 100644 index 0000000000..f45a0d4bed --- /dev/null +++ b/gfx/wr/wrench/reftests/text/Proggy-License.txt @@ -0,0 +1,10 @@ +The "Proggy.ttf" font was downloaded from https://proggyfonts.net/download/ on Dec 5, 2017. +The following license applies to "Proggy.ttf": + +Copyright (c) 2004, 2005 Tristan Grimmer + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/gfx/wr/wrench/reftests/text/Proggy.ttf b/gfx/wr/wrench/reftests/text/Proggy.ttf Binary files differnew file mode 100644 index 0000000000..308d3e1ac9 --- /dev/null +++ b/gfx/wr/wrench/reftests/text/Proggy.ttf diff --git a/gfx/wr/wrench/reftests/text/VeraBd.ttf b/gfx/wr/wrench/reftests/text/VeraBd.ttf Binary files differnew file mode 100644 index 0000000000..51d6111d72 --- /dev/null +++ b/gfx/wr/wrench/reftests/text/VeraBd.ttf diff --git a/gfx/wr/wrench/reftests/text/ahem-ref.yaml b/gfx/wr/wrench/reftests/text/ahem-ref.yaml new file mode 100644 index 0000000000..061e62abbf --- /dev/null +++ b/gfx/wr/wrench/reftests/text/ahem-ref.yaml @@ -0,0 +1,18 @@ +--- +root: + items: + - type: rect + bounds: [ 16, 16, 520, 280 ] + color: 128 128 128 1.0 + - type: rect + bounds: [ 56, 56, 440, 200 ] + color: white + - type: rect + bounds: [ 56, 56, 80, 160 ] + color: blue + - type: rect + bounds: [ 56, 216, 120, 40 ] + color: black + - type: rect + bounds: [ 176, 56, 80, 160 ] + color: 255 165 0 1.0000 diff --git a/gfx/wr/wrench/reftests/text/ahem.yaml b/gfx/wr/wrench/reftests/text/ahem.yaml new file mode 100644 index 0000000000..94817b6fe0 --- /dev/null +++ b/gfx/wr/wrench/reftests/text/ahem.yaml @@ -0,0 +1,243 @@ +--- +root: + items: + - + bounds: [0, 0, 0, 0] + "clip-rect": [0, 0, 0, 0] + "backface-visible": true + - + bounds: [0, 0, 2560, 1294] + "clip-rect": [0, 0, 2560, 1294] + "backface-visible": true + type: rect + color: white + - + bounds: [0, 0, 2560, 1294] + "clip-rect": [0, 0, 2560, 1294] + "backface-visible": true + type: clip + id: 10 + "content-size": [2560, 1294] + - + "clip-rect": [0, 0, 2560, 1294] + "clip-and-scroll": 10 + "backface-visible": true + type: "scroll-frame" + id: 2 + "content-size": [2560, 1294] + bounds: [0, 0, 2560, 1294] + - + bounds: [0, 0, 2560, 1294] + "clip-rect": [0, 0, 2560, 1294] + "clip-and-scroll": 2 + "backface-visible": true + type: clip + id: 3 + "content-size": [2560, 1294] + - + bounds: [0, 0, 2560, 1294] + "clip-rect": [0, 0, 2560, 1294] + "clip-and-scroll": 3 + "backface-visible": true + type: rect + color: white + - + bounds: [16, 16, 520, 280] + "clip-rect": [16, 16, 520, 280] + "clip-and-scroll": 3 + "backface-visible": true + type: border + width: 40 + "border-type": normal + color: 128 128 128 1.0000 + style: solid + - + bounds: [56, 216, 80, 40] + "clip-rect": [56, 216, 80, 40] + "clip-and-scroll": 2 + "backface-visible": true + type: clip + id: 4 + "content-size": [80, 40] + - + bounds: [56, 216, 80, 40] + "clip-rect": [56, 216, 80, 40] + "clip-and-scroll": 4 + "backface-visible": true + type: rect + color: black + - + bounds: [54, 55, 124, 42] + "clip-rect": [0, 0, 2560, 1294] + "clip-and-scroll": 3 + "backface-visible": true + glyphs: [67, 68] + offsets: [56, 88, 96, 88] + size: 30 + color: 0 0 255 1.0000 + font: "Ahem.ttf" + - + bounds: [54, 95, 124, 42] + "clip-rect": [0, 0, 2560, 1294] + "clip-and-scroll": 3 + "backface-visible": true + glyphs: [69, 70] + offsets: [56, 128, 96, 128] + size: 30 + color: 0 0 255 1.0000 + font: "Ahem.ttf" + - + bounds: [54, 135, 124, 42] + "clip-rect": [0, 0, 2560, 1294] + "clip-and-scroll": 3 + "backface-visible": true + glyphs: [71, 72] + offsets: [56, 168, 96, 168] + size: 30 + color: 0 0 255 1.0000 + font: "Ahem.ttf" + - + bounds: [54, 175, 124, 42] + "clip-rect": [0, 0, 2560, 1294] + "clip-and-scroll": 3 + "backface-visible": true + glyphs: [73, 74] + offsets: [56, 208, 96, 208] + size: 30 + color: 0 0 255 1.0000 + font: "Ahem.ttf" + - + bounds: [54, 215, 124, 42] + "clip-rect": [0, 0, 2560, 1294] + "clip-and-scroll": 3 + "backface-visible": true + glyphs: [19, 20, 21] + offsets: [56, 248, 96, 248, 136, 248] + size: 30 + color: black + font: "Ahem.ttf" + - + bounds: [174, 55, 124, 42] + "clip-rect": [0, 0, 2560, 1294] + "clip-and-scroll": 3 + "backface-visible": true + glyphs: [75, 76] + offsets: [176, 88, 216, 88] + size: 30 + color: 255 165 0 1.0000 + font: "Ahem.ttf" + - + bounds: [174, 95, 124, 42] + "clip-rect": [0, 0, 2560, 1294] + "clip-and-scroll": 3 + "backface-visible": true + glyphs: [77, 78] + offsets: [176, 128, 216, 128] + size: 30 + color: 255 165 0 1.0000 + font: "Ahem.ttf" + - + bounds: [174, 135, 124, 42] + "clip-rect": [0, 0, 2560, 1294] + "clip-and-scroll": 3 + "backface-visible": true + glyphs: [79, 80] + offsets: [176, 168, 216, 168] + size: 30 + color: 255 165 0 1.0000 + font: "Ahem.ttf" + - + bounds: [174, 175, 124, 42] + "clip-rect": [0, 0, 2560, 1294] + "clip-and-scroll": 3 + "backface-visible": true + glyphs: [81, 83] + offsets: [176, 208, 216, 208] + size: 30 + color: 255 165 0 1.0000 + font: "Ahem.ttf" + - + bounds: [174, 215, 124, 42] + "clip-rect": [0, 0, 2560, 1294] + "clip-and-scroll": 3 + "backface-visible": true + glyphs: [67, 68] + offsets: [176, 248, 216, 248] + size: 30 + color: white + font: "Ahem.ttf" + - + bounds: [294, 55, 124, 42] + "clip-rect": [0, 0, 2560, 1294] + "clip-and-scroll": 3 + "backface-visible": true + glyphs: [69, 70] + offsets: [296, 88, 336, 88] + size: 30 + color: white + font: "Ahem.ttf" + - + bounds: [294, 95, 124, 42] + "clip-rect": [0, 0, 2560, 1294] + "clip-and-scroll": 3 + "backface-visible": true + glyphs: [71, 72] + offsets: [296, 128, 336, 128] + size: 30 + color: white + font: "Ahem.ttf" + - + bounds: [294, 135, 124, 42] + "clip-rect": [0, 0, 2560, 1294] + "clip-and-scroll": 3 + "backface-visible": true + glyphs: [73, 74] + offsets: [296, 168, 336, 168] + size: 30 + color: white + font: "Ahem.ttf" + - + bounds: [294, 175, 124, 42] + "clip-rect": [0, 0, 2560, 1294] + "clip-and-scroll": 3 + "backface-visible": true + glyphs: [84, 85] + offsets: [296, 208, 336, 208] + size: 30 + color: white + font: "Ahem.ttf" + - + bounds: [294, 215, 124, 42] + "clip-rect": [0, 0, 2560, 1294] + "clip-and-scroll": 3 + "backface-visible": true + glyphs: [86, 87] + offsets: [296, 248, 336, 248] + size: 30 + color: white + font: "Ahem.ttf" + - + bounds: [414, 55, 124, 42] + "clip-rect": [0, 0, 2560, 1294] + "clip-and-scroll": 3 + "backface-visible": true + glyphs: [88, 89] + offsets: [416, 88, 456, 88] + size: 30 + color: white + font: "Ahem.ttf" + - + bounds: [414, 95, 124, 42] + "clip-rect": [0, 0, 2560, 1294] + "clip-and-scroll": 3 + "backface-visible": true + glyphs: [90, 91] + offsets: [416, 128, 456, 128] + size: 30 + color: white + font: "Ahem.ttf" + - + bounds: [0, 0, 0, 0] + "clip-rect": [0, 0, 0, 0] + "clip-and-scroll": root-scroll-node + "backface-visible": true diff --git a/gfx/wr/wrench/reftests/text/allow-subpixel-ref.yaml b/gfx/wr/wrench/reftests/text/allow-subpixel-ref.yaml new file mode 100644 index 0000000000..d99c91b77f --- /dev/null +++ b/gfx/wr/wrench/reftests/text/allow-subpixel-ref.yaml @@ -0,0 +1,8 @@ +--- +root: + items: + - text: "This should not be subpixel text" + origin: 20 120 + size: 18 + color: black + font: "VeraBd.ttf" diff --git a/gfx/wr/wrench/reftests/text/allow-subpixel.yaml b/gfx/wr/wrench/reftests/text/allow-subpixel.yaml new file mode 100644 index 0000000000..d7bd98a287 --- /dev/null +++ b/gfx/wr/wrench/reftests/text/allow-subpixel.yaml @@ -0,0 +1,19 @@ +--- # Verify that subpixel AA is disabled if the text's enclosing stacking context requires an intermediate surface +root: + items: + - type: stacking-context + bounds: [0, 0, 500, 200] + blend-container: true + items: + - text: "This should not be subpixel text" + origin: 20 120 + size: 18 + color: black + font: "VeraBd.ttf" + - type: stacking-context + bounds: [0, 0, 100, 100] + mix-blend-mode: multiply + items: + - type: rect + bounds: [0, 0, 100, 100] + color: white diff --git a/gfx/wr/wrench/reftests/text/alpha-transform.png b/gfx/wr/wrench/reftests/text/alpha-transform.png Binary files differnew file mode 100644 index 0000000000..e22066b8c6 --- /dev/null +++ b/gfx/wr/wrench/reftests/text/alpha-transform.png diff --git a/gfx/wr/wrench/reftests/text/alpha-transform.yaml b/gfx/wr/wrench/reftests/text/alpha-transform.yaml new file mode 100644 index 0000000000..8a623b8067 --- /dev/null +++ b/gfx/wr/wrench/reftests/text/alpha-transform.yaml @@ -0,0 +1,10 @@ +root: + items: + - type: stacking-context + bounds: [0, 0, 660, 210] + transform: scale(1.5, 2.5) rotate(-10) + items: + - text: "a Bcd Efgh Ijklm Nopqrs Tuvwxyz" + origin: 20 50 + size: 20 + font: "FreeSans.ttf" diff --git a/gfx/wr/wrench/reftests/text/bg-color-ref.yaml b/gfx/wr/wrench/reftests/text/bg-color-ref.yaml new file mode 100644 index 0000000000..01af0e93b6 --- /dev/null +++ b/gfx/wr/wrench/reftests/text/bg-color-ref.yaml @@ -0,0 +1,8 @@ +--- +root: + items: + - text: "A" + origin: 30 220 + size: 200 + color: black + font: "FreeSans.ttf" diff --git a/gfx/wr/wrench/reftests/text/bg-color.yaml b/gfx/wr/wrench/reftests/text/bg-color.yaml new file mode 100644 index 0000000000..14f53d79be --- /dev/null +++ b/gfx/wr/wrench/reftests/text/bg-color.yaml @@ -0,0 +1,15 @@ +# verify that drawing a text run on an off-screen surface with a +# specified background color gives the same result as drawing a +# subpixel text run directly on the background. +--- +root: + items: + - type: stacking-context + transform-style: preserve-3d + items: + - text: "A" + origin: 30 220 + size: 200 + color: black + font: "FreeSans.ttf" + bg-color: white diff --git a/gfx/wr/wrench/reftests/text/blank.yaml b/gfx/wr/wrench/reftests/text/blank.yaml new file mode 100644 index 0000000000..c4eb3ab673 --- /dev/null +++ b/gfx/wr/wrench/reftests/text/blank.yaml @@ -0,0 +1,2 @@ +--- +root: diff --git a/gfx/wr/wrench/reftests/text/blurred-shadow-local-clip-rect-ref.png b/gfx/wr/wrench/reftests/text/blurred-shadow-local-clip-rect-ref.png Binary files differnew file mode 100644 index 0000000000..944d0b7847 --- /dev/null +++ b/gfx/wr/wrench/reftests/text/blurred-shadow-local-clip-rect-ref.png diff --git a/gfx/wr/wrench/reftests/text/blurred-shadow-local-clip-rect.yaml b/gfx/wr/wrench/reftests/text/blurred-shadow-local-clip-rect.yaml new file mode 100644 index 0000000000..bbfc2f1f9f --- /dev/null +++ b/gfx/wr/wrench/reftests/text/blurred-shadow-local-clip-rect.yaml @@ -0,0 +1,48 @@ +# This test ensures that for text that has a shadow and blurred shadow, the +# shadows are clipped in the same way (via the local clip rect) as the shadowed +# element. +--- +root: + items: + - + type: "shadow" + bounds: [10, 14, 220, 200] + blur-radius: 0 + offset: [0, 50] + color: black + - + type: "shadow" + bounds: [10, 14, 220, 100] + blur-radius: 3 + offset: [0, 25] + color: black + - + bounds: [10, 14, 215, 45] + clip-rect: [10, 14, 122, 40] + glyphs: [55, 75, 76, 86, 3, 76, 86, 3, 87, 75, 72, 3, 69, 72, 86, 87] + offsets: [16, 43, 35.533333, 43, 51.533333, 43, 60.4, 43, 72.833336, 43, 80.833336, 43, 89.7, 43, 102.13333, 43, 110.13333, 43, 119, 43, 135, 43, 149.2, 43, 157.2, 43, 173.2, 43, 187.4, 43, 196.26666, 43] + size: 18 + color: green + font: "VeraBd.ttf" + - + type: line + clip-rect: [10, 14, 122, 40] + baseline: 45 + start: 14 + end: 210 + width: 3 + orientation: horizontal + color: green + style: solid + - + type: line + clip-rect: [10, 14, 122, 40] + baseline: 32 + start: 14 + end: 210 + width: 3 + orientation: horizontal + color: green + style: solid + - + type: "pop-all-shadows" diff --git a/gfx/wr/wrench/reftests/text/border-radius-alpha.png b/gfx/wr/wrench/reftests/text/border-radius-alpha.png Binary files differnew file mode 100644 index 0000000000..8ff8700a59 --- /dev/null +++ b/gfx/wr/wrench/reftests/text/border-radius-alpha.png diff --git a/gfx/wr/wrench/reftests/text/border-radius-subpx.png b/gfx/wr/wrench/reftests/text/border-radius-subpx.png Binary files differnew file mode 100644 index 0000000000..948fa48f93 --- /dev/null +++ b/gfx/wr/wrench/reftests/text/border-radius-subpx.png diff --git a/gfx/wr/wrench/reftests/text/border-radius.yaml b/gfx/wr/wrench/reftests/text/border-radius.yaml new file mode 100644 index 0000000000..cda868891d --- /dev/null +++ b/gfx/wr/wrench/reftests/text/border-radius.yaml @@ -0,0 +1,17 @@ +--- +root: + items: + - type: clip + bounds: [20, 20, 100, 100] + complex: + - rect: [20, 20, 100, 100] + radius: 32 + items: + - type: rect + bounds: [20, 20, 100, 100] + color: blue + - text: "A" + origin: 30 120 + size: 200 + color: red + font: "FreeSans.ttf" diff --git a/gfx/wr/wrench/reftests/text/clipped-transform.png b/gfx/wr/wrench/reftests/text/clipped-transform.png Binary files differnew file mode 100644 index 0000000000..24459d2d3c --- /dev/null +++ b/gfx/wr/wrench/reftests/text/clipped-transform.png diff --git a/gfx/wr/wrench/reftests/text/clipped-transform.yaml b/gfx/wr/wrench/reftests/text/clipped-transform.yaml new file mode 100644 index 0000000000..7f9c9b8661 --- /dev/null +++ b/gfx/wr/wrench/reftests/text/clipped-transform.yaml @@ -0,0 +1,12 @@ +--- # checks that local clip rects don't inappropriately shear transformed glyphs +root: + items: + - type: stacking-context + bounds: [0, 0, 65, 70] + transform: [0.7086478, 0.7055624, 0, 0, -0.7055624, 0.7086478, 0, 0, 0, 0, 1, 0, 40, 10, 0, 1] + items: + - text: "O" + clip-rect: [0, 0, 44, 44] + origin: 0 38 + size: 30 + font: "FreeSans.ttf" diff --git a/gfx/wr/wrench/reftests/text/color-bitmap-shadow-ref.yaml b/gfx/wr/wrench/reftests/text/color-bitmap-shadow-ref.yaml new file mode 100644 index 0000000000..039f3c6edf --- /dev/null +++ b/gfx/wr/wrench/reftests/text/color-bitmap-shadow-ref.yaml @@ -0,0 +1,30 @@ +--- +root: + items: + - + text: "\u263A" + origin: [8, 56] + size: 36 + color: white + family: "Apple Color Emoji" + embedded-bitmaps: true + - + type: rect + bounds: [56, 56, 48, 48] + color: yellow + - + type: rect + bounds: [56, 56, 48, 12] + color: black + - + type: rect + bounds: [56, 92, 48, 12] + color: black + - + type: rect + bounds: [56, 56, 12, 48] + color: black + - + type: rect + bounds: [92, 56, 12, 48] + color: black diff --git a/gfx/wr/wrench/reftests/text/color-bitmap-shadow.yaml b/gfx/wr/wrench/reftests/text/color-bitmap-shadow.yaml new file mode 100644 index 0000000000..4ead9270cd --- /dev/null +++ b/gfx/wr/wrench/reftests/text/color-bitmap-shadow.yaml @@ -0,0 +1,34 @@ +--- # checks that color emoji fast shadows use the shadow color +root: + items: + - + type: "shadow" + bounds: [0, 0, 115, 115] + offset: [48, 48] + blur-radius: 0 + color: yellow + - + text: "\u263A" + origin: [8, 56] + size: 36 + color: blue + family: "Apple Color Emoji" + embedded-bitmaps: true + - + type: "pop-all-shadows" + - + type: rect + bounds: [56, 56, 48, 12] + color: black + - + type: rect + bounds: [56, 92, 48, 12] + color: black + - + type: rect + bounds: [56, 56, 12, 48] + color: black + - + type: rect + bounds: [92, 56, 12, 48] + color: black diff --git a/gfx/wr/wrench/reftests/text/colors-alpha.png b/gfx/wr/wrench/reftests/text/colors-alpha.png Binary files differnew file mode 100644 index 0000000000..3e8d985025 --- /dev/null +++ b/gfx/wr/wrench/reftests/text/colors-alpha.png diff --git a/gfx/wr/wrench/reftests/text/colors-subpx.png b/gfx/wr/wrench/reftests/text/colors-subpx.png Binary files differnew file mode 100644 index 0000000000..50d5c36be3 --- /dev/null +++ b/gfx/wr/wrench/reftests/text/colors-subpx.png diff --git a/gfx/wr/wrench/reftests/text/colors.yaml b/gfx/wr/wrench/reftests/text/colors.yaml new file mode 100644 index 0000000000..aceb032898 --- /dev/null +++ b/gfx/wr/wrench/reftests/text/colors.yaml @@ -0,0 +1,211 @@ +root: + items: + - type: rect + bounds: [10, 10, 250, 50] + color: white + - text: "A B C a b c" + origin: 20 50 + size: 32 + font: "FreeSans.ttf" + + - type: rect + bounds: [270, 10, 250, 50] + color: red + - text: "A B C a b c" + origin: 280 50 + size: 32 + font: "FreeSans.ttf" + + - type: rect + bounds: [530, 10, 250, 50] + color: green + - text: "A B C a b c" + origin: 540 50 + size: 32 + font: "FreeSans.ttf" + + - type: rect + bounds: [10, 70, 250, 50] + color: blue + - text: "A B C a b c" + origin: 20 110 + size: 32 + font: "FreeSans.ttf" + + - type: rect + bounds: [270, 70, 250, 50] + color: [100, 100, 100] + - text: "A B C a b c" + origin: 280 110 + size: 32 + font: "FreeSans.ttf" + + - type: rect + bounds: [530, 70, 250, 50] + color: [200, 100, 150] + - text: "A B C a b c" + origin: 540 110 + size: 32 + font: "FreeSans.ttf" + + - type: rect + bounds: [10, 130, 250, 50] + color: white + - text: "A B C a b c" + origin: 20 170 + size: 32 + font: "FreeSans.ttf" + color: white + + - type: rect + bounds: [270, 130, 250, 50] + color: red + - text: "A B C a b c" + origin: 280 170 + size: 32 + font: "FreeSans.ttf" + color: white + + - type: rect + bounds: [530, 130, 250, 50] + color: green + - text: "A B C a b c" + origin: 540 170 + size: 32 + font: "FreeSans.ttf" + color: white + + - type: rect + bounds: [10, 190, 250, 50] + color: blue + - text: "A B C a b c" + origin: 20 230 + size: 32 + font: "FreeSans.ttf" + color: white + + - type: rect + bounds: [270, 190, 250, 50] + color: [100, 100, 100] + - text: "A B C a b c" + origin: 280 230 + size: 32 + font: "FreeSans.ttf" + color: white + + - type: rect + bounds: [530, 190, 250, 50] + color: [200, 100, 150] + - text: "A B C a b c" + origin: 540 230 + size: 32 + font: "FreeSans.ttf" + color: white + + - type: rect + bounds: [10, 250, 250, 50] + color: white + - text: "A B C a b c" + origin: 20 290 + size: 32 + font: "FreeSans.ttf" + color: [200, 180, 200] + + - type: rect + bounds: [270, 250, 250, 50] + color: red + - text: "A B C a b c" + origin: 280 290 + size: 32 + font: "FreeSans.ttf" + color: [200, 180, 200] + + - type: rect + bounds: [530, 250, 250, 50] + color: green + - text: "A B C a b c" + origin: 540 290 + size: 32 + font: "FreeSans.ttf" + color: [200, 180, 200] + + - type: rect + bounds: [10, 310, 250, 50] + color: blue + - text: "A B C a b c" + origin: 20 350 + size: 32 + font: "FreeSans.ttf" + color: [200, 180, 200] + + - type: rect + bounds: [270, 310, 250, 50] + color: [100, 100, 100] + - text: "A B C a b c" + origin: 280 350 + size: 32 + font: "FreeSans.ttf" + color: [200, 180, 200] + + - type: rect + bounds: [530, 310, 250, 50] + color: [200, 100, 150] + - text: "A B C a b c" + origin: 540 350 + size: 32 + font: "FreeSans.ttf" + color: [200, 180, 200] + + - type: rect + bounds: [10, 370, 250, 50] + color: white + - text: "A B C a b c" + origin: 20 410 + size: 32 + font: "FreeSans.ttf" + color: [50, 50, 50, 0.5] + + - type: rect + bounds: [270, 370, 250, 50] + color: red + - text: "A B C a b c" + origin: 280 410 + size: 32 + font: "FreeSans.ttf" + color: [50, 50, 50, 0.5] + + - type: rect + bounds: [530, 370, 250, 50] + color: green + - text: "A B C a b c" + origin: 540 410 + size: 32 + font: "FreeSans.ttf" + color: [50, 50, 50, 0.5] + + - type: rect + bounds: [10, 430, 250, 50] + color: blue + - text: "A B C a b c" + origin: 20 470 + size: 32 + font: "FreeSans.ttf" + color: [50, 50, 50, 0.5] + + - type: rect + bounds: [270, 430, 250, 50] + color: [100, 100, 100] + - text: "A B C a b c" + origin: 280 470 + size: 32 + font: "FreeSans.ttf" + color: [50, 50, 50, 0.5] + + - type: rect + bounds: [530, 430, 250, 50] + color: [200, 100, 150] + - text: "A B C a b c" + origin: 540 470 + size: 32 + font: "FreeSans.ttf" + color: [50, 50, 50, 0.5] diff --git a/gfx/wr/wrench/reftests/text/decorations-ref.yaml b/gfx/wr/wrench/reftests/text/decorations-ref.yaml new file mode 100644 index 0000000000..5ad75109fa --- /dev/null +++ b/gfx/wr/wrench/reftests/text/decorations-ref.yaml @@ -0,0 +1,19 @@ +--- +root: + items: + - type: rect # short, horizontal + bounds: [ 4, 2, 5, 1 ] + color: green + - type: rect # short, vertical + bounds: [ 12, 14, 1, 5 ] + color: red + style: solid + - type: rect # long, horizontal + bounds: [ 34, 32, 200, 3 ] + color: blue + style: solid + - type: rect # long, vertical + bounds: [ 52, 54, 3, 200 ] + color: black + style: solid + diff --git a/gfx/wr/wrench/reftests/text/decorations-suite.png b/gfx/wr/wrench/reftests/text/decorations-suite.png Binary files differnew file mode 100644 index 0000000000..dedc1fe847 --- /dev/null +++ b/gfx/wr/wrench/reftests/text/decorations-suite.png diff --git a/gfx/wr/wrench/reftests/text/decorations-suite.yaml b/gfx/wr/wrench/reftests/text/decorations-suite.yaml new file mode 100644 index 0000000000..bbe02dcc95 --- /dev/null +++ b/gfx/wr/wrench/reftests/text/decorations-suite.yaml @@ -0,0 +1,348 @@ +--- +root: + items: + - type: line + baseline: 10 + start: 10 + end: 210 + width: 1 + orientation: horizontal + color: black + style: solid + - type: line + baseline: 20 + start: 10 + end: 210 + width: 1 + orientation: horizontal + color: blue + style: dashed + - type: line + baseline: 30 + start: 10 + end: 210 + width: 1 + orientation: horizontal + color: green + style: dotted + - type: line + baseline: 40 + start: 10 + end: 210 + width: 3 + thickness: 1 + orientation: horizontal + color: red + style: wavy + + - type: line + baseline: 50 + start: 10 + end: 210 + width: 2 + orientation: horizontal + color: black + style: solid + - type: line + baseline: 65 + start: 10 + end: 210 + width: 2 + orientation: horizontal + color: blue + style: dashed + - type: line + baseline: 80 + start: 10 + end: 207 # pruposefully cut off + width: 2 + orientation: horizontal + color: green + style: dotted + - type: line + baseline: 95 + start: 10 + end: 210 + width: 6 + thickness: 2 + orientation: horizontal + color: red + style: wavy + + - + type: "shadow" + bounds: [8, 100, 225, 50] + blur-radius: 0 + offset: [2, 2] + color: red + - type: line + baseline: 110 + start: 10 + end: 210 + width: 1 + orientation: horizontal + color: [0,0,0,0] + style: solid + - type: line + baseline: 120 + start: 10 + end: 210 + width: 1 + orientation: horizontal + color: [0,0,0,0] + style: dashed + - type: line + baseline: 130 + start: 10 + end: 209 + width: 1 + orientation: horizontal + color: [0,0,0,0] + style: dotted + - type: line + baseline: 140 + start: 10 + end: 210 + width: 3 + thickness: 1 + orientation: horizontal + color: [0,0,0,0] + style: wavy + - + type: pop-all-shadows + + - + type: "shadow" + bounds: [8, 145, 225, 65] + blur-radius: 1 + offset: [2, 3] + color: red + - type: line + baseline: 150 + start: 10 + end: 210 + width: 2 + orientation: horizontal + color: black + style: solid + - type: line + baseline: 165 + start: 10 + end: 210 + width: 2 + orientation: horizontal + color: blue + style: dashed + - type: line + baseline: 180 + start: 10 + end: 207 # purposefully cut off + width: 2 + orientation: horizontal + color: green + style: dotted + - type: line + baseline: 195 + start: 10 + end: 210 + width: 6 + thickness: 2 + orientation: horizontal + color: red + style: wavy + - + type: pop-all-shadows + + - + type: "shadow" + bounds: [8, 220, 225, 40] + blur-radius: 0 + offset: [5, 7] + color: red + - type: line + baseline: 230 + start: 10 + end: 210 + width: 8 + orientation: horizontal + color: black + style: solid + - type: line + baseline: 250 + start: 10 + end: 210 + width: 8 + orientation: horizontal + color: blue + style: dashed + - type: line + baseline: 270 + start: 10 + end: 205 # purposefully cut off + width: 8 + orientation: horizontal + color: green + style: dotted + - type: line + baseline: 290 + start: 10 + end: 210 + width: 12 + thickness: 3 + orientation: horizontal + color: black + style: wavy + - + type: "pop-all-shadows" + + - + type: "shadow" + bounds: [0, 320, 240, 140] + blur-radius: 3 + offset: [5, 7] + color: red + - type: line + baseline: 330 + start: 10 + end: 210 + width: 8 + orientation: horizontal + color: black + style: solid + - type: line + baseline: 350 + start: 10 + end: 210 + width: 8 + orientation: horizontal + color: blue + style: dashed + - type: line + baseline: 370 + start: 10 + end: 205 # purposefully cut off + width: 8 + orientation: horizontal + color: green + style: dotted + - type: line + baseline: 390 + start: 10 + end: 210 + width: 16 + thickness: 4 + orientation: horizontal + color: black + style: wavy + - + type: "pop-all-shadows" + + - type: line + baseline: 220 + start: 10 + end: 210 + width: 1 + orientation: vertical + color: black + style: solid + - type: line + baseline: 230 + start: 10 + end: 210 + width: 1 + orientation: vertical + color: blue + style: dashed + - type: line + baseline: 240 + start: 10 + end: 210 + width: 1 + orientation: vertical + color: green + style: dotted + - type: line + baseline: 250 + start: 10 + end: 210 + thickness: 1 + width: 3 + orientation: vertical + color: red + style: wavy + + - type: line + baseline: 270 + start: 10 + end: 210 + width: 2 + orientation: vertical + color: black + style: solid + - type: line + baseline: 290 + start: 10 + end: 210 + width: 2 + orientation: vertical + color: blue + style: dashed + - type: line + baseline: 310 + start: 10 + end: 207 # purposefully cut off + width: 2 + orientation: vertical + color: green + style: dotted + - type: line + baseline: 330 + start: 10 + end: 210 + thickness: 2 + width: 6 + orientation: vertical + color: red + style: wavy + + - + type: "shadow" + bounds: [350, 0, 120, 240] + blur-radius: 3 + offset: [5, 2] + color: black + - type: line + baseline: 380 + start: 10 + end: 210 + width: 8 + orientation: vertical + color: yellow + style: solid + - type: line + baseline: 400 + start: 10 + end: 210 + width: 8 + orientation: vertical + color: blue + style: dashed + - type: line + baseline: 420 + start: 10 + end: 205 # purposefully cut off + width: 8 + orientation: vertical + color: green + style: dotted + - type: line + baseline: 440 + start: 10 + end: 210 + thickness: 4 + width: 16 + orientation: vertical + color: red + style: wavy + - + type: "pop-all-shadows" diff --git a/gfx/wr/wrench/reftests/text/decorations.yaml b/gfx/wr/wrench/reftests/text/decorations.yaml new file mode 100644 index 0000000000..db15551a74 --- /dev/null +++ b/gfx/wr/wrench/reftests/text/decorations.yaml @@ -0,0 +1,36 @@ +--- +root: + items: + - type: line # short, horizontal + baseline: 2 + start: 4 + end: 9 + width: 1 + orientation: horizontal + color: green + style: solid + - type: line # short, vertical + baseline: 12 + start: 14 + end: 19 + width: 1 + orientation: vertical + color: red + style: solid + - type: line # long, horizontal + baseline: 32 + start: 34 + end: 234 + width: 3 + orientation: horizontal + color: blue + style: solid + - type: line # long, vertical + baseline: 52 + start: 54 + end: 254 + width: 3 + orientation: vertical + color: black + style: solid + diff --git a/gfx/wr/wrench/reftests/text/diacritics-ref.yaml b/gfx/wr/wrench/reftests/text/diacritics-ref.yaml new file mode 100644 index 0000000000..334e1899ee --- /dev/null +++ b/gfx/wr/wrench/reftests/text/diacritics-ref.yaml @@ -0,0 +1,6 @@ +root: + items: + - text: "x" + origin: 20 30 + size: 20 + font: "FreeSans.ttf" diff --git a/gfx/wr/wrench/reftests/text/diacritics.yaml b/gfx/wr/wrench/reftests/text/diacritics.yaml new file mode 100644 index 0000000000..7c613c3aa6 --- /dev/null +++ b/gfx/wr/wrench/reftests/text/diacritics.yaml @@ -0,0 +1,6 @@ +root: + items: + - text: "x̂" + origin: 20 30 + size: 20 + font: "FreeSans.ttf" diff --git a/gfx/wr/wrench/reftests/text/embedded-bitmaps.png b/gfx/wr/wrench/reftests/text/embedded-bitmaps.png Binary files differnew file mode 100644 index 0000000000..a8039015a5 --- /dev/null +++ b/gfx/wr/wrench/reftests/text/embedded-bitmaps.png diff --git a/gfx/wr/wrench/reftests/text/embedded-bitmaps.yaml b/gfx/wr/wrench/reftests/text/embedded-bitmaps.yaml new file mode 100644 index 0000000000..f22b11d95f --- /dev/null +++ b/gfx/wr/wrench/reftests/text/embedded-bitmaps.yaml @@ -0,0 +1,9 @@ +--- # checks that embedded bitmaps are rasterized and use a proper layout +root: + items: + - text: "ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz 0123456789 {}[]()<>$*-+=/#_%^@\\&|~?'\"!,.;:" + origin: 20 30 + bounds: [0, 0, 710, 50] + size: 8.25 + font: "Proggy.ttf" + embedded-bitmaps: true diff --git a/gfx/wr/wrench/reftests/text/intermediate-transform.yaml b/gfx/wr/wrench/reftests/text/intermediate-transform.yaml new file mode 100644 index 0000000000..ab2e51804c --- /dev/null +++ b/gfx/wr/wrench/reftests/text/intermediate-transform.yaml @@ -0,0 +1,54 @@ +# This test case makes the text flipped relative to the surface it renders to, but not to the world. +--- +root: + items: + - + type: "stacking-context" + items: + - + type: "reference-frame" + transform: [0.7753850221633911, 0, 0, 0, 0, 0.7753850221633911, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1] + items: + - + type: "stacking-context" + items: + - + type: "stacking-context" + transform-style: "preserve-3d" + origin: [237, 246] + items: + - + type: "reference-frame" + transform-style: "preserve-3d" + transform: [1, 0, 0, 0, 0, 1, 0, 0, -0.09215625375509262, -0.05100416764616966, 1, -0.0001250000059371814, 0, -3, 0, 1] + items: + - + type: "stacking-context" + transform-style: "preserve-3d" + items: + - + type: "reference-frame" + transform: [-1, 0, 0, 0, 0, -0.9659258127212524, 0.258819043636322, 0, 0, 0.258819043636322, 0.9659258127212524, 0, 1474.5, 802.0977172851563, -105.5981674194336, 1] + items: + - + type: "stacking-context" + items: + - + rect: [0, 0, 1475, 408] + color: red + - + type: "reference-frame" + transform: [-1, 0, 0, 0, 0, -1, 0, 0, 0, 0, 1, 0, 1474.5, 408, 0, 1] + items: + - + type: "stacking-context" + items: + - + glyphs: [55,43,40,3,44,54,36,37,40,47,47,36] + offsets: [511, 290, 551.2000122070313, 290, 597.066650390625, 290, 637.2666625976563, 290, 656.1333618164063, 290, 682.0999755859375, 290, 716.6333618164063, 290, 759.6666870117188, 290, 799.8666381835938, 290, 840.066650390625, 290, 880.2666625976563, 290, 920.4666748046875, 290] + size: 22 + color: black + font: "../text/VeraBd.ttf" + bounds: [509, 250, 457, 54] + clip-rect: [508, 249, 459, 56] + diff --git a/gfx/wr/wrench/reftests/text/isolated-text.png b/gfx/wr/wrench/reftests/text/isolated-text.png Binary files differnew file mode 100644 index 0000000000..a0c8ed3650 --- /dev/null +++ b/gfx/wr/wrench/reftests/text/isolated-text.png diff --git a/gfx/wr/wrench/reftests/text/isolated-text.yaml b/gfx/wr/wrench/reftests/text/isolated-text.yaml new file mode 100644 index 0000000000..897d410a84 --- /dev/null +++ b/gfx/wr/wrench/reftests/text/isolated-text.yaml @@ -0,0 +1,14 @@ +root: + items: + - type: stacking-context + bounds: [0, 0, 1000, 100] + transform: perspective(1000) + items: + - type: stacking-context + bounds: [0, 0, 1000, 100] + transform-style: preserve-3d + items: + - text: "Cats making all the muffins knock over christmas tree" + origin: 20 30 + size: 20 + font: "FreeSans.ttf" diff --git a/gfx/wr/wrench/reftests/text/large-glyphs.yaml b/gfx/wr/wrench/reftests/text/large-glyphs.yaml new file mode 100644 index 0000000000..4bbd3ee10c --- /dev/null +++ b/gfx/wr/wrench/reftests/text/large-glyphs.yaml @@ -0,0 +1,8 @@ +--- # Verify that large glyphs actually render at all. +root: + items: + - text: "HI" + origin: 0 1234 + size: 1234 + color: black + font: "VeraBd.ttf" diff --git a/gfx/wr/wrench/reftests/text/large-line-decoration.yaml b/gfx/wr/wrench/reftests/text/large-line-decoration.yaml new file mode 100644 index 0000000000..ec12a5dc31 --- /dev/null +++ b/gfx/wr/wrench/reftests/text/large-line-decoration.yaml @@ -0,0 +1,43 @@ +--- +root: + items: + - type: line + baseline: 0 + start: 0 + end: 50 + width: 5000 + thickness: 5000 + orientation: horizontal + color: red + style: solid + + - type: line + baseline: 0 + start: 100 + end: 150 + width: 5000 + thickness: 5000 + orientation: horizontal + color: green + style: dashed + + - type: line + baseline: 0 + start: 200 + end: 250 + width: 5000 + thickness: 5000 + orientation: horizontal + color: blue + style: dotted + + - type: line + baseline: 0 + start: 300 + end: 350 + width: 5000 + thickness: 5000 + orientation: horizontal + color: yellow + style: wavy + diff --git a/gfx/wr/wrench/reftests/text/long-text.yaml b/gfx/wr/wrench/reftests/text/long-text.yaml new file mode 100644 index 0000000000..e44658ca99 --- /dev/null +++ b/gfx/wr/wrench/reftests/text/long-text.yaml @@ -0,0 +1,610 @@ +--- +root: + items: + - + bounds: [14, 18, 205, 35] + glyphs: [55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, + 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, + 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, + 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, + 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, + 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, + 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, + 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, + 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, + 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, + 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, + 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, + 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, + 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, + 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, + 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, + 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, + 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, + 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, + 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, + 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, + 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, + 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, + 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, + 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, + 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, + 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, + 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, + 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, + 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, + 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, + 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, + 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, + 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, + 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, + 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, + 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, + 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, + 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, + 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, + 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, + 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, + 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, + 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, + 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, + 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, + 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, + 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, + 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, + 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, + 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, + 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, + 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, + 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, + 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, + 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, + 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, + 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, + 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, + 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, + 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, + 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, + 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, + 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, + 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, + 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, + 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, + 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, + 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, + 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, + 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, + 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, + 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, + 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, + 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, + 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, + 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, + 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, + 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, + 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, + 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, + 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, + 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, + 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, + 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, + 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, + 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, + 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, + 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, + 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, + 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, + 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, + 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, + 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, + 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, + 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, + 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, + 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, + 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, + 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, + 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, + 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, + 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, + 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, + 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, + 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, + 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, + 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, + 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, + 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, + 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, + 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, + 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, + 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, + 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, + 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, + 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, + 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, + 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, + 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, + 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, + 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, + 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, + 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, + 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, + 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, + 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, + 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, + 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, + 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, + 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, + 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, + 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, + 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, + 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, + 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, + 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, + 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, + 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, + 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, + 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, + 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, + 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, + 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, + 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, + 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, + 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, + 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, + 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, + 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, + 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, + 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, + 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, + 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, + 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, + 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, + 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, + 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, + 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, + 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, + 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, + 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, + 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, + 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, + 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, + 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, + 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, + 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, + 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, + 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, + 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, + 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, + 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, + 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, + 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, + 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, + 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, + 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, + 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, + 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, + 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, + 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, + 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, + 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, + 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, + 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, + 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, + 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, + 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, + 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, + 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, + 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, + 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, + 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, + 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, + 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, + 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, + 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, + 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, + 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, + 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, + 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, + 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, + 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, + 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, + 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, + 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, + 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, + 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, + 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, + 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, + 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, + 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, + 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, + 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, + 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, + 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, + 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, + 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, + 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, + 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, + 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, + 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, + 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, + 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, + 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, + 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, + 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, + 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, + 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, + 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, + 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, + 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, + 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, + 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, + 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, + 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, + 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, + 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, + 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, + 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, + 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, + 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, + 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, + 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, + 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, + 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, + 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, + 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, + 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, + 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, + 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, + 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, + 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, + 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, + 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, + 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, + 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, + 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, + 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, + 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, + 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, + 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, + 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, + 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, + 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, + 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, + 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, + 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, + 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, + 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, + 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, + 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, + 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, + 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, + 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, + 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, + 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, + 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, + 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, + 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, + 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, + 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, + 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, + 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, + 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, + 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, + 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, + 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, + 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, + 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, + 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, + 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, + 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, + 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, + 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, + 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, + 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, + 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, + 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, + ] + offsets: [16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, + 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, + 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, + 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, + 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, + 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, + 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, + 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, + 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, + 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, + 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, + 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, + 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, + 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, + 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, + 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, + 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, + 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, + 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, + 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, + 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, + 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, + 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, + 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, + 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, + 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, + 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, + 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, + 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, + 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, + 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, + 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, + 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, + 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, + 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, + 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, + 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, + 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, + 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, + 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, + 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, + 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, + 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, + 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, + 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, + 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, + 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, + 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, + 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, + 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, + 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, + 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, + 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, + 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, + 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, + 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, + 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, + 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, + 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, + 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, + 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, + 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, + 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, + 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, + 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, + 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, + 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, + 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, + 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, + 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, + 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, + 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, + 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, + 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, + 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, + 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, + 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, + 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, + 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, + 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, + 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, + 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, + 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, + 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, + 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, + 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, + 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, + 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, + 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, + 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, + 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, + 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, + 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, + 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, + 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, + 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, + 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, + 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, + 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, + 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, + 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, + 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, + 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, + 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, + 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, + 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, + 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, + 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, + 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, + 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, + 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, + 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, + 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, + 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, + 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, + 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, + 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, + 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, + 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, + 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, + 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, + 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, + 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, + 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, + 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, + 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, + 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, + 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, + 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, + 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, + 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, + 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, + 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, + 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, + 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, + 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, + 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, + 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, + 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, + 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, + 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, + 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, + 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, + 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, + 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, + 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, + 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, + 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, + 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, + 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, + 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, + 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, + 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, + 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, + 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, + 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, + 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, + 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, + 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, + 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, + 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, + 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, + 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, + 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, + 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, + 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, + 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, + 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, + 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, + 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, + 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, + 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, + 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, + 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, + 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, + 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, + 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, + 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, + 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, + 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, + 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, + 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, + 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, + 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, + 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, + 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, + 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, + 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, + 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, + 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, + 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, + 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, + 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, + 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, + 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, + 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, + 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, + 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, + 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, + 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, + 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, + 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, + 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, + 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, + 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, + 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, + 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, + 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, + 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, + 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, + 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, + 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, + 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, + 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, + 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, + 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, + 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, + 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, + 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, + 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, + 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, + 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, + 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, + 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, + 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, + 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, + 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, + 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, + 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, + 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, + 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, + 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, + 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, + 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, + 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, + 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, + 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, + 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, + 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, + 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, + 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, + 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, + 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, + 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, + 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, + 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, + 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, + 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, + 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, + 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, + 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, + 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, + 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, + 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, + 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, + 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, + 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, + 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, + 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, + 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, + 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, + 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, + 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, + 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, + 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, + 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, + 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, + 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, + 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, + 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, + 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, + 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, + 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, + 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, + 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, + 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, + 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, + 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, + 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, + 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, + 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, + 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, + 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, + 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, + 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, + 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, + 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, + 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, + 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, + 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, + 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, + 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, + 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, + 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, + 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, + 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, + 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, + 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, + 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, + 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, 16, 43, + ] + size: 18 + color: black + font: "VeraBd.ttf" diff --git a/gfx/wr/wrench/reftests/text/negative-pos.yaml b/gfx/wr/wrench/reftests/text/negative-pos.yaml new file mode 100644 index 0000000000..7dac5c4961 --- /dev/null +++ b/gfx/wr/wrench/reftests/text/negative-pos.yaml @@ -0,0 +1,10 @@ +--- +root: + items: + - + bounds: [14, 18, 205, 35] + glyphs: [55] + offsets: [-2, 43] + size: 24 + color: black + font: "VeraBd.ttf" diff --git a/gfx/wr/wrench/reftests/text/non-opaque-notref.yaml b/gfx/wr/wrench/reftests/text/non-opaque-notref.yaml new file mode 100644 index 0000000000..53d878b958 --- /dev/null +++ b/gfx/wr/wrench/reftests/text/non-opaque-notref.yaml @@ -0,0 +1,10 @@ +--- +root: + items: + - + bounds: [0, 0, 500, 500] + glyphs: [55] + offsets: [200, 200] + size: 100 + color: [0, 0, 0] + font: "VeraBd.ttf" diff --git a/gfx/wr/wrench/reftests/text/non-opaque.yaml b/gfx/wr/wrench/reftests/text/non-opaque.yaml new file mode 100644 index 0000000000..ff2573dbfa --- /dev/null +++ b/gfx/wr/wrench/reftests/text/non-opaque.yaml @@ -0,0 +1,10 @@ +--- +root: + items: + - + bounds: [0, 0, 500, 500] + glyphs: [55] + offsets: [200, 200] + size: 100 + color: [0, 0, 0, 0.5] + font: "VeraBd.ttf" diff --git a/gfx/wr/wrench/reftests/text/perspective-clip.png b/gfx/wr/wrench/reftests/text/perspective-clip.png Binary files differnew file mode 100644 index 0000000000..3a836ecb2a --- /dev/null +++ b/gfx/wr/wrench/reftests/text/perspective-clip.png diff --git a/gfx/wr/wrench/reftests/text/perspective-clip.yaml b/gfx/wr/wrench/reftests/text/perspective-clip.yaml new file mode 100644 index 0000000000..1fdf50f529 --- /dev/null +++ b/gfx/wr/wrench/reftests/text/perspective-clip.yaml @@ -0,0 +1,27 @@ +--- +root: + items: + - + type: stacking-context + perspective: 1 + perspective-origin: 0 0 + items: + - + type: stacking-context + transform: 10 0 0 0 0 10 0 0 0 0 10 0 0 0 -9 1 + items: + - type: clip + bounds: [50, 50, 200, 200] + complex: + - rect: [50, 50, 200, 200] + radius: 8 + items: + - + type: rect + bounds: [50, 50, 200, 200] + color: green + - + text: "X" + origin: 100 150 + size: 100 + font: "Ahem.ttf" diff --git a/gfx/wr/wrench/reftests/text/raster-space-snap-ref.yaml b/gfx/wr/wrench/reftests/text/raster-space-snap-ref.yaml new file mode 100644 index 0000000000..43e4ccdf46 --- /dev/null +++ b/gfx/wr/wrench/reftests/text/raster-space-snap-ref.yaml @@ -0,0 +1,10 @@ +root: + items: + - type: stacking-context + bounds: [0, 0, 480, 80] + raster-space: screen + items: + - text: "a Bcd Efgh Ijklm Nopqrs Tuvwxyz" + origin: 20.5 50 + size: 20 + font: "FreeSans.ttf" diff --git a/gfx/wr/wrench/reftests/text/raster-space-snap.yaml b/gfx/wr/wrench/reftests/text/raster-space-snap.yaml new file mode 100644 index 0000000000..4ae3f8c99f --- /dev/null +++ b/gfx/wr/wrench/reftests/text/raster-space-snap.yaml @@ -0,0 +1,10 @@ +root: + items: + - type: stacking-context + bounds: [0, 0, 480, 80] + raster-space: local(1.0) + items: + - text: "a Bcd Efgh Ijklm Nopqrs Tuvwxyz" + origin: 20.5 50 + size: 20 + font: "FreeSans.ttf" diff --git a/gfx/wr/wrench/reftests/text/raster-space.png b/gfx/wr/wrench/reftests/text/raster-space.png Binary files differnew file mode 100644 index 0000000000..e6a1b38865 --- /dev/null +++ b/gfx/wr/wrench/reftests/text/raster-space.png diff --git a/gfx/wr/wrench/reftests/text/raster-space.yaml b/gfx/wr/wrench/reftests/text/raster-space.yaml new file mode 100644 index 0000000000..a4efba37fd --- /dev/null +++ b/gfx/wr/wrench/reftests/text/raster-space.yaml @@ -0,0 +1,29 @@ +root: + items: + - type: stacking-context + transform: scale(5.0) rotate(-45) + transform-origin: 300 300 + raster-space: local(1.0) + filters: [opacity(0.5)] + items: + - text: "Local" + origin: 20 50 + size: 20 + font: "FreeSans.ttf" + - type: stacking-context + transform: scale(5.0) rotate(-45) + transform-origin: 0 400 + items: + - text: "Screen" + origin: 20 50 + size: 20 + font: "FreeSans.ttf" + - type: stacking-context + transform: scale(5.0) rotate(-45) + transform-origin: -80 240 + raster-space: local(5.0) + items: + - text: "Local (scaled)" + origin: 20 50 + size: 10 + font: "FreeSans.ttf" diff --git a/gfx/wr/wrench/reftests/text/raster_root_C_8192.yaml b/gfx/wr/wrench/reftests/text/raster_root_C_8192.yaml new file mode 100644 index 0000000000..9d5b8e78df --- /dev/null +++ b/gfx/wr/wrench/reftests/text/raster_root_C_8192.yaml @@ -0,0 +1,385 @@ +root:
+ items:
+ - type: "stacking-context"
+ transform: scale(0.125)
+ items:
+ - type: "stacking-context"
+ perspective: 100
+ perspective-origin: 100 50
+ blend-container: true
+ items:
+ - image: checkerboard(0, 512, 16);
+ bounds: [1600, 1600, 8192, 8192]
+ - type: rect
+ color: [180, 140, 120, 0.4]
+ bounds: 2400 2400 8192 8192
+ - type: "stacking-context"
+ bounds: [0, 0, 8192, 8192]
+ filters: [invert(1)]
+ mix-blend-mode: exclusion
+ complex-clip:
+ rect: [1920, 1920, 4096, 4096]
+ radius: [2048, 2048]
+ items:
+ - type: "stacking-context"
+ transform: scale(24)
+ items:
+ - type: line
+ baseline: 16
+ start: 16
+ end: 208
+ width: 1
+ orientation: horizontal
+ color: black
+ style: solid
+ - type: line
+ baseline: 24
+ start: 16
+ end: 208
+ width: 1
+ orientation: horizontal
+ color: blue
+ style: dashed
+ - type: line
+ baseline: 32
+ start: 16
+ end: 208
+ width: 1
+ orientation: horizontal
+ color: green
+ style: dotted
+ - type: line
+ baseline: 40
+ start: 16
+ end: 208
+ width: 4
+ thickness: 1
+ orientation: horizontal
+ color: red
+ style: wavy
+ - type: line
+ baseline: 48
+ start: 16
+ end: 208
+ width: 2
+ orientation: horizontal
+ color: black
+ style: solid
+ - type: line
+ baseline: 64
+ start: 16
+ end: 208
+ width: 2
+ orientation: horizontal
+ color: blue
+ style: dashed
+ - type: line
+ baseline: 80
+ start: 16
+ end: 207 # pruposefully cut off
+ width: 2
+ orientation: horizontal
+ color: green
+ style: dotted
+ - type: line
+ baseline: 96
+ start: 16
+ end: 208
+ width: 6
+ thickness: 2
+ orientation: horizontal
+ color: red
+ style: wavy
+
+ -
+ type: "shadow"
+ bounds: [8, 100, 225, 50]
+ blur-radius: 0
+ offset: [2, 2]
+ color: red
+ - type: line
+ baseline: 112
+ start: 16
+ end: 208
+ width: 1
+ orientation: horizontal
+ color: [0,0,0,0]
+ style: solid
+ - type: line
+ baseline: 120
+ start: 16
+ end: 208
+ width: 1
+ orientation: horizontal
+ color: [0,0,0,0]
+ style: dashed
+ - type: line
+ baseline: 128
+ start: 16
+ end: 209
+ width: 1
+ orientation: horizontal
+ color: [0,0,0,0]
+ style: dotted
+ - type: line
+ baseline: 136
+ start: 16
+ end: 208
+ width: 4
+ thickness: 1
+ orientation: horizontal
+ color: [0,0,0,0]
+ style: wavy
+ -
+ type: pop-all-shadows
+
+ -
+ type: "shadow"
+ bounds: [8, 145, 225, 65]
+ blur-radius: 1
+ offset: [2, 3]
+ color: red
+ - type: line
+ baseline: 160
+ start: 16
+ end: 208
+ width: 2
+ orientation: horizontal
+ color: black
+ style: solid
+ - type: line
+ baseline: 168
+ start: 16
+ end: 208
+ width: 2
+ orientation: horizontal
+ color: blue
+ style: dashed
+ - type: line
+ baseline: 184
+ start: 16
+ end: 207 # purposefully cut off
+ width: 2
+ orientation: horizontal
+ color: green
+ style: dotted
+ - type: line
+ baseline: 192
+ start: 16
+ end: 208
+ width: 6
+ thickness: 2
+ orientation: horizontal
+ color: red
+ style: wavy
+ -
+ type: pop-all-shadows
+
+ -
+ type: "shadow"
+ bounds: [8, 220, 225, 40]
+ blur-radius: 0
+ offset: [5, 7]
+ color: red
+ - type: line
+ baseline: 232
+ start: 16
+ end: 208
+ width: 8
+ orientation: horizontal
+ color: black
+ style: solid
+ - type: line
+ baseline: 248
+ start: 16
+ end: 208
+ width: 8
+ orientation: horizontal
+ color: blue
+ style: dashed
+ - type: line
+ baseline: 272
+ start: 16
+ end: 205 # purposefully cut off
+ width: 8
+ orientation: horizontal
+ color: green
+ style: dotted
+ - type: line
+ baseline: 296
+ start: 16
+ end: 208
+ width: 12
+ thickness: 3
+ orientation: horizontal
+ color: black
+ style: wavy
+ -
+ type: "pop-all-shadows"
+
+ -
+ type: "shadow"
+ bounds: [0, 320, 240, 140]
+ blur-radius: 3
+ offset: [5, 7]
+ color: red
+ - type: line
+ baseline: 320
+ start: 16
+ end: 208
+ width: 8
+ orientation: horizontal
+ color: black
+ style: solid
+ - type: line
+ baseline: 352
+ start: 16
+ end: 208
+ width: 8
+ orientation: horizontal
+ color: blue
+ style: dashed
+ - type: line
+ baseline: 368
+ start: 16
+ end: 205 # purposefully cut off
+ width: 8
+ orientation: horizontal
+ color: green
+ style: dotted
+ - type: line
+ baseline: 392
+ start: 16
+ end: 208
+ width: 16
+ thickness: 4
+ orientation: horizontal
+ color: black
+ style: wavy
+ -
+ type: "pop-all-shadows"
+
+ - type: line
+ baseline: 224
+ start: 16
+ end: 208
+ width: 1
+ orientation: vertical
+ color: black
+ style: solid
+ - type: line
+ baseline: 232
+ start: 16
+ end: 208
+ width: 1
+ orientation: vertical
+ color: blue
+ style: dashed
+ - type: line
+ baseline: 240
+ start: 16
+ end: 208
+ width: 1
+ orientation: vertical
+ color: green
+ style: dotted
+ - type: line
+ baseline: 256
+ start: 16
+ end: 208
+ thickness: 1
+ width: 4
+ orientation: vertical
+ color: red
+ style: wavy
+
+ - type: line
+ baseline: 272
+ start: 16
+ end: 208
+ width: 2
+ orientation: vertical
+ color: black
+ style: solid
+ - type: line
+ baseline: 296
+ start: 16
+ end: 208
+ width: 2
+ orientation: vertical
+ color: blue
+ style: dashed
+ - type: line
+ baseline: 320
+ start: 16
+ end: 207 # purposefully cut off
+ width: 2
+ orientation: vertical
+ color: green
+ style: dotted
+ - type: line
+ baseline: 336
+ start: 16
+ end: 208
+ thickness: 2
+ width: 6
+ orientation: vertical
+ color: red
+ style: wavy
+
+ -
+ type: "shadow"
+ bounds: [350, 0, 120, 240]
+ blur-radius: 3
+ offset: [5, 2]
+ color: black
+ - type: line
+ baseline: 384
+ start: 16
+ end: 208
+ width: 8
+ orientation: vertical
+ color: yellow
+ style: solid
+ - type: line
+ baseline: 400
+ start: 16
+ end: 208
+ width: 8
+ orientation: vertical
+ color: blue
+ style: dashed
+ - type: line
+ baseline: 416
+ start: 16
+ end: 205 # purposefully cut off
+ width: 8
+ orientation: vertical
+ color: green
+ style: dotted
+ - type: line
+ baseline: 440
+ start: 16
+ end: 208
+ thickness: 4
+ width: 16
+ orientation: vertical
+ color: red
+ style: wavy
+ -
+ type: "pop-all-shadows"
+ - text: "side-left"
+ origin: 80 120
+ size: 32
+ transpose: true
+ flip-x: true
+ font: "VeraBd.ttf"
+ color: [40,40,40,1.0]
+ - text: "side-right"
+ origin: 240 240
+ size: 32
+ color: [190,180,200,1.0]
+ transpose: true
+ flip-y: true
+ font: "FreeSans.ttf"
+
diff --git a/gfx/wr/wrench/reftests/text/raster_root_C_ref.yaml b/gfx/wr/wrench/reftests/text/raster_root_C_ref.yaml new file mode 100644 index 0000000000..32358efe7a --- /dev/null +++ b/gfx/wr/wrench/reftests/text/raster_root_C_ref.yaml @@ -0,0 +1,385 @@ +root:
+ items:
+ - type: "stacking-context"
+ transform: scale(0.5)
+ items:
+ - type: "stacking-context"
+ perspective: 100
+ perspective-origin: 100 50
+ blend-container: true
+ items:
+ - image: checkerboard(0, 128, 16);
+ bounds: [400, 400, 2048, 2048]
+ - type: rect
+ color: [180, 140, 120, 0.4]
+ bounds: 600 600 2048 2048
+ - type: "stacking-context"
+ bounds: [0, 0, 2048, 2048]
+ filters: [invert(1)]
+ mix-blend-mode: exclusion
+ complex-clip:
+ rect: [480, 480, 1024, 1024]
+ radius: [512, 512]
+ items:
+ - type: "stacking-context"
+ transform: scale(6)
+ items:
+ - type: line
+ baseline: 16
+ start: 16
+ end: 208
+ width: 1
+ orientation: horizontal
+ color: black
+ style: solid
+ - type: line
+ baseline: 24
+ start: 16
+ end: 208
+ width: 1
+ orientation: horizontal
+ color: blue
+ style: dashed
+ - type: line
+ baseline: 32
+ start: 16
+ end: 208
+ width: 1
+ orientation: horizontal
+ color: green
+ style: dotted
+ - type: line
+ baseline: 40
+ start: 16
+ end: 208
+ width: 4
+ thickness: 1
+ orientation: horizontal
+ color: red
+ style: wavy
+ - type: line
+ baseline: 48
+ start: 16
+ end: 208
+ width: 2
+ orientation: horizontal
+ color: black
+ style: solid
+ - type: line
+ baseline: 64
+ start: 16
+ end: 208
+ width: 2
+ orientation: horizontal
+ color: blue
+ style: dashed
+ - type: line
+ baseline: 80
+ start: 16
+ end: 207 # pruposefully cut off
+ width: 2
+ orientation: horizontal
+ color: green
+ style: dotted
+ - type: line
+ baseline: 96
+ start: 16
+ end: 208
+ width: 6
+ thickness: 2
+ orientation: horizontal
+ color: red
+ style: wavy
+
+ -
+ type: "shadow"
+ bounds: [8, 100, 225, 50]
+ blur-radius: 0
+ offset: [2, 2]
+ color: red
+ - type: line
+ baseline: 112
+ start: 16
+ end: 208
+ width: 1
+ orientation: horizontal
+ color: [0,0,0,0]
+ style: solid
+ - type: line
+ baseline: 120
+ start: 16
+ end: 208
+ width: 1
+ orientation: horizontal
+ color: [0,0,0,0]
+ style: dashed
+ - type: line
+ baseline: 128
+ start: 16
+ end: 209
+ width: 1
+ orientation: horizontal
+ color: [0,0,0,0]
+ style: dotted
+ - type: line
+ baseline: 136
+ start: 16
+ end: 208
+ width: 4
+ thickness: 1
+ orientation: horizontal
+ color: [0,0,0,0]
+ style: wavy
+ -
+ type: pop-all-shadows
+
+ -
+ type: "shadow"
+ bounds: [8, 145, 225, 65]
+ blur-radius: 1
+ offset: [2, 3]
+ color: red
+ - type: line
+ baseline: 160
+ start: 16
+ end: 208
+ width: 2
+ orientation: horizontal
+ color: black
+ style: solid
+ - type: line
+ baseline: 168
+ start: 16
+ end: 208
+ width: 2
+ orientation: horizontal
+ color: blue
+ style: dashed
+ - type: line
+ baseline: 184
+ start: 16
+ end: 207 # purposefully cut off
+ width: 2
+ orientation: horizontal
+ color: green
+ style: dotted
+ - type: line
+ baseline: 192
+ start: 16
+ end: 208
+ width: 6
+ thickness: 2
+ orientation: horizontal
+ color: red
+ style: wavy
+ -
+ type: pop-all-shadows
+
+ -
+ type: "shadow"
+ bounds: [8, 220, 225, 40]
+ blur-radius: 0
+ offset: [5, 7]
+ color: red
+ - type: line
+ baseline: 232
+ start: 16
+ end: 208
+ width: 8
+ orientation: horizontal
+ color: black
+ style: solid
+ - type: line
+ baseline: 248
+ start: 16
+ end: 208
+ width: 8
+ orientation: horizontal
+ color: blue
+ style: dashed
+ - type: line
+ baseline: 272
+ start: 16
+ end: 205 # purposefully cut off
+ width: 8
+ orientation: horizontal
+ color: green
+ style: dotted
+ - type: line
+ baseline: 296
+ start: 16
+ end: 208
+ width: 12
+ thickness: 3
+ orientation: horizontal
+ color: black
+ style: wavy
+ -
+ type: "pop-all-shadows"
+
+ -
+ type: "shadow"
+ bounds: [0, 320, 240, 140]
+ blur-radius: 3
+ offset: [5, 7]
+ color: red
+ - type: line
+ baseline: 320
+ start: 16
+ end: 208
+ width: 8
+ orientation: horizontal
+ color: black
+ style: solid
+ - type: line
+ baseline: 352
+ start: 16
+ end: 208
+ width: 8
+ orientation: horizontal
+ color: blue
+ style: dashed
+ - type: line
+ baseline: 368
+ start: 16
+ end: 205 # purposefully cut off
+ width: 8
+ orientation: horizontal
+ color: green
+ style: dotted
+ - type: line
+ baseline: 392
+ start: 16
+ end: 208
+ width: 16
+ thickness: 4
+ orientation: horizontal
+ color: black
+ style: wavy
+ -
+ type: "pop-all-shadows"
+
+ - type: line
+ baseline: 224
+ start: 16
+ end: 208
+ width: 1
+ orientation: vertical
+ color: black
+ style: solid
+ - type: line
+ baseline: 232
+ start: 16
+ end: 208
+ width: 1
+ orientation: vertical
+ color: blue
+ style: dashed
+ - type: line
+ baseline: 240
+ start: 16
+ end: 208
+ width: 1
+ orientation: vertical
+ color: green
+ style: dotted
+ - type: line
+ baseline: 256
+ start: 16
+ end: 208
+ thickness: 1
+ width: 4
+ orientation: vertical
+ color: red
+ style: wavy
+
+ - type: line
+ baseline: 272
+ start: 16
+ end: 208
+ width: 2
+ orientation: vertical
+ color: black
+ style: solid
+ - type: line
+ baseline: 296
+ start: 16
+ end: 208
+ width: 2
+ orientation: vertical
+ color: blue
+ style: dashed
+ - type: line
+ baseline: 320
+ start: 16
+ end: 207 # purposefully cut off
+ width: 2
+ orientation: vertical
+ color: green
+ style: dotted
+ - type: line
+ baseline: 336
+ start: 16
+ end: 208
+ thickness: 2
+ width: 6
+ orientation: vertical
+ color: red
+ style: wavy
+
+ -
+ type: "shadow"
+ bounds: [350, 0, 120, 240]
+ blur-radius: 3
+ offset: [5, 2]
+ color: black
+ - type: line
+ baseline: 384
+ start: 16
+ end: 208
+ width: 8
+ orientation: vertical
+ color: yellow
+ style: solid
+ - type: line
+ baseline: 400
+ start: 16
+ end: 208
+ width: 8
+ orientation: vertical
+ color: blue
+ style: dashed
+ - type: line
+ baseline: 416
+ start: 16
+ end: 205 # purposefully cut off
+ width: 8
+ orientation: vertical
+ color: green
+ style: dotted
+ - type: line
+ baseline: 440
+ start: 16
+ end: 208
+ thickness: 4
+ width: 16
+ orientation: vertical
+ color: red
+ style: wavy
+ -
+ type: "pop-all-shadows"
+ - text: "side-left"
+ origin: 80 120
+ size: 32
+ transpose: true
+ flip-x: true
+ font: "VeraBd.ttf"
+ color: [40,40,40,1.0]
+ - text: "side-right"
+ origin: 240 240
+ size: 32
+ color: [190,180,200,1.0]
+ transpose: true
+ flip-y: true
+ font: "FreeSans.ttf"
+
diff --git a/gfx/wr/wrench/reftests/text/reftest.list b/gfx/wr/wrench/reftests/text/reftest.list new file mode 100644 index 0000000000..579b4e8928 --- /dev/null +++ b/gfx/wr/wrench/reftests/text/reftest.list @@ -0,0 +1,84 @@ +!= text.yaml blank.yaml +!= long-text.yaml blank.yaml +!= negative-pos.yaml blank.yaml +!= shadow.yaml text.yaml +!= shadow-single.yaml blank.yaml +!= shadow-cover-1.yaml blank.yaml +!= shadow-cover-2.yaml blank.yaml + +skip_on(android,device) fuzzy(1,3) == shadow.yaml shadow-ref.yaml # Fails on Pixel2 +fuzzy(1,1) == shadow-huge.yaml shadow-huge-ref.yaml +!= shadow-cover-1.yaml shadow-cover-2.yaml +!= shadow-many.yaml shadow.yaml +!= shadow-complex.yaml shadow-many.yaml +!= shadow-clipped-text.yaml blank.yaml +!= non-opaque.yaml non-opaque-notref.yaml +== decorations.yaml decorations-ref.yaml +skip_on(android,device) fuzzy(1,3010) fuzzy-if(platform(swgl),3,14624) == decorations-suite.yaml decorations-suite.png # Fails on Pixel2 +== 1658.yaml 1658-ref.yaml +fuzzy(2,405) == split-batch.yaml split-batch-ref.yaml +# Next 3 tests affected by bug 1548099 on Android +skip_on(android) == shadow-red.yaml shadow-red-ref.yaml +skip_on(android) fuzzy(1,999) fuzzy-if(platform(swgl),2,1081) == shadow-grey.yaml shadow-grey-ref.yaml +skip_on(android) fuzzy(1,828) fuzzy-if(platform(swgl),1,1249) == shadow-grey-transparent.yaml shadow-grey-ref.yaml +== subtle-shadow.yaml subtle-shadow-ref.yaml +fuzzy(1,64) == shadow-atomic.yaml shadow-atomic-ref.yaml +fuzzy(1,64) == shadow-clip-rect.yaml shadow-atomic-ref.yaml +fuzzy(1,1) platform(linux) == shadow-ordering.yaml shadow-ordering-ref.yaml +# Next 6 tests affected by bug 1548099 on Android +skip_on(android) != synthetic-bold.yaml synthetic-bold-not-ref.yaml +skip_on(android) fuzzy(1,1786) options(disable-subpixel) == synthetic-bold-transparent.yaml synthetic-bold-transparent-ref.yaml +skip_on(android) != synthetic-bold-transparent.yaml synthetic-bold.yaml +skip_on(android) != synthetic-italics.yaml synthetic-italics-ref.yaml +skip_on(android) != synthetic-italics-custom.yaml synthetic-italics-ref.yaml +skip_on(android) != synthetic-italics-custom.yaml synthetic-italics.yaml +options(disable-aa) == ahem.yaml ahem-ref.yaml +platform(linux) == isolated-text.yaml isolated-text.png +platform(mac) skip_on(mac,>=10.14) fuzzy(3,67) == white-opacity.yaml white-opacity.png +fuzzy(1,113) platform(linux) options(disable-subpixel) == colors.yaml colors-alpha.png +# Run without dual-source blending path, batches are broken when text colors change. +fuzzy(1,1256) platform(linux) options(disable-dual-source-blending) draw_calls(6) == colors.yaml colors-subpx.png +# Run with both dual-source blending, ensuring batching is improved. +fuzzy(1,774) platform(linux) draw_calls(3) == colors.yaml colors-subpx.png +platform(linux) options(disable-subpixel) == border-radius.yaml border-radius-alpha.png +platform(linux) == border-radius.yaml border-radius-subpx.png +options(disable-aa) == transparent-no-aa.yaml transparent-no-aa-ref.yaml +!= diacritics.yaml diacritics-ref.yaml +fuzzy(1,1) platform(linux) options(disable-subpixel) == text-masking.yaml text-masking-alpha.png +fuzzy(1,44) platform(linux) == text-masking.yaml text-masking-subpx.png +fuzzy(1,30) platform(linux) options(disable-subpixel) == alpha-transform.yaml alpha-transform.png +fuzzy(1,20) platform(linux) == subpixel-rotate.yaml subpixel-rotate.png +fuzzy(1,72) platform(linux) == subpixel-scale.yaml subpixel-scale.png +fuzzy(1,26) platform(linux) == subpixel-skew.yaml subpixel-skew.png +fuzzy(1,381) platform(linux) == subpixel-translate.yaml subpixel-translate-ref.yaml +!= shadow-rotate.yaml blank.yaml +platform(linux) == embedded-bitmaps.yaml embedded-bitmaps.png +fuzzy(1,13) platform(linux) == clipped-transform.yaml clipped-transform.png +platform(mac) fuzzy(195,30) == color-bitmap-shadow.yaml color-bitmap-shadow-ref.yaml +platform(linux) == writing-modes.yaml writing-modes-ref.yaml +fuzzy(1,5) platform(linux) == blurred-shadow-local-clip-rect.yaml blurred-shadow-local-clip-rect-ref.png +fuzzy(1,1) platform(linux) == two-shadows.yaml two-shadows.png +== shadow-clip.yaml shadow-clip-ref.yaml +== shadow-fast-clip.yaml shadow-fast-clip-ref.yaml +skip_on(android,device) == shadow-partial-glyph.yaml shadow-partial-glyph-ref.yaml # Fails on Pixel2 +fuzzy(2,212) platform(linux) == shadow-transforms.yaml shadow-transforms.png +fuzzy(2,370) platform(linux) == raster-space.yaml raster-space.png +skip_on(android) skip_on(mac,>=10.14) != allow-subpixel.yaml allow-subpixel-ref.yaml # Android: we don't enable sub-px aa on this platform. +skip_on(android,device) == bg-color.yaml bg-color-ref.yaml # Fails on Pixel2 +!= large-glyphs.yaml blank.yaml +!= large-line-decoration.yaml blank.yaml +skip_on(android,device) == snap-text-offset.yaml snap-text-offset-ref.yaml +fuzzy(5,4435) == shadow-border.yaml shadow-solid-ref.yaml +fuzzy(5,4435) == shadow-image.yaml shadow-solid-ref.yaml +options(disable-aa) == snap-clip.yaml snap-clip-ref.yaml +platform(linux) == perspective-clip.yaml perspective-clip.png +fuzzy(1,150) options(disable-subpixel) == raster-space-snap.yaml raster-space-snap-ref.yaml +# == intermediate-transform.yaml intermediate-transform-ref.yaml # fails because of AA inavailable with an intermediate surface +fuzzy(1,15) platform(linux) force_subpixel_aa_where_possible(true) == text-fixed-slice.yaml text-fixed-slice-slow.png +fuzzy(1,15) platform(linux) force_subpixel_aa_where_possible(false) == text-fixed-slice.yaml text-fixed-slice-fast.png + +# a 8544x8544 raster root vs. 2136x2136 +# most pixels are off by a small amount, but a few pixels on the edge vary by a lot, pushing up the fuzzy max-diff; +# the main goal of the test is that everything is in the same place, at the same scale, clipped the same way, +# despite 4x on-the-fly scale change. +skip_on(android) fuzzy-range(<=3,*21700,<=20,*3500,<=115,*543) fuzzy-if(platform(swgl),103,24907) == raster_root_C_8192.yaml raster_root_C_ref.yaml diff --git a/gfx/wr/wrench/reftests/text/shadow-atomic-ref.yaml b/gfx/wr/wrench/reftests/text/shadow-atomic-ref.yaml new file mode 100644 index 0000000000..ccf159b5a7 --- /dev/null +++ b/gfx/wr/wrench/reftests/text/shadow-atomic-ref.yaml @@ -0,0 +1,81 @@ +--- +root: + items: +# equivalent of shadow with [20, 16] offset + - + type: line + baseline: 61 + start: 34 + end: 230 + width: 3 + orientation: horizontal + color: green + style: solid + - + bounds: [34, 34, 205, 35] + glyphs: [55, 75, 76, 86, 3, 76, 86, 3, 87, 75, 72, 3, 69, 72, 86, 87] + offsets: [36, 59, 55.533333, 59, 71.533333, 59, 80.4, 59, 92.833336, 59, 100.833336, 59, 109.7, 59, 122.13333, 59, 130.13333, 59, 139, 59, 155, 59, 169.2, 59, 177.2, 59, 193.2, 59, 207.4, 59, 216.26666, 59] + size: 18 + color: green + font: "VeraBd.ttf" + - + type: line + baseline: 48 + start: 34 + end: 230 + width: 3 + orientation: horizontal + color: green + style: solid +# equivalent of shadow with [10, 8] offset + - + type: line + baseline: 53 + start: 24 + end: 220 + width: 3 + orientation: horizontal + color: black + style: solid + - + bounds: [24, 26, 205, 35] + glyphs: [55, 75, 76, 86, 3, 76, 86, 3, 87, 75, 72, 3, 69, 72, 86, 87] + offsets: [26, 51, 45.533333, 51, 61.533333, 51, 70.4, 51, 82.833336, 51, 90.833336, 51, 99.7, 51, 112.13333, 51, 120.13333, 51, 129, 51, 145, 51, 159.2, 51, 167.2, 51, 183.2, 51, 197.4, 51, 206.26666, 51] + size: 18 + color: black + font: "VeraBd.ttf" + - + type: line + baseline: 40 + start: 24 + end: 220 + width: 3 + orientation: horizontal + color: black + style: solid +# same as shadow-atomic.yaml + - + type: line + baseline: 45 + start: 14 + end: 210 + width: 3 + orientation: horizontal + color: red + style: solid + - + bounds: [14, 18, 205, 35] + glyphs: [55, 75, 76, 86, 3, 76, 86, 3, 87, 75, 72, 3, 69, 72, 86, 87] + offsets: [16, 43, 35.533333, 43, 51.533333, 43, 60.4, 43, 72.833336, 43, 80.833336, 43, 89.7, 43, 102.13333, 43, 110.13333, 43, 119, 43, 135, 43, 149.2, 43, 157.2, 43, 173.2, 43, 187.4, 43, 196.26666, 43] + size: 18 + color: red + font: "VeraBd.ttf" + - + type: line + baseline: 32 + start: 14 + end: 210 + width: 3 + orientation: horizontal + color: red + style: solid diff --git a/gfx/wr/wrench/reftests/text/shadow-atomic.yaml b/gfx/wr/wrench/reftests/text/shadow-atomic.yaml new file mode 100644 index 0000000000..21b9eac876 --- /dev/null +++ b/gfx/wr/wrench/reftests/text/shadow-atomic.yaml @@ -0,0 +1,42 @@ +--- # checks that decorations on "real" content and "shadow" content are on seperate, atomic, layers +root: + items: + - + type: "shadow" + bounds: [14, 18, 205, 35] + blur-radius: 0 + offset: [20, 16] + color: green + - + type: "shadow" + bounds: [14, 18, 205, 35] + blur-radius: 0 + offset: [10, 8] + color: black + - + type: line + baseline: 45 + start: 14 + end: 210 + width: 3 + orientation: horizontal + color: red + style: solid + - + bounds: [14, 18, 205, 35] + glyphs: [55, 75, 76, 86, 3, 76, 86, 3, 87, 75, 72, 3, 69, 72, 86, 87] + offsets: [16, 43, 35.533333, 43, 51.533333, 43, 60.4, 43, 72.833336, 43, 80.833336, 43, 89.7, 43, 102.13333, 43, 110.13333, 43, 119, 43, 135, 43, 149.2, 43, 157.2, 43, 173.2, 43, 187.4, 43, 196.26666, 43] + size: 18 + color: red + font: "VeraBd.ttf" + - + type: line + baseline: 32 + start: 14 + end: 210 + width: 3 + orientation: horizontal + color: red + style: solid + - + type: "pop-all-shadows" diff --git a/gfx/wr/wrench/reftests/text/shadow-border.yaml b/gfx/wr/wrench/reftests/text/shadow-border.yaml new file mode 100644 index 0000000000..b05fb88cb5 --- /dev/null +++ b/gfx/wr/wrench/reftests/text/shadow-border.yaml @@ -0,0 +1,19 @@ +--- +root: + items: + - + type: "shadow" + blur-radius: 25 + bounds: [0, 0, 90, 90] + offset: [0, 0] + color: [0, 0, 0, 0.8] + - + type: border + bounds: [ 30, 30, 30, 30 ] + width: [ 15, 15, 15, 15 ] + border-type: normal + style: solid + color: blue + radius: 0 + - + type: "pop-all-shadows" diff --git a/gfx/wr/wrench/reftests/text/shadow-clip-rect.yaml b/gfx/wr/wrench/reftests/text/shadow-clip-rect.yaml new file mode 100644 index 0000000000..6edf6ccb5a --- /dev/null +++ b/gfx/wr/wrench/reftests/text/shadow-clip-rect.yaml @@ -0,0 +1,45 @@ +--- # checks that decorations on "real" content and "shadow" content are on seperate, atomic, layers +root: + items: + - + type: "shadow" + bounds: [14, 18, 205, 35] + blur-radius: 0 + offset: [20, 16] + color: green + - + type: "shadow" + bounds: [14, 18, 205, 35] + blur-radius: 0 + offset: [10, 8] + color: black + - + type: line + clip-rect: [14, 18, 205, 35] + baseline: 45 + start: 14 + end: 210 + width: 3 + orientation: horizontal + color: red + style: solid + - + bounds: [14, 18, 205, 35] + clip-rect: [14, 18, 205, 35] + glyphs: [55, 75, 76, 86, 3, 76, 86, 3, 87, 75, 72, 3, 69, 72, 86, 87] + offsets: [16, 43, 35.533333, 43, 51.533333, 43, 60.4, 43, 72.833336, 43, 80.833336, 43, 89.7, 43, 102.13333, 43, 110.13333, 43, 119, 43, 135, 43, 149.2, 43, 157.2, 43, 173.2, 43, 187.4, 43, 196.26666, 43] + size: 18 + color: red + font: "VeraBd.ttf" + - + type: line + clip-rect: [14, 18, 205, 35] + baseline: 32 + start: 14 + end: 210 + width: 3 + orientation: horizontal + color: red + style: solid + - + type: "pop-all-shadows" diff --git a/gfx/wr/wrench/reftests/text/shadow-clip-ref.yaml b/gfx/wr/wrench/reftests/text/shadow-clip-ref.yaml new file mode 100644 index 0000000000..ff57bfde63 --- /dev/null +++ b/gfx/wr/wrench/reftests/text/shadow-clip-ref.yaml @@ -0,0 +1,11 @@ +# Test that the clip-chain local rect is not applied +# to the text run being drawn in the shadow. If it was +# applied, the edges of the quad will be a slightly +# different color, since the blur will include some +# clipped out pixels. +--- +root: + items: + - type: rect + bounds: [28, 28, 80, 80] + color: [255, 127, 127, 1] diff --git a/gfx/wr/wrench/reftests/text/shadow-clip.yaml b/gfx/wr/wrench/reftests/text/shadow-clip.yaml new file mode 100644 index 0000000000..ecfade06dc --- /dev/null +++ b/gfx/wr/wrench/reftests/text/shadow-clip.yaml @@ -0,0 +1,25 @@ +# Test that the clip-chain local rect is not applied +# to the text run being drawn in the shadow. If it was +# applied, the edges of the quad will be a slightly +# different color, since the blur will include some +# clipped out pixels. +--- +root: + items: + - type: clip + bounds: [28, 28, 80, 80] + items: + - + type: "shadow" + bounds: [0, 0, 200, 200] + blur-radius: 2 + color: [255, 0, 0, 0.5] + - + bounds: [6, 6, 132, 133] + glyphs: [67] + offsets: [8, 111] + size: 128 + color: [0, 0, 0, 0] + font: "Ahem.ttf" + - + type: "pop-all-shadows" diff --git a/gfx/wr/wrench/reftests/text/shadow-clipped-text.yaml b/gfx/wr/wrench/reftests/text/shadow-clipped-text.yaml new file mode 100644 index 0000000000..9ab01d0a3f --- /dev/null +++ b/gfx/wr/wrench/reftests/text/shadow-clipped-text.yaml @@ -0,0 +1,24 @@ +# Tests that the unclipped parts of a shadow still render even if the associated +# text is clipped out. +--- +root: + items: + - type: scroll-frame + bounds: [14, 18, 10, 5] + content-size: [10, 5] + items: + - + type: "shadow" + bounds: [11, 20, 100, 100] + blur-radius: 3 + offset: [0, 0] + color: black + - + bounds: [14, 23, 100, 100] + glyphs: [55] + offsets: [16, 43] + size: 18 + color: black + font: "VeraBd.ttf" + - + type: "pop-all-shadows" diff --git a/gfx/wr/wrench/reftests/text/shadow-complex.yaml b/gfx/wr/wrench/reftests/text/shadow-complex.yaml new file mode 100644 index 0000000000..e1bfbc1b3a --- /dev/null +++ b/gfx/wr/wrench/reftests/text/shadow-complex.yaml @@ -0,0 +1,46 @@ +--- # The same as shadow-many.yaml, except the shadows only apply to parts of the text +root: + items: + - + type: "shadow" + bounds: [14, 18, 205, 35] + blur-radius: 5 + offset: [0, 0] + color: black + - + type: "shadow" + bounds: [14, 18, 205, 35] + blur-radius: 0 + offset: [2, 3] + color: red + - + bounds: [14, 18, 205, 35] + glyphs: [55, 75, 76, 86] + offsets: [16, 43, 35.533333, 43, 51.533333, 43, 60.4, 43] + size: 18 + color: [0, 0, 0, 0] # actual text is transparent + font: "VeraBd.ttf" + - + type: "pop-all-shadows" + - + type: "shadow" + bounds: [14, 18, 205, 35] + blur-radius: 3 + offset: [-2, 3.5] + color: blue + - + bounds: [14, 18, 205, 35] + glyphs: [3, 76, 86, 3, 87, 75] + offsets: [72.833336, 43, 80.833336, 43, 89.7, 43, 102.13333, 43, 110.13333, 43, 119, 43] + size: 18 + color: [0, 0, 0, 0] # actual text is transparent + font: "VeraBd.ttf" + - + bounds: [14, 18, 205, 35] + glyphs: [72, 3, 69, 72, 86, 87] + offsets: [135, 43, 149.2, 43, 157.2, 43, 173.2, 43, 187.4, 43, 196.26666, 43] + size: 18 + color: [0, 0, 0, 0] # actual text is transparent + font: "VeraBd.ttf" + - + type: "pop-all-shadows" diff --git a/gfx/wr/wrench/reftests/text/shadow-cover-1.yaml b/gfx/wr/wrench/reftests/text/shadow-cover-1.yaml new file mode 100644 index 0000000000..088c26f1c5 --- /dev/null +++ b/gfx/wr/wrench/reftests/text/shadow-cover-1.yaml @@ -0,0 +1,18 @@ +--- # text covering a shadow +root: + items: + - + type: "shadow" + bounds: [14, 18, 205, 35] + blur-radius: 3 + offset: [0, 0] + color: red + - + bounds: [14, 18, 205, 35] + glyphs: [55, 75, 76, 86, 3, 76, 86, 3, 87, 75, 72, 3, 69, 72, 86, 87] + offsets: [16, 43, 35.533333, 43, 51.533333, 43, 60.4, 43, 72.833336, 43, 80.833336, 43, 89.7, 43, 102.13333, 43, 110.13333, 43, 119, 43, 135, 43, 149.2, 43, 157.2, 43, 173.2, 43, 187.4, 43, 196.26666, 43] + size: 18 + color: green + font: "VeraBd.ttf" + - + type: "pop-all-shadows" diff --git a/gfx/wr/wrench/reftests/text/shadow-cover-2.yaml b/gfx/wr/wrench/reftests/text/shadow-cover-2.yaml new file mode 100644 index 0000000000..c18e277340 --- /dev/null +++ b/gfx/wr/wrench/reftests/text/shadow-cover-2.yaml @@ -0,0 +1,26 @@ +--- # shadow covering text +root: + items: + - + bounds: [14, 18, 205, 35] + glyphs: [55, 75, 76, 86, 3, 76, 86, 3, 87, 75, 72, 3, 69, 72, 86, 87] + offsets: [16, 43, 35.533333, 43, 51.533333, 43, 60.4, 43, 72.833336, 43, 80.833336, 43, 89.7, 43, 102.13333, 43, 110.13333, 43, 119, 43, 135, 43, 149.2, 43, 157.2, 43, 173.2, 43, 187.4, 43, 196.26666, 43] + size: 18 + color: green + font: "VeraBd.ttf" + - + type: "shadow" + bounds: [14, 18, 205, 35] + blur-radius: 3 + offset: [0, 0] + color: red + - + bounds: [14, 18, 205, 35] + glyphs: [55, 75, 76, 86, 3, 76, 86, 3, 87, 75, 72, 3, 69, 72, 86, 87] + offsets: [16, 43, 35.533333, 43, 51.533333, 43, 60.4, 43, 72.833336, 43, 80.833336, 43, 89.7, 43, 102.13333, 43, 110.13333, 43, 119, 43, 135, 43, 149.2, 43, 157.2, 43, 173.2, 43, 187.4, 43, 196.26666, 43] + size: 18 + color: [0, 0, 0, 0] # text transparent + font: "VeraBd.ttf" + - + type: "pop-all-shadows" + diff --git a/gfx/wr/wrench/reftests/text/shadow-fast-clip-ref.yaml b/gfx/wr/wrench/reftests/text/shadow-fast-clip-ref.yaml new file mode 100644 index 0000000000..3e1b08de5f --- /dev/null +++ b/gfx/wr/wrench/reftests/text/shadow-fast-clip-ref.yaml @@ -0,0 +1,21 @@ +# Test that fast shadows actually apply clips +--- +root: + items: + - type: clip + bounds: [28, 28, 80, 80] + items: + - + bounds: [6, 6, 132, 133] + text: "overflow text" + origin: [9, 101] + size: 12 + color: [0, 0, 0, 1] + font: "VeraBd.ttf" + - + bounds: [6, 6, 132, 133] + text: "overflow text" + origin: [8, 100] + size: 12 + color: [255, 0, 0, 1] + font: "VeraBd.ttf" diff --git a/gfx/wr/wrench/reftests/text/shadow-fast-clip.yaml b/gfx/wr/wrench/reftests/text/shadow-fast-clip.yaml new file mode 100644 index 0000000000..f28213573c --- /dev/null +++ b/gfx/wr/wrench/reftests/text/shadow-fast-clip.yaml @@ -0,0 +1,22 @@ +# Test that fast shadows actually apply clips +--- +root: + items: + - type: clip + bounds: [28, 28, 80, 80] + items: + - + type: "shadow" + bounds: [0, 0, 200, 200] + blur-radius: 0 + offset: [1, 1] + color: [0, 0, 0, 1] + - + bounds: [6, 6, 132, 133] + text: "overflow text" + origin: [8, 100] + size: 12 + color: [255, 0, 0, 1] + font: "VeraBd.ttf" + - + type: "pop-all-shadows" diff --git a/gfx/wr/wrench/reftests/text/shadow-grey-ref.yaml b/gfx/wr/wrench/reftests/text/shadow-grey-ref.yaml new file mode 100644 index 0000000000..d40d997161 --- /dev/null +++ b/gfx/wr/wrench/reftests/text/shadow-grey-ref.yaml @@ -0,0 +1,6 @@ +--- +root: + items: + - rect: [14, 10, 205, 38] + color: [100, 100, 100, 1.0] + diff --git a/gfx/wr/wrench/reftests/text/shadow-grey-transparent.yaml b/gfx/wr/wrench/reftests/text/shadow-grey-transparent.yaml new file mode 100644 index 0000000000..ba54ede1e2 --- /dev/null +++ b/gfx/wr/wrench/reftests/text/shadow-grey-transparent.yaml @@ -0,0 +1,19 @@ +--- +root: + items: + - rect: [14, 10, 205, 38] + color: [100, 100, 100, 1.0] + - + type: "shadow" + blur-radius: 2 + color: [100, 100, 100, 0.2] + bounds: [14, 10, 205, 38] + - + bounds: [14, 18, 205, 35] + glyphs: [55, 75, 76, 86, 3, 76, 86, 3, 87, 75, 72, 3, 69, 72, 86, 87] + offsets: [16, 43, 35.533333, 43, 51.533333, 43, 60.4, 43, 72.833336, 43, 80.833336, 43, 89.7, 43, 102.13333, 43, 110.13333, 43, 119, 43, 135, 43, 149.2, 43, 157.2, 43, 173.2, 43, 187.4, 43, 196.26666, 43] + size: 24 + color: [0,0,0,0] + - + type: "pop-all-shadows" + diff --git a/gfx/wr/wrench/reftests/text/shadow-grey.yaml b/gfx/wr/wrench/reftests/text/shadow-grey.yaml new file mode 100644 index 0000000000..a728518ce3 --- /dev/null +++ b/gfx/wr/wrench/reftests/text/shadow-grey.yaml @@ -0,0 +1,19 @@ +--- +root: + items: + - rect: [14, 10, 205, 38] + color: [100, 100, 100, 1.0] + - + type: "shadow" + blur-radius: 2 + color: [100, 100, 100, 1.0] + bounds: [14, 10, 205, 38] + - + bounds: [14, 18, 205, 35] + glyphs: [55, 75, 76, 86, 3, 76, 86, 3, 87, 75, 72, 3, 69, 72, 86, 87] + offsets: [16, 43, 35.533333, 43, 51.533333, 43, 60.4, 43, 72.833336, 43, 80.833336, 43, 89.7, 43, 102.13333, 43, 110.13333, 43, 119, 43, 135, 43, 149.2, 43, 157.2, 43, 173.2, 43, 187.4, 43, 196.26666, 43] + size: 24 + color: [0,0,0,0] + - + type: "pop-all-shadows" + diff --git a/gfx/wr/wrench/reftests/text/shadow-huge-ref.yaml b/gfx/wr/wrench/reftests/text/shadow-huge-ref.yaml new file mode 100644 index 0000000000..c0f8332a9e --- /dev/null +++ b/gfx/wr/wrench/reftests/text/shadow-huge-ref.yaml @@ -0,0 +1,18 @@ +--- +root: + items: + - + type: "shadow" + bounds: [14, 18, 205, 35] + blur-radius: 600 + offset: [10, 10] + color: black + - + bounds: [14, 18, 205, 35] + glyphs: [55, 75, 76, 86, 3, 76, 86, 3, 87, 75, 72, 3, 69, 72, 86, 87] + offsets: [16, 43, 35.533333, 43, 51.533333, 43, 60.4, 43, 72.833336, 43, 80.833336, 43, 89.7, 43, 102.13333, 43, 110.13333, 43, 119, 43, 135, 43, 149.2, 43, 157.2, 43, 173.2, 43, 187.4, 43, 196.26666, 43] + size: 18 + color: [0, 0, 0, 1] + font: "VeraBd.ttf" + - + type: "pop-all-shadows" diff --git a/gfx/wr/wrench/reftests/text/shadow-huge.yaml b/gfx/wr/wrench/reftests/text/shadow-huge.yaml new file mode 100644 index 0000000000..1814dcf1df --- /dev/null +++ b/gfx/wr/wrench/reftests/text/shadow-huge.yaml @@ -0,0 +1,18 @@ +--- +root: + items: + - + type: "shadow" + bounds: [14, 18, 205, 35] + blur-radius: 100000000 + offset: [10, 10] + color: black + - + bounds: [14, 18, 205, 35] + glyphs: [55, 75, 76, 86, 3, 76, 86, 3, 87, 75, 72, 3, 69, 72, 86, 87] + offsets: [16, 43, 35.533333, 43, 51.533333, 43, 60.4, 43, 72.833336, 43, 80.833336, 43, 89.7, 43, 102.13333, 43, 110.13333, 43, 119, 43, 135, 43, 149.2, 43, 157.2, 43, 173.2, 43, 187.4, 43, 196.26666, 43] + size: 18 + color: [0, 0, 0, 1] + font: "VeraBd.ttf" + - + type: "pop-all-shadows" diff --git a/gfx/wr/wrench/reftests/text/shadow-image.yaml b/gfx/wr/wrench/reftests/text/shadow-image.yaml new file mode 100644 index 0000000000..4d472aadc4 --- /dev/null +++ b/gfx/wr/wrench/reftests/text/shadow-image.yaml @@ -0,0 +1,14 @@ +--- +root: + items: + - + type: "shadow" + blur-radius: 25 + bounds: [0, 0, 90, 90] + offset: [0, 0] + color: [0, 0, 0, 0.8] + - + bounds: [ 30, 30, 30, 30 ] + image: solid-color(0, 0, 255, 255, 30, 30) + - + type: "pop-all-shadows" diff --git a/gfx/wr/wrench/reftests/text/shadow-many.yaml b/gfx/wr/wrench/reftests/text/shadow-many.yaml new file mode 100644 index 0000000000..b5daabe669 --- /dev/null +++ b/gfx/wr/wrench/reftests/text/shadow-many.yaml @@ -0,0 +1,30 @@ +--- # the same as shadow.yaml, except there are many shadows with different offsets and colors +root: + items: + - + type: "shadow" + bounds: [14, 18, 205, 35] + blur-radius: 5 + offset: [0, 0] + color: black + - + type: "shadow" + bounds: [14, 18, 205, 35] + blur-radius: 0 + offset: [2, 3] + color: red + - + type: "shadow" + bounds: [14, 18, 205, 35] + blur-radius: 3 + offset: [-2, 3.5] + color: blue + - + bounds: [14, 18, 205, 35] + glyphs: [55, 75, 76, 86, 3, 76, 86, 3, 87, 75, 72, 3, 69, 72, 86, 87] + offsets: [16, 43, 35.533333, 43, 51.533333, 43, 60.4, 43, 72.833336, 43, 80.833336, 43, 89.7, 43, 102.13333, 43, 110.13333, 43, 119, 43, 135, 43, 149.2, 43, 157.2, 43, 173.2, 43, 187.4, 43, 196.26666, 43] + size: 18 + color: [0, 0, 0, 0] # actual text is transparent + font: "VeraBd.ttf" + - + type: "pop-all-shadows" diff --git a/gfx/wr/wrench/reftests/text/shadow-ordering-ref.yaml b/gfx/wr/wrench/reftests/text/shadow-ordering-ref.yaml new file mode 100644 index 0000000000..cc0b378cb0 --- /dev/null +++ b/gfx/wr/wrench/reftests/text/shadow-ordering-ref.yaml @@ -0,0 +1,131 @@ +--- # checks that decorations on "real" content and "shadow" content are on seperate, atomic, layers +root: + items: + - + type: "shadow" + bounds: [44, 42, 205, 35] + blur-radius: 1.0 + offset: [30, 24] + color: blue + - + type: line + baseline: 45 + start: 14 + end: 210 + width: 3 + orientation: horizontal + color: [0,0,0,0] # transparent + style: solid + - + bounds: [14, 18, 205, 35] + glyphs: [55, 75, 76, 86, 3, 76, 86, 3, 87, 75, 72, 3, 69, 72, 86, 87] + offsets: [16, 43, 35.533333, 43, 51.533333, 43, 60.4, 43, 72.833336, 43, 80.833336, 43, 89.7, 43, 102.13333, 43, 110.13333, 43, 119, 43, 135, 43, 149.2, 43, 157.2, 43, 173.2, 43, 187.4, 43, 196.26666, 43] + size: 18 + color: [0,0,0,0] # transparent + font: "VeraBd.ttf" + - + type: line + baseline: 32 + start: 14 + end: 210 + width: 3 + orientation: horizontal + color: [0,0,0,0] # transparent + style: solid + - + type: "pop-all-shadows" + + - + type: "shadow" + bounds: [34, 34, 205, 35] + blur-radius: 0.0 # no blur to tigger fast shadows + offset: [20, 16] + color: green + - + type: line + baseline: 45 + start: 14 + end: 210 + width: 3 + orientation: horizontal + color: [0,0,0,0] # transparent + style: solid + - + bounds: [14, 18, 205, 35] + glyphs: [55, 75, 76, 86, 3, 76, 86, 3, 87, 75, 72, 3, 69, 72, 86, 87] + offsets: [16, 43, 35.533333, 43, 51.533333, 43, 60.4, 43, 72.833336, 43, 80.833336, 43, 89.7, 43, 102.13333, 43, 110.13333, 43, 119, 43, 135, 43, 149.2, 43, 157.2, 43, 173.2, 43, 187.4, 43, 196.26666, 43] + size: 18 + color: [0,0,0,0] # transparent + font: "VeraBd.ttf" + - + type: line + baseline: 32 + start: 14 + end: 210 + width: 3 + orientation: horizontal + color: [0,0,0,0] # transparent + style: solid + - + type: "pop-all-shadows" + + - + type: "shadow" + bounds: [24, 26, 205, 35] + blur-radius: 1.0 + offset: [10, 8] + color: black + - + type: line + baseline: 45 + start: 14 + end: 210 + width: 3 + orientation: horizontal + color: [0,0,0,0] # transparent + style: solid + - + bounds: [14, 18, 205, 35] + glyphs: [55, 75, 76, 86, 3, 76, 86, 3, 87, 75, 72, 3, 69, 72, 86, 87] + offsets: [16, 43, 35.533333, 43, 51.533333, 43, 60.4, 43, 72.833336, 43, 80.833336, 43, 89.7, 43, 102.13333, 43, 110.13333, 43, 119, 43, 135, 43, 149.2, 43, 157.2, 43, 173.2, 43, 187.4, 43, 196.26666, 43] + size: 18 + color: [0,0,0,0] # transparent + font: "VeraBd.ttf" + - + type: line + baseline: 32 + start: 14 + end: 210 + width: 3 + orientation: horizontal + color: [0,0,0,0] # transparent + style: solid + - + type: "pop-all-shadows" + + # real text + - + type: line + baseline: 45 + start: 14 + end: 210 + width: 3 + orientation: horizontal + color: red + style: solid + - + bounds: [14, 18, 205, 35] + glyphs: [55, 75, 76, 86, 3, 76, 86, 3, 87, 75, 72, 3, 69, 72, 86, 87] + offsets: [16, 43, 35.533333, 43, 51.533333, 43, 60.4, 43, 72.833336, 43, 80.833336, 43, 89.7, 43, 102.13333, 43, 110.13333, 43, 119, 43, 135, 43, 149.2, 43, 157.2, 43, 173.2, 43, 187.4, 43, 196.26666, 43] + size: 18 + color: red + font: "VeraBd.ttf" + - + type: line + baseline: 32 + start: 14 + end: 210 + width: 3 + orientation: horizontal + color: red + style: solid diff --git a/gfx/wr/wrench/reftests/text/shadow-ordering.yaml b/gfx/wr/wrench/reftests/text/shadow-ordering.yaml new file mode 100644 index 0000000000..d1969ef09b --- /dev/null +++ b/gfx/wr/wrench/reftests/text/shadow-ordering.yaml @@ -0,0 +1,48 @@ +--- # checks that decorations on "real" content and "shadow" content are on seperate, atomic, layers +root: + items: + - + type: "shadow" + bounds: [44, 42, 205, 35] + blur-radius: 1.0 + offset: [30, 24] + color: blue + - + type: "shadow" + bounds: [34, 34, 205, 35] + blur-radius: 0.0 # no blur to tigger fast shadows + offset: [20, 16] + color: green + - + type: "shadow" + bounds: [24, 26, 205, 35] + blur-radius: 1.0 + offset: [10, 8] + color: black + - + type: line + baseline: 45 + start: 14 + end: 210 + width: 3 + orientation: horizontal + color: red + style: solid + - + bounds: [14, 18, 205, 35] + glyphs: [55, 75, 76, 86, 3, 76, 86, 3, 87, 75, 72, 3, 69, 72, 86, 87] + offsets: [16, 43, 35.533333, 43, 51.533333, 43, 60.4, 43, 72.833336, 43, 80.833336, 43, 89.7, 43, 102.13333, 43, 110.13333, 43, 119, 43, 135, 43, 149.2, 43, 157.2, 43, 173.2, 43, 187.4, 43, 196.26666, 43] + size: 18 + color: red + font: "VeraBd.ttf" + - + type: line + baseline: 32 + start: 14 + end: 210 + width: 3 + orientation: horizontal + color: red + style: solid + - + type: "pop-all-shadows" diff --git a/gfx/wr/wrench/reftests/text/shadow-partial-glyph-ref.yaml b/gfx/wr/wrench/reftests/text/shadow-partial-glyph-ref.yaml new file mode 100644 index 0000000000..e49ec68e97 --- /dev/null +++ b/gfx/wr/wrench/reftests/text/shadow-partial-glyph-ref.yaml @@ -0,0 +1,50 @@ +--- # taking the shadow of multiple copies of a glyph with different clips should look the same as the unclipped glyph
+root:
+ items:
+ -
+ type: "shadow"
+ blur-radius: 2
+ bounds: [14, 18, 205, 35]
+ offset: [40, 0]
+ color: black
+ -
+ bounds: [14, 18, 205, 35]
+ glyphs: [58]
+ offsets: [16, 43]
+ size: 18
+ color: [0, 0, 0, 0]
+ font: "VeraBd.ttf"
+ -
+ type: "pop-all-shadows"
+ -
+ bounds: [14, 18, 205, 35]
+ clip-rect: [16, 18, 14, 14]
+ glyphs: [58]
+ offsets: [16, 43]
+ size: 18
+ color: [255, 0, 0, 1]
+ font: "VeraBd.ttf"
+ -
+ bounds: [14, 18, 205, 35]
+ clip-rect: [30, 18, 14, 14]
+ glyphs: [58]
+ offsets: [16, 43]
+ size: 18
+ color: [0, 255, 0, 1]
+ font: "VeraBd.ttf"
+ -
+ bounds: [14, 18, 205, 35]
+ clip-rect: [16, 32, 14, 14]
+ glyphs: [58]
+ offsets: [16, 43]
+ size: 18
+ color: [0, 0, 255, 1]
+ font: "VeraBd.ttf"
+ -
+ bounds: [14, 18, 205, 35]
+ clip-rect: [30, 32, 14, 14]
+ glyphs: [58]
+ offsets: [16, 43]
+ size: 18
+ color: [255, 0, 255, 1]
+ font: "VeraBd.ttf"
\ No newline at end of file diff --git a/gfx/wr/wrench/reftests/text/shadow-partial-glyph.yaml b/gfx/wr/wrench/reftests/text/shadow-partial-glyph.yaml new file mode 100644 index 0000000000..ccf455d0f6 --- /dev/null +++ b/gfx/wr/wrench/reftests/text/shadow-partial-glyph.yaml @@ -0,0 +1,43 @@ +--- # taking the shadow of multiple copies of a glyph with different clips should look the same as the unclipped glyph
+root:
+ items:
+ -
+ type: "shadow"
+ blur-radius: 2
+ bounds: [14, 18, 205, 35]
+ offset: [40, 0]
+ color: black
+ -
+ bounds: [14, 18, 205, 35]
+ clip-rect: [16, 18, 14, 14]
+ glyphs: [58]
+ offsets: [16, 43]
+ size: 18
+ color: [255, 0, 0, 1]
+ font: "VeraBd.ttf"
+ -
+ bounds: [14, 18, 205, 35]
+ clip-rect: [30, 18, 14, 14]
+ glyphs: [58]
+ offsets: [16, 43]
+ size: 18
+ color: [0, 255, 0, 1]
+ font: "VeraBd.ttf"
+ -
+ bounds: [14, 18, 205, 35]
+ clip-rect: [16, 32, 14, 14]
+ glyphs: [58]
+ offsets: [16, 43]
+ size: 18
+ color: [0, 0, 255, 1]
+ font: "VeraBd.ttf"
+ -
+ bounds: [14, 18, 205, 35]
+ clip-rect: [30, 32, 14, 14]
+ glyphs: [58]
+ offsets: [16, 43]
+ size: 18
+ color: [255, 0, 255, 1]
+ font: "VeraBd.ttf"
+ -
+ type: "pop-all-shadows"
\ No newline at end of file diff --git a/gfx/wr/wrench/reftests/text/shadow-red-ref.yaml b/gfx/wr/wrench/reftests/text/shadow-red-ref.yaml new file mode 100644 index 0000000000..6c2f50fba0 --- /dev/null +++ b/gfx/wr/wrench/reftests/text/shadow-red-ref.yaml @@ -0,0 +1,5 @@ +--- +root: + items: + - rect: [14, 10, 205, 38] + color: red diff --git a/gfx/wr/wrench/reftests/text/shadow-red.yaml b/gfx/wr/wrench/reftests/text/shadow-red.yaml new file mode 100644 index 0000000000..62df9fc39c --- /dev/null +++ b/gfx/wr/wrench/reftests/text/shadow-red.yaml @@ -0,0 +1,19 @@ +--- +root: + items: + - rect: [14, 10, 205, 38] + color: red + - + type: "shadow" + blur-radius: 1 + color: red + bounds: [14, 10, 205, 38] + - + bounds: [14, 18, 205, 35] + glyphs: [55, 75, 76, 86, 3, 76, 86, 3, 87, 75, 72, 3, 69, 72, 86, 87] + offsets: [16, 43, 35.533333, 43, 51.533333, 43, 60.4, 43, 72.833336, 43, 80.833336, 43, 89.7, 43, 102.13333, 43, 110.13333, 43, 119, 43, 135, 43, 149.2, 43, 157.2, 43, 173.2, 43, 187.4, 43, 196.26666, 43] + size: 24 + color: [0,0,0,0] + - + type: "pop-all-shadows" + diff --git a/gfx/wr/wrench/reftests/text/shadow-ref.yaml b/gfx/wr/wrench/reftests/text/shadow-ref.yaml new file mode 100644 index 0000000000..efc8d2d9f0 --- /dev/null +++ b/gfx/wr/wrench/reftests/text/shadow-ref.yaml @@ -0,0 +1,25 @@ +--- +root: + items: + - # Compare non-blurred offset shadow to text with all glyphs offset that much + bounds: [16, 21, 205, 35] + glyphs: [55, 75, 76, 86, 3, 76, 86, 3, 87, 75, 72, 3, 69, 72, 86, 87] + offsets: [18, 46, 37.533333, 46, 53.533333, 46, 62.4, 46, 74.833336, 46, 82.833336, 46, 91.7, 46, 104.13333, 46, 112.13333, 46, 121, 46, 137, 46, 151.2, 46, 159.2, 46, 175.2, 46, 189.4, 46, 198.26666, 46] + size: 18 + color: black + font: "VeraBd.ttf" + - # Compare blurred offset shadow to shadow + type: "shadow" + bounds: [12, 314, 205, 35] + blur-radius: 5 + offset: [0, 0] + color: red + - + bounds: [14, 318, 205, 35] + glyphs: [55, 75, 76, 86, 3, 76, 86, 3, 87, 75, 72, 3, 69, 72, 86, 87] + offsets: [14, 339, 33.533333, 339, 49.533333, 339, 58.4, 339, 70.833336, 339, 78.833336, 339, 87.7, 339, 100.13333, 339, 108.13333, 339, 117, 339, 133, 339, 147.2, 339, 155.2, 339, 171.2, 339, 185.4, 339, 194.26666, 339] + size: 18 + color: [0, 0, 0, 0] # actual text is transparent + font: "VeraBd.ttf" + - + type: "pop-all-shadows" diff --git a/gfx/wr/wrench/reftests/text/shadow-rotate.yaml b/gfx/wr/wrench/reftests/text/shadow-rotate.yaml new file mode 100644 index 0000000000..e0ffc9ac03 --- /dev/null +++ b/gfx/wr/wrench/reftests/text/shadow-rotate.yaml @@ -0,0 +1,18 @@ +--- #checks that transformed text shadows can locate glyphs in the glyph cache +root: + items: + - type: stacking-context + bounds: [0, 0, 430, 330] + transform: rotate(30) + items: + - type: "shadow" + bounds: [0, 0, 430, 330] + blur-radius: 1 + offset: [0, 1] + color: blue + - text: "a Bcd Efgh Ijklm Nopqrs Tuvwxyz" + origin: 50 200 + size: 20 + font: "FreeSans.ttf" + - type: "pop-all-shadows" + diff --git a/gfx/wr/wrench/reftests/text/shadow-single.yaml b/gfx/wr/wrench/reftests/text/shadow-single.yaml new file mode 100644 index 0000000000..1804a073ff --- /dev/null +++ b/gfx/wr/wrench/reftests/text/shadow-single.yaml @@ -0,0 +1,18 @@ +--- +root: + items: + - + type: "shadow" + blur-radius: 5 + bounds: [14, 18, 205, 35] + offset: [0, 0] + color: black + - + bounds: [14, 18, 205, 35] + glyphs: [55] + offsets: [16, 43] + size: 18 + color: [0, 0, 0, 0] # actual text is transparent + font: "VeraBd.ttf" + - + type: "pop-all-shadows" diff --git a/gfx/wr/wrench/reftests/text/shadow-solid-ref.yaml b/gfx/wr/wrench/reftests/text/shadow-solid-ref.yaml new file mode 100644 index 0000000000..264b1e1096 --- /dev/null +++ b/gfx/wr/wrench/reftests/text/shadow-solid-ref.yaml @@ -0,0 +1,16 @@ +--- +root: + items: + - + type: "shadow" + blur-radius: 25 + bounds: [0, 0, 90, 90] + offset: [0, 0] + color: [0, 0, 0, 0.8] + - + bounds: [30, 30, 30, 30] + type: rect + style: solid + color: blue + - + type: "pop-all-shadows" diff --git a/gfx/wr/wrench/reftests/text/shadow-transforms.png b/gfx/wr/wrench/reftests/text/shadow-transforms.png Binary files differnew file mode 100644 index 0000000000..05af37e1e7 --- /dev/null +++ b/gfx/wr/wrench/reftests/text/shadow-transforms.png diff --git a/gfx/wr/wrench/reftests/text/shadow-transforms.yaml b/gfx/wr/wrench/reftests/text/shadow-transforms.yaml new file mode 100644 index 0000000000..7a75133dab --- /dev/null +++ b/gfx/wr/wrench/reftests/text/shadow-transforms.yaml @@ -0,0 +1,58 @@ +# Various tests for rotated text shadows, such as +# blur radius, offset, shadow color. +root: + items: + - type: stacking-context + transform: rotate(-30) + transform-origin: 80 80 + items: + - + type: "shadow" + bounds: [0, 0, 350, 100] + blur-radius: 5 + color: [255, 0, 0, 1] + - text: "A red shadow" + origin: 50 40 + size: 20 + font: "FreeSans.ttf" + - + type: "pop-all-shadows" + + - + type: "shadow" + bounds: [100, 100, 350, 100] + blur-radius: 2 + offset: 10 10 + color: [0, 255, 0, 0.5] + - text: "Red text, green shadow" + origin: 150 140 + size: 20 + font: "FreeSans.ttf" + color: red + - + type: "pop-all-shadows" + + - type: stacking-context + perspective: 100 + perspective-origin: 650 100 + items: + - type: "stacking-context" + transform-origin: 235 235 + transform: rotate-x(-15) + items: + - + type: "shadow" + blur-radius: 5 + color: [255, 0, 0, 1] + offset: [0, 20] + - + type: "shadow" + blur-radius: 0 + color: [0, 0, 255, 1] + offset: [0, -20] + - text: "PERSPECTIVE!!!" + origin: 500 100 + size: 100 + font: "FreeSans.ttf" + - + type: "pop-all-shadows" diff --git a/gfx/wr/wrench/reftests/text/shadow.yaml b/gfx/wr/wrench/reftests/text/shadow.yaml new file mode 100644 index 0000000000..56ffdde93b --- /dev/null +++ b/gfx/wr/wrench/reftests/text/shadow.yaml @@ -0,0 +1,33 @@ +--- +root: + items: + - + type: "shadow" + bounds: [14, 18, 205, 35] + blur-radius: 0 + offset: [2, 3] + color: black + - + bounds: [14, 18, 205, 35] + glyphs: [55, 75, 76, 86, 3, 76, 86, 3, 87, 75, 72, 3, 69, 72, 86, 87] + offsets: [16, 43, 35.533333, 43, 51.533333, 43, 60.4, 43, 72.833336, 43, 80.833336, 43, 89.7, 43, 102.13333, 43, 110.13333, 43, 119, 43, 135, 43, 149.2, 43, 157.2, 43, 173.2, 43, 187.4, 43, 196.26666, 43] + size: 18 + color: [0, 0, 0, 0] # actual text is transparent + font: "VeraBd.ttf" + - + type: "pop-all-shadows" + - + type: "shadow" + bounds: [12, 314, 205, 35] + blur-radius: 5 + offset: [-2, -4] + color: red + - + bounds: [14, 318, 205, 35] + glyphs: [55, 75, 76, 86, 3, 76, 86, 3, 87, 75, 72, 3, 69, 72, 86, 87] + offsets: [16, 343, 35.533333, 343, 51.533333, 343, 60.4, 343, 72.833336, 343, 80.833336, 343, 89.7, 343, 102.13333, 343, 110.13333, 343, 119, 343, 135, 343, 149.2, 343, 157.2, 343, 173.2, 343, 187.4, 343, 196.26666, 343] + size: 18 + color: [0, 0, 0, 0] # actual text is transparent + font: "VeraBd.ttf" + - + type: "pop-all-shadows" diff --git a/gfx/wr/wrench/reftests/text/snap-clip-ref.yaml b/gfx/wr/wrench/reftests/text/snap-clip-ref.yaml new file mode 100644 index 0000000000..676b7c80c5 --- /dev/null +++ b/gfx/wr/wrench/reftests/text/snap-clip-ref.yaml @@ -0,0 +1,7 @@ +root: + items: + - bounds: [0, 0, 35, 35] + glyphs: [50] + offsets: [10, 30] + size: 20 + font: "FreeSans.ttf" diff --git a/gfx/wr/wrench/reftests/text/snap-clip.yaml b/gfx/wr/wrench/reftests/text/snap-clip.yaml new file mode 100644 index 0000000000..6ee30aa09b --- /dev/null +++ b/gfx/wr/wrench/reftests/text/snap-clip.yaml @@ -0,0 +1,8 @@ +root: + items: + - bounds: [0, 0, 35, 35] + glyphs: [50] + offsets: [10.3, 30] + clip-rect: [0, 0, 29.7, 35] + size: 20 + font: "FreeSans.ttf" diff --git a/gfx/wr/wrench/reftests/text/snap-text-offset-ref.yaml b/gfx/wr/wrench/reftests/text/snap-text-offset-ref.yaml new file mode 100644 index 0000000000..51b6a8c7c9 --- /dev/null +++ b/gfx/wr/wrench/reftests/text/snap-text-offset-ref.yaml @@ -0,0 +1,11 @@ +root: + items: + - type: stacking-context + bounds: [0, 0, 200, 100] + transform: translate(0.5, 0.5) + items: + - bounds: [0, 0, 200, 100] + glyphs: [68, 3, 37, 70, 71, 3, 40, 73, 74, 75] + offsets: [20.3, 50, 35, 50, 43, 50.49, 61.2, 50, 75.4, 50, 90.6, 50, 98.8, 50, 116.7, 50, 124.1, 50, 139.5, 50] + size: 20 + font: "FreeSans.ttf" diff --git a/gfx/wr/wrench/reftests/text/snap-text-offset.yaml b/gfx/wr/wrench/reftests/text/snap-text-offset.yaml new file mode 100644 index 0000000000..df8c3680d8 --- /dev/null +++ b/gfx/wr/wrench/reftests/text/snap-text-offset.yaml @@ -0,0 +1,10 @@ +root: + items: + - type: stacking-context + bounds: [0.5, 0.5, 200, 100] + items: + - bounds: [0, 0, 200, 100] + glyphs: [68, 3, 37, 70, 71, 3, 40, 73, 74, 75] + offsets: [20.3, 50, 35, 50, 43, 50.49, 61.2, 50, 75.4, 50, 90.6, 50, 98.8, 50, 116.7, 50, 124.1, 50, 139.5, 50] + size: 20 + font: "FreeSans.ttf" diff --git a/gfx/wr/wrench/reftests/text/split-batch-ref.yaml b/gfx/wr/wrench/reftests/text/split-batch-ref.yaml new file mode 100644 index 0000000000..687b051607 --- /dev/null +++ b/gfx/wr/wrench/reftests/text/split-batch-ref.yaml @@ -0,0 +1,18 @@ +--- +root: + items: + - + type: "shadow" + bounds: [0, 0, 650, 670] + blur-radius: 2 + offset: [10, 10] + color: black + - + bounds: [0, 0, 650, 670] + glyphs: [55, 45] + offsets: [20, 500, 400, 500] + size: 500 + color: [255, 0, 0, 1] + font: "VeraBd.ttf" + - + type: "pop-all-shadows" diff --git a/gfx/wr/wrench/reftests/text/split-batch.yaml b/gfx/wr/wrench/reftests/text/split-batch.yaml new file mode 100644 index 0000000000..687b051607 --- /dev/null +++ b/gfx/wr/wrench/reftests/text/split-batch.yaml @@ -0,0 +1,18 @@ +--- +root: + items: + - + type: "shadow" + bounds: [0, 0, 650, 670] + blur-radius: 2 + offset: [10, 10] + color: black + - + bounds: [0, 0, 650, 670] + glyphs: [55, 45] + offsets: [20, 500, 400, 500] + size: 500 + color: [255, 0, 0, 1] + font: "VeraBd.ttf" + - + type: "pop-all-shadows" diff --git a/gfx/wr/wrench/reftests/text/subpixel-rotate.png b/gfx/wr/wrench/reftests/text/subpixel-rotate.png Binary files differnew file mode 100644 index 0000000000..1eaf89db1f --- /dev/null +++ b/gfx/wr/wrench/reftests/text/subpixel-rotate.png diff --git a/gfx/wr/wrench/reftests/text/subpixel-rotate.yaml b/gfx/wr/wrench/reftests/text/subpixel-rotate.yaml new file mode 100644 index 0000000000..296afb0d28 --- /dev/null +++ b/gfx/wr/wrench/reftests/text/subpixel-rotate.yaml @@ -0,0 +1,10 @@ +root: + items: + - type: stacking-context + bounds: [0, 0, 430, 330] + transform: rotate(-30) + items: + - text: "a Bcd Efgh Ijklm Nopqrs Tuvwxyz" + origin: 50 200 + size: 20 + font: "FreeSans.ttf" diff --git a/gfx/wr/wrench/reftests/text/subpixel-scale.png b/gfx/wr/wrench/reftests/text/subpixel-scale.png Binary files differnew file mode 100644 index 0000000000..5999d2d5dd --- /dev/null +++ b/gfx/wr/wrench/reftests/text/subpixel-scale.png diff --git a/gfx/wr/wrench/reftests/text/subpixel-scale.yaml b/gfx/wr/wrench/reftests/text/subpixel-scale.yaml new file mode 100644 index 0000000000..84e7b72bfd --- /dev/null +++ b/gfx/wr/wrench/reftests/text/subpixel-scale.yaml @@ -0,0 +1,10 @@ +root: + items: + - type: stacking-context + bounds: [0, 0, 680, 80] + transform: scale-x(1.5) + items: + - text: "a Bcd Efgh Ijklm Nopqrs Tuvwxyz" + origin: 20 50 + size: 20 + font: "FreeSans.ttf" diff --git a/gfx/wr/wrench/reftests/text/subpixel-skew.png b/gfx/wr/wrench/reftests/text/subpixel-skew.png Binary files differnew file mode 100644 index 0000000000..9dcfde0088 --- /dev/null +++ b/gfx/wr/wrench/reftests/text/subpixel-skew.png diff --git a/gfx/wr/wrench/reftests/text/subpixel-skew.yaml b/gfx/wr/wrench/reftests/text/subpixel-skew.yaml new file mode 100644 index 0000000000..7d06f722b2 --- /dev/null +++ b/gfx/wr/wrench/reftests/text/subpixel-skew.yaml @@ -0,0 +1,10 @@ +root: + items: + - type: stacking-context + bounds: [0, 0, 480, 80] + transform: skew-x(30) + items: + - text: "a Bcd Efgh Ijklm Nopqrs Tuvwxyz" + origin: 20 50 + size: 20 + font: "FreeSans.ttf" diff --git a/gfx/wr/wrench/reftests/text/subpixel-translate-ref.yaml b/gfx/wr/wrench/reftests/text/subpixel-translate-ref.yaml new file mode 100644 index 0000000000..a4377ee76d --- /dev/null +++ b/gfx/wr/wrench/reftests/text/subpixel-translate-ref.yaml @@ -0,0 +1,12 @@ +root: + items: + - type: stacking-context + bounds: [0, 0, 500, 500] + items: + - + bounds: [0, 0, 500, 500] + glyphs: [80, 80, 80, 80, 80] + offsets: [50, 100, 71.111, 100, 92.222, 100, 113.333, 100, 134.444, 100] + origin: 0 0 + size: 20 + font: "FreeSans.ttf" diff --git a/gfx/wr/wrench/reftests/text/subpixel-translate.yaml b/gfx/wr/wrench/reftests/text/subpixel-translate.yaml new file mode 100644 index 0000000000..940dc6fef7 --- /dev/null +++ b/gfx/wr/wrench/reftests/text/subpixel-translate.yaml @@ -0,0 +1,13 @@ +root: + items: + - type: stacking-context + bounds: [0, 0, 500, 500] + transform: translate(0.444, 0) + items: + - + bounds: [0, 0, 500, 500] + glyphs: [80, 80, 80, 80, 80] + offsets: [50, 100, 71.111, 100, 92.222, 100, 113.333, 100, 134.444, 100] + origin: 0 0 + size: 20 + font: "FreeSans.ttf" diff --git a/gfx/wr/wrench/reftests/text/subtle-shadow-ref.yaml b/gfx/wr/wrench/reftests/text/subtle-shadow-ref.yaml new file mode 100644 index 0000000000..54374e1191 --- /dev/null +++ b/gfx/wr/wrench/reftests/text/subtle-shadow-ref.yaml @@ -0,0 +1,27 @@ +--- # incredibly faint shadows showing up as opaque black?? +root: + items: + - type: rect + bounds: [0, 0, 255, 85] + color: [245, 100, 100, 1.0] + - + type: "shadow" + bounds: [14, 18, 205, 35] + blur-radius: 0 + offset: [0, 1] + color: [0.0,0.0,0.0, 0.101961] + - + bounds: [14, 18, 205, 35] + glyphs: [55, 75, 76, 86, 3, 76, 86, 3, 87, 75, 72, 3, 69, 72, 86, 87] + offsets: [16, 43, 35.533333, 43, 51.533333, 43, 60.4, 43, 72.833336, 43, 80.833336, 43, 89.7, 43, 102.13333, 43, 110.13333, 43, 119, 43, 135, 43, 149.2, 43, 157.2, 43, 173.2, 43, 187.4, 43, 196.26666, 43] + size: 12 + color: [168, 168, 168, 0.0] + font: "VeraBd.ttf" + - + type: "pop-all-shadows" + - bounds: [14, 18, 205, 35] + glyphs: [55, 75, 76, 86, 3, 76, 86, 3, 87, 75, 72, 3, 69, 72, 86, 87] + offsets: [16, 43, 35.533333, 43, 51.533333, 43, 60.4, 43, 72.833336, 43, 80.833336, 43, 89.7, 43, 102.13333, 43, 110.13333, 43, 119, 43, 135, 43, 149.2, 43, 157.2, 43, 173.2, 43, 187.4, 43, 196.26666, 43] + size: 12 + color: [168, 168, 168, 1.0] + font: "VeraBd.ttf" diff --git a/gfx/wr/wrench/reftests/text/subtle-shadow.yaml b/gfx/wr/wrench/reftests/text/subtle-shadow.yaml new file mode 100644 index 0000000000..67d19e81fd --- /dev/null +++ b/gfx/wr/wrench/reftests/text/subtle-shadow.yaml @@ -0,0 +1,21 @@ +--- +root: + items: + - type: rect + bounds: [0, 0, 255, 85] + color: [245, 100, 100, 1.0] + - + type: "shadow" + bounds: [14, 18, 205, 35] + blur-radius: 0 + offset: [0, 1] + color: [0.0,0.0,0.0, 0.101961] + - + bounds: [14, 18, 205, 35] + glyphs: [55, 75, 76, 86, 3, 76, 86, 3, 87, 75, 72, 3, 69, 72, 86, 87] + offsets: [16, 43, 35.533333, 43, 51.533333, 43, 60.4, 43, 72.833336, 43, 80.833336, 43, 89.7, 43, 102.13333, 43, 110.13333, 43, 119, 43, 135, 43, 149.2, 43, 157.2, 43, 173.2, 43, 187.4, 43, 196.26666, 43] + size: 12 + color: [168, 168, 168, 1.0] + font: "VeraBd.ttf" + - + type: "pop-all-shadows" diff --git a/gfx/wr/wrench/reftests/text/synthetic-bold-not-ref.yaml b/gfx/wr/wrench/reftests/text/synthetic-bold-not-ref.yaml new file mode 100644 index 0000000000..b947bf4597 --- /dev/null +++ b/gfx/wr/wrench/reftests/text/synthetic-bold-not-ref.yaml @@ -0,0 +1,5 @@ +root: + items: + - text: "Fake bold is great" + origin: 20 40 + size: 20 diff --git a/gfx/wr/wrench/reftests/text/synthetic-bold-transparent-ref.yaml b/gfx/wr/wrench/reftests/text/synthetic-bold-transparent-ref.yaml new file mode 100644 index 0000000000..c7db0a3426 --- /dev/null +++ b/gfx/wr/wrench/reftests/text/synthetic-bold-transparent-ref.yaml @@ -0,0 +1,10 @@ +root: + items: + - type: stacking-context + bounds: [0, 0, 660, 210] + filters: opacity(0.5) + items: + - text: "Fake bold is great" + origin: 20 40 + size: 20 + synthetic-bold: true diff --git a/gfx/wr/wrench/reftests/text/synthetic-bold-transparent.yaml b/gfx/wr/wrench/reftests/text/synthetic-bold-transparent.yaml new file mode 100644 index 0000000000..043a6da781 --- /dev/null +++ b/gfx/wr/wrench/reftests/text/synthetic-bold-transparent.yaml @@ -0,0 +1,7 @@ +root: + items: + - text: "Fake bold is great" + origin: 20 40 + size: 20 + color: [0, 0, 0, 0.5] + synthetic-bold: true diff --git a/gfx/wr/wrench/reftests/text/synthetic-bold.yaml b/gfx/wr/wrench/reftests/text/synthetic-bold.yaml new file mode 100644 index 0000000000..8181dbb84e --- /dev/null +++ b/gfx/wr/wrench/reftests/text/synthetic-bold.yaml @@ -0,0 +1,6 @@ +root: + items: + - text: "Fake bold is great" + origin: 20 40 + size: 20 + synthetic-bold: true diff --git a/gfx/wr/wrench/reftests/text/synthetic-italics-custom.yaml b/gfx/wr/wrench/reftests/text/synthetic-italics-custom.yaml new file mode 100644 index 0000000000..00f30a776f --- /dev/null +++ b/gfx/wr/wrench/reftests/text/synthetic-italics-custom.yaml @@ -0,0 +1,7 @@ +root: + items: + - text: "Fake italics are great" + origin: 20 40 + size: 20 + synthetic-italics: 45 + diff --git a/gfx/wr/wrench/reftests/text/synthetic-italics-ref.yaml b/gfx/wr/wrench/reftests/text/synthetic-italics-ref.yaml new file mode 100644 index 0000000000..5c5be707f7 --- /dev/null +++ b/gfx/wr/wrench/reftests/text/synthetic-italics-ref.yaml @@ -0,0 +1,5 @@ +root: + items: + - text: "Fake italics are great" + origin: 20 40 + size: 20 diff --git a/gfx/wr/wrench/reftests/text/synthetic-italics.yaml b/gfx/wr/wrench/reftests/text/synthetic-italics.yaml new file mode 100644 index 0000000000..fa9b78a3f0 --- /dev/null +++ b/gfx/wr/wrench/reftests/text/synthetic-italics.yaml @@ -0,0 +1,7 @@ +root: + items: + - text: "Fake italics are great" + origin: 20 40 + size: 20 + synthetic-italics: true + diff --git a/gfx/wr/wrench/reftests/text/text-fixed-slice-fast.png b/gfx/wr/wrench/reftests/text/text-fixed-slice-fast.png Binary files differnew file mode 100644 index 0000000000..e6d6147219 --- /dev/null +++ b/gfx/wr/wrench/reftests/text/text-fixed-slice-fast.png diff --git a/gfx/wr/wrench/reftests/text/text-fixed-slice-slow.png b/gfx/wr/wrench/reftests/text/text-fixed-slice-slow.png Binary files differnew file mode 100644 index 0000000000..4ccfff39b2 --- /dev/null +++ b/gfx/wr/wrench/reftests/text/text-fixed-slice-slow.png diff --git a/gfx/wr/wrench/reftests/text/text-fixed-slice.yaml b/gfx/wr/wrench/reftests/text/text-fixed-slice.yaml new file mode 100644 index 0000000000..ec0b72e59b --- /dev/null +++ b/gfx/wr/wrench/reftests/text/text-fixed-slice.yaml @@ -0,0 +1,23 @@ +# Verify that the option to configure performance / quality settings for +# subpixel AA with picture caching is respected. +root: + items: + - type: scroll-frame + bounds: [0, 0, 500, 200] + content-size: [500, 500] + id: 2 + items: + - type: rect + bounds: [0, 0, 500, 200] + color: white + - type: clip + bounds: [0, 0, 500, 200] + items: + - type: rect + bounds: [0, 0, 500, 200] + color: white + - text: "The sun has frightened off the night!" + origin: 20 40 + size: 20 + font: "FreeSans.ttf" + clip-and-scroll: [2, 2] diff --git a/gfx/wr/wrench/reftests/text/text-masking-alpha.png b/gfx/wr/wrench/reftests/text/text-masking-alpha.png Binary files differnew file mode 100644 index 0000000000..2b816eb288 --- /dev/null +++ b/gfx/wr/wrench/reftests/text/text-masking-alpha.png diff --git a/gfx/wr/wrench/reftests/text/text-masking-mask.png b/gfx/wr/wrench/reftests/text/text-masking-mask.png Binary files differnew file mode 100644 index 0000000000..a27a494849 --- /dev/null +++ b/gfx/wr/wrench/reftests/text/text-masking-mask.png diff --git a/gfx/wr/wrench/reftests/text/text-masking-subpx.png b/gfx/wr/wrench/reftests/text/text-masking-subpx.png Binary files differnew file mode 100644 index 0000000000..791a4c6347 --- /dev/null +++ b/gfx/wr/wrench/reftests/text/text-masking-subpx.png diff --git a/gfx/wr/wrench/reftests/text/text-masking.yaml b/gfx/wr/wrench/reftests/text/text-masking.yaml new file mode 100644 index 0000000000..b40d391396 --- /dev/null +++ b/gfx/wr/wrench/reftests/text/text-masking.yaml @@ -0,0 +1,27 @@ +--- +root: + items: + - bounds: [0, 0, 750, 100] + "clip-rect": [0, 0, 750, 100] + type: rect + color: [180, 180, 180] + - bounds: [0, 0, 750, 100] + "clip-rect": [0, 0, 750, 100] + type: clip + id: 2 + "content-size": [750, 100] + "image-mask": + image: "text-masking-mask.png" + rect: [0, 0, 750, 100] + repeat: false + - text: "Cats making all the muffins knock over christmas tree" + origin: 40 40 + size: 20 + "clip-and-scroll": 2 + font: "FreeSans.ttf" + - text: "Cats making all the muffins knock over christmas tree" + origin: 40 80 + size: 20 + color: white + "clip-and-scroll": 2 + font: "FreeSans.ttf" diff --git a/gfx/wr/wrench/reftests/text/text.yaml b/gfx/wr/wrench/reftests/text/text.yaml new file mode 100644 index 0000000000..35e51fa92f --- /dev/null +++ b/gfx/wr/wrench/reftests/text/text.yaml @@ -0,0 +1,10 @@ +--- +root: + items: + - + bounds: [14, 18, 205, 35] + glyphs: [55, 75, 76, 86, 3, 76, 86, 3, 87, 75, 72, 3, 69, 72, 86, 87] + offsets: [16, 43, 35.533333, 43, 51.533333, 43, 60.4, 43, 72.833336, 43, 80.833336, 43, 89.7, 43, 102.13333, 43, 110.13333, 43, 119, 43, 135, 43, 149.2, 43, 157.2, 43, 173.2, 43, 187.4, 43, 196.26666, 43] + size: 18 + color: black + font: "VeraBd.ttf" diff --git a/gfx/wr/wrench/reftests/text/transparent-no-aa-ref.yaml b/gfx/wr/wrench/reftests/text/transparent-no-aa-ref.yaml new file mode 100644 index 0000000000..800b7a9f2a --- /dev/null +++ b/gfx/wr/wrench/reftests/text/transparent-no-aa-ref.yaml @@ -0,0 +1,17 @@ +--- +root: + items: + - + type: "shadow" + bounds: [0, 0, 200, 200] + offset: [0, 0] + blur-radius: 0 + color: [0, 0, 0, 0.5] + - + text: "hello everybody" + origin: [10, 20] + size: 18 + color: [0, 0, 0, 0] + font: "VeraBd.ttf" + - + type: "pop-all-shadows" diff --git a/gfx/wr/wrench/reftests/text/transparent-no-aa.yaml b/gfx/wr/wrench/reftests/text/transparent-no-aa.yaml new file mode 100644 index 0000000000..3a5376f7a2 --- /dev/null +++ b/gfx/wr/wrench/reftests/text/transparent-no-aa.yaml @@ -0,0 +1,9 @@ +--- +root: + items: + - + text: "hello everybody" + origin: [10, 20] + size: 18 + color: [0, 0, 0, 0.5] + font: "VeraBd.ttf" diff --git a/gfx/wr/wrench/reftests/text/two-shadows.png b/gfx/wr/wrench/reftests/text/two-shadows.png Binary files differnew file mode 100644 index 0000000000..3907f1be74 --- /dev/null +++ b/gfx/wr/wrench/reftests/text/two-shadows.png diff --git a/gfx/wr/wrench/reftests/text/two-shadows.yaml b/gfx/wr/wrench/reftests/text/two-shadows.yaml new file mode 100644 index 0000000000..cd16bd1fcf --- /dev/null +++ b/gfx/wr/wrench/reftests/text/two-shadows.yaml @@ -0,0 +1,24 @@ +--- # A simple example of two shadows +root: + items: + - + type: "shadow" + bounds: [14, 18, 205, 35] + blur-radius: 2 + offset: [-2, -2] + color: [255, 0, 0, 1] + - + type: "shadow" + bounds: [14, 18, 205, 35] + blur-radius: 2 + offset: [2, 2] + color: [0, 0, 255, 1] + - + bounds: [14, 18, 205, 35] + glyphs: [55, 75, 76, 86, 3, 76, 86, 3, 87, 75, 72, 3, 69, 72, 86, 87] + offsets: [16, 43, 35.533333, 43, 51.533333, 43, 60.4, 43, 72.833336, 43, 80.833336, 43, 89.7, 43, 102.13333, 43, 110.13333, 43, 119, 43, 135, 43, 149.2, 43, 157.2, 43, 173.2, 43, 187.4, 43, 196.26666, 43] + size: 18 + color: [0, 0, 0, 0] + font: "VeraBd.ttf" + - + type: "pop-all-shadows" diff --git a/gfx/wr/wrench/reftests/text/white-opacity.png b/gfx/wr/wrench/reftests/text/white-opacity.png Binary files differnew file mode 100644 index 0000000000..69c76b28ae --- /dev/null +++ b/gfx/wr/wrench/reftests/text/white-opacity.png diff --git a/gfx/wr/wrench/reftests/text/white-opacity.yaml b/gfx/wr/wrench/reftests/text/white-opacity.yaml new file mode 100644 index 0000000000..0e16856c14 --- /dev/null +++ b/gfx/wr/wrench/reftests/text/white-opacity.yaml @@ -0,0 +1,17 @@ +root: + items: + - type: stacking-context + bounds: [10, 10, 1000, 100] + items: + - type: rect + bounds: [0, 0, 720, 100] + color: [211, 211, 211, 1] + - type: stacking-context + bounds: [0, 0, 500, 100] + filters: [opacity(0.4)] + items: + - text: "Look, no white edges!!" + origin: 20 50 + size: 40 + color: white + font: "VeraBd.ttf" diff --git a/gfx/wr/wrench/reftests/text/writing-modes-ref.yaml b/gfx/wr/wrench/reftests/text/writing-modes-ref.yaml new file mode 100644 index 0000000000..c392822e60 --- /dev/null +++ b/gfx/wr/wrench/reftests/text/writing-modes-ref.yaml @@ -0,0 +1,19 @@ +root: + items: + - type: stacking-context + bounds: [0, 0, 300, 60] + transform: rotate(-90) translate(-120, 160) + items: + - text: "This is sideways-left" + origin: 0 40 + size: 20 + font: "FreeSans.ttf" + - type: stacking-context + bounds: [0, 0, 300, 60] + transform: rotate(90) translate(-90, 120) + items: + - text: "This is sideways-right" + origin: 0 40 + size: 20 + font: "FreeSans.ttf" + diff --git a/gfx/wr/wrench/reftests/text/writing-modes.yaml b/gfx/wr/wrench/reftests/text/writing-modes.yaml new file mode 100644 index 0000000000..2c55e209e0 --- /dev/null +++ b/gfx/wr/wrench/reftests/text/writing-modes.yaml @@ -0,0 +1,15 @@ +root: + items: + - text: "This is sideways-left" + origin: 20 40 + size: 20 + transpose: true + flip-x: true + font: "FreeSans.ttf" + - text: "This is sideways-right" + origin: 70 300 + size: 20 + transpose: true + flip-y: true + font: "FreeSans.ttf" + diff --git a/gfx/wr/wrench/reftests/tiles/prim-suite.yaml b/gfx/wr/wrench/reftests/tiles/prim-suite.yaml new file mode 100644 index 0000000000..2a170f8fc9 --- /dev/null +++ b/gfx/wr/wrench/reftests/tiles/prim-suite.yaml @@ -0,0 +1,45 @@ +--- +root: + items: + - type: stacking-context + bounds: [50, 50, 100, 100] + transform: rotate(30) + items: + - type: rect + bounds: [ 10, 10, 80, 80 ] + color: [0, 255, 0] + - type: box-shadow + bounds: [ 10, 10, 80, 80 ] + blur-radius: 25 + clip-mode: inset + + - type: rect + bounds: [ 140, 10, 80, 80 ] + color: [0, 255, 0] + - type: box-shadow + bounds: [ 140, 10, 80, 80 ] + blur-radius: 25 + clip-mode: outset + + - type: border + bounds: [ 250, 10, 100, 100 ] + width: [ 10, 10, 10, 10 ] + border-type: normal + style: solid + color: [ red, green, blue, black ] + radius: { + top-left: [20, 20], + top-right: [10, 10], + bottom-left: [25, 25], + bottom-right: [0, 0], + } + + - bounds: [150, 150, 128, 128] + image: checkerboard(4, 15, 8) + stretch-size: 128 128 + + - type: radial-gradient + bounds: 300 150 100 100 + center: 50 50 + radius: 50 50 + stops: [0, red, 1, blue] diff --git a/gfx/wr/wrench/reftests/tiles/rect.yaml b/gfx/wr/wrench/reftests/tiles/rect.yaml new file mode 100644 index 0000000000..e3f71ac9dd --- /dev/null +++ b/gfx/wr/wrench/reftests/tiles/rect.yaml @@ -0,0 +1,6 @@ +--- +root: + items: + - type: rect + bounds: 50 50 200 200 + color: red diff --git a/gfx/wr/wrench/reftests/tiles/reftest.list b/gfx/wr/wrench/reftests/tiles/reftest.list new file mode 100644 index 0000000000..7c04207b18 --- /dev/null +++ b/gfx/wr/wrench/reftests/tiles/reftest.list @@ -0,0 +1,4 @@ +** rect.yaml +** simple-gradient.yaml +# TODO: Fix rasterizer inaccuracies so this is the same regardless of tile size! +!* prim-suite.yaml diff --git a/gfx/wr/wrench/reftests/tiles/simple-gradient.yaml b/gfx/wr/wrench/reftests/tiles/simple-gradient.yaml new file mode 100644 index 0000000000..0879b2442f --- /dev/null +++ b/gfx/wr/wrench/reftests/tiles/simple-gradient.yaml @@ -0,0 +1,9 @@ +--- +root: + items: + - type: gradient + bounds: [ 0, 0, 1980, 1080] + start: [ 0, -2000 ] + end: [ 0, 4000 ] + stops: [ 0.0, red, 1.0, green ] + repeat: false diff --git a/gfx/wr/wrench/reftests/transforms/big-axis-aligned-scale-ref.yaml b/gfx/wr/wrench/reftests/transforms/big-axis-aligned-scale-ref.yaml new file mode 100644 index 0000000000..357981c103 --- /dev/null +++ b/gfx/wr/wrench/reftests/transforms/big-axis-aligned-scale-ref.yaml @@ -0,0 +1,6 @@ +--- +root: + items: + - type: rect + bounds: [ 0, 0, 200, 44 ] + color: green diff --git a/gfx/wr/wrench/reftests/transforms/big-axis-aligned-scale.yaml b/gfx/wr/wrench/reftests/transforms/big-axis-aligned-scale.yaml new file mode 100644 index 0000000000..4dfb19fbb0 --- /dev/null +++ b/gfx/wr/wrench/reftests/transforms/big-axis-aligned-scale.yaml @@ -0,0 +1,10 @@ +--- +root: + items: + - type: stacking-context + transform-style: preserve-3d + transform: scale(-2, 44, 44727) + items: + - type: rect + bounds: [ -100, -100, 200, 101 ] + color: green diff --git a/gfx/wr/wrench/reftests/transforms/blank.yaml b/gfx/wr/wrench/reftests/transforms/blank.yaml new file mode 100644 index 0000000000..c4eb3ab673 --- /dev/null +++ b/gfx/wr/wrench/reftests/transforms/blank.yaml @@ -0,0 +1,2 @@ +--- +root: diff --git a/gfx/wr/wrench/reftests/transforms/border-scale-2.png b/gfx/wr/wrench/reftests/transforms/border-scale-2.png Binary files differnew file mode 100644 index 0000000000..04476e399a --- /dev/null +++ b/gfx/wr/wrench/reftests/transforms/border-scale-2.png diff --git a/gfx/wr/wrench/reftests/transforms/border-scale-2.yaml b/gfx/wr/wrench/reftests/transforms/border-scale-2.yaml new file mode 100644 index 0000000000..f841033766 --- /dev/null +++ b/gfx/wr/wrench/reftests/transforms/border-scale-2.yaml @@ -0,0 +1,19 @@ +--- +root: + items: + - type: stacking-context + bounds: [50, 50, 100, 100] + transform: scale(0.5) + items: + - type: border + bounds: [ 100, 100, 400, 200 ] + width: [ 20, 20, 20, 20 ] + border-type: normal + style: solid + color: [ blue, blue, blue, blue ] + radius: { + top-left: [100, 100], + top-right: [100, 100], + bottom-left: [100, 100], + bottom-right: [100, 100], + } diff --git a/gfx/wr/wrench/reftests/transforms/border-scale-3.png b/gfx/wr/wrench/reftests/transforms/border-scale-3.png Binary files differnew file mode 100644 index 0000000000..c8f7b517a1 --- /dev/null +++ b/gfx/wr/wrench/reftests/transforms/border-scale-3.png diff --git a/gfx/wr/wrench/reftests/transforms/border-scale-3.yaml b/gfx/wr/wrench/reftests/transforms/border-scale-3.yaml new file mode 100644 index 0000000000..9308f2471d --- /dev/null +++ b/gfx/wr/wrench/reftests/transforms/border-scale-3.yaml @@ -0,0 +1,19 @@ +--- +root: + items: + - type: stacking-context + bounds: [50, 50, 100, 100] + transform: [10,0,0,0, 0,1,0,0, 0,0,1,0, 0,0,0,1] + items: + - type: border + bounds: [ 5, 50, 20, 100 ] + width: [ 10, 1, 10, 1 ] + border-type: normal + style: solid + color: blue + radius: { + top-left: [5, 50], + top-right: [5, 50], + bottom-left: [5, 50], + bottom-right: [5, 50], + } diff --git a/gfx/wr/wrench/reftests/transforms/border-scale-4.png b/gfx/wr/wrench/reftests/transforms/border-scale-4.png Binary files differnew file mode 100644 index 0000000000..7accbb30c2 --- /dev/null +++ b/gfx/wr/wrench/reftests/transforms/border-scale-4.png diff --git a/gfx/wr/wrench/reftests/transforms/border-scale-4.yaml b/gfx/wr/wrench/reftests/transforms/border-scale-4.yaml new file mode 100644 index 0000000000..b2e50bbd2c --- /dev/null +++ b/gfx/wr/wrench/reftests/transforms/border-scale-4.yaml @@ -0,0 +1,19 @@ +--- +root: + items: + - type: stacking-context + bounds: [50, 50, 100, 100] + transform: [1,0,0,0, 0,10,0,0, 0,0,1,0, 0,0,0,1] + items: + - type: border + bounds: [ 50, 5, 200, 10 ] + width: [ 1, 10, 1, 10 ] + border-type: normal + style: solid + color: [ blue, blue, blue, blue ] + radius: { + top-left: [50, 5], + top-right: [50, 5], + bottom-left: [50, 5], + bottom-right: [50, 5], + } diff --git a/gfx/wr/wrench/reftests/transforms/border-scale.png b/gfx/wr/wrench/reftests/transforms/border-scale.png Binary files differnew file mode 100644 index 0000000000..3f9fae051b --- /dev/null +++ b/gfx/wr/wrench/reftests/transforms/border-scale.png diff --git a/gfx/wr/wrench/reftests/transforms/border-scale.yaml b/gfx/wr/wrench/reftests/transforms/border-scale.yaml new file mode 100644 index 0000000000..4bf10c3029 --- /dev/null +++ b/gfx/wr/wrench/reftests/transforms/border-scale.yaml @@ -0,0 +1,19 @@ +--- +root: + items: + - type: stacking-context + bounds: [50, 50, 100, 100] + transform: scale(10) + items: + - type: border + bounds: [ 5, 5, 20, 10 ] + width: [ 1, 1, 1, 1 ] + border-type: normal + style: solid + color: [ blue, blue, blue, blue ] + radius: { + top-left: [5, 5], + top-right: [5, 5], + bottom-left: [5, 5], + bottom-right: [5, 5], + } diff --git a/gfx/wr/wrench/reftests/transforms/border-zoom.png b/gfx/wr/wrench/reftests/transforms/border-zoom.png Binary files differnew file mode 100644 index 0000000000..056e6ce728 --- /dev/null +++ b/gfx/wr/wrench/reftests/transforms/border-zoom.png diff --git a/gfx/wr/wrench/reftests/transforms/border-zoom.yaml b/gfx/wr/wrench/reftests/transforms/border-zoom.yaml new file mode 100644 index 0000000000..f3f472bf21 --- /dev/null +++ b/gfx/wr/wrench/reftests/transforms/border-zoom.yaml @@ -0,0 +1,19 @@ +--- +root: + items: + - type: stacking-context + bounds: [50, 50, 100, 100] + transform: rotate(-30) + items: + - type: border + bounds: [ 10, 10, 100, 100 ] + width: [ 10, 10, 10, 10 ] + border-type: normal + style: solid + color: [ red, green, blue, black ] + radius: { + top-left: [20, 20], + top-right: [10, 10], + bottom-left: [25, 25], + bottom-right: [0, 0], + } diff --git a/gfx/wr/wrench/reftests/transforms/clip-translate-ref.yaml b/gfx/wr/wrench/reftests/transforms/clip-translate-ref.yaml new file mode 100644 index 0000000000..412397d90f --- /dev/null +++ b/gfx/wr/wrench/reftests/transforms/clip-translate-ref.yaml @@ -0,0 +1,6 @@ +--- +root: + items: + - type: rect + color: red + bounds: [6, 168, 18, 18] diff --git a/gfx/wr/wrench/reftests/transforms/clip-translate.yaml b/gfx/wr/wrench/reftests/transforms/clip-translate.yaml new file mode 100644 index 0000000000..3b278a14aa --- /dev/null +++ b/gfx/wr/wrench/reftests/transforms/clip-translate.yaml @@ -0,0 +1,21 @@ +--- +root: + items: + - + type: "stacking-context" + transform: [0.75, 0, 0, 0, 0, 0.75, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1] + items: + - + type: "stacking-context" + transform: [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 8, 224, 0, 1] + items: + - type: clip + bounds: [0, 0, 24, 24] + image-mask: + image: solid-color(255, 0, 0, 255, 24, 24) + rect: [0, 0, 24, 24] + repeat: false + items: + - type: rect + color: red + bounds: [0, 0, 24, 24] diff --git a/gfx/wr/wrench/reftests/transforms/complex-preserve-3d.yaml b/gfx/wr/wrench/reftests/transforms/complex-preserve-3d.yaml new file mode 100644 index 0000000000..9aa0884f62 --- /dev/null +++ b/gfx/wr/wrench/reftests/transforms/complex-preserve-3d.yaml @@ -0,0 +1,24 @@ +# the root sc should dominate backface-visibility and hide the rect + +--- +root: + items: + - + bounds: [300, 300, 300, 300] + clip-rect: [300, 300, 300, 300] + type: "stacking-context" + transform: rotate-y(180) + transform-style: flat + backface-visible: false + items: + - + type: "stacking-context" + transform-style: preserve-3d + backface-visible: true + items: + - + bounds: [350, 350, 150, 150] + clip-rect: [350, 350, 150, 150] + type: rect + color: 255 255 0 0.4000 + backface-visible: true diff --git a/gfx/wr/wrench/reftests/transforms/content-offset.png b/gfx/wr/wrench/reftests/transforms/content-offset.png Binary files differnew file mode 100644 index 0000000000..16a39791b2 --- /dev/null +++ b/gfx/wr/wrench/reftests/transforms/content-offset.png diff --git a/gfx/wr/wrench/reftests/transforms/content-offset.yaml b/gfx/wr/wrench/reftests/transforms/content-offset.yaml new file mode 100644 index 0000000000..379b269fe6 --- /dev/null +++ b/gfx/wr/wrench/reftests/transforms/content-offset.yaml @@ -0,0 +1,18 @@ +--- +root: + items: + - + type: "stacking-context" + perspective: 1000 + perspective-origin: 0 0 + "transform-style": "preserve-3d" + items: + - + type: "stacking-context" + transform: rotate-x(-45) translate(100, 100, 0) + "transform-style": "preserve-3d" + items: + - + bounds: [0, 0, 200, 200] + type: rect + color: red diff --git a/gfx/wr/wrench/reftests/transforms/coord-system.png b/gfx/wr/wrench/reftests/transforms/coord-system.png Binary files differnew file mode 100644 index 0000000000..e3617f4194 --- /dev/null +++ b/gfx/wr/wrench/reftests/transforms/coord-system.png diff --git a/gfx/wr/wrench/reftests/transforms/coord-system.yaml b/gfx/wr/wrench/reftests/transforms/coord-system.yaml new file mode 100644 index 0000000000..6da2117056 --- /dev/null +++ b/gfx/wr/wrench/reftests/transforms/coord-system.yaml @@ -0,0 +1,24 @@ +--- +root: + items: + - + type: "stacking-context" + perspective: [1, 0, 0, 0, 0, 1, 0, 0, -0.102400005, -0.185, 1, -0.0005, 0, 0, 0, 1] + items: + - + type: "scroll-frame" + id: 2 + "content-size": [1024, 740] + bounds: [0, 0, 1024, 740] + - + bounds: [0, 0, 1024, 200] + "clip-rect": [0, 0, 1024, 200] + "clip-and-scroll": 2 + type: "stacking-context" + transform: [0.70710677, 0, -0.70710677, 0, 0, 1, 0, 0, 0.70710677, 0, 0.70710677, 0, 149.96133, 0, -937.9613, 1] + items: + - + bounds: [0, 0, 1024, 200] + "clip-rect": [0, 0, 1024, 200] + type: rect + color: 0 128 0 1.0000 diff --git a/gfx/wr/wrench/reftests/transforms/flatten-preserve-3d-root-ref.yaml b/gfx/wr/wrench/reftests/transforms/flatten-preserve-3d-root-ref.yaml new file mode 100644 index 0000000000..5dbf829e02 --- /dev/null +++ b/gfx/wr/wrench/reftests/transforms/flatten-preserve-3d-root-ref.yaml @@ -0,0 +1,6 @@ +--- +root: + items: + - bounds: [100, 150, 150, 75] + type: rect + color: green diff --git a/gfx/wr/wrench/reftests/transforms/flatten-preserve-3d-root.yaml b/gfx/wr/wrench/reftests/transforms/flatten-preserve-3d-root.yaml new file mode 100644 index 0000000000..b3507a985a --- /dev/null +++ b/gfx/wr/wrench/reftests/transforms/flatten-preserve-3d-root.yaml @@ -0,0 +1,23 @@ +# This test ensures that we flatten the trasformations (i.e. zero out Z coordinates) +# at the boundaries of preserve-3d hierarchies. +# If the stacking context isn't flattened at the preserve-3d boundary here, +# it's non-zero Z component starts affecting the screen space position +# due to the "rotate-x" transform at the top level. +--- +root: + items: + - + bounds: [100, 100, 0, 0] + type: stacking-context + transform: rotate-x(60) + transform-style: flat + items: + - + type: "stacking-context" + transform: translate(0, 0, 200) + transform-style: preserve-3d + items: + - + bounds: [0, 0, 150, 150] + type: rect + color: green diff --git a/gfx/wr/wrench/reftests/transforms/flatten-twice-ref.yaml b/gfx/wr/wrench/reftests/transforms/flatten-twice-ref.yaml new file mode 100644 index 0000000000..27e4183555 --- /dev/null +++ b/gfx/wr/wrench/reftests/transforms/flatten-twice-ref.yaml @@ -0,0 +1,6 @@ +--- +root: + items: + - type: rect + bounds: [100, 100, 200, 100] + color: green diff --git a/gfx/wr/wrench/reftests/transforms/flatten-twice.yaml b/gfx/wr/wrench/reftests/transforms/flatten-twice.yaml new file mode 100644 index 0000000000..9af750a7c0 --- /dev/null +++ b/gfx/wr/wrench/reftests/transforms/flatten-twice.yaml @@ -0,0 +1,21 @@ +# This test ensures that we flatten the "flat" style trasformations. +# If the flattening doesn't happen here, the rect gets rotated back +# to the original position. +--- +root: + items: + - + bounds: [100, 100, 0, 0] + type: stacking-context + transform: rotate-x(45) + transform-origin: 0 0 + items: + - + type: "stacking-context" + transform: rotate-x(-45) + transform-origin: 0 0 + items: + - + bounds: [0, 0, 200, 200] + type: rect + color: green diff --git a/gfx/wr/wrench/reftests/transforms/image-rotated-clip.png b/gfx/wr/wrench/reftests/transforms/image-rotated-clip.png Binary files differnew file mode 100644 index 0000000000..fda2872a3e --- /dev/null +++ b/gfx/wr/wrench/reftests/transforms/image-rotated-clip.png diff --git a/gfx/wr/wrench/reftests/transforms/image-rotated-clip.yaml b/gfx/wr/wrench/reftests/transforms/image-rotated-clip.yaml new file mode 100644 index 0000000000..31803b5530 --- /dev/null +++ b/gfx/wr/wrench/reftests/transforms/image-rotated-clip.yaml @@ -0,0 +1,19 @@ +--- +root: + items: + - + bounds: [18, 18, 400, 400] + "clip-rect": [18, 18, 400, 400] + type: clip + id: 2 + "content-size": [400, 400] + - + bounds: [0, 0, 0, 0] + "clip-and-scroll": 2 + type: "stacking-context" + transform: [0.70710677, 0.70710677, 0, 0, -0.70710677, 0.70710677, 0, 0, 0, 0, 1, 0, 218, -64.84271, 0, 1] + items: + - + bounds: [0, 0, 400, 400] + "clip-rect": [0, 0, 400, 400] + image: solid-color(255, 0, 0, 255, 400, 400) diff --git a/gfx/wr/wrench/reftests/transforms/image.png b/gfx/wr/wrench/reftests/transforms/image.png Binary files differnew file mode 100644 index 0000000000..c8ec5aefcc --- /dev/null +++ b/gfx/wr/wrench/reftests/transforms/image.png diff --git a/gfx/wr/wrench/reftests/transforms/large-raster-root.yaml b/gfx/wr/wrench/reftests/transforms/large-raster-root.yaml new file mode 100644 index 0000000000..0c5176d06d --- /dev/null +++ b/gfx/wr/wrench/reftests/transforms/large-raster-root.yaml @@ -0,0 +1,14 @@ +--- +root: + items: + - type: stacking-context + bounds: [0, 0, 600, 600] + perspective: 20 + items: + - type: stacking-context + transform: rotate-z(-45) rotate-x(-45) + filters: drop-shadow([0, 0], 10000, blue) + items: + - type: rect + bounds: [0, 0, 20000, 100] + color: green diff --git a/gfx/wr/wrench/reftests/transforms/local-clip.png b/gfx/wr/wrench/reftests/transforms/local-clip.png Binary files differnew file mode 100644 index 0000000000..92e25ec5e5 --- /dev/null +++ b/gfx/wr/wrench/reftests/transforms/local-clip.png diff --git a/gfx/wr/wrench/reftests/transforms/local-clip.yaml b/gfx/wr/wrench/reftests/transforms/local-clip.yaml new file mode 100644 index 0000000000..661b40bed7 --- /dev/null +++ b/gfx/wr/wrench/reftests/transforms/local-clip.yaml @@ -0,0 +1,26 @@ +--- +root: + items: + - + bounds: [0, 0, 1000, 1000] + "clip-rect": [0, 0, 1000, 1000] + type: clip + id: 3 + "content-size": [1000, 1000] + - + bounds: [0, 0, 0, 0] + "clip-and-scroll": 3 + type: "stacking-context" + transform: rotate(-45) translate(200, 200) + items: + - + bounds: [0, 0, 100, 100] + "clip-rect": [0, 0, 100, 100] + type: clip + id: 4 + "content-size": [100, 100] + - + bounds: [2, -182, 152, 216] + "clip-rect": [2, 0, 152, 34] + "clip-and-scroll": 4 + image: solid-color(255, 0, 0, 255, 100, 100) diff --git a/gfx/wr/wrench/reftests/transforms/near-plane-clip.png b/gfx/wr/wrench/reftests/transforms/near-plane-clip.png Binary files differnew file mode 100644 index 0000000000..f6bf5df777 --- /dev/null +++ b/gfx/wr/wrench/reftests/transforms/near-plane-clip.png diff --git a/gfx/wr/wrench/reftests/transforms/near-plane-clip.yaml b/gfx/wr/wrench/reftests/transforms/near-plane-clip.yaml new file mode 100644 index 0000000000..3bbafca974 --- /dev/null +++ b/gfx/wr/wrench/reftests/transforms/near-plane-clip.yaml @@ -0,0 +1,18 @@ +# Test the calculation for screen bounds for transformed primitives that cross the near plane. +--- +root: + items: + - + bounds: [0, 0, 1000, 1000] + type: "stacking-context" + perspective: 200 + items: + - + bounds: [0, 0, 1000, 1000] + type: "stacking-context" + transform: rotate-x(30) + items: + - + bounds: [350, 200, 260, 300] + image: checkerboard(2, 16, 16) + stretch-size: 260 260 diff --git a/gfx/wr/wrench/reftests/transforms/nested-preserve-3d.png b/gfx/wr/wrench/reftests/transforms/nested-preserve-3d.png Binary files differnew file mode 100644 index 0000000000..686a22cf0a --- /dev/null +++ b/gfx/wr/wrench/reftests/transforms/nested-preserve-3d.png diff --git a/gfx/wr/wrench/reftests/transforms/nested-preserve-3d.yaml b/gfx/wr/wrench/reftests/transforms/nested-preserve-3d.yaml new file mode 100644 index 0000000000..e7f0f05407 --- /dev/null +++ b/gfx/wr/wrench/reftests/transforms/nested-preserve-3d.yaml @@ -0,0 +1,28 @@ +--- +root: + items: + - + bounds: [260, 260, 231, 231] + "clip-rect": [260, 260, 231, 231] + type: border + width: 3 + "border-type": normal + color: 0 0 255 1.0000 + style: dashed + - + bounds: [300, 300, 0, 0] + "clip-rect": [300, 300, 0, 0] + type: "stacking-context" + transform: [1, 0, 0, 0, 0, 0, 1, 0, 0, -1, 0, 0, 0, 75, -75, 1] + transform-style: preserve-3d + items: + - + type: "stacking-context" + transform: [1, 0, 0, 0, 0, 0.8660254, -0.5, 0, 0, 0.5, 0.8660254, 0, 0, 10.048096, 37.5, 1] + transform-style: preserve-3d + items: + - + bounds: [0, 0, 150, 150] + "clip-rect": [0, 0, 150, 150] + type: rect + color: 255 255 0 0.4000 diff --git a/gfx/wr/wrench/reftests/transforms/nested-rotate-x-flat.png b/gfx/wr/wrench/reftests/transforms/nested-rotate-x-flat.png Binary files differnew file mode 100644 index 0000000000..ca33ca1336 --- /dev/null +++ b/gfx/wr/wrench/reftests/transforms/nested-rotate-x-flat.png diff --git a/gfx/wr/wrench/reftests/transforms/nested-rotate-x-flat.yaml b/gfx/wr/wrench/reftests/transforms/nested-rotate-x-flat.yaml new file mode 100644 index 0000000000..ed25c8f09d --- /dev/null +++ b/gfx/wr/wrench/reftests/transforms/nested-rotate-x-flat.yaml @@ -0,0 +1,27 @@ +# This is the same as nested-rotate-x.yaml but without the preserve-3d. +--- +root: + items: + - + bounds: [260, 260, 231, 231] + "clip-rect": [260, 260, 231, 231] + type: border + width: 3 + "border-type": normal + color: 0 0 255 1.0000 + style: dashed + - + bounds: [300, 300, 0, 0] + "clip-rect": [300, 300, 0, 0] + type: "stacking-context" + transform: [1, 0, 0, 0, 0, 0, 1, 0, 0, -1, 0, 0, 0, 75, -75, 1] + items: + - + type: "stacking-context" + transform: [1, 0, 0, 0, 0, 0.8660254, -0.5, 0, 0, 0.5, 0.8660254, 0, 0, 10.048096, 37.5, 1] + items: + - + bounds: [0, 0, 150, 150] + "clip-rect": [0, 0, 150, 150] + type: rect + color: 255 255 0 0.4000 diff --git a/gfx/wr/wrench/reftests/transforms/nested-rotate-x.png b/gfx/wr/wrench/reftests/transforms/nested-rotate-x.png Binary files differnew file mode 100644 index 0000000000..73ad1cec41 --- /dev/null +++ b/gfx/wr/wrench/reftests/transforms/nested-rotate-x.png diff --git a/gfx/wr/wrench/reftests/transforms/nested-rotate-x.yaml b/gfx/wr/wrench/reftests/transforms/nested-rotate-x.yaml new file mode 100644 index 0000000000..f1f8bd36c9 --- /dev/null +++ b/gfx/wr/wrench/reftests/transforms/nested-rotate-x.yaml @@ -0,0 +1,27 @@ +--- +root: + items: + - + bounds: [260, 260, 231, 231] + "clip-rect": [260, 260, 231, 231] + type: border + width: 3 + "border-type": normal + color: 0 0 255 1.0000 + style: dashed + - + bounds: [300, 300, 0, 0] + "clip-rect": [300, 300, 0, 0] + type: "stacking-context" + transform: [1, 0, 0, 0, 0, 0, 1, 0, 0, -1, 0, 0, 0, 75, -75, 1] + transform-style: preserve-3d + items: + - + type: "stacking-context" + transform: [1, 0, 0, 0, 0, 0.8660254, -0.5, 0, 0, 0.5, 0.8660254, 0, 0, 10.048096, 37.5, 1] + items: + - + bounds: [0, 0, 150, 150] + "clip-rect": [0, 0, 150, 150] + type: rect + color: 255 255 0 0.4000 diff --git a/gfx/wr/wrench/reftests/transforms/non-inversible-world-rect.yaml b/gfx/wr/wrench/reftests/transforms/non-inversible-world-rect.yaml new file mode 100644 index 0000000000..f94404f58e --- /dev/null +++ b/gfx/wr/wrench/reftests/transforms/non-inversible-world-rect.yaml @@ -0,0 +1,23 @@ +# Tests that `get_raster_rects` raster -> world transform is inversible in general, +# but one of the vertices of the world rectangles can't map back to the raster. +--- +root: + items: + - type: stacking-context + bounds: 0 0 400 400 + perspective: 800 + perspective-origin: 50% 200 + items: + - type: stacking-context + bounds: 0 0 400 400 + transform-style: preserve-3d + transform: rotate-z(40) translate(400, 200, 0) + margin: 100 + items: + - type: stacking-context + bounds: 0 0 1000 1000 + transform: rotate-y(-75) translate(0, 0, -500) + items: + - type: rect + bounds: [0, 0, 200, 200] + color: red diff --git a/gfx/wr/wrench/reftests/transforms/perspective-border-radius.png b/gfx/wr/wrench/reftests/transforms/perspective-border-radius.png Binary files differnew file mode 100644 index 0000000000..bb401a837e --- /dev/null +++ b/gfx/wr/wrench/reftests/transforms/perspective-border-radius.png diff --git a/gfx/wr/wrench/reftests/transforms/perspective-border-radius.yaml b/gfx/wr/wrench/reftests/transforms/perspective-border-radius.yaml new file mode 100644 index 0000000000..41b43cd48a --- /dev/null +++ b/gfx/wr/wrench/reftests/transforms/perspective-border-radius.yaml @@ -0,0 +1,20 @@ +--- +root: + items: + - + bounds: [0, 0, 1000, 1000] + type: "stacking-context" + perspective: 256 + items: + - + bounds: [128, 128, 256, 256] + type: "stacking-context" + transform: rotate-x(-60) rotate-y(-120) + items: + - + bounds: [128, 128, 256, 256] + type: rect + color: blue + complex-clip: + rect: [128, 128, 256, 256] + radius: [64, 32] diff --git a/gfx/wr/wrench/reftests/transforms/perspective-box-shadow-ref.yaml b/gfx/wr/wrench/reftests/transforms/perspective-box-shadow-ref.yaml new file mode 100644 index 0000000000..36df831e19 --- /dev/null +++ b/gfx/wr/wrench/reftests/transforms/perspective-box-shadow-ref.yaml @@ -0,0 +1,24 @@ +--- +root: + items: + - + type: "stacking-context" + transform-style: "preserve-3d" + items: + - + type: "reference-frame" + transform: [1, 0, 0, 0, -0.20399817824363708, 0.05275486409664154, 0.9659258127212524, -0.0008049382013268769, -0.05466114357113838, -1.0211405754089355, 0.258819043636322, -0.00021568253578152508, 52.22355651855469, 242.49476623535156, -247.27700805664063, 1.206064224243164] + items: + - + type: "stacking-context" + items: + - + type: "box-shadow" + bounds: [30, 0, 507, 512] + box-bounds: [30, 0, 507, 512] + offset: [-14, 4] + blur-radius: 8 + spread-radius: -4 + border-radius: 256 + clip-mode: "inset" + color: red diff --git a/gfx/wr/wrench/reftests/transforms/perspective-box-shadow.yaml b/gfx/wr/wrench/reftests/transforms/perspective-box-shadow.yaml new file mode 100644 index 0000000000..99e247bf49 --- /dev/null +++ b/gfx/wr/wrench/reftests/transforms/perspective-box-shadow.yaml @@ -0,0 +1,23 @@ +--- +root: + items: + - + type: "stacking-context" + items: + - + type: "reference-frame" + transform: [1, 0, 0, 0, -0.20399817824363708, 0.05275486409664154, 0.9659258127212524, -0.0008049382013268769, -0.05466114357113838, -1.0211405754089355, 0.258819043636322, -0.00021568253578152508, 52.22355651855469, 242.49476623535156, -247.27700805664063, 1.206064224243164] + items: + - + type: "stacking-context" + items: + - + type: "box-shadow" + bounds: [30, 0, 507, 512] + box-bounds: [30, 0, 507, 512] + offset: [-14, 4] + blur-radius: 8 + spread-radius: -4 + border-radius: 256 + clip-mode: "inset" + color: red diff --git a/gfx/wr/wrench/reftests/transforms/perspective-clip-1.png b/gfx/wr/wrench/reftests/transforms/perspective-clip-1.png Binary files differnew file mode 100644 index 0000000000..2708424772 --- /dev/null +++ b/gfx/wr/wrench/reftests/transforms/perspective-clip-1.png diff --git a/gfx/wr/wrench/reftests/transforms/perspective-clip-1.yaml b/gfx/wr/wrench/reftests/transforms/perspective-clip-1.yaml new file mode 100644 index 0000000000..22220bbf29 --- /dev/null +++ b/gfx/wr/wrench/reftests/transforms/perspective-clip-1.yaml @@ -0,0 +1,25 @@ +--- +root: + items: + - + type: stacking-context + bounds: [0, 0, 0, 0] + perspective: [1, 0, 0, 0, 0, 1, 0, 0, -300, -250, 1, -0.5, 0, 0, 0, 1] + items: + - + bounds: [0, 0, 0, 0] + type: stacking-context + transform: [10, 0, 0, 0, 0, 10, 0, 0, 0, 0, 1, 0, -5382, -3222, -18, 1] + items: + - + bounds: [0, 0, 100, 100] + type: rect + color: red + - + bounds: [0, 0, 100, 100] + type: rect + color: green + complex-clip: + rect: [0, 0, 100, 100] + radius: 16 + diff --git a/gfx/wr/wrench/reftests/transforms/perspective-clip.png b/gfx/wr/wrench/reftests/transforms/perspective-clip.png Binary files differnew file mode 100644 index 0000000000..b304ca7db5 --- /dev/null +++ b/gfx/wr/wrench/reftests/transforms/perspective-clip.png diff --git a/gfx/wr/wrench/reftests/transforms/perspective-clip.yaml b/gfx/wr/wrench/reftests/transforms/perspective-clip.yaml new file mode 100644 index 0000000000..ae905b8a44 --- /dev/null +++ b/gfx/wr/wrench/reftests/transforms/perspective-clip.yaml @@ -0,0 +1,27 @@ +# Test that a local space clip is correctly applied to +# a primitive with a perspective transform. +--- +root: + items: + - type: clip + bounds: [225, 200, 150, 200] + complex: + - rect: [225, 200, 150, 200] + radius: 32 + items: + - + type: "stacking-context" + bounds: 0 0 1000 1000 + perspective: 100 + perspective-origin: 300 300 + items: + - + type: "stacking-context" + transform: rotate-x(-10) + transform-origin: 300 300 + filters: identity + items: + - + bounds: [200, 200, 200, 200] + image: checkerboard(2, 16, 12) + stretch-size: 200 200 diff --git a/gfx/wr/wrench/reftests/transforms/perspective-mask.png b/gfx/wr/wrench/reftests/transforms/perspective-mask.png Binary files differnew file mode 100644 index 0000000000..cffefbd5b2 --- /dev/null +++ b/gfx/wr/wrench/reftests/transforms/perspective-mask.png diff --git a/gfx/wr/wrench/reftests/transforms/perspective-mask.yaml b/gfx/wr/wrench/reftests/transforms/perspective-mask.yaml new file mode 100644 index 0000000000..eadc48e0ba --- /dev/null +++ b/gfx/wr/wrench/reftests/transforms/perspective-mask.yaml @@ -0,0 +1,22 @@ +--- +root: + items: + - + type: "scroll-frame" + id: 2 + "content-size": [500, 100] + bounds: [0, 0, 500, 100] + items: + - + type: "stacking-context" + perspective: 125 + items: + - + type: "stacking-context" + bounds: [0, 0, 250, 100] + transform: rotate-y(54) + items: + - + bounds: [0, 0, 128, 128] + type: rect + color: red diff --git a/gfx/wr/wrench/reftests/transforms/perspective-origin.png b/gfx/wr/wrench/reftests/transforms/perspective-origin.png Binary files differnew file mode 100644 index 0000000000..cd98b9e83a --- /dev/null +++ b/gfx/wr/wrench/reftests/transforms/perspective-origin.png diff --git a/gfx/wr/wrench/reftests/transforms/perspective-origin.yaml b/gfx/wr/wrench/reftests/transforms/perspective-origin.yaml new file mode 100644 index 0000000000..ca5eb5f95c --- /dev/null +++ b/gfx/wr/wrench/reftests/transforms/perspective-origin.yaml @@ -0,0 +1,16 @@ +--- +root: + items: + - + bounds: [0, 0, 1000, 1000] + type: "stacking-context" + perspective: 200 + items: + - + bounds: [0, 0, 1000, 1000] + type: "stacking-context" + transform: rotate-x(-45) + items: + - + bounds: [350, 400, 260, 260] + image: checkerboard(2, 16, 16) diff --git a/gfx/wr/wrench/reftests/transforms/perspective-shadow.png b/gfx/wr/wrench/reftests/transforms/perspective-shadow.png Binary files differnew file mode 100644 index 0000000000..07befbd35b --- /dev/null +++ b/gfx/wr/wrench/reftests/transforms/perspective-shadow.png diff --git a/gfx/wr/wrench/reftests/transforms/perspective-shadow.yaml b/gfx/wr/wrench/reftests/transforms/perspective-shadow.yaml new file mode 100644 index 0000000000..8b8e7c87d2 --- /dev/null +++ b/gfx/wr/wrench/reftests/transforms/perspective-shadow.yaml @@ -0,0 +1,27 @@ +--- +root: + items: + - + type: stacking-context + bounds: [0, 0, 0, 0] + transform: [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 139, 0, 1] + items: + - + type: stacking-context + bounds: [0, 0, 0, 0] + perspective: [1, 0, 0, 0, 0, 1, 0, 0, -299, -250, 1, -0.5, 0, 0, 0, 1] + items: + - + bounds: [0, 0, 0, 0] + type: stacking-context + transform: [10, 0, 0, 0, 0, 10, 0, 0, 0, 0, 1, 0, -5382, -3222, -18, 1] + items: + - + type: box-shadow + bounds: [548, 200, 100, 100] + color: 0 0 0 0.7020 + blur-radius: 20 + - + bounds: [548, 200, 100, 100] + type: rect + color: 0 255 0 1.0000 diff --git a/gfx/wr/wrench/reftests/transforms/perspective.png b/gfx/wr/wrench/reftests/transforms/perspective.png Binary files differnew file mode 100644 index 0000000000..79992dd892 --- /dev/null +++ b/gfx/wr/wrench/reftests/transforms/perspective.png diff --git a/gfx/wr/wrench/reftests/transforms/perspective.yaml b/gfx/wr/wrench/reftests/transforms/perspective.yaml new file mode 100644 index 0000000000..2ebd0899c6 --- /dev/null +++ b/gfx/wr/wrench/reftests/transforms/perspective.yaml @@ -0,0 +1,54 @@ +--- +root: + items: + - + type: "stacking-context" + items: + - + type: "stacking-context" + transform: [1, 0, 0, 0, -1.0606601, -0.35355338, 0.70710677, -0.0035355338, -1.0606601, -1.767767, 0.70710677, -0.0035355338, 306.06604, 335.35535, -70.71068, 1.3535534] + items: + - + bounds: [0, 0, 200, 200] + image: checkerboard(2, 16, 12) + stretch-size: 200 200 + - + type: "stacking-context" + transform: [3.1819804, 1.0606601, -0.70710677, 0.0035355338, 0, 1, 0, 0, -1.7677668, -1.0606601, 0.70710677, -0.0035355338, 381.80194, 93.93398, 70.71068, 0.6464466] + items: + - + bounds: [0, 0, 200, 200] + image: checkerboard(2, 16, 12) + stretch-size: 200 200 + - + type: "stacking-context" + transform: [3.182372, 1.088346, -0.4353384, 0.002176692, -1.0183089, 0.7350135, 0.10599462, -0.00052997307, -4.481691, -1.2350134, 0.89400536, -0.0044700266, 883.5937, 117.66405, 32.93438, 0.8353281] + items: + - + bounds: [0, 0, 200, 200] + image: checkerboard(2, 16, 12) + stretch-size: 200 200 + - + type: "stacking-context" + transform: [0.29134378, -0.9896399, 0.6324555, -0.0015811388, 0.3543281, 1.4948199, -0.31622776, 0.0007905694, -1.1627856, -0.92120904, 0.70710677, -0.0017677669, 235.43283, 649.48206, -31.622776, 1.079057] + items: + - + bounds: [0, 0, 200, 200] + image: checkerboard(2, 16, 12) + stretch-size: 200 200 + - + type: "stacking-context" + transform: [1, 0, 0, 0, 1, 1, 0, 0, -3.5, -3.5, 1, -0.005, 500, 600, 0, 1] + items: + - + bounds: [0, 0, 200, 200] + image: checkerboard(2, 16, 12) + stretch-size: 200 200 + - + type: "stacking-context" + transform: [0.82903755, 0.78133285, 0, 0, -0.5591929, 0.67920226, 0, 0, -5.5, -3.5, 1, -0.005, 1073.0155, 553.9465, 0, 1] + items: + - + bounds: [0, 0, 200, 200] + image: checkerboard(2, 16, 12) + stretch-size: 200 200 diff --git a/gfx/wr/wrench/reftests/transforms/prim-suite.png b/gfx/wr/wrench/reftests/transforms/prim-suite.png Binary files differnew file mode 100644 index 0000000000..131c3d4ac5 --- /dev/null +++ b/gfx/wr/wrench/reftests/transforms/prim-suite.png diff --git a/gfx/wr/wrench/reftests/transforms/prim-suite.yaml b/gfx/wr/wrench/reftests/transforms/prim-suite.yaml new file mode 100644 index 0000000000..241a2e1c0a --- /dev/null +++ b/gfx/wr/wrench/reftests/transforms/prim-suite.yaml @@ -0,0 +1,45 @@ +--- +root: + items: + - type: stacking-context + bounds: [50, 50, 100, 100] + transform: rotate(-30) + items: + - type: rect + bounds: [ 10, 10, 80, 80 ] + color: [0, 255, 0] + - type: box-shadow + bounds: [ 10, 10, 80, 80 ] + blur-radius: 25 + clip-mode: inset + + - type: rect + bounds: [ 140, 10, 80, 80 ] + color: [0, 255, 0] + - type: box-shadow + bounds: [ 140, 10, 80, 80 ] + blur-radius: 25 + clip-mode: outset + + - type: border + bounds: [ 250, 10, 100, 100 ] + width: [ 10, 10, 10, 10 ] + border-type: normal + style: solid + color: [ red, green, blue, black ] + radius: { + top-left: [20, 20], + top-right: [10, 10], + bottom-left: [25, 25], + bottom-right: [0, 0], + } + + - bounds: [150, 150, 128, 128] + image: checkerboard(4, 15, 8) + stretch-size: 128 128 + + - type: radial-gradient + bounds: 300 150 100 100 + center: 50 50 + radius: 50 50 + stops: [0, red, 1, blue] diff --git a/gfx/wr/wrench/reftests/transforms/raster-root-huge-scale.yaml b/gfx/wr/wrench/reftests/transforms/raster-root-huge-scale.yaml new file mode 100644 index 0000000000..fd63c63031 --- /dev/null +++ b/gfx/wr/wrench/reftests/transforms/raster-root-huge-scale.yaml @@ -0,0 +1,36 @@ +# Tests that raster roots with very large scaling factors do not cause device rects to overflow. +# See bug 1642440 +--- +root: + items: + - type: stacking-context + bounds: 0 0 0 0 + transform: perspective(1) scale(99999999) + transform-style: preserve-3d + filters: invert(1) + items: + - type: stacking-context + bounds: 0 0 0 0 + transform: perspective(1) scale(0.0000001) + transform-style: preserve-3d + items: + - type: clip + bounds: [0, 0, 60000, 60000] + clip-rect: [0, 0, 60000, 60000] + id: 2 + complex: + - rect: [0, 0, 100, 100] + radius: [20, 20] + "clip-mode": clip + - type: stacking-context + bounds: 0 0 0 0 + clip-and-scroll: 2 + items: + - rect: 0 0 100 100 + color: red + - type: box-shadow + bounds: 0 0 100 100 + color: blue + offset: 10 20 + blur-radius: 10 + border-radius: [ 20, 20, 20, 20 ] diff --git a/gfx/wr/wrench/reftests/transforms/raster-root-large-mask.yaml b/gfx/wr/wrench/reftests/transforms/raster-root-large-mask.yaml new file mode 100644 index 0000000000..4517f81651 --- /dev/null +++ b/gfx/wr/wrench/reftests/transforms/raster-root-large-mask.yaml @@ -0,0 +1,29 @@ +# Make sure we don't panic by trying to create an excessively large mask render task +# See bug 1637796 +--- +root: + items: + - type: stacking-context + bounds: 0 0 0 0 + transform: perspective(300) + items: + - type: stacking-context + bounds: 0 0 0 0 + transform-style: preserve-3d + transform: ["scale(0.001667, 0.001667)"] + items: + - type: clip + bounds: [10, 10, 60000, 60000] + clip-rect: [10, 10, 60000, 60000] + id: 2 + complex: + - rect: [10, 10, 60000, 60000] + radius: [10000, 10000] + "clip-mode": clip + - type: stacking-context + bounds: 0 0 0 0 + clip-and-scroll: 2 + items: + - type: rect + bounds: 0 0 60000 60000 + color: blue diff --git a/gfx/wr/wrench/reftests/transforms/raster-root-scaling-2-ref.yaml b/gfx/wr/wrench/reftests/transforms/raster-root-scaling-2-ref.yaml new file mode 100644 index 0000000000..925d81951e --- /dev/null +++ b/gfx/wr/wrench/reftests/transforms/raster-root-scaling-2-ref.yaml @@ -0,0 +1,11 @@ +# Tests that the correct device pixel scale is propagated to child surfaces. +# See bug 1639729 +--- +root: + items: + - type: stacking-context + bounds: [0, 0, 0, 0] + filters: invert(1) + items: + - image: checkerboard(2, 16, 16) + bounds: [0, 0, 260, 260] diff --git a/gfx/wr/wrench/reftests/transforms/raster-root-scaling-2.yaml b/gfx/wr/wrench/reftests/transforms/raster-root-scaling-2.yaml new file mode 100644 index 0000000000..6aebd744ce --- /dev/null +++ b/gfx/wr/wrench/reftests/transforms/raster-root-scaling-2.yaml @@ -0,0 +1,22 @@ +# Tests that the correct device pixel scale is propagated to child surfaces. +# See bug 1639729 +--- +root: + items: + - type: stacking-context + bounds: [0, 0, 0, 0] + # Force WebRender to form a raster root + transform: perspective(1000) + items: + - type: stacking-context + bounds: [0, 0, 0, 0] + transform-style: preserve-3d + transform: scale(10,10) + items: + - type: stacking-context + bounds: 0 0 0 0 + # Create a non-raster root surface + filters: invert(1) + items: + - image: checkerboard(2, 16, 16) + bounds: [0, 0, 26, 26] diff --git a/gfx/wr/wrench/reftests/transforms/raster-root-scaling-ref.yaml b/gfx/wr/wrench/reftests/transforms/raster-root-scaling-ref.yaml new file mode 100644 index 0000000000..5088e01756 --- /dev/null +++ b/gfx/wr/wrench/reftests/transforms/raster-root-scaling-ref.yaml @@ -0,0 +1,10 @@ + +# Tests that surfaces created by raster roots are scaled based on the surface to parent transform. +--- +root: + items: + - type: stacking-context + bounds: [0, 0, 0, 0] + items: + - image: checkerboard(2, 16, 16) + bounds: [0, 0, 260, 260] diff --git a/gfx/wr/wrench/reftests/transforms/raster-root-scaling.yaml b/gfx/wr/wrench/reftests/transforms/raster-root-scaling.yaml new file mode 100644 index 0000000000..3a592635a3 --- /dev/null +++ b/gfx/wr/wrench/reftests/transforms/raster-root-scaling.yaml @@ -0,0 +1,16 @@ +# Tests that surfaces created by raster roots are scaled based on the surface to parent transform. +--- +root: + items: + - type: stacking-context + bounds: [0, 0, 0, 0] + # Force WebRender to form a raster root + transform: perspective(1000) + items: + - type: stacking-context + bounds: [0, 0, 0, 0] + transform-style: preserve-3d + transform: scale(10,10) + items: + - image: checkerboard(2, 16, 16) + bounds: [0, 0, 26, 26] diff --git a/gfx/wr/wrench/reftests/transforms/raster_root_A_8192.yaml b/gfx/wr/wrench/reftests/transforms/raster_root_A_8192.yaml new file mode 100644 index 0000000000..034631d031 --- /dev/null +++ b/gfx/wr/wrench/reftests/transforms/raster_root_A_8192.yaml @@ -0,0 +1,20 @@ +root: + items: + - type: "stacking-context" + transform: scale(0.125) + items: + - type: "stacking-context" + perspective: 100 + perspective-origin: 100 50 + items: + - image: checkerboard(0, 512, 16); + bounds: [1600, 1600, 8192, 8192] + - type: "stacking-context" + bounds: [0, 0, 8192, 8192] + mix-blend-mode: difference + complex-clip: + rect: [2048, 2048, 4096, 4096] + radius: [1024, 1024] + items: + - image: checkerboard(0, 4096, 2); + bounds: [0, 0, 8192, 8192] diff --git a/gfx/wr/wrench/reftests/transforms/raster_root_A_ref.yaml b/gfx/wr/wrench/reftests/transforms/raster_root_A_ref.yaml new file mode 100644 index 0000000000..b5e28256bf --- /dev/null +++ b/gfx/wr/wrench/reftests/transforms/raster_root_A_ref.yaml @@ -0,0 +1,20 @@ +root: + items: + - type: "stacking-context" + transform: scale(0.5) + items: + - type: "stacking-context" + perspective: 100 + perspective-origin: 100 50 + items: + - image: checkerboard(0, 128, 16); + bounds: 400 400 2048 2048 + - type: "stacking-context" + bounds: [0, 0, 2048, 2048] + mix-blend-mode: difference + complex-clip: + rect: [512, 512, 1024, 1024] + radius: [256, 256] + items: + - image: checkerboard(0, 1024, 2); + bounds: [0, 0, 2048, 2048] diff --git a/gfx/wr/wrench/reftests/transforms/raster_root_B_8192.yaml b/gfx/wr/wrench/reftests/transforms/raster_root_B_8192.yaml new file mode 100644 index 0000000000..9f8a58f5cc --- /dev/null +++ b/gfx/wr/wrench/reftests/transforms/raster_root_B_8192.yaml @@ -0,0 +1,14 @@ +root: + items: + - type: stacking-context + bounds: [0, 0, 600, 600] + perspective: 100 + items: + - type: stacking-context + transform: rotate-z(20) rotate-x(60) + filters: [invert(1)] + mix-blend-mode: difference + items: + - type: rect + bounds: [0, 0, 20000, 100] + color: [20, 120, 18, 1.0] diff --git a/gfx/wr/wrench/reftests/transforms/raster_root_B_ref.yaml b/gfx/wr/wrench/reftests/transforms/raster_root_B_ref.yaml new file mode 100644 index 0000000000..3fea3a19db --- /dev/null +++ b/gfx/wr/wrench/reftests/transforms/raster_root_B_ref.yaml @@ -0,0 +1,14 @@ +root: + items: + - type: stacking-context + bounds: [0, 0, 600, 600] + perspective: 100 + items: + - type: stacking-context + transform: rotate-z(20) rotate-x(60) + filters: [invert(1)] + mix-blend-mode: difference + items: + - type: rect + bounds: [0, 0, 4000, 100] + color: [20, 120, 18, 1.0] diff --git a/gfx/wr/wrench/reftests/transforms/reftest.list b/gfx/wr/wrench/reftests/transforms/reftest.list new file mode 100644 index 0000000000..256b63e989 --- /dev/null +++ b/gfx/wr/wrench/reftests/transforms/reftest.list @@ -0,0 +1,55 @@ +platform(linux,mac) == local-clip.yaml local-clip.png +platform(linux,mac) == rotated-clip.yaml rotated-clip.png +platform(linux,mac) == rotated-clip-large.yaml rotated-clip-large.png +platform(linux,mac) == image-rotated-clip.yaml image-rotated-clip.png +# Something leaks the state: the test passes if only run `reftest reftests/transform` +# but fails when all the tests are run +platform(linux,mac) fuzzy(1,6) == rotated-image.yaml rotated-image.png +== singular.yaml singular-ref.yaml +platform(linux) fuzzy(1,630) == perspective.yaml perspective.png +platform(linux,mac) fuzzy(1,156) == prim-suite.yaml prim-suite.png +== segments-bug.yaml segments-bug-ref.yaml +platform(linux,mac) == content-offset.yaml content-offset.png +platform(linux,mac) == coord-system.yaml coord-system.png +platform(linux,mac) fuzzy(1,15) zoom(4) == border-zoom.yaml border-zoom.png +platform(linux) fuzzy(1,520) == perspective-origin.yaml perspective-origin.png +platform(linux,mac) color_targets(3) alpha_targets(0) fuzzy(1,180) == screen-space-blit.yaml screen-space-blit.png +platform(linux,mac) fuzzy(1,346) color_targets(2) alpha_targets(0) == screen-space-blit-trivial.yaml screen-space-blit-trivial.png +platform(linux) fuzzy(11,4592) == screen-space-blur.yaml screen-space-blur.png +platform(linux,mac) fuzzy(1,25) == nested-rotate-x.yaml nested-rotate-x.png +platform(linux,mac) != nested-rotate-x.yaml nested-rotate-x-flat.yaml +platform(linux,mac) fuzzy(1,25) == nested-rotate-x-flat.yaml nested-rotate-x-flat.png +platform(linux,mac) fuzzy(1,25) == nested-preserve-3d.yaml nested-preserve-3d.png +platform(linux,mac) fuzzy(1,283) == near-plane-clip.yaml near-plane-clip.png +platform(linux,mac) == perspective-mask.yaml perspective-mask.png +== rotate-clip.yaml rotate-clip-ref.yaml +== clip-translate.yaml clip-translate-ref.yaml +platform(linux,mac) fuzzy(1,1) == perspective-clip.yaml perspective-clip.png +platform(linux,mac) fuzzy(1,2) == perspective-clip-1.yaml perspective-clip-1.png +platform(linux,mac) fuzzy(1,2) == perspective-shadow.yaml perspective-shadow.png +# The ref YAML here produces significantly worse quality +fuzzy(200,4200) == perspective-box-shadow.yaml perspective-box-shadow-ref.yaml +== complex-preserve-3d.yaml blank.yaml +platform(linux,mac) fuzzy(9,348) == perspective-border-radius.yaml perspective-border-radius.png +fuzzy(1,38) == snapped-preserve-3d.yaml snapped-preserve-3d-ref.yaml +platform(linux,mac) fuzzy(1,122) == border-scale.yaml border-scale.png +platform(linux,mac) fuzzy(1,16) == border-scale-2.yaml border-scale-2.png +platform(linux,mac) fuzzy(1,69) == border-scale-3.yaml border-scale-3.png +platform(linux,mac) fuzzy(1,74) == border-scale-4.yaml border-scale-4.png +# Just make sure we aren't crashing here +!= large-raster-root.yaml blank.yaml +== flatten-preserve-3d-root.yaml flatten-preserve-3d-root-ref.yaml +== flatten-twice.yaml flatten-twice-ref.yaml +== strange-w.yaml strange-w-ref.yaml +== big-axis-aligned-scale.yaml big-axis-aligned-scale-ref.yaml +# Compare ~8K raster root (>MAX_SURFACE_SIZE) with ~2K raster root. fuzzy due to lerping on edges. +skip_on(android) fuzzy-range(<=3,*3077,<=10,*133,<=93,*490) == raster_root_A_8192.yaml raster_root_A_ref.yaml +# Same as large-raster-root.yaml but resulting in a 10302×100 raster root (= >4096) vs 4000x100 in ref: +skip_on(android) fuzzy(60,917) == raster_root_B_8192.yaml raster_root_B_ref.yaml +# Make sure we don't panic +!= raster-root-large-mask.yaml blank.yaml +skip_on(android) == raster-root-scaling.yaml raster-root-scaling-ref.yaml +skip_on(android) == raster-root-scaling-2.yaml raster-root-scaling-2-ref.yaml +# Make sure we don't panic +!= raster-root-huge-scale.yaml blank.yaml +!= non-inversible-world-rect.yaml blank.yaml diff --git a/gfx/wr/wrench/reftests/transforms/rotate-clip-ref.yaml b/gfx/wr/wrench/reftests/transforms/rotate-clip-ref.yaml new file mode 100644 index 0000000000..133279fca8 --- /dev/null +++ b/gfx/wr/wrench/reftests/transforms/rotate-clip-ref.yaml @@ -0,0 +1,7 @@ +--- +root: + items: + - + bounds: [100, 146, 150, 107] + type: rect + color: 0 128 0 1.0000 diff --git a/gfx/wr/wrench/reftests/transforms/rotate-clip.yaml b/gfx/wr/wrench/reftests/transforms/rotate-clip.yaml new file mode 100644 index 0000000000..209d53d103 --- /dev/null +++ b/gfx/wr/wrench/reftests/transforms/rotate-clip.yaml @@ -0,0 +1,18 @@ +--- +root: + items: + - + type: clip + bounds: [0, 0, 2000, 2000] + clip-rect: [0, 0, 2000, 2000] + items: + - + bounds: [100, 0, 150, 150] + type: "stacking-context" + transform: rotate-x(45) + transform-origin: [0, 500] + items: + - + bounds: [0, 0, 150, 150] + type: rect + color: 0 128 0 1.0000 diff --git a/gfx/wr/wrench/reftests/transforms/rotated-clip-large.png b/gfx/wr/wrench/reftests/transforms/rotated-clip-large.png Binary files differnew file mode 100644 index 0000000000..5d5757237e --- /dev/null +++ b/gfx/wr/wrench/reftests/transforms/rotated-clip-large.png diff --git a/gfx/wr/wrench/reftests/transforms/rotated-clip-large.yaml b/gfx/wr/wrench/reftests/transforms/rotated-clip-large.yaml new file mode 100644 index 0000000000..ec57e6c697 --- /dev/null +++ b/gfx/wr/wrench/reftests/transforms/rotated-clip-large.yaml @@ -0,0 +1,17 @@ +--- +root: + items: + - + bounds: 100 100 300 300 + items: + - type: clip + bounds: [20, 20, 200, 200] + complex: + - rect: [20, 20, 200, 200] + radius: 32 + items: + - type: rect + bounds: 20 20 200 200 + color: blue + type: stacking-context + transform: rotate(-33) diff --git a/gfx/wr/wrench/reftests/transforms/rotated-clip.png b/gfx/wr/wrench/reftests/transforms/rotated-clip.png Binary files differnew file mode 100644 index 0000000000..33d2771d3a --- /dev/null +++ b/gfx/wr/wrench/reftests/transforms/rotated-clip.png diff --git a/gfx/wr/wrench/reftests/transforms/rotated-clip.yaml b/gfx/wr/wrench/reftests/transforms/rotated-clip.yaml new file mode 100644 index 0000000000..a4305e6449 --- /dev/null +++ b/gfx/wr/wrench/reftests/transforms/rotated-clip.yaml @@ -0,0 +1,17 @@ +--- +root: + items: + - + bounds: 100 100 100 100 + items: + - type: clip + bounds: [20, 20, 100, 100] + complex: + - rect: [20, 20, 100, 100] + radius: 32 + items: + - type: rect + bounds: 20 20 100 100 + color: blue + type: stacking-context + transform: rotate(-30) diff --git a/gfx/wr/wrench/reftests/transforms/rotated-image.png b/gfx/wr/wrench/reftests/transforms/rotated-image.png Binary files differnew file mode 100644 index 0000000000..0374b9ad66 --- /dev/null +++ b/gfx/wr/wrench/reftests/transforms/rotated-image.png diff --git a/gfx/wr/wrench/reftests/transforms/rotated-image.yaml b/gfx/wr/wrench/reftests/transforms/rotated-image.yaml new file mode 100644 index 0000000000..5ab5d3b757 --- /dev/null +++ b/gfx/wr/wrench/reftests/transforms/rotated-image.yaml @@ -0,0 +1,75 @@ +--- +root: + items: + - + bounds: [0, 0, 2880, 1482] + "clip-rect": [0, 0, 2880, 1482] + "backface-visible": true + type: rect + color: white + - + bounds: [0, 0, 2880, 1482] + "clip-rect": [0, 0, 2880, 1482] + "backface-visible": true + type: clip + id: 10 + "content-size": [2880, 1482] + - + "clip-rect": [0, 0, 2880, 1482] + "clip-and-scroll": 10 + "backface-visible": true + type: "scroll-frame" + id: 2 + "content-size": [2880, 1482] + bounds: [0, 0, 2880, 1482] + - + bounds: [0, 0, 2880, 1482] + "clip-rect": [0, 0, 2880, 1482] + "clip-and-scroll": 2 + "backface-visible": true + type: clip + id: 3 + "content-size": [2880, 1482] + - + bounds: [0, 0, 2880, 1482] + "clip-rect": [0, 0, 2880, 1482] + "clip-and-scroll": 3 + "backface-visible": true + type: rect + color: white + - + bounds: [0, 0, 0, 0] + "clip-rect": [0, 0, 0, 0] + "clip-and-scroll": 3 + "backface-visible": true + type: "stacking-context" + "scroll-policy": scrollable + transform: rotate-z(-1) + "transform-style": flat + items: + - + bounds: [2, 2, 200, 200] + "clip-rect": [2, 2, 200, 200] + "backface-visible": true + type: clip + id: 4 + "content-size": [200, 200] + - + bounds: [2, -182, 152, 216] + "clip-rect": [2, 0, 152, 34] + "clip-and-scroll": 4 + "backface-visible": true + image: "image.png" + "stretch-size": [152, 216] + "tile-spacing": [0, 0] + - + bounds: [0, 0, 204, 204] + "clip-rect": [0, 0, 204, 204] + "backface-visible": true + type: border + width: 2 + "border-type": normal + color: 0 0 255 1.0000 + style: solid + id: [1, 1] +pipelines: [] diff --git a/gfx/wr/wrench/reftests/transforms/screen-space-blit-trivial.png b/gfx/wr/wrench/reftests/transforms/screen-space-blit-trivial.png Binary files differnew file mode 100644 index 0000000000..ee1a8cc736 --- /dev/null +++ b/gfx/wr/wrench/reftests/transforms/screen-space-blit-trivial.png diff --git a/gfx/wr/wrench/reftests/transforms/screen-space-blit-trivial.yaml b/gfx/wr/wrench/reftests/transforms/screen-space-blit-trivial.yaml new file mode 100644 index 0000000000..76b2578faa --- /dev/null +++ b/gfx/wr/wrench/reftests/transforms/screen-space-blit-trivial.yaml @@ -0,0 +1,22 @@ +# This test is similar to "screen-space-blit" but without filters, +# so the implementation doesn't attempt to bake the contents +# into a separate render target. +--- +root: + items: + - type: "stacking-context" + perspective: 100 + perspective-origin: 100 100 + items: + - type: "stacking-context" + transform-origin: 235 235 + transform: rotate-x(-15) + items: + - image: checkerboard(2, 16, 16) + bounds: [100, 100, 260, 260] + - type: "stacking-context" + transform-origin: 635 235 + transform: rotate-z(-45) + items: + - image: checkerboard(2, 16, 16) + bounds: [500, 100, 260, 260] diff --git a/gfx/wr/wrench/reftests/transforms/screen-space-blit.png b/gfx/wr/wrench/reftests/transforms/screen-space-blit.png Binary files differnew file mode 100644 index 0000000000..9506d174c6 --- /dev/null +++ b/gfx/wr/wrench/reftests/transforms/screen-space-blit.png diff --git a/gfx/wr/wrench/reftests/transforms/screen-space-blit.yaml b/gfx/wr/wrench/reftests/transforms/screen-space-blit.yaml new file mode 100644 index 0000000000..0bae3a3736 --- /dev/null +++ b/gfx/wr/wrench/reftests/transforms/screen-space-blit.yaml @@ -0,0 +1,22 @@ +# This test uses `identity` filter on a preserve3D context to test how +# filters mix up with the SC's baking for preserve3d. +--- +root: + items: + - type: "stacking-context" + perspective: 100 + perspective-origin: 100 100 + items: + - type: "stacking-context" + transform-origin: 235 235 + transform: rotate-x(-15) + filters: identity + items: + - image: checkerboard(2, 16, 16) + bounds: [100, 100, 260, 260] + - type: "stacking-context" + transform-origin: 635 235 + transform: rotate-z(-45) + items: + - image: checkerboard(2, 16, 16) + bounds: [500, 100, 260, 260] diff --git a/gfx/wr/wrench/reftests/transforms/screen-space-blur.png b/gfx/wr/wrench/reftests/transforms/screen-space-blur.png Binary files differnew file mode 100644 index 0000000000..cfa1a7eb4d --- /dev/null +++ b/gfx/wr/wrench/reftests/transforms/screen-space-blur.png diff --git a/gfx/wr/wrench/reftests/transforms/screen-space-blur.yaml b/gfx/wr/wrench/reftests/transforms/screen-space-blur.yaml new file mode 100644 index 0000000000..6d93260c83 --- /dev/null +++ b/gfx/wr/wrench/reftests/transforms/screen-space-blur.yaml @@ -0,0 +1,20 @@ +root: + items: + - type: "stacking-context" + perspective: 100 + perspective-origin: 100 100 + items: + - type: "stacking-context" + transform-origin: 235 235 + transform: rotate-x(-15) + filters: blur(3, 3) + items: + - image: checkerboard(2, 16, 16) + bounds: [100, 100, 260, 260] + - type: "stacking-context" + transform-origin: 635 235 + transform: rotate-z(-45) + filters: blur(3, 3) + items: + - image: checkerboard(2, 16, 16) + bounds: [500, 100, 260, 260] diff --git a/gfx/wr/wrench/reftests/transforms/segments-bug-ref.yaml b/gfx/wr/wrench/reftests/transforms/segments-bug-ref.yaml new file mode 100644 index 0000000000..aad75347ed --- /dev/null +++ b/gfx/wr/wrench/reftests/transforms/segments-bug-ref.yaml @@ -0,0 +1,24 @@ +--- +root: + items: + - + type: "stacking-context" + items: + - + bounds: [12, 12, 130, 130] + type: clip + id: 4 + complex: + - + rect: [12, 12, 130, 130] + radius: 20 + "clip-mode": clip + - + clip-and-scroll: 4 + type: "stacking-context" + items: + - + bounds: [12, 12, 130, 130] + clip-and-scroll: 4 + type: rect + color: 0 128 0 1.0000 diff --git a/gfx/wr/wrench/reftests/transforms/segments-bug.yaml b/gfx/wr/wrench/reftests/transforms/segments-bug.yaml new file mode 100644 index 0000000000..72130413fc --- /dev/null +++ b/gfx/wr/wrench/reftests/transforms/segments-bug.yaml @@ -0,0 +1,27 @@ +# Test that opaque/alpha segments are correctly calculated +# when the clip is in a different (but compatible) coordinate +# space from the primitive. +--- +root: + items: + - + type: "stacking-context" + items: + - + bounds: [12, 12, 130, 130] + type: clip + id: 4 + complex: + - + rect: [12, 12, 130, 130] + radius: 20 + "clip-mode": clip + - + "clip-and-scroll": 4 + type: "stacking-context" + transform: [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 12, 12, 0, 1] + items: + - + bounds: [0, 0, 130, 130] + type: rect + color: 0 128 0 1.0000 diff --git a/gfx/wr/wrench/reftests/transforms/singular-ref.yaml b/gfx/wr/wrench/reftests/transforms/singular-ref.yaml new file mode 100644 index 0000000000..8401017c0d --- /dev/null +++ b/gfx/wr/wrench/reftests/transforms/singular-ref.yaml @@ -0,0 +1,28 @@ +--- +root: + items: + - + bounds: [0, 0, 200, 200] + "clip-rect": [0, 0, 200, 200] + type: clip + id: 2 + "content-size": [200, 200] + - + bounds: [0, 100, 100, 100] + "clip-rect": [0, 100, 100, 100] + "clip-and-scroll": 2 + type: rect + color: blue + - + bounds: [100, 0, 100, 100] + "clip-rect": [100, 0, 100, 100] + "clip-and-scroll": 2 + type: rect + color: green + - + bounds: [100, 100, 100, 100] + "clip-rect": [100, 100, 100, 100] + "clip-and-scroll": 2 + type: rect + color: red + diff --git a/gfx/wr/wrench/reftests/transforms/singular.yaml b/gfx/wr/wrench/reftests/transforms/singular.yaml new file mode 100644 index 0000000000..78d133b3ab --- /dev/null +++ b/gfx/wr/wrench/reftests/transforms/singular.yaml @@ -0,0 +1,39 @@ +--- +root: + items: + - + bounds: [0, 0, 200, 200] + "clip-rect": [0, 0, 200, 200] + type: clip + id: 2 + "content-size": [200, 200] + - + bounds: [10, 10, 80, 80] + clip-and-scroll: 2 + type: "stacking-context" + transform: [0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1] + items: + - + bounds: [0, 0, 80, 80] + "clip-rect": [0, 0, 80, 80] + type: rect + color: black + - + bounds: [0, 100, 100, 100] + "clip-rect": [0, 100, 100, 100] + clip-and-scroll: 2 + type: rect + color: blue + - + bounds: [100, 0, 100, 100] + "clip-rect": [100, 0, 100, 100] + clip-and-scroll: 2 + type: rect + color: green + - + bounds: [100, 100, 100, 100] + "clip-rect": [100, 100, 100, 100] + clip-and-scroll: 2 + type: rect + color: red + diff --git a/gfx/wr/wrench/reftests/transforms/snapped-preserve-3d-ref.yaml b/gfx/wr/wrench/reftests/transforms/snapped-preserve-3d-ref.yaml new file mode 100644 index 0000000000..a2e8972981 --- /dev/null +++ b/gfx/wr/wrench/reftests/transforms/snapped-preserve-3d-ref.yaml @@ -0,0 +1,19 @@ +--- +root: + items: + - + type: "stacking-context" + transform: translate(10, 10.5, 0) + items: + - + type: "stacking-context" + transform: translate(10, 10, 0) + items: + - + bounds: [10, 10.5, 200, 1] + type: rect + color: red + - + bounds: [10, 0, 200, 1] + type: rect + color: red diff --git a/gfx/wr/wrench/reftests/transforms/snapped-preserve-3d.yaml b/gfx/wr/wrench/reftests/transforms/snapped-preserve-3d.yaml new file mode 100644 index 0000000000..cd2cd8b1a7 --- /dev/null +++ b/gfx/wr/wrench/reftests/transforms/snapped-preserve-3d.yaml @@ -0,0 +1,21 @@ +--- +root: + items: + - + type: "stacking-context" + transform: translate(10, 10.5, 0) + "transform-style": "preserve-3d" + items: + - + type: "stacking-context" + transform: translate(10, 10, 0) + "transform-style": "preserve-3d" + items: + - + bounds: [10, 10.5, 200, 1] + type: rect + color: red + - + bounds: [10, 0, 200, 1] + type: rect + color: red diff --git a/gfx/wr/wrench/reftests/transforms/strange-w-ref.yaml b/gfx/wr/wrench/reftests/transforms/strange-w-ref.yaml new file mode 100644 index 0000000000..be50589d2a --- /dev/null +++ b/gfx/wr/wrench/reftests/transforms/strange-w-ref.yaml @@ -0,0 +1,12 @@ +--- +root: + items: + - type: stacking-context + bounds: [50, 50, 600, 600] + perspective: 20 + items: + - type: stacking-context + items: + - type: rect + bounds: [25, 25, 50, 50] + color: red diff --git a/gfx/wr/wrench/reftests/transforms/strange-w.yaml b/gfx/wr/wrench/reftests/transforms/strange-w.yaml new file mode 100644 index 0000000000..8e2a71b197 --- /dev/null +++ b/gfx/wr/wrench/reftests/transforms/strange-w.yaml @@ -0,0 +1,15 @@ +# don't assume w=1 when checking if the transform is just a translation + +--- +root: + items: + - type: stacking-context + bounds: [50, 50, 600, 600] + perspective: 20 + items: + - type: stacking-context + transform: [1,0,0,0, 0,1,0,0, 0,0,1,0, 0,0,0,2] + items: + - type: rect + bounds: [50, 50, 100, 100] + color: red diff --git a/gfx/wr/wrench/res/wrench.exe.manifest b/gfx/wr/wrench/res/wrench.exe.manifest new file mode 100644 index 0000000000..223d04d93f --- /dev/null +++ b/gfx/wr/wrench/res/wrench.exe.manifest @@ -0,0 +1,24 @@ +<?xml version="1.0" encoding="UTF-8" standalone="yes"?> +<assembly xmlns="urn:schemas-microsoft-com:asm.v1" + manifestVersion="1.0" + xmlns:asmv3="urn:schemas-microsoft-com:asm.v3"> + <assemblyIdentity type="win32" + name="webrender.Wrench" + version="0.1.0.0"/> + + <compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1"> + <application> + <supportedOS Id="{35138b9a-5d96-4fbd-8e2d-a2440225f93a}"/> <!-- Windows 7 --> + <supportedOS Id="{4a2f28e3-53b9-4441-ba9c-d69d4a4a6e38}"/> <!-- Windows 8 --> + <supportedOS Id="{1f676c76-80e1-4239-95bb-83d0f6d0da78}"/> <!-- Windows 8.1 --> + <supportedOS Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}"/> <!-- Windows 10 --> + </application> + </compatibility> + + <asmv3:application> + <asmv3:windowsSettings xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings"> + <dpiAware>true</dpiAware> + </asmv3:windowsSettings> + </asmv3:application> +</assembly> + diff --git a/gfx/wr/wrench/script/benchmark_server.py b/gfx/wr/wrench/script/benchmark_server.py new file mode 100644 index 0000000000..b735b4380d --- /dev/null +++ b/gfx/wr/wrench/script/benchmark_server.py @@ -0,0 +1,59 @@ +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + +from __future__ import print_function +import json +import os +import subprocess +import time +import urllib2 + +FILE = 'perf.json' +URL = 'https://wrperf.org/submit' + +while True: + try: + # Remove any previous results + try: + os.remove(FILE) + except: + pass + + # Pull latest code + subprocess.call(["git", "pull"]) + + # Get the git revision of this build + revision = subprocess.check_output(["git", "rev-parse", "HEAD"]).strip() + + # Build + subprocess.call(["cargo", "build", "--release"]) + + # Run benchmarks + env = os.environ.copy() + # Ensure that vsync is disabled, to get meaningful 'composite' times. + env['vblank_mode'] = '0' + subprocess.call(["cargo", "run", "--release", "--", "perf", FILE], env=env) + + # Read the results + with open(FILE) as file: + results = json.load(file) + + # Post the results to server + payload = { + 'key': env['WEBRENDER_PERF_KEY'], + 'revision': revision, + 'timestamp': str(time.time()), + 'tests': results['tests'], + } + + req = urllib2.Request(URL, + headers={"Content-Type": "application/json"}, + data=json.dumps(payload)) + + f = urllib2.urlopen(req) + except Exception as e: + print(e) + + # Delay a bit until next benchmark + time.sleep(60 * 60) diff --git a/gfx/wr/wrench/script/gen-many-images.py b/gfx/wr/wrench/script/gen-many-images.py new file mode 100644 index 0000000000..bd97ad05c2 --- /dev/null +++ b/gfx/wr/wrench/script/gen-many-images.py @@ -0,0 +1,15 @@ +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + +SIZE = 8 + +with open("../benchmarks/many-images.yaml", "w") as text_file: + text_file.write("root:\n") + text_file.write(" items:\n") + for y in range(0, 64): + yb = SIZE * y + for x in range(0, 128): + xb = SIZE * x + text_file.write(" - image: solid-color({0}, {1}, 0, 255, {2}, {2})\n".format(x, y, SIZE)) + text_file.write(" bounds: {0} {1} {2} {2}\n".format(xb, yb, SIZE)) diff --git a/gfx/wr/wrench/script/headless.py b/gfx/wr/wrench/script/headless.py new file mode 100755 index 0000000000..109fca1cb2 --- /dev/null +++ b/gfx/wr/wrench/script/headless.py @@ -0,0 +1,152 @@ +#!/usr/bin/python + +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + +# Build and run wrench with off-screen software rendering (OSMesa/LLVMpipe) +# for platform-independent results. This is good for running reference tests. +# +# Usage: headless.py ARGS +# +# Pass ARGS through to wrench, after '--headless' and '--no-scissor'. +# +# Environment variables: +# +# WRENCH_HEADLESS_TARGET: If set, don't rebuild wrench. Instead, the value should +# be the path to an already-built cargo 'target' directory. This is useful +# for running a cross-compiled wrench. +# +# CARGOFLAGS: Extra flags to be passed to 'cargo build'. Split on whitespace. +# +# OPTIMIZED: This script uses the release build by default, but if this variable +# is set to '0' or 'false', the script uses the debug build. +# +# DEBUGGER: If set, run wrench under a debugger. Permitted values are 'rr' (run +# under 'rr record'), or 'gdb', 'rust-gdb', or 'cgdb' (run under the given +# debugger, and arrange to supply ARGS to the wrench debuggee, not the +# debugger) + +from __future__ import print_function +import contextlib +import os +import subprocess +import sys +from os import path +from glob import glob + + +@contextlib.contextmanager +def cd(new_path): + """Context manager for changing the current working directory""" + previous_path = os.getcwd() + try: + os.chdir(new_path) + yield + finally: + os.chdir(previous_path) + + +def find_dep_path_newest(package, bin_path): + deps_path = path.join(path.split(bin_path)[0], "build") + with cd(deps_path): + candidates = glob(package + '-*') + candidates = (path.join(deps_path, c) for c in candidates) + """ For some reason cargo can create an extra osmesa-src without libs """ + candidates = (c for c in candidates if path.exists(path.join(c, 'out'))) + candidate_times = sorted(((path.getmtime(c), c) for c in candidates), reverse=True) + if len(candidate_times) > 0: + return candidate_times[0][1] + return None + + +def is_windows(): + """ Detect windows, mingw, cygwin """ + return sys.platform == 'win32' or sys.platform == 'msys' or sys.platform == 'cygwin' + + +def is_macos(): + return sys.platform == 'darwin' + + +def is_linux(): + return sys.platform.startswith('linux') + + +def debugger(): + if "DEBUGGER" in os.environ: + return os.environ["DEBUGGER"] + return None + + +def use_gdb(): + return debugger() in ['gdb', 'cgdb', 'rust-gdb'] + + +def use_rr(): + return debugger() == 'rr' + + +def optimized_build(): + if "OPTIMIZED" in os.environ: + opt = os.environ["OPTIMIZED"] + return opt not in ["0", "false"] + return True + + +def set_osmesa_env(bin_path): + """Set proper LD_LIBRARY_PATH and DRIVE for software rendering on Linux and OSX""" + base = find_dep_path_newest('osmesa-src', bin_path) + osmesa_path = path.join(base, "out", "mesa", "src", "gallium", "targets", "osmesa") + os.environ["GALLIUM_DRIVER"] = "llvmpipe" + if is_linux(): + print(osmesa_path) + os.environ["LD_LIBRARY_PATH"] = osmesa_path + elif is_macos(): + osmesa_path = path.join(base, "out", "mesa", "src", "gallium", "targets", "osmesa") + glapi_path = path.join(base, "out", "mesa", "src", "mapi", "shared-glapi") + os.environ["DYLD_LIBRARY_PATH"] = osmesa_path + ":" + glapi_path + + +extra_flags = os.getenv('CARGOFLAGS', None) +extra_flags = extra_flags.split(' ') if extra_flags else [] + +wrench_headless_target = os.getenv('WRENCH_HEADLESS_TARGET', None) + +if wrench_headless_target: + target_folder = wrench_headless_target +else: + target_folder = '../target/' + +if optimized_build(): + target_folder += 'release/' +else: + target_folder += 'debug/' + +# For CI purposes, don't build if WRENCH_HEADLESS_TARGET is set. +# This environment variable is used to point to the location of a cross-compiled +# wrench for the CI on some platforms. +if not wrench_headless_target: + build_cmd = ['cargo', 'build'] + extra_flags + ['--verbose', '--features', 'headless'] + if optimized_build(): + build_cmd += ['--release'] + subprocess.check_call(build_cmd) + +dbg_cmd = [] +if use_rr(): + dbg_cmd = ['rr', 'record'] +elif use_gdb(): + dbg_cmd = [debugger(), '--args'] +elif debugger(): + print("Unknown debugger: " + debugger()) + sys.exit(1) + +set_osmesa_env(target_folder) +# TODO(gw): We have an occasional accuracy issue or bug (could be WR or OSMesa) +# where the output of a previous test that uses intermediate targets can +# cause 1.0 / 255.0 pixel differences in a subsequent test. For now, we +# run tests with no-scissor mode, which ensures a complete target clear +# between test runs. But we should investigate this further... +cmd = dbg_cmd + [target_folder + 'wrench', '--no-scissor', '--headless'] + sys.argv[1:] +print('Running: `' + ' '.join(cmd) + '`') +subprocess.check_call(cmd, stderr=subprocess.STDOUT) diff --git a/gfx/wr/wrench/script/reftest-analyzer.xhtml b/gfx/wr/wrench/script/reftest-analyzer.xhtml new file mode 100644 index 0000000000..9fad3544b3 --- /dev/null +++ b/gfx/wr/wrench/script/reftest-analyzer.xhtml @@ -0,0 +1,857 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- -*- Mode: HTML; tab-width: 2; indent-tabs-mode: nil; -*- --> +<!-- vim: set shiftwidth=2 tabstop=2 autoindent expandtab: --> +<!-- This Source Code Form is subject to the terms of the Mozilla Public + - License, v. 2.0. If a copy of the MPL was not distributed with this + - file, You can obtain one at http://mozilla.org/MPL/2.0/. --> +<!-- + +Features to add: +* make the left and right parts of the viewer independently scrollable +* make the test list filterable +** default to only showing unexpecteds +* add other ways to highlight differences other than circling? +* add zoom/pan to images +* Add ability to load log via XMLHttpRequest (also triggered via URL param) +* color the test list based on pass/fail and expected/unexpected/random/skip +* ability to load multiple logs ? +** rename them by clicking on the name and editing +** turn the test list into a collapsing tree view +** move log loading into popup from viewer UI + +--> +<!DOCTYPE html> +<html lang="en-US" xml:lang="en-US" xmlns="http://www.w3.org/1999/xhtml"> +<head> + <title>Reftest analyzer</title> + <style type="text/css"><![CDATA[ + + html, body { margin: 0; } + html { padding: 0; } + body { padding: 4px; } + + #pixelarea, #itemlist, #images { position: absolute; } + #itemlist, #images { overflow: auto; } + #pixelarea { top: 0; left: 0; width: 320px; height: 84px; overflow: visible } + #itemlist { top: 84px; left: 0; width: 320px; bottom: 0; } + #images { top: 0; bottom: 0; left: 320px; right: 0; } + + #leftpane { width: 320px; } + #images { position: fixed; top: 10px; left: 340px; } + + form#imgcontrols { margin: 0; display: block; } + + #itemlist > table { border-collapse: collapse; } + #itemlist > table > tbody > tr > td { border: 1px solid; padding: 1px; } + #itemlist td.activeitem { background-color: yellow; } + + /* + #itemlist > table > tbody > tr.pass > td.url { background: lime; } + #itemlist > table > tbody > tr.fail > td.url { background: red; } + */ + + #magnification > svg { display: block; width: 84px; height: 84px; } + + #pixelinfo { font: small sans-serif; position: absolute; width: 200px; left: 84px; } + #pixelinfo table { border-collapse: collapse; } + #pixelinfo table th { white-space: nowrap; text-align: left; padding: 0; } + #pixelinfo table td { font-family: monospace; padding: 0 0 0 0.25em; } + + #pixelhint { display: inline; color: #88f; cursor: help; } + #pixelhint > * { display: none; position: absolute; margin: 8px 0 0 8px; padding: 4px; width: 400px; background: #ffa; color: black; box-shadow: 3px 3px 2px #888; z-index: 1; } + #pixelhint:hover { color: #000; } + #pixelhint:hover > * { display: block; } + #pixelhint p { margin: 0; } + #pixelhint p + p { margin-top: 1em; } + + ]]></style> + <script type="text/javascript"><![CDATA[ + +let heatmapCanvas = null; +let heatmapUMouse; +let gl = null; + +function heatmap_render_setup(canvas) { + gl = canvas.getContext('webgl', {antialias: false, depth: false, preserveDrawingBuffer:false}); + + const vertices = [ + 0, 0, + 1, 0, + 0, 1, + 1, 1, + ]; + + const vertexBuffer = gl.createBuffer(); + gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer); + gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vertices), gl.STATIC_DRAW); + + const vsCode = + ` + attribute vec2 a_vertCoord; + varying vec2 v_texCoord; + void main(void) { + gl_Position = vec4(2.0 * a_vertCoord - 1.0, 0.0, 1.0); + v_texCoord = a_vertCoord; + }`; + + const VS = gl.createShader(gl.VERTEX_SHADER); + gl.shaderSource(VS, vsCode); + gl.compileShader(VS); + + const psCode = + ` + precision mediump float; + uniform vec2 heatmapUMouse; + varying vec2 v_texCoord; + uniform sampler2D u_image1, u_image2; + void main(void) { + vec2 dxy = abs(heatmapUMouse - gl_FragCoord.xy); + if(dxy.x < 1.0 || dxy.y < 1.0) { // crosshair + gl_FragColor = vec4( 1.0, 1.0, 0.5, 1.0 ); + return; + } + + vec3 img1 = texture2D(u_image1, v_texCoord).rgb; + vec3 img2 = texture2D(u_image2, v_texCoord).rgb; + + bool is_top = gl_FragCoord.y > float(heatmapUMouse.y); + bool is_left = gl_FragCoord.x < float(heatmapUMouse.x); + + vec3 rgb; + if(is_top) { + if(is_left) { + rgb = img1; + } else { + rgb = img2; + } + } else { + vec3 diff = abs(img1 - img2); + if(is_left) { + rgb = diff; + } else { + float max_diff = max(diff.r, max(diff.g, diff.b)); + if(max_diff == 0.0) { + rgb = vec3(0.0, 0.0, 0.2); + } else { + // some arbitrary colorization -- transition from green to red + // with some contrast tweaks to make red stand out a bit more + // at about 0.5'ish + rgb = vec3( pow(max_diff, 0.5), pow(1.0 - max_diff, 3.0), 0.0 ); + } + } + } + + gl_FragColor = vec4( rgb, 1.0 ); + }`; + + const FS = gl.createShader(gl.FRAGMENT_SHADER); + gl.shaderSource(FS, psCode); + gl.compileShader(FS); + + const program = gl.createProgram(); + gl.attachShader(program, VS); + gl.attachShader(program, FS); + gl.linkProgram(program); + if (!gl.getProgramParameter(program, gl.LINK_STATUS)) { + console.error('Link failed: ' + gl.getProgramInfoLog(program)); + console.error('vs info-log: ' + gl.getShaderInfoLog(VS)); + console.error('fs info-log: ' + gl.getShaderInfoLog(FS)); + return; // don't assign heatmapCanvas + } + gl.useProgram(program); + + gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer); + + const coord = gl.getAttribLocation(program, "a_vertCoord"); + gl.vertexAttribPointer(coord, 2, gl.FLOAT, false, 0, 0); + gl.enableVertexAttribArray(coord); + + heatmapUMouse = gl.getUniformLocation(program, "heatmapUMouse"); + + gl.uniform1i(gl.getUniformLocation(program, 'u_image1'), 0); + gl.uniform1i(gl.getUniformLocation(program, 'u_image2'), 1); + + gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, true); + heatmapCanvas = canvas; +} + +function heatmap_change_image(index, image) { + if (heatmapCanvas === null) { + return; + } + const texture = gl.createTexture(); + gl.activeTexture(gl.TEXTURE0 + index); + gl.bindTexture (gl.TEXTURE_2D, texture); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR); + gl.texImage2D (gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, image); +} + +function heatmap_render(mouse_x, mouse_y) { + if (heatmapCanvas === null) { + return; + } + + gl.uniform2f(heatmapUMouse, mouse_x, mouse_y); + + // the canvas resizes as user selects different reftests + gl.viewport(0, 0, heatmapCanvas.width, heatmapCanvas.height); + + gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4); +} + +function heatmap_on_mousemove(mousemove_event) { + if (heatmapCanvas === null) { + return; + } + const rect = heatmapCanvas.getBoundingClientRect(); + let x = mousemove_event.clientX - rect.left; + let y = mousemove_event.clientY - rect.top; + x = x * heatmapCanvas.width / heatmapCanvas.clientWidth; + y = y * heatmapCanvas.height / heatmapCanvas.clientHeight; + + // mouse has Y == 0 at the top, GL has it at the bottom: + const flip_y = heatmapCanvas.height-1 - y; + heatmap_render(x, flip_y); + + return { x:x, y:y }; +} + + ]]></script> + + <script type="text/javascript"><![CDATA[ + +var XLINK_NS = "http://www.w3.org/1999/xlink"; +var SVG_NS = "http://www.w3.org/2000/svg"; +var IMAGE_NOT_AVAILABLE = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAKAAAAASCAYAAADczdVTAAAACXBIWXMAAAsTAAALEwEAmpwYAAAHy0lEQVRoge2aX2hb5xnGf2dYabROgqQkpMuKnWUJLmxHMFaa/SscteQiF5EvUgqLctEVrDJKK1+MolzkQr4IctgW+SLIheJc1BpFpswJw92FbaZsTCGTL0465AtntUekJdJ8lByVHbnnwLsLKbKdSJbiZBVjeuAYn+/P+z3fc97vfd9zbEVEhB566BK+1m0CPfx/o+eAPXQVbR3QqVapOl8FlR46h0O1Wu02iacCZfsasMKEz8vbx1JYE6fY/dXx6mEbFObPcvDVDBlznpc9G+2r8xNcvLqK2w39r4UI+fs7tFjmytgFFu718865EIebPGincI3zFz7Bcrtx97/GL0P+p+IPbSOgRwXtW3vpewqL/a/g5rgf39hit2m0hGUAHOHrrq3trmef4/lDB7Ay57n01zuPZXPX7jUunv+Yf9ktR7D/0CHca7/n3KXPsHbAuynkCWCZptgiImKLaVqP9NuW1bT9ceybpr3j+WJbYrVa3rbEatGZi2uixvWdrysilmWKae2M+5PqlktoosayLfubcrN10dAk24aynUsIxMVsadwUs+EX7dEyAlaXLqMoCj6fj5HkUqO9MD+Govjx+xXcXi+uoRAhvwuv182Z8Ws4AJUlxoZ8uNxuvF43ii/EtdXNNUuV68lR/IqC4gsxPj7KkE/BF5qmClRXrzFSt+/1ulDOjLNU6eQ4OcyPDqH4hhg5O4LicuN2K4xcvk6jjHUKJM8O1fvcKMoZkouFOq1VPp1OcuXGAvrvfsv0lWmSySTzN0sdH+jyYhK/ouB2e/G6XfjPJikBVG8SUhT8fl99nwVGfQp+vx+f4iO5VO1AtwJjfgXF58M/kqSVJP9ef0xuAI6NlwWmL41xxqeg+PyMXr72yBqW3cI4JaZHh1DcXrxeLy5liORiB7q1PiZFyeV0mQqz9TRZeUmFVUGLSjqdkgCIFp2RTCosEJOiiIihSyKWkDl9WYrFnCQCCNF0w0QmHhBQJTEzJ+nZSQmAoEYks2KIGBkJgASiM5I3LbGMnCSCCEQl38GJMvMZiag1e+nlFcmmIgKaZEwREaPGhWGZ1VfEMFZkNj4sgCSyhoihSzwSlqCGoAUlEo1IJByW+Oxyh+dZJJ+eklhiRnIrRcnrM6KCxLOmiNiipyICSGR2pTY2O1m7T2XEsNrrJmJLfjkn6amwoMbFaMEhG28eAVtzExErW3sOBCWVzkpmNiEqCOEZ2RyLTT3eJAKaMhVEUMOSXjHEtg3JTIUFkNTK9rGwbQrWm2xGb6QoWxIqEtdtEWO28aDtoi6JSFCAjUtL1AUzJA4SSW/IZ2VjjU0V0zEBJBiJSzwWk1g8IZEAAmrdidrBkoSKxB4IW08tGVNEzIxoIJM5a8v4SQ1RY5lGSy6x8xScz6QkHFBre1Zre49nH+y1KDEQLV7TcyU1LBCtHVppp9smxk2dYAMtHXA7blZWNJDZ4sZ4MxPbdHjrbc3WNuvOq4YlkYhLLBaXeKx2sLcrBUS2ScFtUbUBh3WgajvgOYgGuKjw4Rsqb1uvkssbWLbJXFQFqL/I9IEKa2WzYcqy16E2BNteB1R+cuwoRwcHGRx4nlfenWMuPclRDx3goSraqd+7Gj/Y5d76SrXLu3VKLYW1rMZbo/QpB4+9zt6fT1I0Law/LRMBaLzC7ePNuSgL7/2GpcotLr7+AZG5t9gH0Fa3zuFq1tiWG4DKs5tebV1NDDW1XYd26iWO9A8wODjAUfUN5ubm+Ch4ZFuuLRzQoVwqUCqXyN9fg3tFSuUShVIZhyr5O2vo94o42DwD/PP23fq8Bf5urLO+BoHBwxzc20c++wcmz+lAkWLFATwcf3+YDwIDhMYmuDw+wt5j5+C5ZwDYP/gSoLP6xX5+fOIkJ47/lIP8g49/Nc3tDj59OZUiRR3uFYsAVO/eZoE1yvkyeA6gAaff+zU3SxUcp8LilQucnoFTP3hhix19/garlQqFW9eZOBti9Mqt9mubXwBw+NALeDC4cfVDzgP3i3keUN/nf4uo+hEver/DRaK84/9mY/72uoFTKVMolVn5/HPgPvlSmVKhRL2bSrlEqVyidH8N/d7t2u/lakfcKneLgM4rvxhncbXA6tI8kTffB+0NjnrAqZYplcrk83ceXdtzgB+psHD7S/pfPs7JkydQB1x8dnWS2SVje9GaxkVLl+DmNNC4NJn/S6JxH5nJyNRwrW7Qi7oMgxBMyd9molvmRKO1cExgshG6l9NTEhkOynAkLlOJoKBuhPV8ZlK0h9aNTqVbv3ltEK/VIiAQEN0yZVLbuM+aImLoEgts3VdsJrfFil1M1/ZSv9RAROaWO8n/hkyF1Q3bgeFGygvPrDRG5Wcf1IJbq9rlNrrNbra96aqlUVMSWrNnNiw5uw23T/4o4Xq7FtA29h2My3K9WtETgRZr13UxdIk+pGswkpCcsX0N2OZD9BOgWqFsgWePp20KWb0ywkDgEIa8y55Gq0O5XKHP7cGz++l/haxWylgOuD17aG7eoVpxwL27RX8b27jZ42n1qdahXKrg2bfnUW0eQ7edoD232l+/LPp2pHvNfh8eT2f8/3sO2AZLyRAvns6gqToLOgxP6Uz87HvdoNJDF9E1B6ysLrLw5yW+3PUNvv3dH/L9wX3doNFDl9E1B+yhB+j9O1YPXcZ/AAl9BWJNvZE7AAAAAElFTkSuQmCC"; + +var gPhases = null; + +var gIDCache = {}; + +var gMagPixPaths = []; // 2D array of array-of-two <path> objects used in the pixel magnifier +var gMagWidth = 5; // number of zoomed in pixels to show horizontally +var gMagHeight = 5; // number of zoomed in pixels to show vertically +var gMagZoom = 16; // size of the zoomed in pixels +var gImage1Data; // ImageData object for the reference image +var gImage2Data; // ImageData object for the test output image +var gFlashingPixels = []; // array of <path> objects that should be flashed due to pixel color mismatch +var gParams; + +function ID(id) { + if (!(id in gIDCache)) + gIDCache[id] = document.getElementById(id); + return gIDCache[id]; +} + +function hash_parameters() { + var result = { }; + var params = window.location.hash.substr(1).split(/[&;]/); + for (var i = 0; i < params.length; i++) { + var parts = params[i].split("="); + result[parts[0]] = unescape(unescape(parts[1])); + } + return result; +} + +function load() { + gPhases = [ ID("entry"), ID("loading"), ID("viewer") ]; + build_mag(); + gParams = hash_parameters(); + if (gParams.log) { + show_phase("loading"); + process_log(gParams.log); + } else if (gParams.logurl) { + show_phase("loading"); + var req = new XMLHttpRequest(); + req.onreadystatechange = function() { + if (req.readyState === 4) { + process_log(req.responseText); + } + }; + req.open('GET', gParams.logurl, true); + req.send(); + } + window.addEventListener('keypress', handle_keyboard_shortcut); + ID("image1").addEventListener('error', image_load_error); + ID("image2").addEventListener('error', image_load_error); +} + +function image_load_error(e) { + e.target.setAttributeNS(XLINK_NS, "xlink:href", IMAGE_NOT_AVAILABLE); +} + +function build_mag() { + var mag = ID("mag"); + + var r = document.createElementNS(SVG_NS, "rect"); + r.setAttribute("x", gMagZoom * -gMagWidth / 2); + r.setAttribute("y", gMagZoom * -gMagHeight / 2); + r.setAttribute("width", gMagZoom * gMagWidth); + r.setAttribute("height", gMagZoom * gMagHeight); + mag.appendChild(r); + + mag.setAttribute("transform", "translate(" + (gMagZoom * (gMagWidth / 2) + 1) + "," + (gMagZoom * (gMagHeight / 2) + 1) + ")"); + + for (var x = 0; x < gMagWidth; x++) { + gMagPixPaths[x] = []; + for (var y = 0; y < gMagHeight; y++) { + var p1 = document.createElementNS(SVG_NS, "path"); + p1.setAttribute("d", "M" + ((x - gMagWidth / 2) + 1) * gMagZoom + "," + (y - gMagHeight / 2) * gMagZoom + "h" + -gMagZoom + "v" + gMagZoom); + p1.setAttribute("stroke", "black"); + p1.setAttribute("stroke-width", "1px"); + p1.setAttribute("fill", "#aaa"); + + var p2 = document.createElementNS(SVG_NS, "path"); + p2.setAttribute("d", "M" + ((x - gMagWidth / 2) + 1) * gMagZoom + "," + (y - gMagHeight / 2) * gMagZoom + "v" + gMagZoom + "h" + -gMagZoom); + p2.setAttribute("stroke", "black"); + p2.setAttribute("stroke-width", "1px"); + p2.setAttribute("fill", "#888"); + + mag.appendChild(p1); + mag.appendChild(p2); + gMagPixPaths[x][y] = [p1, p2]; + } + } + + var flashedOn = false; + setInterval(function() { + flashedOn = !flashedOn; + flash_pixels(flashedOn); + }, 500); +} + +function show_phase(phaseid) { + for (var i in gPhases) { + var phase = gPhases[i]; + phase.style.display = (phase.id == phaseid) ? "" : "none"; + } + + if (phase == "viewer") + ID("images").style.display = "none"; +} + +function fileentry_changed() { + show_phase("loading"); + var input = ID("fileentry"); + var files = input.files; + if (files.length > 0) { + // Only handle the first file; don't handle multiple selection. + // The parts of the log we care about are ASCII-only. Since we + // can ignore lines we don't care about, best to read in as + // iso-8859-1, which guarantees we don't get decoding errors. + var fileReader = new FileReader(); + fileReader.onload = function(e) { + var log = null; + + log = e.target.result; + + if (log) + process_log(log); + else + show_phase("entry"); + } + fileReader.readAsText(files[0], "iso-8859-1"); + } + // So the user can process the same filename again (after + // overwriting the log), clear the value on the form input so we + // will always get an onchange event. + input.value = ""; +} + +function log_pasted() { + show_phase("loading"); + var entry = ID("logentry"); + var log = entry.value; + entry.value = ""; + process_log(log); +} + +var gTestItems; + +function process_log(contents) { + var lines = contents.split(/[\r\n]+/); + gTestItems = []; + for (var j in lines) { + var line = lines[j]; + // Ignore duplicated output in logcat. + if (line.match(/I\/Gecko.*?REFTEST/)) + continue; + var match = line.match(/^(?:.*? (?:INFO|ERROR) -\s+)?(?:REFTEST\s+)?(.*)$/); + if (!match) + continue; + line = match[1]; + match = line.match(/^(TEST-PASS|TEST-UNEXPECTED-PASS|TEST-KNOWN-FAIL|TEST-UNEXPECTED-FAIL|TEST-DEBUG-INFO)(\(EXPECTED RANDOM\)|) \| ([^\|]+) \|(.*)/); + if (match) { + var state = match[1]; + var random = match[2]; + var url = match[3]; + var extra = match[4]; + gTestItems.push( + { + pass: !state.match(/DEBUG-INFO$|FAIL$/), + // only one of the following three should ever be true + unexpected: !!state.match(/^TEST-UNEXPECTED/), + random: (random == "(EXPECTED RANDOM)"), + skip: (extra == " (SKIP)"), + url: url, + images: [], + imageLabels: [] + }); + continue; + } + match = line.match(/IMAGE([^:]*): (data:.*)$/); + if (match) { + var item = gTestItems[gTestItems.length - 1]; + item.images.push(match[2]); + item.imageLabels.push(match[1]); + } + } + + build_viewer(); +} + +function build_viewer() { + if (gTestItems.length == 0) { + show_phase("entry"); + return; + } + + var cell = ID("itemlist"); + while (cell.childNodes.length > 0) + cell.removeChild(cell.childNodes[cell.childNodes.length - 1]); + + var table = document.createElement("table"); + var tbody = document.createElement("tbody"); + table.appendChild(tbody); + + for (var i in gTestItems) { + var item = gTestItems[i]; + + // optional url filter for only showing unexpected results + if (parseInt(gParams.only_show_unexpected) && !item.unexpected) + continue; + + // XXX regardless skip expected pass items until we have filtering UI + if (item.pass && !item.unexpected) + continue; + + var tr = document.createElement("tr"); + var rowclass = item.pass ? "pass" : "fail"; + var td; + var text; + + td = document.createElement("td"); + text = ""; + if (item.unexpected) { text += "!"; rowclass += " unexpected"; } + if (item.random) { text += "R"; rowclass += " random"; } + if (item.skip) { text += "S"; rowclass += " skip"; } + td.appendChild(document.createTextNode(text)); + tr.appendChild(td); + + td = document.createElement("td"); + td.id = "item" + i; + td.className = "url"; + // Only display part of URL after "/mozilla/". + var match = item.url.match(/\/mozilla\/(.*)/); + text = document.createTextNode(match ? match[1] : item.url); + if (item.images.length > 0) { + var a = document.createElement("a"); + a.href = "javascript:show_images(" + i + ")"; + a.appendChild(text); + td.appendChild(a); + } else { + td.appendChild(text); + } + tr.appendChild(td); + + tbody.appendChild(tr); + } + + cell.appendChild(table); + + show_phase("viewer"); +} + +function get_image_data(src, whenReady) { + var img = new Image(); + img.onload = function() { + var canvas = document.createElement("canvas"); + canvas.width = img.naturalWidth; + canvas.height = img.naturalHeight; + + var ctx = canvas.getContext("2d"); + ctx.drawImage(img, 0, 0); + + whenReady(ctx.getImageData(0, 0, img.naturalWidth, img.naturalHeight)); + }; + img.src = src; +} + +function sync_svg_size(imageData) { + // We need the size of the 'svg' and its 'image' elements to match the size + // of the ImageData objects that we're going to read pixels from or else our + // magnify() function will be very broken. + ID("svg").setAttribute("width", imageData.width); + ID("svg").setAttribute("height", imageData.height); +} + +function sync_heatmap_size(imageData) { + ID("heat_canvas").setAttribute("width" , imageData.width); + ID("heat_canvas").setAttribute("height", imageData.height); +} + +function show_images(i) { + var item = gTestItems[i]; + var cell = ID("images"); + + // Remove activeitem class from any existing elements + var activeItems = document.querySelectorAll(".activeitem"); + for (var activeItemIdx = activeItems.length; activeItemIdx-- != 0;) { + activeItems[activeItemIdx].classList.remove("activeitem"); + } + + ID("item" + i).classList.add("activeitem"); + ID("image1").style.display = ""; + ID("image2").style.display = "none"; + show_diff_none(); + ID("imgcontrols").reset(); + ID("diffcontrols").reset(); + + ID("image1").setAttributeNS(XLINK_NS, "xlink:href", item.images[0]); + // Making the href be #image1 doesn't seem to work + ID("feimage1").setAttributeNS(XLINK_NS, "xlink:href", item.images[0]); + if (item.images.length == 1) { + ID("imgcontrols").style.display = "none"; + } else { + ID("imgcontrols").style.display = ""; + + ID("image2").setAttributeNS(XLINK_NS, "xlink:href", item.images[1]); + // Making the href be #image2 doesn't seem to work + ID("feimage2").setAttributeNS(XLINK_NS, "xlink:href", item.images[1]); + + ID("label1").textContent = 'Image ' + item.imageLabels[0]; + ID("label2").textContent = 'Image ' + item.imageLabels[1]; + } + + cell.style.display = ""; + + get_image_data(item.images[0], function(data) { gImage1Data = data; sync_svg_size(gImage1Data); sync_heatmap_size(gImage1Data); heatmap_change_image(0, gImage1Data); }); + get_image_data(item.images[1], function(data) { gImage2Data = data; heatmap_change_image(1, gImage2Data); }); +} + +function show_image(i) { + if (i == 1) { + ID("image1").style.display = ""; + ID("image2").style.display = "none"; + } else { + ID("image1").style.display = "none"; + ID("image2").style.display = ""; + } +} + +function handle_keyboard_shortcut(event) { + switch (event.charCode) { + case 49: // "1" key + document.getElementById("radio1").checked = true; + show_image(1); + break; + case 50: // "2" key + document.getElementById("radio2").checked = true; + show_image(2); + break; + case 100: // "d" key + document.getElementById("radio_diff_circle").click(); + break; + case 104: // "h" key + document.getElementById("radio_diff_heatmap").click(); + break; + case 112: // "p" key + shift_images(-1); + break; + case 110: // "n" key + shift_images(1); + break; + } +} + +function shift_images(dir) { + var activeItem = document.querySelector(".activeitem"); + if (!activeItem) { + return; + } + for (var elm = activeItem; elm; elm = elm.parentElement) { + if (elm.tagName != "tr") { + continue; + } + elm = dir > 0 ? elm.nextElementSibling : elm.previousElementSibling; + if (elm) { + elm.getElementsByTagName("a")[0].click(); + } + return; + } +} + +function show_diff_none() { + ID("svg") .style.display = ""; + ID("diffrect") .style.display = "none"; + ID("heat_canvas").style.display = "none"; +} + +function show_diff_circle() { + ID("svg") .style.display = ""; + ID("diffrect") .style.display = ""; + ID("heat_canvas").style.display = "none"; +} + +function show_diff_heatmap() { + ID("svg") .style.display = "none"; + ID("diffrect") .style.display = "none"; + ID("heat_canvas").style.display = ""; + + if (heatmapCanvas === null) { + canvas = document.getElementById('heat_canvas'); + heatmap_render_setup(canvas); + heatmap_change_image(0, gImage1Data); + heatmap_change_image(1, gImage2Data); + heatmap_render(0, 0); + + window.addEventListener('mousemove', e => { + var { x: x, y: y } = heatmap_on_mousemove(e); + magnify_around(Math.floor(x), Math.floor(y)); + }); + } +} + +function flash_pixels(on) { + var stroke = on ? "red" : "black"; + var strokeWidth = on ? "2px" : "1px"; + for (var i = 0; i < gFlashingPixels.length; i++) { + gFlashingPixels[i].setAttribute("stroke", stroke); + gFlashingPixels[i].setAttribute("stroke-width", strokeWidth); + } +} + +function cursor_point(evt) { + var m = evt.target.getScreenCTM().inverse(); + var p = ID("svg").createSVGPoint(); + p.x = evt.clientX; + p.y = evt.clientY; + p = p.matrixTransform(m); + return { x: Math.floor(p.x), y: Math.floor(p.y) }; +} + +function hex2(i) { + return (i < 16 ? "0" : "") + i.toString(16); +} + +function canvas_pixel_as_hex(data, x, y) { + var offset = (y * data.width + x) * 4; + var r = data.data[offset]; + var g = data.data[offset + 1]; + var b = data.data[offset + 2]; + return "#" + hex2(r) + hex2(g) + hex2(b); +} + +function hex_as_rgb(hex) { + return "rgb(" + [parseInt(hex.substring(1, 3), 16), parseInt(hex.substring(3, 5), 16), parseInt(hex.substring(5, 7), 16)] + ")"; +} + +function magnify(evt) { + var { x: x, y: y } = cursor_point(evt); + magnify_around(x, y); +} + +function magnify_around(x, y) { + if (x < 0 || y < 0 || x >= gImage1Data.width || y >= gImage1Data.height) { + return; + } + var centerPixelColor1, centerPixelColor2; + + var dx_lo = -Math.floor(gMagWidth / 2); + var dx_hi = Math.floor(gMagWidth / 2); + var dy_lo = -Math.floor(gMagHeight / 2); + var dy_hi = Math.floor(gMagHeight / 2); + + flash_pixels(false); + gFlashingPixels = []; + for (var j = dy_lo; j <= dy_hi; j++) { + for (var i = dx_lo; i <= dx_hi; i++) { + var px = x + i; + var py = y + j; + var p1 = gMagPixPaths[i + dx_hi][j + dy_hi][0]; + var p2 = gMagPixPaths[i + dx_hi][j + dy_hi][1]; + // Here we just use the dimensions of gImage1Data since we expect test + // and reference to have the same dimensions. + if (px < 0 || py < 0 || px >= gImage1Data.width || py >= gImage1Data.height) { + p1.setAttribute("fill", "#aaa"); + p2.setAttribute("fill", "#888"); + } else { + var color1 = canvas_pixel_as_hex(gImage1Data, x + i, y + j); + var color2 = canvas_pixel_as_hex(gImage2Data, x + i, y + j); + p1.setAttribute("fill", color1); + p2.setAttribute("fill", color2); + if (color1 != color2) { + gFlashingPixels.push(p1, p2); + p1.parentNode.appendChild(p1); + p2.parentNode.appendChild(p2); + } + if (i == 0 && j == 0) { + centerPixelColor1 = color1; + centerPixelColor2 = color2; + } + } + } + } + flash_pixels(true); + show_pixelinfo(x, y, centerPixelColor1, hex_as_rgb(centerPixelColor1), centerPixelColor2, hex_as_rgb(centerPixelColor2)); +} + +function show_pixelinfo(x, y, pix1rgb, pix1hex, pix2rgb, pix2hex) { + var pixelinfo = ID("pixelinfo"); + ID("coords").textContent = [x, y]; + ID("pix1hex").textContent = pix1hex; + ID("pix1rgb").textContent = pix1rgb; + ID("pix2hex").textContent = pix2hex; + ID("pix2rgb").textContent = pix2rgb; +} + + ]]></script> + +</head> +<body onload="load()"> + +<div id="entry"> + +<h1>Reftest analyzer: load reftest log</h1> + +<p>Either paste your log into this textarea:<br /> +<textarea cols="80" rows="10" id="logentry"/><br/> +<input type="button" value="Process pasted log" onclick="log_pasted()" /></p> + +<p>... or load it from a file:<br/> +<input type="file" id="fileentry" onchange="fileentry_changed()" /> +</p> +</div> + +<div id="loading" style="display:none">Loading log...</div> + +<div id="viewer" style="display:none"> + <div id="pixelarea"> + <div id="pixelinfo"> + <table> + <tbody> + <tr><th>Pixel at:</th><td colspan="2" id="coords"/></tr> + <tr><th>Image 1:</th><td id="pix1rgb"></td><td id="pix1hex"></td></tr> + <tr><th>Image 2:</th><td id="pix2rgb"></td><td id="pix2hex"></td></tr> + </tbody> + </table> + <div> + <div id="pixelhint">★ + <div> + <p>Move the mouse over the reftest image on the right to show + magnified pixels on the left. The color information above is for + the pixel centered in the magnified view.</p> + <p>Image 1 is shown in the upper triangle of each pixel and Image 2 + is shown in the lower triangle.</p> + </div> + </div> + </div> + </div> + <div id="magnification"> + <svg xmlns="http://www.w3.org/2000/svg" width="84" height="84" shape-rendering="optimizeSpeed"> + <g id="mag"/> + </svg> + </div> + </div> + <div id="itemlist"></div> + <div id="images" style="display:none"> + <form id="imgcontrols"> + <input id="radio1" type="radio" name="which" value="0" onchange="show_image(1)" checked="checked" /><label id="label1" title="1" for="radio1">Image 1</label> + <input id="radio2" type="radio" name="which" value="1" onchange="show_image(2)" /><label id="label2" title="2" for="radio2">Image 2</label> + </form> + + <form id="diffcontrols"> + Differences: + <input id="radio_diff_none" name="diff" value="0" type="radio" onchange="show_diff_none()" checked="checked"/> + <label for="radio_diff_none">None</label> + <input id="radio_diff_circle" name="diff" value="1" type="radio" onchange="show_diff_circle()" /> + <label for="radio_diff_circle">Circle</label> + <input id="radio_diff_heatmap" name="diff" value="2" type="radio" onchange="show_diff_heatmap()" /> + <label for="radio_diff_heatmap">Heatmap</label> + </form> + + <canvas width="800" height="1000" id="heat_canvas" style="display:none;"></canvas> + + <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="800" height="1000" id="svg"> + <defs> + <!-- use sRGB to avoid loss of data --> + <filter id="showDifferences" x="0%" y="0%" width="100%" height="100%" + style="color-interpolation-filters: sRGB"> + <feImage id="feimage1" result="img1" xlink:href="#image1" /> + <feImage id="feimage2" result="img2" xlink:href="#image2" /> + <!-- inv1 and inv2 are the images with RGB inverted --> + <feComponentTransfer result="inv1" in="img1"> + <feFuncR type="linear" slope="-1" intercept="1" /> + <feFuncG type="linear" slope="-1" intercept="1" /> + <feFuncB type="linear" slope="-1" intercept="1" /> + </feComponentTransfer> + <feComponentTransfer result="inv2" in="img2"> + <feFuncR type="linear" slope="-1" intercept="1" /> + <feFuncG type="linear" slope="-1" intercept="1" /> + <feFuncB type="linear" slope="-1" intercept="1" /> + </feComponentTransfer> + <!-- w1 will have non-white pixels anywhere that img2 + is brighter than img1, and w2 for the reverse. + It would be nice not to have to go through these + intermediate states, but feComposite + type="arithmetic" can't transform the RGB channels + and leave the alpha channel untouched. --> + <feComposite result="w1" in="img1" in2="inv2" operator="arithmetic" k2="1" k3="1" /> + <feComposite result="w2" in="img2" in2="inv1" operator="arithmetic" k2="1" k3="1" /> + <!-- c1 will have non-black pixels anywhere that img2 + is brighter than img1, and c2 for the reverse --> + <feComponentTransfer result="c1" in="w1"> + <feFuncR type="linear" slope="-1" intercept="1" /> + <feFuncG type="linear" slope="-1" intercept="1" /> + <feFuncB type="linear" slope="-1" intercept="1" /> + </feComponentTransfer> + <feComponentTransfer result="c2" in="w2"> + <feFuncR type="linear" slope="-1" intercept="1" /> + <feFuncG type="linear" slope="-1" intercept="1" /> + <feFuncB type="linear" slope="-1" intercept="1" /> + </feComponentTransfer> + <!-- c will be nonblack (and fully on) for every pixel+component where there are differences --> + <feComposite result="c" in="c1" in2="c2" operator="arithmetic" k2="255" k3="255" /> + <!-- a will be opaque for every pixel with differences and transparent for all others --> + <feColorMatrix result="a" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0" /> + + <!-- a, dilated by 1 pixel --> + <feMorphology result="dila1" in="a" operator="dilate" radius="1" /> + <!-- a, dilated by 2 pixels --> + <feMorphology result="dila2" in="dila1" operator="dilate" radius="1" /> + + <!-- all the pixels in the 2-pixel dilation of a but not in the 1-pixel dilation, to highlight the diffs --> + <feComposite result="highlight" in="dila2" in2="dila1" operator="out" /> + + <feFlood result="red" flood-color="red" /> + <feComposite result="redhighlight" in="red" in2="highlight" operator="in" /> + <feFlood result="black" flood-color="black" flood-opacity="0.5" /> + <feMerge> + <feMergeNode in="black" /> + <feMergeNode in="redhighlight" /> + </feMerge> + </filter> + </defs> + <g onmousemove="magnify(evt)"> + <image x="0" y="0" width="100%" height="100%" id="image1" /> + <image x="0" y="0" width="100%" height="100%" id="image2" /> + </g> + <rect id="diffrect" filter="url(#showDifferences)" pointer-events="none" x="0" y="0" width="100%" height="100%" /> + </svg> + </div> +</div> + +</body> +</html> diff --git a/gfx/wr/wrench/script/reftest-debugger.py b/gfx/wr/wrench/script/reftest-debugger.py new file mode 100755 index 0000000000..19a2a19890 --- /dev/null +++ b/gfx/wr/wrench/script/reftest-debugger.py @@ -0,0 +1,15 @@ +#!/usr/bin/python + +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + +from __future__ import print_function +import subprocess + +with open('reftest.log', "w") as out: + try: + subprocess.check_call(['script/headless.py', 'reftest'], stdout=out) + print("All tests passed.") + except subprocess.CalledProcessError as ex: + subprocess.check_call(['firefox', 'reftest-analyzer.xhtml#logurl=reftest.log']) diff --git a/gfx/wr/wrench/script/wrench_with_renderer.py b/gfx/wr/wrench/script/wrench_with_renderer.py new file mode 100755 index 0000000000..e2685e8476 --- /dev/null +++ b/gfx/wr/wrench/script/wrench_with_renderer.py @@ -0,0 +1,52 @@ +#!/usr/bin/python + +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + +import os +import subprocess +import sys + + +def is_linux(): + return sys.platform.startswith('linux') + + +if is_linux(): + requested_renderer = sys.argv[1] + renderer = "default" + + if requested_renderer == 'hardware': + pass + elif requested_renderer == 'llvmpipe': + os.environ["LIBGL_ALWAYS_SOFTWARE"] = "1" + os.environ["GALLIUM_DRIVER"] = "llvmpipe" + elif requested_renderer == 'softpipe': + os.environ["LIBGL_ALWAYS_SOFTWARE"] = "1" + os.environ["GALLIUM_DRIVER"] = "softpipe" + elif requested_renderer == 'swiftshader': + # TODO: Set up LD_LIBRARY_PATH to SwiftShader libraries automatically. + renderer = 'es3' + else: + print('Unknown renderer ' + requested_renderer) + sys.exit(1) + + cmd = [ + 'cargo', + 'run', + '--release', + '--', + '--no-block', # Run as fast as possible, for benchmarking + '--no-picture-caching', # Disable picture caching, to test rasterization performance + '--no-subpixel-aa', # SwiftShader doesn't support dual source blending + '--renderer', # Select GL3/ES3 renderer API + renderer, + 'load' + ] + + cmd += sys.argv[2:] + print('Running: ' + ' '.join(cmd)) + subprocess.check_call(cmd) +else: + print('This script is only supported on Linux') diff --git a/gfx/wr/wrench/src/angle.rs b/gfx/wr/wrench/src/angle.rs new file mode 100644 index 0000000000..bdd538bda2 --- /dev/null +++ b/gfx/wr/wrench/src/angle.rs @@ -0,0 +1,62 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +use glutin::{self, ContextBuilder, ContextCurrentState, CreationError}; +use winit::{EventsLoop, Window, WindowBuilder}; + +#[cfg(not(windows))] +pub enum Context {} + +#[cfg(windows)] +pub use crate::egl::Context; + +impl Context { + #[cfg(not(windows))] + pub fn with_window<T: ContextCurrentState>( + _: WindowBuilder, + _: ContextBuilder<'_, T>, + _: &EventsLoop, + ) -> Result<(Window, Self), CreationError> { + Err(CreationError::PlatformSpecific( + "ANGLE rendering is only supported on Windows".into(), + )) + } + + #[cfg(windows)] + pub fn with_window<T: ContextCurrentState>( + window_builder: WindowBuilder, + context_builder: ContextBuilder<'_, T>, + events_loop: &EventsLoop, + ) -> Result<(Window, Self), CreationError> { + use winit::os::windows::WindowExt; + + // FIXME: &context_builder.pf_reqs https://github.com/tomaka/glutin/pull/1002 + let pf_reqs = &glutin::PixelFormatRequirements::default(); + let gl_attr = &context_builder.gl_attr.map_sharing(|_| unimplemented!()); + let window = window_builder.build(events_loop)?; + Self::new(pf_reqs, gl_attr) + .and_then(|p| p.finish(window.get_hwnd() as _)) + .map(|context| (window, context)) + } + + #[cfg(not(windows))] + pub unsafe fn make_current(&self) -> Result<(), glutin::ContextError> { + match *self {} + } + + #[cfg(not(windows))] + pub fn get_proc_address(&self, _: &str) -> *const () { + match *self {} + } + + #[cfg(not(windows))] + pub fn swap_buffers(&self) -> Result<(), glutin::ContextError> { + match *self {} + } + + #[cfg(not(windows))] + pub fn get_api(&self) -> glutin::Api { + match *self {} + } +} diff --git a/gfx/wr/wrench/src/args.yaml b/gfx/wr/wrench/src/args.yaml new file mode 100644 index 0000000000..6213817a21 --- /dev/null +++ b/gfx/wr/wrench/src/args.yaml @@ -0,0 +1,194 @@ +name: wrench +version: "0.1" +author: Vladimir Vukicevic <vladimir@pobox.com> +about: WebRender testing and debugging utility + +args: + - precache: + short: c + long: precache + help: Precache shaders + - verbose: + short: v + long: verbose + help: Enable verbose display + - zoom: + short: z + long: zoom + help: Set zoom factor + takes_value: true + - shaders: + long: shaders + help: Override path for shaders + takes_value: true + - use_unoptimized_shaders: + long: use-unoptimized-shaders + help: Use unoptimized shaders rather than the shaders optimized at build-time + - rebuild: + short: r + long: rebuild + help: Rebuild display list from scratch every frame + - no_subpixel_aa: + short: a + long: no-subpixel-aa + help: Disable subpixel aa + - slow_subpixel: + long: slow-subpixel + help: Disable dual source blending + - headless: + long: headless + help: Enable headless rendering + - angle: + long: angle + help: Enable ANGLE rendering (on Windows only) + - software: + long: software + help: Enable software rendering + - dp_ratio: + short: p + long: device-pixel-ratio + help: Device pixel ratio + takes_value: true + - size: + short: s + long: size + help: Window size, specified as widthxheight (e.g. 1024x768), in pixels + takes_value: true + - vsync: + long: vsync + help: Enable vsync for OpenGL window + - no_scissor: + long: no-scissor + help: Disable scissors when clearing render targets + - no_batch: + long: no-batch + help: Disable batching of instanced draw calls + - chase: + long: chase + help: Chase a particular primitive matching the local rect or ID + takes_value: true + - dump_shader_source: + long: dump-shader-source + help: Dump the source of the specified shader + takes_value: true + global: true + - renderer: + long: renderer + help: Select rendering API (gl3, es3) + takes_value: true + global: true + - no_block: + long: no-block + help: Don't block on UI events - run event loop as fast as possible. + - profiler_ui: + long: profiler-ui + takes_value: true + help: A string describing what to show on in the profiler HUD (See https://github.com/servo/webrender/wiki/Debugging-WebRender#anchor_6). + +subcommands: + - png: + about: render frame described by YAML and save it to a png file + args: + - surface: + short: s + long: surface + help: 'What rendered surface to save as PNG, one of: screen, gpu-cache' + takes_value: true + - INPUT: + help: The input YAML file + required: true + index: 1 + - OUTPUT: + help: Optional output path to save to. + required: false + index: 2 + - show: + about: show frame(s) described by YAML, binary recording, or capture + aliases: ['load', 'replay'] + args: + - include: + long: include + help: Include the given element type. Can be specified multiple times. (rect/image/text/glyphs/border) (YAML only) + multiple: true + takes_value: true + - list-resources: + long: list-resources + help: List the resources used by this render (YAML only) + - watch: + short: w + long: watch + help: Watch the given file, reloading whenever it changes (YAML only) + - keyframes: + short: k + long: keyframes + takes_value: true + help: Provide a keyframes file, that can be used to animate the yaml input file + - scene-id: + short: s + long: scene-id + takes_value: true + help: Select a starting scene sequence ID (YAML capture sequence only). + - frame-id: + short: f + long: frame-id + takes_value: true + help: Select a starting frame sequence ID (YAML capture sequence only). + - INPUT: + help: The input YAML, binary recording, or capture directory + required: true + index: 1 + - reftest: + about: run reftests + args: + - fuzz_tolerance: + long: fuzzy + takes_value: true + help: Add a minimum fuzziness tolerance to all tests. + required: false + - REFTEST: + help: a specific reftest or directory to run + required: false + index: 1 + - rawtest: + about: run rawtests + - perf: + about: run benchmarks + args: + - filename: + help: name of the file to save benchmarks to + required: true + index: 1 + - benchmark: + help: benchmark list filename (default is benchmarks/benchmarks.list) + required: false + index: 2 + - auto-filename: + long: auto-filename + help: generate output filename from date and time (user provided filename is the directory prefix) + required: false + - csv: + long: csv + help: save benchmark results as .csv (default is json) + required: false + - warmup_frames: + long: warmup_frames + takes_value: true + help: number of frames to skip before recording timings + required: false + - sample_count: + long: sample_count + takes_value: true + help: number of samples to capture + - test_invalidation: + about: run invalidation tests + - compare_perf: + about: compare two benchmark files + args: + - first_filename: + help: first benchmark file to compare + required: true + index: 1 + - second_filename: + help: second benchmark file to compare + required: true + index: 2 diff --git a/gfx/wr/wrench/src/blob.rs b/gfx/wr/wrench/src/blob.rs new file mode 100644 index 0000000000..a720d31323 --- /dev/null +++ b/gfx/wr/wrench/src/blob.rs @@ -0,0 +1,213 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +// A very basic BlobImageRasterizer that can only render a checkerboard pattern. + +use std::collections::HashMap; +use std::sync::Arc; +use std::sync::Mutex; +use webrender::api::*; +use webrender::api::units::{BlobDirtyRect, BlobToDeviceTranslation, TileOffset}; +use webrender::api::units::DeviceIntRect; + +// Serialize/deserialize the blob. + +pub fn serialize_blob(color: ColorU) -> Arc<Vec<u8>> { + Arc::new(vec![color.r, color.g, color.b, color.a]) +} + +fn deserialize_blob(blob: &[u8]) -> Result<ColorU, ()> { + let mut iter = blob.iter(); + return match (iter.next(), iter.next(), iter.next(), iter.next()) { + (Some(&r), Some(&g), Some(&b), Some(&a)) => Ok(ColorU::new(r, g, b, a)), + (Some(&a), None, None, None) => Ok(ColorU::new(a, a, a, a)), + _ => Err(()), + }; +} + +// perform floor((x * a) / 255. + 0.5) see "Three wrongs make a right" for derivation +fn premul(x: u8, a: u8) -> u8 { + let t = (x as u32) * (a as u32) + 128; + ((t + (t >> 8)) >> 8) as u8 +} + +// This is the function that applies the deserialized drawing commands and generates +// actual image data. +fn render_blob( + color: ColorU, + descriptor: &BlobImageDescriptor, + tile: TileOffset, + _tile_size: TileSize, + dirty_rect: &BlobDirtyRect, +) -> BlobImageResult { + // Allocate storage for the result. Right now the resource cache expects the + // tiles to have have no stride or offset. + let buf_size = descriptor.rect.size.area() * + descriptor.format.bytes_per_pixel(); + let mut texels = vec![0u8; (buf_size) as usize]; + + // Generate a per-tile pattern to see it in the demo. For a real use case it would not + // make sense for the rendered content to depend on its tile. + let tile_checker = (tile.x % 2 == 0) != (tile.y % 2 == 0); + + let dirty_rect = dirty_rect.to_subrect_of(&descriptor.rect); + + // We want the dirty rect local to the tile rather than the whole image. + let tx: BlobToDeviceTranslation = (-descriptor.rect.origin.to_vector()).into(); + + let rasterized_rect = tx.transform_rect(&dirty_rect); + + for y in rasterized_rect.min_y() .. rasterized_rect.max_y() { + for x in rasterized_rect.min_x() .. rasterized_rect.max_x() { + // Apply the tile's offset. This is important: all drawing commands should be + // translated by this offset to give correct results with tiled blob images. + let x2 = x + descriptor.rect.origin.x; + let y2 = y + descriptor.rect.origin.y; + + // Render a simple checkerboard pattern + let checker = if (x2 % 20 >= 10) != (y2 % 20 >= 10) { + 1 + } else { + 0 + }; + // ..nested in the per-tile checkerboard pattern + let tc = if tile_checker { 0 } else { (1 - checker) * 40 }; + + match descriptor.format { + ImageFormat::BGRA8 => { + let a = color.a * checker + tc; + let pixel_offset = ((y * descriptor.rect.size.width + x) * 4) as usize; + texels[pixel_offset + 0] = premul(color.b * checker + tc, a); + texels[pixel_offset + 1] = premul(color.g * checker + tc, a); + texels[pixel_offset + 2] = premul(color.r * checker + tc, a); + texels[pixel_offset + 3] = a; + } + ImageFormat::R8 => { + texels[(y * descriptor.rect.size.width + x) as usize] = color.a * checker + tc; + } + _ => { + return Err(BlobImageError::Other( + format!("Unsupported image format {:?}", descriptor.format), + )); + } + } + } + } + + Ok(RasterizedBlobImage { + data: Arc::new(texels), + rasterized_rect, + }) +} + +/// See rawtest.rs. We use this to test that blob images are requested the right +/// amount of times. +pub struct BlobCallbacks { + pub request: Box<dyn Fn(&[BlobImageParams]) + Send + 'static>, +} + +impl BlobCallbacks { + pub fn new() -> Self { + BlobCallbacks { request: Box::new(|_|()) } + } +} + +pub struct CheckerboardRenderer { + image_cmds: HashMap<BlobImageKey, (ColorU, TileSize)>, + callbacks: Arc<Mutex<BlobCallbacks>>, +} + +impl CheckerboardRenderer { + pub fn new(callbacks: Arc<Mutex<BlobCallbacks>>) -> Self { + CheckerboardRenderer { + callbacks, + image_cmds: HashMap::new(), + } + } +} + +impl BlobImageHandler for CheckerboardRenderer { + fn create_similar(&self) -> Box<dyn BlobImageHandler> { + Box::new(CheckerboardRenderer::new(Arc::clone(&self.callbacks))) + } + + fn add(&mut self, key: BlobImageKey, cmds: Arc<BlobImageData>, + _visible_rect: &DeviceIntRect, tile_size: TileSize) { + self.image_cmds + .insert(key, (deserialize_blob(&cmds[..]).unwrap(), tile_size)); + } + + fn update(&mut self, key: BlobImageKey, cmds: Arc<BlobImageData>, + _visible_rect: &DeviceIntRect, _dirty_rect: &BlobDirtyRect) { + // Here, updating is just replacing the current version of the commands with + // the new one (no incremental updates). + self.image_cmds.get_mut(&key).unwrap().0 = deserialize_blob(&cmds[..]).unwrap(); + } + + fn delete(&mut self, key: BlobImageKey) { + self.image_cmds.remove(&key); + } + + fn delete_font(&mut self, _key: FontKey) {} + + fn delete_font_instance(&mut self, _key: FontInstanceKey) {} + + fn clear_namespace(&mut self, _namespace: IdNamespace) {} + + fn prepare_resources( + &mut self, + _services: &dyn BlobImageResources, + requests: &[BlobImageParams], + ) { + if !requests.is_empty() { + (self.callbacks.lock().unwrap().request)(&requests); + } + } + + fn create_blob_rasterizer(&mut self) -> Box<dyn AsyncBlobImageRasterizer> { + Box::new(Rasterizer { image_cmds: self.image_cmds.clone() }) + } + + fn enable_multithreading(&mut self, _enable: bool) {} +} + +struct Command { + request: BlobImageRequest, + color: ColorU, + descriptor: BlobImageDescriptor, + tile: TileOffset, + tile_size: TileSize, + dirty_rect: BlobDirtyRect, +} + +struct Rasterizer { + image_cmds: HashMap<BlobImageKey, (ColorU, TileSize)>, +} + +impl AsyncBlobImageRasterizer for Rasterizer { + fn rasterize( + &mut self, + requests: &[BlobImageParams], + _low_priority: bool + ) -> Vec<(BlobImageRequest, BlobImageResult)> { + let requests: Vec<Command> = requests.into_iter().map( + |item| { + let (color, tile_size) = self.image_cmds[&item.request.key]; + + Command { + request: item.request, + color, + tile_size, + tile: item.request.tile, + descriptor: item.descriptor, + dirty_rect: item.dirty_rect, + } + } + ).collect(); + + requests.iter().map(|cmd| { + (cmd.request, render_blob(cmd.color, &cmd.descriptor, cmd.tile, cmd.tile_size, &cmd.dirty_rect)) + }).collect() + } +} diff --git a/gfx/wr/wrench/src/egl.rs b/gfx/wr/wrench/src/egl.rs new file mode 100644 index 0000000000..4508646b45 --- /dev/null +++ b/gfx/wr/wrench/src/egl.rs @@ -0,0 +1,611 @@ +// Licensed under the Apache License, Version 2.0. +// This file may not be copied, modified, or distributed except according to those terms. + +//! Based on https://github.com/tomaka/glutin/blob/1b2d62c0e9/src/api/egl/mod.rs +#![cfg(windows)] +#![allow(unused_variables)] + +use glutin::ContextError; +use glutin::CreationError; +use glutin::GlAttributes; +use glutin::GlRequest; +use glutin::PixelFormat; +use glutin::PixelFormatRequirements; +use glutin::ReleaseBehavior; +use glutin::Robustness; +use glutin::Api; + +use std::ffi::{CStr, CString}; +use std::os::raw::c_int; +use std::ptr; +use std::cell::Cell; + +use mozangle::egl::ffi as egl; +mod ffi { + pub use mozangle::egl::ffi as egl; + pub use mozangle::egl::ffi::*; +} + +pub struct Context { + display: ffi::egl::types::EGLDisplay, + context: ffi::egl::types::EGLContext, + surface: Cell<ffi::egl::types::EGLSurface>, + api: Api, + pixel_format: PixelFormat, +} + +impl Context { + /// Start building an EGL context. + /// + /// This function initializes some things and chooses the pixel format. + /// + /// To finish the process, you must call `.finish(window)` on the `ContextPrototype`. + pub fn new<'a>( + pf_reqs: &PixelFormatRequirements, + opengl: &'a GlAttributes<&'a Context>, + ) -> Result<ContextPrototype<'a>, CreationError> + { + if opengl.sharing.is_some() { + unimplemented!() + } + + // calling `eglGetDisplay` or equivalent + let display = unsafe { egl::GetDisplay(ptr::null_mut()) }; + + if display.is_null() { + return Err(CreationError::PlatformSpecific("Could not create EGL display object".to_string())); + } + + let egl_version = unsafe { + let mut major: ffi::egl::types::EGLint = 0; // out param + let mut minor: ffi::egl::types::EGLint = 0; // out param + + if egl::Initialize(display, &mut major, &mut minor) == 0 { + return Err(CreationError::OsError(format!("eglInitialize failed"))) + } + + (major, minor) + }; + + // the list of extensions supported by the client once initialized is different from the + // list of extensions obtained earlier + let extensions = if egl_version >= (1, 2) { + let p = unsafe { CStr::from_ptr(egl::QueryString(display, ffi::egl::EXTENSIONS as i32)) }; + let list = String::from_utf8(p.to_bytes().to_vec()).unwrap_or_else(|_| format!("")); + list.split(' ').map(|e| e.to_string()).collect::<Vec<_>>() + + } else { + vec![] + }; + + // binding the right API and choosing the version + let (version, api) = unsafe { + match opengl.version { + GlRequest::Latest => { + if egl_version >= (1, 4) { + if egl::BindAPI(ffi::egl::OPENGL_API) != 0 { + (None, Api::OpenGl) + } else if egl::BindAPI(ffi::egl::OPENGL_ES_API) != 0 { + (None, Api::OpenGlEs) + } else { + return Err(CreationError::OpenGlVersionNotSupported); + } + } else { + (None, Api::OpenGlEs) + } + }, + GlRequest::Specific(Api::OpenGlEs, version) => { + if egl_version >= (1, 2) { + if egl::BindAPI(ffi::egl::OPENGL_ES_API) == 0 { + return Err(CreationError::OpenGlVersionNotSupported); + } + } + (Some(version), Api::OpenGlEs) + }, + GlRequest::Specific(Api::OpenGl, version) => { + if egl_version < (1, 4) { + return Err(CreationError::OpenGlVersionNotSupported); + } + if egl::BindAPI(ffi::egl::OPENGL_API) == 0 { + return Err(CreationError::OpenGlVersionNotSupported); + } + (Some(version), Api::OpenGl) + }, + GlRequest::Specific(_, _) => return Err(CreationError::OpenGlVersionNotSupported), + GlRequest::GlThenGles { opengles_version, opengl_version } => { + if egl_version >= (1, 4) { + if egl::BindAPI(ffi::egl::OPENGL_API) != 0 { + (Some(opengl_version), Api::OpenGl) + } else if egl::BindAPI(ffi::egl::OPENGL_ES_API) != 0 { + (Some(opengles_version), Api::OpenGlEs) + } else { + return Err(CreationError::OpenGlVersionNotSupported); + } + } else { + (Some(opengles_version), Api::OpenGlEs) + } + }, + } + }; + + let (config_id, pixel_format) = unsafe { + choose_fbconfig(display, &egl_version, api, version, pf_reqs)? + }; + + Ok(ContextPrototype { + opengl: opengl, + display: display, + egl_version: egl_version, + extensions: extensions, + api: api, + version: version, + config_id: config_id, + pixel_format: pixel_format, + }) + } + + #[inline] + pub fn swap_buffers(&self) -> Result<(), ContextError> { + if self.surface.get() == ffi::egl::NO_SURFACE { + return Err(ContextError::ContextLost); + } + + let ret = unsafe { + egl::SwapBuffers(self.display, self.surface.get()) + }; + + if ret == 0 { + match unsafe { egl::GetError() } as u32 { + ffi::egl::CONTEXT_LOST => return Err(ContextError::ContextLost), + err => panic!("eglSwapBuffers failed (eglGetError returned 0x{:x})", err) + } + + } else { + Ok(()) + } + } + + pub unsafe fn make_current(&self) -> Result<(), ContextError> { + let ret = egl::MakeCurrent(self.display, self.surface.get(), self.surface.get(), self.context); + + if ret == 0 { + match egl::GetError() as u32 { + ffi::egl::CONTEXT_LOST => return Err(ContextError::ContextLost), + err => panic!("eglMakeCurrent failed (eglGetError returned 0x{:x})", err) + } + + } else { + Ok(()) + } + } + + #[inline] + pub fn is_current(&self) -> bool { + unsafe { egl::GetCurrentContext() == self.context } + } + + pub fn get_proc_address(&self, addr: &str) -> *const () { + let addr = CString::new(addr.as_bytes()).unwrap(); + let addr = addr.as_ptr(); + unsafe { + egl::GetProcAddress(addr) as *const _ + } + } + + #[inline] + pub fn get_api(&self) -> Api { + self.api + } + + #[inline] + pub fn get_pixel_format(&self) -> PixelFormat { + self.pixel_format.clone() + } +} + +unsafe impl Send for Context {} +unsafe impl Sync for Context {} + +impl Drop for Context { + fn drop(&mut self) { + unsafe { + // we don't call MakeCurrent(0, 0) because we are not sure that the context + // is still the current one + egl::DestroyContext(self.display, self.context); + egl::DestroySurface(self.display, self.surface.get()); + egl::Terminate(self.display); + } + } +} + +pub struct ContextPrototype<'a> { + opengl: &'a GlAttributes<&'a Context>, + display: ffi::egl::types::EGLDisplay, + egl_version: (ffi::egl::types::EGLint, ffi::egl::types::EGLint), + extensions: Vec<String>, + api: Api, + version: Option<(u8, u8)>, + config_id: ffi::egl::types::EGLConfig, + pixel_format: PixelFormat, +} + +impl<'a> ContextPrototype<'a> { + pub fn get_native_visual_id(&self) -> ffi::egl::types::EGLint { + let mut value = 0; + let ret = unsafe { egl::GetConfigAttrib(self.display, self.config_id, + ffi::egl::NATIVE_VISUAL_ID + as ffi::egl::types::EGLint, &mut value) }; + if ret == 0 { panic!("eglGetConfigAttrib failed") }; + value + } + + pub fn finish(self, native_window: ffi::EGLNativeWindowType) + -> Result<Context, CreationError> + { + let surface = unsafe { + let surface = egl::CreateWindowSurface(self.display, self.config_id, native_window, + ptr::null()); + if surface.is_null() { + return Err(CreationError::OsError(format!("eglCreateWindowSurface failed"))) + } + surface + }; + + self.finish_impl(surface) + } + + pub fn finish_pbuffer(self, dimensions: (u32, u32)) -> Result<Context, CreationError> { + let attrs = &[ + ffi::egl::WIDTH as c_int, dimensions.0 as c_int, + ffi::egl::HEIGHT as c_int, dimensions.1 as c_int, + ffi::egl::NONE as c_int, + ]; + + let surface = unsafe { + let surface = egl::CreatePbufferSurface(self.display, self.config_id, + attrs.as_ptr()); + if surface.is_null() { + return Err(CreationError::OsError(format!("eglCreatePbufferSurface failed"))) + } + surface + }; + + self.finish_impl(surface) + } + + fn finish_impl(self, surface: ffi::egl::types::EGLSurface) + -> Result<Context, CreationError> + { + let context = unsafe { + if let Some(version) = self.version { + create_context(self.display, &self.egl_version, + &self.extensions, self.api, version, self.config_id, + self.opengl.debug, self.opengl.robustness)? + + } else if self.api == Api::OpenGlEs { + if let Ok(ctxt) = create_context(self.display, &self.egl_version, + &self.extensions, self.api, (2, 0), self.config_id, + self.opengl.debug, self.opengl.robustness) + { + ctxt + } else if let Ok(ctxt) = create_context(self.display, &self.egl_version, + &self.extensions, self.api, (1, 0), + self.config_id, self.opengl.debug, + self.opengl.robustness) + { + ctxt + } else { + return Err(CreationError::OpenGlVersionNotSupported); + } + + } else { + if let Ok(ctxt) = create_context(self.display, &self.egl_version, + &self.extensions, self.api, (3, 2), self.config_id, + self.opengl.debug, self.opengl.robustness) + { + ctxt + } else if let Ok(ctxt) = create_context(self.display, &self.egl_version, + &self.extensions, self.api, (3, 1), + self.config_id, self.opengl.debug, + self.opengl.robustness) + { + ctxt + } else if let Ok(ctxt) = create_context(self.display, &self.egl_version, + &self.extensions, self.api, (1, 0), + self.config_id, self.opengl.debug, + self.opengl.robustness) + { + ctxt + } else { + return Err(CreationError::OpenGlVersionNotSupported); + } + } + }; + + Ok(Context { + display: self.display, + context: context, + surface: Cell::new(surface), + api: self.api, + pixel_format: self.pixel_format, + }) + } +} + +unsafe fn choose_fbconfig(display: ffi::egl::types::EGLDisplay, + egl_version: &(ffi::egl::types::EGLint, ffi::egl::types::EGLint), + api: Api, version: Option<(u8, u8)>, reqs: &PixelFormatRequirements) + -> Result<(ffi::egl::types::EGLConfig, PixelFormat), CreationError> +{ + let descriptor = { + let mut out: Vec<c_int> = Vec::with_capacity(37); + + if egl_version >= &(1, 2) { + out.push(ffi::egl::COLOR_BUFFER_TYPE as c_int); + out.push(ffi::egl::RGB_BUFFER as c_int); + } + + out.push(ffi::egl::SURFACE_TYPE as c_int); + // TODO: Some versions of Mesa report a BAD_ATTRIBUTE error + // if we ask for PBUFFER_BIT as well as WINDOW_BIT + out.push((ffi::egl::WINDOW_BIT) as c_int); + + match (api, version) { + (Api::OpenGlEs, Some((3, _))) => { + if egl_version < &(1, 3) { return Err(CreationError::NoAvailablePixelFormat); } + out.push(ffi::egl::RENDERABLE_TYPE as c_int); + out.push(ffi::egl::OPENGL_ES3_BIT as c_int); + out.push(ffi::egl::CONFORMANT as c_int); + out.push(ffi::egl::OPENGL_ES3_BIT as c_int); + }, + (Api::OpenGlEs, Some((2, _))) => { + if egl_version < &(1, 3) { return Err(CreationError::NoAvailablePixelFormat); } + out.push(ffi::egl::RENDERABLE_TYPE as c_int); + out.push(ffi::egl::OPENGL_ES2_BIT as c_int); + out.push(ffi::egl::CONFORMANT as c_int); + out.push(ffi::egl::OPENGL_ES2_BIT as c_int); + }, + (Api::OpenGlEs, Some((1, _))) => { + if egl_version >= &(1, 3) { + out.push(ffi::egl::RENDERABLE_TYPE as c_int); + out.push(ffi::egl::OPENGL_ES_BIT as c_int); + out.push(ffi::egl::CONFORMANT as c_int); + out.push(ffi::egl::OPENGL_ES_BIT as c_int); + } + }, + (Api::OpenGlEs, _) => unimplemented!(), + (Api::OpenGl, _) => { + if egl_version < &(1, 3) { return Err(CreationError::NoAvailablePixelFormat); } + out.push(ffi::egl::RENDERABLE_TYPE as c_int); + out.push(ffi::egl::OPENGL_BIT as c_int); + out.push(ffi::egl::CONFORMANT as c_int); + out.push(ffi::egl::OPENGL_BIT as c_int); + }, + (_, _) => unimplemented!(), + }; + + if let Some(hardware_accelerated) = reqs.hardware_accelerated { + out.push(ffi::egl::CONFIG_CAVEAT as c_int); + out.push(if hardware_accelerated { + ffi::egl::NONE as c_int + } else { + ffi::egl::SLOW_CONFIG as c_int + }); + } + + if let Some(color) = reqs.color_bits { + out.push(ffi::egl::RED_SIZE as c_int); + out.push((color / 3) as c_int); + out.push(ffi::egl::GREEN_SIZE as c_int); + out.push((color / 3 + if color % 3 != 0 { 1 } else { 0 }) as c_int); + out.push(ffi::egl::BLUE_SIZE as c_int); + out.push((color / 3 + if color % 3 == 2 { 1 } else { 0 }) as c_int); + } + + if let Some(alpha) = reqs.alpha_bits { + out.push(ffi::egl::ALPHA_SIZE as c_int); + out.push(alpha as c_int); + } + + if let Some(depth) = reqs.depth_bits { + out.push(ffi::egl::DEPTH_SIZE as c_int); + out.push(depth as c_int); + } + + if let Some(stencil) = reqs.stencil_bits { + out.push(ffi::egl::STENCIL_SIZE as c_int); + out.push(stencil as c_int); + } + + if let Some(true) = reqs.double_buffer { + return Err(CreationError::NoAvailablePixelFormat); + } + + if let Some(multisampling) = reqs.multisampling { + out.push(ffi::egl::SAMPLES as c_int); + out.push(multisampling as c_int); + } + + if reqs.stereoscopy { + return Err(CreationError::NoAvailablePixelFormat); + } + + // FIXME: srgb is not taken into account + + match reqs.release_behavior { + ReleaseBehavior::Flush => (), + ReleaseBehavior::None => { + // TODO: with EGL you need to manually set the behavior + unimplemented!() + }, + } + + out.push(ffi::egl::NONE as c_int); + out + }; + + // calling `eglChooseConfig` + let mut config_id = ptr::null(); // out param + let mut num_configs = 0; // out param + if egl::ChooseConfig(display, descriptor.as_ptr(), &mut config_id, 1, &mut num_configs) == 0 { + return Err(CreationError::OsError(format!("eglChooseConfig failed"))); + } + if num_configs == 0 { + return Err(CreationError::NoAvailablePixelFormat); + } + + // analyzing each config + macro_rules! attrib { + ($display:expr, $config:expr, $attr:expr) => ( + { + let mut value = 0; // out param + let res = egl::GetConfigAttrib($display, $config, + $attr as ffi::egl::types::EGLint, &mut value); + if res == 0 { + return Err(CreationError::OsError(format!("eglGetConfigAttrib failed"))); + } + value + } + ) + }; + + let desc = PixelFormat { + hardware_accelerated: attrib!(display, config_id, ffi::egl::CONFIG_CAVEAT) + != ffi::egl::SLOW_CONFIG as i32, + color_bits: attrib!(display, config_id, ffi::egl::RED_SIZE) as u8 + + attrib!(display, config_id, ffi::egl::BLUE_SIZE) as u8 + + attrib!(display, config_id, ffi::egl::GREEN_SIZE) as u8, + alpha_bits: attrib!(display, config_id, ffi::egl::ALPHA_SIZE) as u8, + depth_bits: attrib!(display, config_id, ffi::egl::DEPTH_SIZE) as u8, + stencil_bits: attrib!(display, config_id, ffi::egl::STENCIL_SIZE) as u8, + stereoscopy: false, + double_buffer: true, + multisampling: match attrib!(display, config_id, ffi::egl::SAMPLES) { + 0 | 1 => None, + a => Some(a as u16), + }, + srgb: false, // TODO: use EGL_KHR_gl_colorspace to know that + }; + + Ok((config_id, desc)) +} + +unsafe fn create_context(display: ffi::egl::types::EGLDisplay, + egl_version: &(ffi::egl::types::EGLint, ffi::egl::types::EGLint), + extensions: &[String], api: Api, version: (u8, u8), + config_id: ffi::egl::types::EGLConfig, gl_debug: bool, + gl_robustness: Robustness) + -> Result<ffi::egl::types::EGLContext, CreationError> +{ + let mut context_attributes = Vec::with_capacity(10); + let mut flags = 0; + + if egl_version >= &(1, 5) || extensions.iter().find(|s| s == &"EGL_KHR_create_context") + .is_some() + { + context_attributes.push(ffi::egl::CONTEXT_MAJOR_VERSION as i32); + context_attributes.push(version.0 as i32); + context_attributes.push(ffi::egl::CONTEXT_MINOR_VERSION as i32); + context_attributes.push(version.1 as i32); + + // handling robustness + let supports_robustness = egl_version >= &(1, 5) || + extensions.iter() + .find(|s| s == &"EGL_EXT_create_context_robustness") + .is_some(); + + match gl_robustness { + Robustness::NotRobust => (), + + Robustness::NoError => { + if extensions.iter().find(|s| s == &"EGL_KHR_create_context_no_error").is_some() { + context_attributes.push(ffi::egl::CONTEXT_OPENGL_NO_ERROR_KHR as c_int); + context_attributes.push(1); + } + }, + + Robustness::RobustNoResetNotification => { + if supports_robustness { + context_attributes.push(ffi::egl::CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY + as c_int); + context_attributes.push(ffi::egl::NO_RESET_NOTIFICATION as c_int); + flags = flags | ffi::egl::CONTEXT_OPENGL_ROBUST_ACCESS as c_int; + } else { + return Err(CreationError::RobustnessNotSupported); + } + }, + + Robustness::TryRobustNoResetNotification => { + if supports_robustness { + context_attributes.push(ffi::egl::CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY + as c_int); + context_attributes.push(ffi::egl::NO_RESET_NOTIFICATION as c_int); + flags = flags | ffi::egl::CONTEXT_OPENGL_ROBUST_ACCESS as c_int; + } + }, + + Robustness::RobustLoseContextOnReset => { + if supports_robustness { + context_attributes.push(ffi::egl::CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY + as c_int); + context_attributes.push(ffi::egl::LOSE_CONTEXT_ON_RESET as c_int); + flags = flags | ffi::egl::CONTEXT_OPENGL_ROBUST_ACCESS as c_int; + } else { + return Err(CreationError::RobustnessNotSupported); + } + }, + + Robustness::TryRobustLoseContextOnReset => { + if supports_robustness { + context_attributes.push(ffi::egl::CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY + as c_int); + context_attributes.push(ffi::egl::LOSE_CONTEXT_ON_RESET as c_int); + flags = flags | ffi::egl::CONTEXT_OPENGL_ROBUST_ACCESS as c_int; + } + }, + } + + if gl_debug { + if egl_version >= &(1, 5) { + context_attributes.push(ffi::egl::CONTEXT_OPENGL_DEBUG as i32); + context_attributes.push(ffi::egl::TRUE as i32); + } + + // TODO: using this flag sometimes generates an error + // there was a change in the specs that added this flag, so it may not be + // supported everywhere ; however it is not possible to know whether it is + // supported or not + //flags = flags | ffi::egl::CONTEXT_OPENGL_DEBUG_BIT_KHR as i32; + } + + context_attributes.push(ffi::egl::CONTEXT_FLAGS_KHR as i32); + context_attributes.push(flags); + + } else if egl_version >= &(1, 3) && api == Api::OpenGlEs { + // robustness is not supported + match gl_robustness { + Robustness::RobustNoResetNotification | Robustness::RobustLoseContextOnReset => { + return Err(CreationError::RobustnessNotSupported); + }, + _ => () + } + + context_attributes.push(ffi::egl::CONTEXT_CLIENT_VERSION as i32); + context_attributes.push(version.0 as i32); + } + + context_attributes.push(ffi::egl::NONE as i32); + + let context = egl::CreateContext(display, config_id, ptr::null(), + context_attributes.as_ptr()); + + if context.is_null() { + match egl::GetError() as u32 { + ffi::egl::BAD_ATTRIBUTE => return Err(CreationError::OpenGlVersionNotSupported), + e => panic!("eglCreateContext failed: 0x{:x}", e), + } + } + + Ok(context) +} + diff --git a/gfx/wr/wrench/src/main.rs b/gfx/wr/wrench/src/main.rs new file mode 100644 index 0000000000..86c735651c --- /dev/null +++ b/gfx/wr/wrench/src/main.rs @@ -0,0 +1,1055 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#[macro_use] +extern crate clap; +#[macro_use] +extern crate log; +#[macro_use] +extern crate serde; +#[macro_use] +extern crate tracy_rs; + +mod angle; +mod blob; +mod egl; +mod parse_function; +mod perf; +mod png; +mod premultiply; +mod rawtest; +mod reftest; +mod test_invalidation; +mod wrench; +mod yaml_frame_reader; +mod yaml_helper; + +use gleam::gl; +#[cfg(feature = "software")] +use gleam::gl::Gl; +use crate::perf::PerfHarness; +use crate::png::save_flipped; +use crate::rawtest::RawtestHarness; +use crate::reftest::{ReftestHarness, ReftestOptions}; +use std::fs; +#[cfg(feature = "headless")] +use std::ffi::CString; +#[cfg(feature = "headless")] +use std::mem; +use std::os::raw::c_void; +use std::path::{Path, PathBuf}; +use std::process; +use std::ptr; +use std::rc::Rc; +#[cfg(feature = "software")] +use std::slice; +use std::sync::mpsc::{channel, Sender, Receiver}; +use webrender::DebugFlags; +use webrender::api::*; +use webrender::render_api::*; +use webrender::api::units::*; +use winit::dpi::{LogicalPosition, LogicalSize}; +use winit::VirtualKeyCode; +use crate::wrench::{CapturedSequence, Wrench, WrenchThing}; +use crate::yaml_frame_reader::YamlFrameReader; + +pub const PLATFORM_DEFAULT_FACE_NAME: &str = "Arial"; + +pub static mut CURRENT_FRAME_NUMBER: u32 = 0; + +#[cfg(feature = "headless")] +pub struct HeadlessContext { + width: i32, + height: i32, + _context: osmesa_sys::OSMesaContext, + _buffer: Vec<u32>, +} + +#[cfg(not(feature = "headless"))] +pub struct HeadlessContext { + width: i32, + height: i32, +} + +impl HeadlessContext { + #[cfg(feature = "headless")] + fn new(width: i32, height: i32) -> Self { + let mut attribs = Vec::new(); + + attribs.push(osmesa_sys::OSMESA_PROFILE); + attribs.push(osmesa_sys::OSMESA_CORE_PROFILE); + attribs.push(osmesa_sys::OSMESA_CONTEXT_MAJOR_VERSION); + attribs.push(3); + attribs.push(osmesa_sys::OSMESA_CONTEXT_MINOR_VERSION); + attribs.push(3); + attribs.push(osmesa_sys::OSMESA_DEPTH_BITS); + attribs.push(24); + attribs.push(0); + + let context = + unsafe { osmesa_sys::OSMesaCreateContextAttribs(attribs.as_ptr(), ptr::null_mut()) }; + + assert!(!context.is_null()); + + let mut buffer = vec![0; (width * height) as usize]; + + unsafe { + let ret = osmesa_sys::OSMesaMakeCurrent( + context, + buffer.as_mut_ptr() as *mut _, + gl::UNSIGNED_BYTE, + width, + height, + ); + assert!(ret != 0); + }; + + HeadlessContext { + width, + height, + _context: context, + _buffer: buffer, + } + } + + #[cfg(not(feature = "headless"))] + fn new(width: i32, height: i32) -> Self { + HeadlessContext { width, height } + } + + #[cfg(feature = "headless")] + fn get_proc_address(s: &str) -> *const c_void { + let c_str = CString::new(s).expect("Unable to create CString"); + unsafe { mem::transmute(osmesa_sys::OSMesaGetProcAddress(c_str.as_ptr())) } + } + + #[cfg(not(feature = "headless"))] + fn get_proc_address(_: &str) -> *const c_void { + ptr::null() as *const _ + } +} + +#[cfg(not(feature = "software"))] +mod swgl { + pub struct Context; +} + +pub enum WindowWrapper { + WindowedContext(glutin::WindowedContext<glutin::PossiblyCurrent>, Rc<dyn gl::Gl>, Option<swgl::Context>), + Angle(winit::Window, angle::Context, Rc<dyn gl::Gl>, Option<swgl::Context>), + Headless(HeadlessContext, Rc<dyn gl::Gl>, Option<swgl::Context>), +} + +pub struct HeadlessEventIterater; + +impl WindowWrapper { + #[cfg(feature = "software")] + fn upload_software_to_native(&self) { + match *self { + WindowWrapper::Headless(..) => return, + _ => {} + } + let swgl = match self.software_gl() { + Some(swgl) => swgl, + None => return, + }; + swgl.finish(); + let gl = self.native_gl(); + let tex = gl.gen_textures(1)[0]; + gl.bind_texture(gl::TEXTURE_2D, tex); + let (data_ptr, w, h, stride) = swgl.get_color_buffer(0, true); + assert!(stride == w * 4); + let buffer = unsafe { slice::from_raw_parts(data_ptr as *const u8, w as usize * h as usize * 4) }; + gl.tex_image_2d(gl::TEXTURE_2D, 0, gl::RGBA8 as gl::GLint, w, h, 0, gl::BGRA, gl::UNSIGNED_BYTE, Some(buffer)); + let fb = gl.gen_framebuffers(1)[0]; + gl.bind_framebuffer(gl::READ_FRAMEBUFFER, fb); + gl.framebuffer_texture_2d(gl::READ_FRAMEBUFFER, gl::COLOR_ATTACHMENT0, gl::TEXTURE_2D, tex, 0); + gl.blit_framebuffer(0, 0, w, h, 0, 0, w, h, gl::COLOR_BUFFER_BIT, gl::NEAREST); + gl.delete_framebuffers(&[fb]); + gl.delete_textures(&[tex]); + gl.finish(); + } + + #[cfg(not(feature = "software"))] + fn upload_software_to_native(&self) { + } + + fn swap_buffers(&self) { + match *self { + WindowWrapper::WindowedContext(ref windowed_context, _, _) => { + windowed_context.swap_buffers().unwrap() + } + WindowWrapper::Angle(_, ref context, _, _) => context.swap_buffers().unwrap(), + WindowWrapper::Headless(_, _, _) => {} + } + } + + fn get_inner_size(&self) -> DeviceIntSize { + fn inner_size(window: &winit::Window) -> DeviceIntSize { + let size = window + .get_inner_size() + .unwrap() + .to_physical(window.get_hidpi_factor()); + DeviceIntSize::new(size.width as i32, size.height as i32) + } + match *self { + WindowWrapper::WindowedContext(ref windowed_context, ..) => { + inner_size(windowed_context.window()) + } + WindowWrapper::Angle(ref window, ..) => inner_size(window), + WindowWrapper::Headless(ref context, ..) => DeviceIntSize::new(context.width, context.height), + } + } + + fn hidpi_factor(&self) -> f32 { + match *self { + WindowWrapper::WindowedContext(ref windowed_context, ..) => { + windowed_context.window().get_hidpi_factor() as f32 + } + WindowWrapper::Angle(ref window, ..) => window.get_hidpi_factor() as f32, + WindowWrapper::Headless(..) => 1.0, + } + } + + fn resize(&mut self, size: DeviceIntSize) { + match *self { + WindowWrapper::WindowedContext(ref mut windowed_context, ..) => { + windowed_context.window() + .set_inner_size(LogicalSize::new(size.width as f64, size.height as f64)) + }, + WindowWrapper::Angle(ref mut window, ..) => { + window.set_inner_size(LogicalSize::new(size.width as f64, size.height as f64)) + }, + WindowWrapper::Headless(..) => unimplemented!(), // requites Glutin update + } + } + + fn set_title(&mut self, title: &str) { + match *self { + WindowWrapper::WindowedContext(ref windowed_context, ..) => { + windowed_context.window().set_title(title) + } + WindowWrapper::Angle(ref window, ..) => window.set_title(title), + WindowWrapper::Headless(..) => (), + } + } + + pub fn software_gl(&self) -> Option<&swgl::Context> { + match *self { + WindowWrapper::WindowedContext(_, _, ref swgl) | + WindowWrapper::Angle(_, _, _, ref swgl) | + WindowWrapper::Headless(_, _, ref swgl) => swgl.as_ref(), + } + } + + pub fn native_gl(&self) -> &dyn gl::Gl { + match *self { + WindowWrapper::WindowedContext(_, ref gl, _) | + WindowWrapper::Angle(_, _, ref gl, _) | + WindowWrapper::Headless(_, ref gl, _) => &**gl, + } + } + + #[cfg(feature = "software")] + pub fn gl(&self) -> &dyn gl::Gl { + if let Some(swgl) = self.software_gl() { + swgl + } else { + self.native_gl() + } + } + + pub fn is_software(&self) -> bool { + self.software_gl().is_some() + } + + #[cfg(not(feature = "software"))] + pub fn gl(&self) -> &dyn gl::Gl { + self.native_gl() + } + + pub fn clone_gl(&self) -> Rc<dyn gl::Gl> { + match *self { + WindowWrapper::WindowedContext(_, ref gl, ref swgl) | + WindowWrapper::Angle(_, _, ref gl, ref swgl) | + WindowWrapper::Headless(_, ref gl, ref swgl) => { + match swgl { + #[cfg(feature = "software")] + Some(ref swgl) => Rc::new(swgl.clone()), + None => gl.clone(), + #[cfg(not(feature = "software"))] + _ => panic!(), + } + } + } + } + + + #[cfg(feature = "software")] + fn update_software(&self, dim: DeviceIntSize) { + if let Some(swgl) = self.software_gl() { + swgl.init_default_framebuffer(0, 0, dim.width, dim.height, 0, std::ptr::null_mut()); + } + } + + #[cfg(not(feature = "software"))] + fn update_software(&self, _dim: DeviceIntSize) { + } + + fn update(&self, wrench: &mut Wrench) { + let dim = self.get_inner_size(); + self.update_software(dim); + wrench.update(dim); + } +} + +#[cfg(feature = "software")] +fn make_software_context() -> swgl::Context { + let ctx = swgl::Context::create(); + ctx.make_current(); + ctx +} + +#[cfg(not(feature = "software"))] +fn make_software_context() -> swgl::Context { + panic!("software feature not enabled") +} + +fn make_window( + size: DeviceIntSize, + dp_ratio: Option<f32>, + vsync: bool, + events_loop: &Option<winit::EventsLoop>, + angle: bool, + gl_request: glutin::GlRequest, + software: bool, +) -> WindowWrapper { + let sw_ctx = if software { + Some(make_software_context()) + } else { + None + }; + + let wrapper = match *events_loop { + Some(ref events_loop) => { + let context_builder = glutin::ContextBuilder::new() + .with_gl(gl_request) + .with_vsync(vsync); + let window_builder = winit::WindowBuilder::new() + .with_title("WRench") + .with_multitouch() + .with_dimensions(LogicalSize::new(size.width as f64, size.height as f64)); + + if angle { + let (_window, _context) = angle::Context::with_window( + window_builder, context_builder, events_loop + ).unwrap(); + + unsafe { + _context + .make_current() + .expect("unable to make context current!"); + } + + let gl = match _context.get_api() { + glutin::Api::OpenGl => unsafe { + gl::GlFns::load_with(|symbol| _context.get_proc_address(symbol) as *const _) + }, + glutin::Api::OpenGlEs => unsafe { + gl::GlesFns::load_with(|symbol| _context.get_proc_address(symbol) as *const _) + }, + glutin::Api::WebGl => unimplemented!(), + }; + + WindowWrapper::Angle(_window, _context, gl, sw_ctx) + } else { + let windowed_context = context_builder + .build_windowed(window_builder, events_loop) + .unwrap(); + + let windowed_context = unsafe { + windowed_context + .make_current() + .expect("unable to make context current!") + }; + + let gl = match windowed_context.get_api() { + glutin::Api::OpenGl => unsafe { + gl::GlFns::load_with( + |symbol| windowed_context.get_proc_address(symbol) as *const _ + ) + }, + glutin::Api::OpenGlEs => unsafe { + gl::GlesFns::load_with( + |symbol| windowed_context.get_proc_address(symbol) as *const _ + ) + }, + glutin::Api::WebGl => unimplemented!(), + }; + + WindowWrapper::WindowedContext(windowed_context, gl, sw_ctx) + } + } + None => { + let gl = match sw_ctx { + #[cfg(feature = "software")] + Some(ref sw_ctx) => Rc::new(sw_ctx.clone()), + None => { + match gl::GlType::default() { + gl::GlType::Gl => unsafe { + gl::GlFns::load_with(|symbol| { + HeadlessContext::get_proc_address(symbol) as *const _ + }) + }, + gl::GlType::Gles => unsafe { + gl::GlesFns::load_with(|symbol| { + HeadlessContext::get_proc_address(symbol) as *const _ + }) + }, + } + } + #[cfg(not(feature = "software"))] + _ => panic!(), + }; + WindowWrapper::Headless(HeadlessContext::new(size.width, size.height), gl, sw_ctx) + } + }; + + let gl = wrapper.gl(); + + gl.clear_color(0.3, 0.0, 0.0, 1.0); + + let gl_version = gl.get_string(gl::VERSION); + let gl_renderer = gl.get_string(gl::RENDERER); + + let dp_ratio = dp_ratio.unwrap_or(wrapper.hidpi_factor()); + println!("OpenGL version {}, {}", gl_version, gl_renderer); + println!( + "hidpi factor: {} (native {})", + dp_ratio, + wrapper.hidpi_factor() + ); + + wrapper +} + +#[derive(Copy, Clone, Debug, PartialEq, Eq)] +pub enum NotifierEvent { + WakeUp { + composite_needed: bool, + }, + ShutDown, +} + +struct Notifier { + tx: Sender<NotifierEvent>, +} + +// setup a notifier so we can wait for frames to be finished +impl RenderNotifier for Notifier { + fn clone(&self) -> Box<dyn RenderNotifier> { + Box::new(Notifier { + tx: self.tx.clone(), + }) + } + + fn wake_up( + &self, + composite_needed: bool, + ) { + let msg = NotifierEvent::WakeUp { + composite_needed, + }; + self.tx.send(msg).unwrap(); + } + + fn shut_down(&self) { + self.tx.send(NotifierEvent::ShutDown).unwrap(); + } + + fn new_frame_ready(&self, + _: DocumentId, + _scrolled: bool, + composite_needed: bool, + _render_time: Option<u64>) { + // TODO(gw): Refactor wrench so that it can take advantage of cases + // where no composite is required when appropriate. + self.wake_up(composite_needed); + } +} + +fn create_notifier() -> (Box<dyn RenderNotifier>, Receiver<NotifierEvent>) { + let (tx, rx) = channel(); + (Box::new(Notifier { tx: tx }), rx) +} + +fn rawtest(mut wrench: Wrench, window: &mut WindowWrapper, rx: Receiver<NotifierEvent>) { + RawtestHarness::new(&mut wrench, window, &rx).run(); + wrench.shut_down(rx); +} + +fn reftest<'a>( + mut wrench: Wrench, + window: &mut WindowWrapper, + subargs: &clap::ArgMatches<'a>, + rx: Receiver<NotifierEvent> +) -> usize { + let dim = window.get_inner_size(); + let base_manifest = if cfg!(target_os = "android") { + Path::new("/sdcard/wrench/reftests/reftest.list") + } else { + Path::new("reftests/reftest.list") + }; + let specific_reftest = subargs.value_of("REFTEST").map(|x| Path::new(x)); + let mut reftest_options = ReftestOptions::default(); + if let Some(allow_max_diff) = subargs.value_of("fuzz_tolerance") { + reftest_options.allow_max_difference = allow_max_diff.parse().unwrap_or(1); + reftest_options.allow_num_differences = dim.width as usize * dim.height as usize; + } + let num_failures = ReftestHarness::new(&mut wrench, window, &rx) + .run(base_manifest, specific_reftest, &reftest_options); + wrench.shut_down(rx); + num_failures +} + +fn main() { + #[cfg(feature = "env_logger")] + env_logger::init(); + + #[cfg(target_os = "macos")] + { + use core_foundation::{self as cf, base::TCFType}; + let i = cf::bundle::CFBundle::main_bundle().info_dictionary(); + let mut i = unsafe { i.to_mutable() }; + i.set( + cf::string::CFString::new("NSSupportsAutomaticGraphicsSwitching"), + cf::boolean::CFBoolean::true_value().into_CFType(), + ); + } + + let args_yaml = load_yaml!("args.yaml"); + let clap = clap::App::from_yaml(args_yaml) + .setting(clap::AppSettings::ArgRequiredElseHelp); + + // On android devices, attempt to read command line arguments + // from a text file located at /sdcard/wrench/args. + let args = if cfg!(target_os = "android") { + // get full backtraces by default because it's hard to request + // externally on android + std::env::set_var("RUST_BACKTRACE", "full"); + + let mut args = vec!["wrench".to_string()]; + + if let Ok(wrench_args) = fs::read_to_string("/sdcard/wrench/args") { + for line in wrench_args.lines() { + if line.starts_with("env: ") { + let envvar = &line[5..]; + if let Some(ix) = envvar.find('=') { + std::env::set_var(&envvar[0..ix], &envvar[ix + 1..]); + } else { + std::env::set_var(envvar, ""); + } + continue; + } + for arg in line.split_whitespace() { + args.push(arg.to_string()); + } + } + } + + clap.get_matches_from(&args) + } else { + clap.get_matches() + }; + + // handle some global arguments + let res_path = args.value_of("shaders").map(|s| PathBuf::from(s)); + let dp_ratio = args.value_of("dp_ratio").map(|v| v.parse::<f32>().unwrap()); + let size = args.value_of("size") + .map(|s| if s == "720p" { + DeviceIntSize::new(1280, 720) + } else if s == "1080p" { + DeviceIntSize::new(1920, 1080) + } else if s == "4k" { + DeviceIntSize::new(3840, 2160) + } else { + let x = s.find('x').expect( + "Size must be specified exactly as 720p, 1080p, 4k, or width x height", + ); + let w = s[0 .. x].parse::<i32>().expect("Invalid size width"); + let h = s[x + 1 ..].parse::<i32>().expect("Invalid size height"); + DeviceIntSize::new(w, h) + }) + .unwrap_or(DeviceIntSize::new(1920, 1080)); + let zoom_factor = args.value_of("zoom").map(|z| z.parse::<f32>().unwrap()); + let chase_primitive = match args.value_of("chase") { + Some(s) => { + match s.find(',') { + Some(_) => { + let items = s + .split(',') + .map(|s| s.parse::<f32>().unwrap()) + .collect::<Vec<_>>(); + let rect = LayoutRect::new( + LayoutPoint::new(items[0], items[1]), + LayoutSize::new(items[2], items[3]), + ); + webrender::ChasePrimitive::LocalRect(rect) + } + None => { + let id = s.parse::<usize>().unwrap(); + webrender::ChasePrimitive::Id(webrender::PrimitiveDebugId(id)) + } + } + }, + None => webrender::ChasePrimitive::Nothing, + }; + + let dump_shader_source = args.value_of("dump_shader_source").map(String::from); + + let mut events_loop = if args.is_present("headless") { + None + } else { + Some(winit::EventsLoop::new()) + }; + + let gl_request = match args.value_of("renderer") { + Some("es3") => { + glutin::GlRequest::Specific(glutin::Api::OpenGlEs, (3, 0)) + } + Some("gl3") => { + glutin::GlRequest::Specific(glutin::Api::OpenGl, (3, 2)) + } + Some("default") | None => { + glutin::GlRequest::GlThenGles { + opengl_version: (3, 2), + opengles_version: (3, 0), + } + } + Some(api) => { + panic!("Unexpected renderer string {}", api); + } + }; + + let software = args.is_present("software"); + + let mut window = make_window( + size, + dp_ratio, + args.is_present("vsync"), + &events_loop, + args.is_present("angle"), + gl_request, + software, + ); + let dp_ratio = dp_ratio.unwrap_or(window.hidpi_factor()); + let dim = window.get_inner_size(); + + let needs_frame_notifier = ["perf", "reftest", "png", "rawtest", "test_invalidation"] + .iter() + .any(|s| args.subcommand_matches(s).is_some()); + let (notifier, rx) = if needs_frame_notifier { + let (notifier, rx) = create_notifier(); + (Some(notifier), Some(rx)) + } else { + (None, None) + }; + + let mut wrench = Wrench::new( + &mut window, + events_loop.as_mut().map(|el| el.create_proxy()), + res_path, + !args.is_present("use_unoptimized_shaders"), + dp_ratio, + dim, + args.is_present("rebuild"), + args.is_present("no_subpixel_aa"), + args.is_present("verbose"), + args.is_present("no_scissor"), + args.is_present("no_batch"), + args.is_present("precache"), + args.is_present("slow_subpixel"), + zoom_factor.unwrap_or(1.0), + chase_primitive, + dump_shader_source, + notifier, + ); + + if let Some(ui_str) = args.value_of("profiler_ui") { + wrench.renderer.set_profiler_ui(&ui_str); + } + + window.update(&mut wrench); + + if let Some(window_title) = wrench.take_title() { + if !cfg!(windows) { + window.set_title(&window_title); + } + } + + if let Some(subargs) = args.subcommand_matches("show") { + let no_block = args.is_present("no_block"); + let no_batch = args.is_present("no_batch"); + render( + &mut wrench, + &mut window, + size, + &mut events_loop, + subargs, + no_block, + no_batch, + ); + } else if let Some(subargs) = args.subcommand_matches("png") { + let surface = match subargs.value_of("surface") { + Some("screen") | None => png::ReadSurface::Screen, + Some("gpu-cache") => png::ReadSurface::GpuCache, + _ => panic!("Unknown surface argument value") + }; + let output_path = subargs.value_of("OUTPUT").map(PathBuf::from); + let reader = YamlFrameReader::new_from_args(subargs); + png::png(&mut wrench, surface, &mut window, reader, rx.unwrap(), output_path); + } else if let Some(subargs) = args.subcommand_matches("reftest") { + // Exit with an error code in order to ensure the CI job fails. + process::exit(reftest(wrench, &mut window, subargs, rx.unwrap()) as _); + } else if let Some(_) = args.subcommand_matches("rawtest") { + rawtest(wrench, &mut window, rx.unwrap()); + return; + } else if let Some(subargs) = args.subcommand_matches("perf") { + // Perf mode wants to benchmark the total cost of drawing + // a new displaty list each frame. + wrench.rebuild_display_lists = true; + + let as_csv = subargs.is_present("csv"); + let auto_filename = subargs.is_present("auto-filename"); + + let warmup_frames = subargs.value_of("warmup_frames").map(|s| s.parse().unwrap()); + let sample_count = subargs.value_of("sample_count").map(|s| s.parse().unwrap()); + + let harness = PerfHarness::new(&mut wrench, + &mut window, + rx.unwrap(), + warmup_frames, + sample_count); + + let benchmark = match subargs.value_of("benchmark") { + Some(path) => path, + None => "benchmarks/benchmarks.list" + }; + println!("Benchmark: {}", benchmark); + let base_manifest = Path::new(benchmark); + + let mut filename = subargs.value_of("filename").unwrap().to_string(); + if auto_filename { + let timestamp = chrono::Local::now().format("%Y-%m-%d-%H-%M-%S"); + filename.push_str( + &format!("/wrench-perf-{}.{}", + timestamp, + if as_csv { "csv" } else { "json" })); + } + harness.run(base_manifest, &filename, as_csv); + return; + } else if let Some(_) = args.subcommand_matches("test_invalidation") { + let harness = test_invalidation::TestHarness::new( + &mut wrench, + &mut window, + rx.unwrap(), + ); + + harness.run(); + } else if let Some(subargs) = args.subcommand_matches("compare_perf") { + let first_filename = subargs.value_of("first_filename").unwrap(); + let second_filename = subargs.value_of("second_filename").unwrap(); + perf::compare(first_filename, second_filename); + return; + } else { + panic!("Should never have gotten here! {:?}", args); + }; + + wrench.renderer.deinit(); +} + +fn render<'a>( + wrench: &mut Wrench, + window: &mut WindowWrapper, + size: DeviceIntSize, + events_loop: &mut Option<winit::EventsLoop>, + subargs: &clap::ArgMatches<'a>, + no_block: bool, + no_batch: bool, +) { + let input_path = subargs.value_of("INPUT").map(PathBuf::from).unwrap(); + + // If the input is a directory, we are looking at a capture. + let mut thing = if input_path.join("scenes").as_path().is_dir() { + let scene_id = subargs.value_of("scene-id").map(|z| z.parse::<u32>().unwrap()); + let frame_id = subargs.value_of("frame-id").map(|z| z.parse::<u32>().unwrap()); + Box::new(CapturedSequence::new( + input_path, + scene_id.unwrap_or(1), + frame_id.unwrap_or(1), + )) + } else if input_path.as_path().is_dir() { + let mut documents = wrench.api.load_capture(input_path, None); + println!("loaded {:?}", documents.iter().map(|cd| cd.document_id).collect::<Vec<_>>()); + let captured = documents.swap_remove(0); + wrench.document_id = captured.document_id; + Box::new(captured) as Box<dyn WrenchThing> + } else { + let extension = input_path + .extension() + .expect("Tried to render with an unknown file type.") + .to_str() + .expect("Tried to render with an unknown file type."); + + match extension { + "yaml" => Box::new(YamlFrameReader::new_from_args(subargs)) as Box<dyn WrenchThing>, + _ => panic!("Tried to render with an unknown file type."), + } + }; + + let mut show_help = false; + let mut do_loop = false; + let mut cursor_position = WorldPoint::zero(); + + window.update(wrench); + thing.do_frame(wrench); + + if let Some(fb_size) = wrench.renderer.device_size() { + window.resize(fb_size); + } + + let mut debug_flags = DebugFlags::empty(); + debug_flags.set(DebugFlags::DISABLE_BATCHING, no_batch); + + // Default the profile overlay on for android. + if cfg!(target_os = "android") { + debug_flags.toggle(DebugFlags::PROFILER_DBG); + wrench.api.send_debug_cmd(DebugCommand::SetFlags(debug_flags)); + } + + let mut body = |wrench: &mut Wrench, events: Vec<winit::Event>| { + let mut do_frame = false; + let mut do_render = false; + + for event in events { + match event { + winit::Event::Awakened => { + do_render = true; + } + winit::Event::WindowEvent { event, .. } => match event { + winit::WindowEvent::CloseRequested => { + return winit::ControlFlow::Break; + } + winit::WindowEvent::Refresh | + winit::WindowEvent::Focused(..) => { + do_render = true; + } + winit::WindowEvent::CursorMoved { position: LogicalPosition { x, y }, .. } => { + cursor_position = WorldPoint::new(x as f32, y as f32); + wrench.renderer.set_cursor_position( + DeviceIntPoint::new( + (cursor_position.x * wrench.device_pixel_ratio).round() as i32, + (cursor_position.y * wrench.device_pixel_ratio).round() as i32, + ), + ); + do_render = true; + } + winit::WindowEvent::KeyboardInput { + input: winit::KeyboardInput { + state: winit::ElementState::Pressed, + virtual_keycode: Some(vk), + .. + }, + .. + } => match vk { + VirtualKeyCode::Escape => { + return winit::ControlFlow::Break; + } + VirtualKeyCode::B => { + debug_flags.toggle(DebugFlags::INVALIDATION_DBG); + wrench.api.send_debug_cmd(DebugCommand::SetFlags(debug_flags)); + do_render = true; + } + VirtualKeyCode::P => { + debug_flags.toggle(DebugFlags::PROFILER_DBG); + wrench.api.send_debug_cmd(DebugCommand::SetFlags(debug_flags)); + do_render = true; + } + VirtualKeyCode::O => { + debug_flags.toggle(DebugFlags::RENDER_TARGET_DBG); + wrench.api.send_debug_cmd(DebugCommand::SetFlags(debug_flags)); + do_render = true; + } + VirtualKeyCode::I => { + debug_flags.toggle(DebugFlags::TEXTURE_CACHE_DBG); + wrench.api.send_debug_cmd(DebugCommand::SetFlags(debug_flags)); + do_render = true; + } + VirtualKeyCode::D => { + debug_flags.toggle(DebugFlags::PICTURE_CACHING_DBG); + wrench.api.send_debug_cmd(DebugCommand::SetFlags(debug_flags)); + do_render = true; + } + VirtualKeyCode::Q => { + debug_flags.toggle(DebugFlags::GPU_TIME_QUERIES | DebugFlags::GPU_SAMPLE_QUERIES); + wrench.api.send_debug_cmd(DebugCommand::SetFlags(debug_flags)); + do_render = true; + } + VirtualKeyCode::V => { + debug_flags.toggle(DebugFlags::SHOW_OVERDRAW); + wrench.api.send_debug_cmd(DebugCommand::SetFlags(debug_flags)); + do_render = true; + } + VirtualKeyCode::G => { + debug_flags.toggle(DebugFlags::GPU_CACHE_DBG); + wrench.api.send_debug_cmd(DebugCommand::SetFlags(debug_flags)); + + // force scene rebuild to see the full set of used GPU cache entries + let mut txn = Transaction::new(); + txn.set_root_pipeline(wrench.root_pipeline_id); + wrench.api.send_transaction(wrench.document_id, txn); + + do_frame = true; + } + VirtualKeyCode::R => { + wrench.set_page_zoom(ZoomFactor::new(1.0)); + do_frame = true; + } + VirtualKeyCode::M => { + wrench.api.notify_memory_pressure(); + do_render = true; + } + VirtualKeyCode::L => { + do_loop = !do_loop; + do_render = true; + } + VirtualKeyCode::Left => { + thing.prev_frame(); + do_frame = true; + } + VirtualKeyCode::Right => { + thing.next_frame(); + do_frame = true; + } + VirtualKeyCode::H => { + show_help = !show_help; + do_render = true; + } + VirtualKeyCode::C => { + let path = PathBuf::from("../captures/wrench"); + wrench.api.save_capture(path, CaptureBits::all()); + } + VirtualKeyCode::Add => { + let current_zoom = wrench.get_page_zoom(); + let new_zoom_factor = ZoomFactor::new(current_zoom.get() + 0.1); + wrench.set_page_zoom(new_zoom_factor); + do_frame = true; + } + VirtualKeyCode::Subtract => { + let current_zoom = wrench.get_page_zoom(); + let new_zoom_factor = ZoomFactor::new((current_zoom.get() - 0.1).max(0.1)); + wrench.set_page_zoom(new_zoom_factor); + do_frame = true; + } + VirtualKeyCode::X => { + let results = wrench.api.hit_test( + wrench.document_id, + None, + cursor_position, + ); + + println!("Hit test results:"); + for item in &results.items { + println!(" • {:?}", item); + } + println!(""); + } + VirtualKeyCode::Z => { + debug_flags.toggle(DebugFlags::ZOOM_DBG); + wrench.api.send_debug_cmd(DebugCommand::SetFlags(debug_flags)); + do_render = true; + } + VirtualKeyCode::Y => { + println!("Clearing all caches..."); + wrench.api.send_debug_cmd(DebugCommand::ClearCaches(ClearCache::all())); + do_frame = true; + } + _ => {} + } + _ => {} + }, + _ => {} + } + } + + window.update(wrench); + + if do_frame { + let frame_num = thing.do_frame(wrench); + unsafe { + CURRENT_FRAME_NUMBER = frame_num; + } + } + + if do_render { + if show_help { + wrench.show_onscreen_help(); + } + + wrench.render(); + window.upload_software_to_native(); + window.swap_buffers(); + + if do_loop { + thing.next_frame(); + } + } + + winit::ControlFlow::Continue + }; + + match *events_loop { + None => { + while body(wrench, vec![winit::Event::Awakened]) == winit::ControlFlow::Continue {} + let fb_rect = FramebufferIntSize::new(size.width, size.height).into(); + let pixels = wrench.renderer.read_pixels_rgba8(fb_rect); + save_flipped("screenshot.png", pixels, size); + } + Some(ref mut events_loop) => { + // We want to ensure that we: + // + // (a) Block the thread when no events are present (for CPU/battery purposes) + // (b) Don't lag the input events by having the event queue back up. + loop { + let mut pending_events = Vec::new(); + + // Block the thread until at least one event arrives + // On Android, we are generally profiling when running + // wrench, and don't want to block on UI events. + if !no_block && cfg!(not(target_os = "android")) { + events_loop.run_forever(|event| { + pending_events.push(event); + winit::ControlFlow::Break + }); + } + + // Collect any other pending events that are also available + events_loop.poll_events(|event| { + pending_events.push(event); + }); + + // Ensure there is at least one event present so that the + // frame gets rendered. + if pending_events.is_empty() { + pending_events.push(winit::Event::Awakened); + } + + // Process all of those pending events in the next vsync period + if body(wrench, pending_events) == winit::ControlFlow::Break { + break; + } + } + } + } +} diff --git a/gfx/wr/wrench/src/parse_function.rs b/gfx/wr/wrench/src/parse_function.rs new file mode 100644 index 0000000000..49cf097c41 --- /dev/null +++ b/gfx/wr/wrench/src/parse_function.rs @@ -0,0 +1,134 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +use std::str::CharIndices; + +// support arguments like '4', 'ab', '4.0', '>=10.14', '*123' +fn acceptable_arg_character(c: char) -> bool { + c.is_alphanumeric() || c == '.' || c == '-' || c == '<' || c == '>' || c == '=' || c == '*' +} + +// A crappy parser for parsing strings like "translate(1, 3) blahblah" +// Returns a tuple with three components: +// - First component is the function name (e.g. "translate") +// - Second component is the list of arguments (e.g. vec!["1", "3"]) +// - Third component is the rest of the string "blahblah" +pub fn parse_function(s: &str) -> (&str, Vec<&str>, &str) { + // XXX: This is not particularly easy to read. Sorry. + struct Parser<'a> { + itr: CharIndices<'a>, + start: usize, + o: Option<(usize, char)>, + } + impl<'a> Parser<'a> { + fn skip_whitespace(&mut self) { + while let Some(k) = self.o { + if !k.1.is_whitespace() { + break; + } + self.start = k.0 + k.1.len_utf8(); + self.o = self.itr.next(); + } + } + } + let mut c = s.char_indices(); + let o = c.next(); + let mut p = Parser { + itr: c, + start: 0, + o: o, + }; + + p.skip_whitespace(); + + let mut end = p.start; + while let Some(k) = p.o { + if !k.1.is_alphabetic() && k.1 != '_' && k.1 != '-' { + break; + } + end = k.0 + k.1.len_utf8(); + p.o = p.itr.next(); + } + + let name = &s[p.start .. end]; + let mut args = Vec::new(); + + p.skip_whitespace(); + + if let Some(k) = p.o { + if k.1 != '(' { + return (name, args, &s[p.start ..]); + } + p.start = k.0 + k.1.len_utf8(); + p.o = p.itr.next(); + } + + loop { + p.skip_whitespace(); + + let mut end = p.start; + let mut brackets: Vec<char> = Vec::new(); + while let Some(k) = p.o { + let prev_bracket_count = brackets.len(); + match k.1 { + '[' | '(' => brackets.push(k.1), + ']' | ')' => { + let open_bracket = match k.1 { + ']' => '[', + ')' => '(', + _ => panic!(), + }; + match brackets.pop() { + // Allow final closing ) for command invocation after args + None if k.1 == ')' => break, + Some(bracket) if bracket == open_bracket => {} + _ => panic!("Unexpected closing bracket {}", k.1), + } + } + _ => {} + } + + let not_in_bracket = brackets.len() == 0 && prev_bracket_count == 0; + if !acceptable_arg_character(k.1) && not_in_bracket { + break; + } + end = k.0 + k.1.len_utf8(); + p.o = p.itr.next(); + } + + args.push(&s[p.start .. end]); + + p.skip_whitespace(); + + if let Some(k) = p.o { + p.start = k.0 + k.1.len_utf8(); + p.o = p.itr.next(); + // unless we find a comma we're done + if k.1 != ',' { + if k.1 != ')' { + panic!("Unexpected closing character: {}", k.1); + } + break; + } + } else { + break; + } + } + (name, args, &s[p.start ..]) +} + +#[test] +fn test() { + assert_eq!(parse_function("rotate(40)").0, "rotate"); + assert_eq!(parse_function(" rotate(40)").0, "rotate"); + assert_eq!(parse_function(" rotate (40)").0, "rotate"); + assert_eq!(parse_function(" rotate ( 40 )").1[0], "40"); + assert_eq!(parse_function("rotate(-40.0)").1[0], "-40.0"); + assert_eq!(parse_function("drop-shadow(0, [1, 2, 3, 4], 5)").1[0], "0"); + assert_eq!(parse_function("drop-shadow(0, [1, 2, 3, 4], 5)").1[1], "[1, 2, 3, 4]"); + assert_eq!(parse_function("drop-shadow(0, [1, 2, 3, 4], 5)").1[2], "5"); + assert_eq!(parse_function("drop-shadow(0, [1, 2, [3, 4]], 5)").1[1], "[1, 2, [3, 4]]"); + assert_eq!(parse_function("func(nest([1, 2]), [3, 4])").1[0], "nest([1, 2])"); + assert_eq!(parse_function("func(nest([1, 2]), [nest(3), nest(4)])").1[1], "[nest(3), nest(4)]"); +} diff --git a/gfx/wr/wrench/src/perf.rs b/gfx/wr/wrench/src/perf.rs new file mode 100644 index 0000000000..a67298ce29 --- /dev/null +++ b/gfx/wr/wrench/src/perf.rs @@ -0,0 +1,352 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +use crate::NotifierEvent; +use crate::WindowWrapper; +use serde_json; +use std::collections::{HashMap, HashSet}; +use std::fs::File; +use std::io::{BufRead, BufReader}; +use std::io::{Read, Write}; +use std::path::{Path, PathBuf}; +use std::sync::mpsc::Receiver; +use crate::wrench::{Wrench, WrenchThing}; +use crate::yaml_frame_reader::YamlFrameReader; +use webrender::DebugFlags; +use webrender::render_api::DebugCommand; + +const COLOR_DEFAULT: &str = "\x1b[0m"; +const COLOR_RED: &str = "\x1b[31m"; +const COLOR_GREEN: &str = "\x1b[32m"; +const COLOR_MAGENTA: &str = "\x1b[95m"; + +const MIN_SAMPLE_COUNT: usize = 50; +const SAMPLE_EXCLUDE_COUNT: usize = 10; + +pub struct Benchmark { + pub test: PathBuf, +} + +pub struct BenchmarkManifest { + pub benchmarks: Vec<Benchmark>, +} + +impl BenchmarkManifest { + pub fn new(manifest: &Path) -> BenchmarkManifest { + let dir = manifest.parent().unwrap(); + let f = + File::open(manifest).expect(&format!("couldn't open manifest: {}", manifest.display())); + let file = BufReader::new(&f); + + let mut benchmarks = Vec::new(); + + for line in file.lines() { + let l = line.unwrap(); + + // strip the comments + let s = &l[0 .. l.find('#').unwrap_or(l.len())]; + let s = s.trim(); + if s.is_empty() { + continue; + } + + let mut items = s.split_whitespace(); + + match items.next() { + Some("include") => { + let include = dir.join(items.next().unwrap()); + + benchmarks.append(&mut BenchmarkManifest::new(include.as_path()).benchmarks); + } + Some(name) => { + let test = dir.join(name); + benchmarks.push(Benchmark { test }); + } + _ => panic!(), + }; + } + + BenchmarkManifest { + benchmarks: benchmarks, + } + } +} + +#[derive(Clone, Serialize, Deserialize)] +struct TestProfileRange { + min: u64, + avg: u64, + max: u64, +} + +#[derive(Clone, Serialize, Deserialize)] +struct TestProfile { + name: String, + backend_time_ns: TestProfileRange, + composite_time_ns: TestProfileRange, + paint_time_ns: TestProfileRange, + draw_calls: usize, +} + +impl TestProfile { + fn csv_header() -> String { + "name,\ + backend_time_ns min, avg, max,\ + composite_time_ns min, avg, max,\ + paint_time_ns min, avg, max,\ + draw_calls\n".to_string() + } + + fn convert_to_csv(&self) -> String { + format!("{},\ + {},{},{},\ + {},{},{},\ + {},{},{},\ + {}\n", + self.name, + self.backend_time_ns.min, self.backend_time_ns.avg, self.backend_time_ns.max, + self.composite_time_ns.min, self.composite_time_ns.avg, self.composite_time_ns.max, + self.paint_time_ns.min, self.paint_time_ns.avg, self.paint_time_ns.max, + self.draw_calls) + } +} + +#[derive(Serialize, Deserialize)] +struct Profile { + tests: Vec<TestProfile>, +} + +impl Profile { + fn new() -> Profile { + Profile { tests: Vec::new() } + } + + fn add(&mut self, profile: TestProfile) { + self.tests.push(profile); + } + + fn save(&self, filename: &str, as_csv: bool) { + let mut file = File::create(&filename).unwrap(); + if as_csv { + file.write_all(&TestProfile::csv_header().into_bytes()).unwrap(); + for test in &self.tests { + file.write_all(&test.convert_to_csv().into_bytes()).unwrap(); + } + } else { + let s = serde_json::to_string_pretty(self).unwrap(); + file.write_all(&s.into_bytes()).unwrap(); + file.write_all(b"\n").unwrap(); + } + } + + fn load(filename: &str) -> Profile { + let mut file = File::open(&filename).unwrap(); + let mut string = String::new(); + file.read_to_string(&mut string).unwrap(); + serde_json::from_str(&string).expect("Unable to load profile!") + } + + fn build_set_and_map_of_tests(&self) -> (HashSet<String>, HashMap<String, TestProfile>) { + let mut hash_set = HashSet::new(); + let mut hash_map = HashMap::new(); + + for test in &self.tests { + hash_set.insert(test.name.clone()); + hash_map.insert(test.name.clone(), test.clone()); + } + + (hash_set, hash_map) + } +} + +pub struct PerfHarness<'a> { + wrench: &'a mut Wrench, + window: &'a mut WindowWrapper, + rx: Receiver<NotifierEvent>, + warmup_frames: usize, + sample_count: usize, +} + +impl<'a> PerfHarness<'a> { + pub fn new(wrench: &'a mut Wrench, + window: &'a mut WindowWrapper, + rx: Receiver<NotifierEvent>, + warmup_frames: Option<usize>, + sample_count: Option<usize>) -> Self { + PerfHarness { + wrench, + window, + rx, + warmup_frames: warmup_frames.unwrap_or(0usize), + sample_count: sample_count.unwrap_or(MIN_SAMPLE_COUNT), + } + } + + pub fn run(mut self, base_manifest: &Path, filename: &str, as_csv: bool) { + let manifest = BenchmarkManifest::new(base_manifest); + + let mut profile = Profile::new(); + + for t in manifest.benchmarks { + let stats = self.render_yaml(t.test.as_path()); + profile.add(stats); + } + + profile.save(filename, as_csv); + } + + fn render_yaml(&mut self, filename: &Path) -> TestProfile { + let mut reader = YamlFrameReader::new(filename); + + // Loop until we get a reasonable number of CPU and GPU + // frame profiles. Then take the mean. + let mut cpu_frame_profiles = Vec::new(); + let mut gpu_frame_profiles = Vec::new(); + + let mut debug_flags = DebugFlags::empty(); + debug_flags.set(DebugFlags::GPU_TIME_QUERIES | DebugFlags::GPU_SAMPLE_QUERIES, true); + self.wrench.api.send_debug_cmd(DebugCommand::SetFlags(debug_flags)); + + let mut frame_count = 0; + + while cpu_frame_profiles.len() < self.sample_count || + gpu_frame_profiles.len() < self.sample_count + { + reader.do_frame(self.wrench); + self.rx.recv().unwrap(); + self.wrench.render(); + self.window.swap_buffers(); + let (cpu_profiles, gpu_profiles) = self.wrench.get_frame_profiles(); + if frame_count >= self.warmup_frames { + cpu_frame_profiles.extend(cpu_profiles); + gpu_frame_profiles.extend(gpu_profiles); + } + frame_count = frame_count + 1; + } + + // Ensure the draw calls match in every sample. + let draw_calls = cpu_frame_profiles[0].draw_calls; + let draw_calls_same = + cpu_frame_profiles + .iter() + .all(|s| s.draw_calls == draw_calls); + + // this can be normal in cases where some elements are cached (eg. linear + // gradients), but print a warning in case it's not (which could make the + // benchmark produce unexpected results). + if !draw_calls_same { + println!("Warning: not every frame has the same number of draw calls"); + } + + let composite_time_ns = extract_sample(&mut cpu_frame_profiles, |a| a.composite_time_ns); + let paint_time_ns = extract_sample(&mut gpu_frame_profiles, |a| a.paint_time_ns); + let backend_time_ns = extract_sample(&mut cpu_frame_profiles, |a| a.backend_time_ns); + + TestProfile { + name: filename.to_str().unwrap().to_string(), + composite_time_ns, + paint_time_ns, + backend_time_ns, + draw_calls, + } + } +} + +// returns min, average, max, after removing the lowest and highest SAMPLE_EXCLUDE_COUNT +// samples (each). +fn extract_sample<F, T>(profiles: &mut [T], f: F) -> TestProfileRange +where + F: Fn(&T) -> u64, +{ + let mut samples: Vec<u64> = profiles.iter().map(f).collect(); + samples.sort(); + let useful_samples = &samples[SAMPLE_EXCLUDE_COUNT .. samples.len() - SAMPLE_EXCLUDE_COUNT]; + let total_time: u64 = useful_samples.iter().sum(); + TestProfileRange { + min: useful_samples[0], + avg: total_time / useful_samples.len() as u64, + max: useful_samples[useful_samples.len()-1] + } +} + +fn select_color(base: f32, value: f32) -> &'static str { + let tolerance = base * 0.1; + if (value - base).abs() < tolerance { + COLOR_DEFAULT + } else if value > base { + COLOR_RED + } else { + COLOR_GREEN + } +} + +pub fn compare(first_filename: &str, second_filename: &str) { + let profile0 = Profile::load(first_filename); + let profile1 = Profile::load(second_filename); + + let (set0, map0) = profile0.build_set_and_map_of_tests(); + let (set1, map1) = profile1.build_set_and_map_of_tests(); + + print!("+------------------------------------------------"); + println!("+--------------+------------------+------------------+"); + print!("| Test name "); + println!("| Draw Calls | Composite (ms) | Paint (ms) |"); + print!("+------------------------------------------------"); + println!("+--------------+------------------+------------------+"); + + for test_name in set0.symmetric_difference(&set1) { + println!( + "| {}{:47}{}|{:14}|{:18}|{:18}|", + COLOR_MAGENTA, + test_name, + COLOR_DEFAULT, + " -", + " -", + " -" + ); + } + + for test_name in set0.intersection(&set1) { + let test0 = &map0[test_name]; + let test1 = &map1[test_name]; + + let composite_time0 = test0.composite_time_ns.avg as f32 / 1000000.0; + let composite_time1 = test1.composite_time_ns.avg as f32 / 1000000.0; + + let paint_time0 = test0.paint_time_ns.avg as f32 / 1000000.0; + let paint_time1 = test1.paint_time_ns.avg as f32 / 1000000.0; + + let draw_calls_color = if test0.draw_calls == test1.draw_calls { + COLOR_DEFAULT + } else if test0.draw_calls > test1.draw_calls { + COLOR_GREEN + } else { + COLOR_RED + }; + + let composite_time_color = select_color(composite_time0, composite_time1); + let paint_time_color = select_color(paint_time0, paint_time1); + + let draw_call_string = format!(" {} -> {}", test0.draw_calls, test1.draw_calls); + let composite_time_string = format!(" {:.2} -> {:.2}", composite_time0, composite_time1); + let paint_time_string = format!(" {:.2} -> {:.2}", paint_time0, paint_time1); + + println!( + "| {:47}|{}{:14}{}|{}{:18}{}|{}{:18}{}|", + test_name, + draw_calls_color, + draw_call_string, + COLOR_DEFAULT, + composite_time_color, + composite_time_string, + COLOR_DEFAULT, + paint_time_color, + paint_time_string, + COLOR_DEFAULT + ); + } + + print!("+------------------------------------------------"); + println!("+--------------+------------------+------------------+"); +} diff --git a/gfx/wr/wrench/src/png.rs b/gfx/wr/wrench/src/png.rs new file mode 100644 index 0000000000..6a7dfd94f8 --- /dev/null +++ b/gfx/wr/wrench/src/png.rs @@ -0,0 +1,118 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +use crate::{WindowWrapper, NotifierEvent}; +use image::png::PNGEncoder; +use image::{self, ColorType, GenericImageView}; +use std::fs::File; +use std::path::{Path, PathBuf}; +use std::sync::mpsc::Receiver; +use webrender::api::units::*; +use crate::wrench::{Wrench, WrenchThing}; +use crate::yaml_frame_reader::YamlFrameReader; + +pub enum ReadSurface { + Screen, + GpuCache, +} + +pub struct SaveSettings { + pub flip_vertical: bool, + pub try_crop: bool, +} + +pub fn save<P: Clone + AsRef<Path>>( + path: P, + orig_pixels: Vec<u8>, + size: DeviceIntSize, + settings: SaveSettings +) { + let mut width = size.width as u32; + let mut height = size.height as u32; + let mut buffer = image::RgbaImage::from_raw( + width, + height, + orig_pixels, + ).expect("bug: unable to construct image buffer"); + + if settings.flip_vertical { + // flip image vertically (texture is upside down) + buffer = image::imageops::flip_vertical(&buffer); + } + + if settings.try_crop { + if let Ok(existing_image) = image::open(path.clone()) { + let old_dims = existing_image.dimensions(); + println!("Crop from {:?} to {:?}", size, old_dims); + width = old_dims.0; + height = old_dims.1; + buffer = image::imageops::crop( + &mut buffer, + 0, + 0, + width, + height + ).to_image(); + } + } + + let encoder = PNGEncoder::new(File::create(path).unwrap()); + encoder + .encode(&buffer, width, height, ColorType::Rgba8) + .expect("Unable to encode PNG!"); +} + +pub fn save_flipped<P: Clone + AsRef<Path>>( + path: P, + orig_pixels: Vec<u8>, + size: DeviceIntSize, +) { + save(path, orig_pixels, size, SaveSettings { + flip_vertical: true, + try_crop: true, + }) +} + +pub fn png( + wrench: &mut Wrench, + surface: ReadSurface, + window: &mut WindowWrapper, + mut reader: YamlFrameReader, + rx: Receiver<NotifierEvent>, + out_path: Option<PathBuf>, +) { + reader.do_frame(wrench); + + // wait for the frame + rx.recv().unwrap(); + wrench.render(); + + let (fb_size, data, settings) = match surface { + ReadSurface::Screen => { + let dim = window.get_inner_size(); + let rect = FramebufferIntSize::new(dim.width, dim.height).into(); + let data = wrench.renderer.read_pixels_rgba8(rect); + (dim, data, SaveSettings { + flip_vertical: true, + try_crop: true, + }) + } + ReadSurface::GpuCache => { + let (size, data) = wrench.renderer + .read_gpu_cache(); + (size, data, SaveSettings { + flip_vertical: false, + try_crop: false, + }) + } + }; + + let out_path = out_path.unwrap_or_else(|| { + let mut path = reader.yaml_path().clone(); + path.set_extension("png"); + path + }); + + save(out_path, data, fb_size, settings); +} diff --git a/gfx/wr/wrench/src/premultiply.rs b/gfx/wr/wrench/src/premultiply.rs new file mode 100644 index 0000000000..04f43add56 --- /dev/null +++ b/gfx/wr/wrench/src/premultiply.rs @@ -0,0 +1,56 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +// These are slow. Gecko's gfx/2d/Swizzle.cpp has better versions +pub fn premultiply(data: &mut [u8]) { + for pixel in data.chunks_mut(4) { + let a = pixel[3] as u32; + let b = pixel[2] as u32; + let g = pixel[1] as u32; + let r = pixel[0] as u32; + + pixel[3] = a as u8; + pixel[2] = ((r * a + 128) / 255) as u8; + pixel[1] = ((g * a + 128) / 255) as u8; + pixel[0] = ((b * a + 128) / 255) as u8; + } +} + +#[allow(unused)] +pub fn unpremultiply(data: &mut [u8]) { + for pixel in data.chunks_mut(4) { + let a = pixel[3] as u32; + let mut b = pixel[2] as u32; + let mut g = pixel[1] as u32; + let mut r = pixel[0] as u32; + + if a > 0 { + r = r * 255 / a; + g = g * 255 / a; + b = b * 255 / a; + } + + pixel[3] = a as u8; + pixel[2] = r as u8; + pixel[1] = g as u8; + pixel[0] = b as u8; + } +} + +#[test] +fn it_works() { + let mut f = [0xff, 0xff, 0xff, 0x80, 0x00, 0xff, 0x00, 0x80]; + premultiply(&mut f); + println!("{:?}", f); + assert!( + f[0] == 0x80 && f[1] == 0x80 && f[2] == 0x80 && f[3] == 0x80 && f[4] == 0x00 && + f[5] == 0x80 && f[6] == 0x00 && f[7] == 0x80 + ); + unpremultiply(&mut f); + println!("{:?}", f); + assert!( + f[0] == 0xff && f[1] == 0xff && f[2] == 0xff && f[3] == 0x80 && f[4] == 0x00 && + f[5] == 0xff && f[6] == 0x00 && f[7] == 0x80 + ); +} diff --git a/gfx/wr/wrench/src/rawtest.rs b/gfx/wr/wrench/src/rawtest.rs new file mode 100644 index 0000000000..580f1cb015 --- /dev/null +++ b/gfx/wr/wrench/src/rawtest.rs @@ -0,0 +1,1455 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +use euclid::{point2, size2, rect}; +use std::sync::Arc; +use std::sync::atomic::{AtomicIsize, Ordering}; +use std::sync::mpsc::Receiver; +use webrender::api::*; +use webrender::render_api::*; +use webrender::api::units::*; +use crate::{WindowWrapper, NotifierEvent}; +use crate::blob; +use crate::reftest::{ReftestImage, ReftestImageComparison}; +use crate::wrench::Wrench; + +pub struct RawtestHarness<'a> { + wrench: &'a mut Wrench, + rx: &'a Receiver<NotifierEvent>, + window: &'a mut WindowWrapper, +} + + +impl<'a> RawtestHarness<'a> { + pub fn new(wrench: &'a mut Wrench, + window: &'a mut WindowWrapper, + rx: &'a Receiver<NotifierEvent>) -> Self { + RawtestHarness { + wrench, + rx, + window, + } + } + + pub fn run(mut self) { + self.test_hit_testing(); + self.test_resize_image(); + self.test_retained_blob_images_test(); + self.test_blob_update_test(); + self.test_blob_update_epoch_test(); + self.test_tile_decomposition(); + self.test_very_large_blob(); + self.test_blob_visible_area(); + self.test_blob_set_visible_area(); + self.test_offscreen_blob(); + self.test_save_restore(); + self.test_blur_cache(); + self.test_capture(); + self.test_zero_height_window(); + self.test_clear_cache(); + } + + fn render_and_get_pixels(&mut self, window_rect: FramebufferIntRect) -> Vec<u8> { + self.rx.recv().unwrap(); + self.wrench.render(); + self.wrench.renderer.read_pixels_rgba8(window_rect) + } + + fn compare_pixels(&self, data1: Vec<u8>, data2: Vec<u8>, size: FramebufferIntSize) { + let size = DeviceIntSize::new(size.width, size.height); + let image1 = ReftestImage { + data: data1, + size, + }; + let image2 = ReftestImage { + data: data2, + size, + }; + + match image1.compare(&image2) { + ReftestImageComparison::Equal => {} + ReftestImageComparison::NotEqual { max_difference, count_different, .. } => { + let t = "rawtest"; + println!( + "{} | {} | {}: {}, {}: {}", + "REFTEST TEST-UNEXPECTED-FAIL", + t, + "image comparison, max difference", + max_difference, + "number of differing pixels", + count_different + ); + println!("REFTEST IMAGE 1: {}", image1.create_data_uri()); + println!("REFTEST IMAGE 2: {}", image2.create_data_uri()); + println!("REFTEST TEST-END | {}", t); + panic!(); + } + } + } + + fn submit_dl( + &mut self, + epoch: &mut Epoch, + layout_size: LayoutSize, + builder: DisplayListBuilder, + mut txn: Transaction, + ) { + let root_background_color = Some(ColorF::new(1.0, 1.0, 1.0, 1.0)); + txn.use_scene_builder_thread(); + + txn.set_display_list( + *epoch, + root_background_color, + layout_size, + builder.finalize(), + false, + ); + epoch.0 += 1; + + txn.generate_frame(0); + self.wrench.api.send_transaction(self.wrench.document_id, txn); + } + + fn make_common_properties(&self, clip_rect: LayoutRect) -> CommonItemProperties { + let space_and_clip = SpaceAndClipInfo::root_scroll(self.wrench.root_pipeline_id); + CommonItemProperties { + clip_rect, + clip_id: space_and_clip.clip_id, + spatial_id: space_and_clip.spatial_id, + flags: PrimitiveFlags::default(), + } + } + + fn make_common_properties_with_clip_and_spatial( + &self, + clip_rect: LayoutRect, + clip_id: ClipId, + spatial_id: SpatialId + ) -> CommonItemProperties { + CommonItemProperties { + clip_rect, + clip_id, + spatial_id, + flags: PrimitiveFlags::default(), + } + } + + fn test_resize_image(&mut self) { + println!("\tresize image..."); + // This test changes the size of an image to make it go switch back and forth + // between tiled and non-tiled. + // The resource cache should be able to handle this without crashing. + + let layout_size = LayoutSize::new(800., 800.); + + let mut txn = Transaction::new(); + let img = self.wrench.api.generate_image_key(); + + // Start with a non-tiled image. + txn.add_image( + img, + ImageDescriptor::new(64, 64, ImageFormat::BGRA8, ImageDescriptorFlags::IS_OPAQUE), + ImageData::new(vec![255; 64 * 64 * 4]), + None, + ); + + let mut builder = DisplayListBuilder::new(self.wrench.root_pipeline_id); + let info = self.make_common_properties(rect(0.0, 0.0, 64.0, 64.0)); + + builder.push_image( + &info, + info.clip_rect, + ImageRendering::Auto, + AlphaType::PremultipliedAlpha, + img, + ColorF::WHITE, + ); + + let mut epoch = Epoch(0); + + self.submit_dl(&mut epoch, layout_size, builder, txn); + self.rx.recv().unwrap(); + self.wrench.render(); + + let mut txn = Transaction::new(); + // Resize the image to something bigger than the max texture size (8196) to force tiling. + txn.update_image( + img, + ImageDescriptor::new(8200, 32, ImageFormat::BGRA8, ImageDescriptorFlags::IS_OPAQUE), + ImageData::new(vec![255; 8200 * 32 * 4]), + &DirtyRect::All, + ); + + let mut builder = DisplayListBuilder::new(self.wrench.root_pipeline_id); + let info = self.make_common_properties(rect(0.0, 0.0, 1024.0, 1024.0)); + + builder.push_image( + &info, + info.clip_rect, + ImageRendering::Auto, + AlphaType::PremultipliedAlpha, + img, + ColorF::WHITE, + ); + + self.submit_dl(&mut epoch, layout_size, builder, txn); + self.rx.recv().unwrap(); + self.wrench.render(); + + let mut txn = Transaction::new(); + // Resize back to something doesn't require tiling. + txn.update_image( + img, + ImageDescriptor::new(64, 64, ImageFormat::BGRA8, ImageDescriptorFlags::IS_OPAQUE), + ImageData::new(vec![64; 64 * 64 * 4]), + &DirtyRect::All, + ); + + let mut builder = DisplayListBuilder::new(self.wrench.root_pipeline_id); + let info = self.make_common_properties(rect(0.0, 0.0, 1024.0, 1024.0)); + + builder.push_image( + &info, + info.clip_rect, + ImageRendering::Auto, + AlphaType::PremultipliedAlpha, + img, + ColorF::WHITE, + ); + + self.submit_dl(&mut epoch, layout_size, builder, txn); + self.rx.recv().unwrap(); + self.wrench.render(); + + txn = Transaction::new(); + txn.delete_image(img); + self.wrench.api.send_transaction(self.wrench.document_id, txn); + } + + fn test_tile_decomposition(&mut self) { + println!("\ttile decomposition..."); + // This exposes a crash in tile decomposition + let layout_size = LayoutSize::new(800., 800.); + let mut txn = Transaction::new(); + + let blob_img = self.wrench.api.generate_blob_image_key(); + txn.add_blob_image( + blob_img, + ImageDescriptor::new(151, 56, ImageFormat::BGRA8, ImageDescriptorFlags::IS_OPAQUE), + blob::serialize_blob(ColorU::new(50, 50, 150, 255)), + rect(0, 0, 151, 56), + Some(128), + ); + + let mut builder = DisplayListBuilder::new(self.wrench.root_pipeline_id); + + let info = self.make_common_properties(rect(448.899994, 74.0, 151.000031, 56.)); + + // setup some malicious image size parameters + builder.push_repeating_image( + &info, + info.clip_rect, + size2(151., 56.0), + size2(151.0, 56.0), + ImageRendering::Auto, + AlphaType::PremultipliedAlpha, + blob_img.as_image(), + ColorF::WHITE, + ); + + let mut epoch = Epoch(0); + + self.submit_dl(&mut epoch, layout_size, builder, txn); + + self.rx.recv().unwrap(); + self.wrench.render(); + + // Leaving a tiled blob image in the resource cache + // confuses the `test_capture`. TODO: remove this + txn = Transaction::new(); + txn.delete_blob_image(blob_img); + self.wrench.api.send_transaction(self.wrench.document_id, txn); + } + + fn test_very_large_blob(&mut self) { + println!("\tvery large blob..."); + + assert_eq!(self.wrench.device_pixel_ratio, 1.); + + let window_size = self.window.get_inner_size(); + + let test_size = FramebufferIntSize::new(800, 800); + + let window_rect = FramebufferIntRect::new( + FramebufferIntPoint::new(0, window_size.height - test_size.height), + test_size, + ); + + // This exposes a crash in tile decomposition + let layout_size = LayoutSize::new(800., 800.); + let mut txn = Transaction::new(); + + let blob_img = self.wrench.api.generate_blob_image_key(); + txn.add_blob_image( + blob_img, + ImageDescriptor::new(15000, 15000, ImageFormat::BGRA8, ImageDescriptorFlags::empty()), + blob::serialize_blob(ColorU::new(50, 50, 150, 255)), + rect(0, 0, 15000, 15000), + Some(100), + ); + + let called = Arc::new(AtomicIsize::new(0)); + let called_inner = Arc::clone(&called); + + self.wrench.callbacks.lock().unwrap().request = Box::new(move |_| { + called_inner.fetch_add(1, Ordering::SeqCst); + }); + + let mut builder = DisplayListBuilder::new(self.wrench.root_pipeline_id); + + let root_space_and_clip = SpaceAndClipInfo::root_scroll(self.wrench.root_pipeline_id); + let clip_id = builder.define_clip_rect( + &root_space_and_clip, + rect(40., 41., 200., 201.), + ); + + let info = CommonItemProperties { + clip_rect: rect(0.0, 0.0, 800.0, 800.0), + clip_id, + spatial_id: root_space_and_clip.spatial_id, + flags: PrimitiveFlags::default(), + }; + + // setup some malicious image size parameters + builder.push_repeating_image( + &info, + size2(15000.0, 15000.0).into(), + size2(15000.0, 15000.0), + size2(0.0, 0.0), + ImageRendering::Auto, + AlphaType::PremultipliedAlpha, + blob_img.as_image(), + ColorF::WHITE, + ); + + let mut epoch = Epoch(0); + + self.submit_dl(&mut epoch, layout_size, builder, txn); + + let pixels = self.render_and_get_pixels(window_rect); + + // make sure we didn't request too many blobs + assert!(called.load(Ordering::SeqCst) < 20); + + //use crate::png; + //png::save_flipped("out.png", pixels.clone(), size2(window_rect.size.width, window_rect.size.height)); + + // make sure things are in the right spot + let w = window_rect.size.width as usize; + let h = window_rect.size.height as usize; + let p1 = (40 + (h - 100) * w) * 4; + assert_eq!(pixels[p1 + 0], 50); + assert_eq!(pixels[p1 + 1], 50); + assert_eq!(pixels[p1 + 2], 150); + assert_eq!(pixels[p1 + 3], 255); + + // Leaving a tiled blob image in the resource cache + // confuses the `test_capture`. TODO: remove this + txn = Transaction::new(); + txn.delete_blob_image(blob_img); + self.wrench.api.send_transaction(self.wrench.document_id, txn); + + *self.wrench.callbacks.lock().unwrap() = blob::BlobCallbacks::new(); + } + + fn test_blob_visible_area(&mut self) { + println!("\tblob visible area..."); + + assert_eq!(self.wrench.device_pixel_ratio, 1.0); + + let window_size = self.window.get_inner_size(); + let test_size = FramebufferIntSize::new(800, 800); + let window_rect = FramebufferIntRect::new( + FramebufferIntPoint::new(0, window_size.height - test_size.height), + test_size, + ); + let layout_size = LayoutSize::new(800.0, 800.0); + let mut txn = Transaction::new(); + + let blob_img = self.wrench.api.generate_blob_image_key(); + txn.add_blob_image( + blob_img, + ImageDescriptor::new(500, 500, ImageFormat::BGRA8, ImageDescriptorFlags::empty()), + blob::serialize_blob(ColorU::new(50, 50, 150, 255)), + DeviceIntRect { + origin: point2(50, 20), + size: size2(400, 400), + }, + Some(100), + ); + + let mut builder = DisplayListBuilder::new(self.wrench.root_pipeline_id); + + let image_size = size2(400.0, 400.0); + + let root_space_and_clip = SpaceAndClipInfo::root_scroll(self.wrench.root_pipeline_id); + let clip_id = builder.define_clip_rect( + &root_space_and_clip, + rect(-1000.0, -1000.0, 2000.0, 2000.0), + ); + + let info = CommonItemProperties { + clip_rect: rect(10.0, 10.0, 400.0, 400.0), + clip_id, + spatial_id: root_space_and_clip.spatial_id, + flags: PrimitiveFlags::default(), + }; + + builder.push_repeating_image( + &info, + info.clip_rect, + image_size, + image_size, + ImageRendering::Auto, + AlphaType::PremultipliedAlpha, + blob_img.as_image(), + ColorF::WHITE, + ); + let mut epoch = Epoch(0); + + self.submit_dl(&mut epoch, layout_size, builder, txn); + + let pixels = self.render_and_get_pixels(window_rect); + + //use super::png; + //png::save_flipped("out.png", pixels.clone(), size2(window_rect.size.width, window_rect.size.height)); + + + // make sure things are in the right spot + let w = window_rect.size.width as usize; + let h = window_rect.size.height as usize; + let p1 = (65 + (h - 15) * w) * 4; + assert_eq!(pixels[p1 + 0], 255); + assert_eq!(pixels[p1 + 1], 255); + assert_eq!(pixels[p1 + 2], 255); + assert_eq!(pixels[p1 + 3], 255); + + let p2 = (25 + (h - 15) * w) * 4; + assert_eq!(pixels[p2 + 0], 221); + assert_eq!(pixels[p2 + 1], 221); + assert_eq!(pixels[p2 + 2], 221); + assert_eq!(pixels[p2 + 3], 255); + + let p3 = (15 + (h - 15) * w) * 4; + assert_eq!(pixels[p3 + 0], 50); + assert_eq!(pixels[p3 + 1], 50); + assert_eq!(pixels[p3 + 2], 150); + assert_eq!(pixels[p3 + 3], 255); + + // Leaving a tiled blob image in the resource cache + // confuses the `test_capture`. TODO: remove this + txn = Transaction::new(); + txn.delete_blob_image(blob_img); + self.wrench.api.send_transaction(self.wrench.document_id, txn); + + *self.wrench.callbacks.lock().unwrap() = blob::BlobCallbacks::new(); + } + + fn test_blob_set_visible_area(&mut self) { + // In this test we first render a blob with a certain visible area, + // then change the visible area without updating the blob image. + + println!("\tblob visible area update..."); + + assert_eq!(self.wrench.device_pixel_ratio, 1.0); + + let window_size = self.window.get_inner_size(); + let test_size = FramebufferIntSize::new(800, 800); + let window_rect = FramebufferIntRect::new( + FramebufferIntPoint::new(0, window_size.height - test_size.height), + test_size, + ); + let layout_size = LayoutSize::new(800.0, 800.0); + let mut txn = Transaction::new(); + + let blob_img = self.wrench.api.generate_blob_image_key(); + txn.add_blob_image( + blob_img, + ImageDescriptor::new(500, 500, ImageFormat::BGRA8, ImageDescriptorFlags::empty()), + blob::serialize_blob(ColorU::new(50, 50, 150, 255)), + DeviceIntRect { + origin: point2(0, 0), + size: size2(500, 500), + }, + Some(128), + ); + + let mut builder = DisplayListBuilder::new(self.wrench.root_pipeline_id); + + let root_space_and_clip = SpaceAndClipInfo::root_scroll(self.wrench.root_pipeline_id); + let clip_id = builder.define_clip_rect( + &root_space_and_clip, + rect(-1000.0, -1000.0, 2000.0, 2000.0), + ); + + let info = CommonItemProperties { + clip_rect: rect(0.0, 0.0, 1000.0, 1000.0), + clip_id, + spatial_id: root_space_and_clip.spatial_id, + flags: PrimitiveFlags::default(), + }; + + builder.push_repeating_image( + &info, + rect(0.0, 0.0, 500.0, 500.0), + size2(500.0, 500.0), + size2(500.0, 500.0), + ImageRendering::Auto, + AlphaType::PremultipliedAlpha, + blob_img.as_image(), + ColorF::WHITE, + ); + let mut epoch = Epoch(0); + + // Render the first display list. We don't care about the result but we + // want to make sure the next display list updates an already rendered + // state. + self.submit_dl(&mut epoch, layout_size, builder, txn); + let _ = self.render_and_get_pixels(window_rect); + + // Now render a similar scene with an updated blob visible area. + // In this test we care about the fact that the visible area was updated + // without using update_blob_image. + + let mut txn = Transaction::new(); + + txn.set_blob_image_visible_area(blob_img, DeviceIntRect { + origin: point2(50, 50), + size: size2(400, 400), + }); + + let mut builder = DisplayListBuilder::new(self.wrench.root_pipeline_id); + + let root_space_and_clip = SpaceAndClipInfo::root_scroll(self.wrench.root_pipeline_id); + let clip_id = builder.define_clip_rect( + &root_space_and_clip, + rect(-1000.0, -1000.0, 2000.0, 2000.0), + ); + + let info = CommonItemProperties { + clip_rect: rect(0.0, 0.0, 1000.0, 1000.0), + clip_id, + spatial_id: root_space_and_clip.spatial_id, + flags: PrimitiveFlags::default(), + }; + + builder.push_repeating_image( + &info, + rect(50.0, 50.0, 400.0, 400.0), + size2(400.0, 400.0), + size2(400.0, 400.0), + ImageRendering::Auto, + AlphaType::PremultipliedAlpha, + blob_img.as_image(), + ColorF::WHITE, + ); + + self.submit_dl(&mut epoch, layout_size, builder, txn); + let resized_pixels = self.render_and_get_pixels(window_rect); + + // Now render the same scene with a new blob image created with the same + // visible area as the previous scene, without going through an update. + + let mut txn = Transaction::new(); + + let blob_img2 = self.wrench.api.generate_blob_image_key(); + txn.add_blob_image( + blob_img2, + ImageDescriptor::new(500, 500, ImageFormat::BGRA8, ImageDescriptorFlags::empty()), + blob::serialize_blob(ColorU::new(50, 50, 150, 255)), + DeviceIntRect { + origin: point2(50, 50), + size: size2(400, 400), + }, + Some(128), + ); + + let mut builder = DisplayListBuilder::new(self.wrench.root_pipeline_id); + + let root_space_and_clip = SpaceAndClipInfo::root_scroll(self.wrench.root_pipeline_id); + let clip_id = builder.define_clip_rect( + &root_space_and_clip, + rect(-1000.0, -1000.0, 2000.0, 2000.0), + ); + + let info = CommonItemProperties { + clip_rect: rect(0.0, 0.0, 1000.0, 1000.0), + clip_id, + spatial_id: root_space_and_clip.spatial_id, + flags: PrimitiveFlags::default(), + }; + + builder.push_repeating_image( + &info, + rect(50.0, 50.0, 400.0, 400.0), + size2(400.0, 400.0), + size2(400.0, 400.0), + ImageRendering::Auto, + AlphaType::PremultipliedAlpha, + blob_img2.as_image(), + ColorF::WHITE, + ); + let mut epoch = Epoch(0); + + self.submit_dl(&mut epoch, layout_size, builder, txn); + + let reference_pixels = self.render_and_get_pixels(window_rect); + + assert_eq!(resized_pixels, reference_pixels); + + txn = Transaction::new(); + txn.delete_blob_image(blob_img); + txn.delete_blob_image(blob_img2); + self.wrench.api.send_transaction(self.wrench.document_id, txn); + } + + fn test_offscreen_blob(&mut self) { + println!("\toffscreen blob update..."); + + assert_eq!(self.wrench.device_pixel_ratio, 1.); + + let window_size = self.window.get_inner_size(); + + let test_size = FramebufferIntSize::new(800, 800); + let window_rect = FramebufferIntRect::new( + point2(0, window_size.height - test_size.height), + test_size, + ); + + // This exposes a crash in tile decomposition + let mut txn = Transaction::new(); + let layout_size = LayoutSize::new(800., 800.); + + let blob_img = self.wrench.api.generate_blob_image_key(); + txn.add_blob_image( + blob_img, + ImageDescriptor::new(1510, 1510, ImageFormat::BGRA8, ImageDescriptorFlags::empty()), + blob::serialize_blob(ColorU::new(50, 50, 150, 255)), + rect(0, 0, 1510, 1510), + None, + ); + + let mut builder = DisplayListBuilder::new(self.wrench.root_pipeline_id); + + let info = self.make_common_properties(rect(0., 0.0, 1510., 1510.)); + + let image_size = size2(1510., 1510.); + + // setup some malicious image size parameters + builder.push_repeating_image( + &info, + info.clip_rect, + image_size, + image_size, + ImageRendering::Auto, + AlphaType::PremultipliedAlpha, + blob_img.as_image(), + ColorF::WHITE, + ); + + let mut epoch = Epoch(0); + + self.submit_dl(&mut epoch, layout_size, builder, txn); + + let original_pixels = self.render_and_get_pixels(window_rect); + + let mut epoch = Epoch(1); + + let mut builder = DisplayListBuilder::new(self.wrench.root_pipeline_id); + + let info = self.make_common_properties(rect(-10000., 0.0, 1510., 1510.)); + + let image_size = size2(1510., 1510.); + + // setup some malicious image size parameters + builder.push_repeating_image( + &info, + info.clip_rect, + image_size, + image_size, + ImageRendering::Auto, + AlphaType::PremultipliedAlpha, + blob_img.as_image(), + ColorF::WHITE, + ); + + self.submit_dl(&mut epoch, layout_size, builder, Transaction::new()); + + let _offscreen_pixels = self.render_and_get_pixels(window_rect); + + let mut txn = Transaction::new(); + + txn.update_blob_image( + blob_img, + ImageDescriptor::new(1510, 1510, ImageFormat::BGRA8, ImageDescriptorFlags::empty()), + blob::serialize_blob(ColorU::new(50, 50, 150, 255)), + rect(0, 0, 1510, 1510), + &rect(10, 10, 100, 100).into(), + ); + + let mut builder = DisplayListBuilder::new(self.wrench.root_pipeline_id); + + let info = self.make_common_properties(rect(0., 0.0, 1510., 1510.)); + + let image_size = size2(1510., 1510.); + + // setup some malicious image size parameters + builder.push_repeating_image( + &info, + info.clip_rect, + image_size, + image_size, + ImageRendering::Auto, + AlphaType::PremultipliedAlpha, + blob_img.as_image(), + ColorF::WHITE, + ); + + let mut epoch = Epoch(2); + + self.submit_dl(&mut epoch, layout_size, builder, txn); + + let pixels = self.render_and_get_pixels(window_rect); + + self.compare_pixels(original_pixels, pixels, window_rect.size); + + // Leaving a tiled blob image in the resource cache + // confuses the `test_capture`. TODO: remove this + txn = Transaction::new(); + txn.delete_blob_image(blob_img); + self.wrench.api.send_transaction(self.wrench.document_id, txn); + } + + fn test_retained_blob_images_test(&mut self) { + println!("\tretained blob images test..."); + let blob_img; + let window_size = self.window.get_inner_size(); + + let test_size = FramebufferIntSize::new(400, 400); + let window_rect = FramebufferIntRect::new( + FramebufferIntPoint::new(0, window_size.height - test_size.height), + test_size, + ); + let layout_size = LayoutSize::new(400., 400.); + + let mut txn = Transaction::new(); + { + let api = &self.wrench.api; + + blob_img = api.generate_blob_image_key(); + txn.add_blob_image( + blob_img, + ImageDescriptor::new(500, 500, ImageFormat::BGRA8, ImageDescriptorFlags::empty()), + blob::serialize_blob(ColorU::new(50, 50, 150, 255)), + rect(0, 0, 500, 500), + None, + ); + } + + let called = Arc::new(AtomicIsize::new(0)); + let called_inner = Arc::clone(&called); + + self.wrench.callbacks.lock().unwrap().request = Box::new(move |_| { + assert_eq!(0, called_inner.fetch_add(1, Ordering::SeqCst)); + }); + + // draw the blob the first time + let mut builder = DisplayListBuilder::new(self.wrench.root_pipeline_id); + let info = self.make_common_properties(rect(0.0, 60.0, 200.0, 200.0)); + + builder.push_image( + &info, + info.clip_rect, + ImageRendering::Auto, + AlphaType::PremultipliedAlpha, + blob_img.as_image(), + ColorF::WHITE, + ); + + let mut epoch = Epoch(0); + + self.submit_dl(&mut epoch, layout_size, builder, txn); + + let pixels_first = self.render_and_get_pixels(window_rect); + + assert_eq!(1, called.load(Ordering::SeqCst)); + + // draw the blob image a second time at a different location + + // make a new display list that refers to the first image + let mut builder = DisplayListBuilder::new(self.wrench.root_pipeline_id); + let info = self.make_common_properties(rect(1.0, 60.0, 200.0, 200.0)); + builder.push_image( + &info, + info.clip_rect, + ImageRendering::Auto, + AlphaType::PremultipliedAlpha, + blob_img.as_image(), + ColorF::WHITE, + ); + + let mut txn = Transaction::new(); + txn.resource_updates.clear(); + + self.submit_dl(&mut epoch, layout_size, builder, txn); + + let pixels_second = self.render_and_get_pixels(window_rect); + + // make sure we only requested once + assert_eq!(1, called.load(Ordering::SeqCst)); + + // use png; + // png::save_flipped("out1.png", &pixels_first, window_rect.size); + // png::save_flipped("out2.png", &pixels_second, window_rect.size); + assert!(pixels_first != pixels_second); + + // cleanup + *self.wrench.callbacks.lock().unwrap() = blob::BlobCallbacks::new(); + } + + fn test_blob_update_epoch_test(&mut self) { + println!("\tblob update epoch test..."); + let (blob_img, blob_img2); + let window_size = self.window.get_inner_size(); + + let test_size = FramebufferIntSize::new(400, 400); + let window_rect = FramebufferIntRect::new( + point2(0, window_size.height - test_size.height), + test_size, + ); + let layout_size = LayoutSize::new(400., 400.); + + let mut txn = Transaction::new(); + let (blob_img, blob_img2) = { + let api = &self.wrench.api; + + blob_img = api.generate_blob_image_key(); + txn.add_blob_image( + blob_img, + ImageDescriptor::new(500, 500, ImageFormat::BGRA8, ImageDescriptorFlags::empty()), + blob::serialize_blob(ColorU::new(50, 50, 150, 255)), + rect(0, 0, 500, 500), + None, + ); + blob_img2 = api.generate_blob_image_key(); + txn.add_blob_image( + blob_img2, + ImageDescriptor::new(500, 500, ImageFormat::BGRA8, ImageDescriptorFlags::empty()), + blob::serialize_blob(ColorU::new(80, 50, 150, 255)), + rect(0, 0, 500, 500), + None, + ); + (blob_img, blob_img2) + }; + + // setup some counters to count how many times each image is requested + let img1_requested = Arc::new(AtomicIsize::new(0)); + let img1_requested_inner = Arc::clone(&img1_requested); + let img2_requested = Arc::new(AtomicIsize::new(0)); + let img2_requested_inner = Arc::clone(&img2_requested); + + // track the number of times that the second image has been requested + self.wrench.callbacks.lock().unwrap().request = Box::new(move |requests| { + for item in requests { + if item.request.key == blob_img { + img1_requested_inner.fetch_add(1, Ordering::SeqCst); + } + if item.request.key == blob_img2 { + img2_requested_inner.fetch_add(1, Ordering::SeqCst); + } + } + }); + + // create two blob images and draw them + let mut builder = DisplayListBuilder::new(self.wrench.root_pipeline_id); + let info = self.make_common_properties(rect(0.0, 60.0, 200.0, 200.0)); + let info2 = self.make_common_properties(rect(200.0, 60.0, 200.0, 200.0)); + let push_images = |builder: &mut DisplayListBuilder| { + builder.push_image( + &info, + info.clip_rect, + ImageRendering::Auto, + AlphaType::PremultipliedAlpha, + blob_img.as_image(), + ColorF::WHITE, + ); + builder.push_image( + &info2, + info2.clip_rect, + ImageRendering::Auto, + AlphaType::PremultipliedAlpha, + blob_img2.as_image(), + ColorF::WHITE, + ); + }; + + push_images(&mut builder); + + let mut epoch = Epoch(0); + + self.submit_dl(&mut epoch, layout_size, builder, txn); + let _pixels_first = self.render_and_get_pixels(window_rect); + + // update and redraw both images + let mut txn = Transaction::new(); + txn.update_blob_image( + blob_img, + ImageDescriptor::new(500, 500, ImageFormat::BGRA8, ImageDescriptorFlags::empty()), + blob::serialize_blob(ColorU::new(50, 50, 150, 255)), + rect(0, 0, 500, 500), + &rect(100, 100, 100, 100).into(), + ); + txn.update_blob_image( + blob_img2, + ImageDescriptor::new(500, 500, ImageFormat::BGRA8, ImageDescriptorFlags::empty()), + blob::serialize_blob(ColorU::new(59, 50, 150, 255)), + rect(0, 0, 500, 500), + &rect(100, 100, 100, 100).into(), + ); + + let mut builder = DisplayListBuilder::new(self.wrench.root_pipeline_id); + push_images(&mut builder); + self.submit_dl(&mut epoch, layout_size, builder, txn); + let _pixels_second = self.render_and_get_pixels(window_rect); + + // only update the first image + let mut txn = Transaction::new(); + txn.update_blob_image( + blob_img, + ImageDescriptor::new(500, 500, ImageFormat::BGRA8, ImageDescriptorFlags::empty()), + blob::serialize_blob(ColorU::new(50, 150, 150, 255)), + rect(0, 0, 500, 500), + &rect(200, 200, 100, 100).into(), + ); + + let mut builder = DisplayListBuilder::new(self.wrench.root_pipeline_id); + push_images(&mut builder); + self.submit_dl(&mut epoch, layout_size, builder, txn); + let _pixels_third = self.render_and_get_pixels(window_rect); + + // the first image should be requested 3 times + assert_eq!(img1_requested.load(Ordering::SeqCst), 3); + // the second image should've been requested twice + assert_eq!(img2_requested.load(Ordering::SeqCst), 2); + + // cleanup + *self.wrench.callbacks.lock().unwrap() = blob::BlobCallbacks::new(); + } + + fn test_blob_update_test(&mut self) { + println!("\tblob update test..."); + let window_size = self.window.get_inner_size(); + + let test_size = FramebufferIntSize::new(400, 400); + let window_rect = FramebufferIntRect::new( + point2(0, window_size.height - test_size.height), + test_size, + ); + let layout_size = LayoutSize::new(400., 400.); + let mut txn = Transaction::new(); + + let blob_img = { + let img = self.wrench.api.generate_blob_image_key(); + txn.add_blob_image( + img, + ImageDescriptor::new(500, 500, ImageFormat::BGRA8, ImageDescriptorFlags::empty()), + blob::serialize_blob(ColorU::new(50, 50, 150, 255)), + rect(0, 0, 500, 500), + None, + ); + img + }; + + // draw the blobs the first time + let mut builder = DisplayListBuilder::new(self.wrench.root_pipeline_id); + let info = self.make_common_properties(rect(0.0, 60.0, 200.0, 200.0)); + + builder.push_image( + &info, + info.clip_rect, + ImageRendering::Auto, + AlphaType::PremultipliedAlpha, + blob_img.as_image(), + ColorF::WHITE, + ); + + let mut epoch = Epoch(0); + + self.submit_dl(&mut epoch, layout_size, builder, txn); + let pixels_first = self.render_and_get_pixels(window_rect); + + // draw the blob image a second time after updating it with the same color + let mut txn = Transaction::new(); + txn.update_blob_image( + blob_img, + ImageDescriptor::new(500, 500, ImageFormat::BGRA8, ImageDescriptorFlags::empty()), + blob::serialize_blob(ColorU::new(50, 50, 150, 255)), + rect(0, 0, 500, 500), + &rect(100, 100, 100, 100).into(), + ); + + // make a new display list that refers to the first image + let mut builder = DisplayListBuilder::new(self.wrench.root_pipeline_id); + let info = self.make_common_properties(rect(0.0, 60.0, 200.0, 200.0)); + builder.push_image( + &info, + info.clip_rect, + ImageRendering::Auto, + AlphaType::PremultipliedAlpha, + blob_img.as_image(), + ColorF::WHITE, + ); + + self.submit_dl(&mut epoch, layout_size, builder, txn); + let pixels_second = self.render_and_get_pixels(window_rect); + + // draw the blob image a third time after updating it with a different color + let mut txn = Transaction::new(); + txn.update_blob_image( + blob_img, + ImageDescriptor::new(500, 500, ImageFormat::BGRA8, ImageDescriptorFlags::empty()), + blob::serialize_blob(ColorU::new(50, 150, 150, 255)), + rect(0, 0, 500, 500), + &rect(200, 200, 100, 100).into(), + ); + + // make a new display list that refers to the first image + let mut builder = DisplayListBuilder::new(self.wrench.root_pipeline_id); + let info = self.make_common_properties(rect(0.0, 60.0, 200.0, 200.0)); + builder.push_image( + &info, + info.clip_rect, + ImageRendering::Auto, + AlphaType::PremultipliedAlpha, + blob_img.as_image(), + ColorF::WHITE, + ); + + self.submit_dl(&mut epoch, layout_size, builder, txn); + let pixels_third = self.render_and_get_pixels(window_rect); + + assert!(pixels_first != pixels_third); + self.compare_pixels(pixels_first, pixels_second, window_rect.size); + } + + // Ensures that content doing a save-restore produces the same results as not + fn test_save_restore(&mut self) { + println!("\tsave/restore..."); + let window_size = self.window.get_inner_size(); + + let test_size = FramebufferIntSize::new(400, 400); + let window_rect = FramebufferIntRect::new( + point2(0, window_size.height - test_size.height), + test_size, + ); + let layout_size = LayoutSize::new(400., 400.); + + let mut do_test = |should_try_and_fail| { + let mut builder = DisplayListBuilder::new(self.wrench.root_pipeline_id); + + let spatial_id = SpatialId::root_scroll_node(self.wrench.root_pipeline_id); + let clip_id = builder.define_clip_rect( + &SpaceAndClipInfo::root_scroll(self.wrench.root_pipeline_id), + rect(110., 120., 200., 200.), + ); + builder.push_rect( + &self.make_common_properties_with_clip_and_spatial( + rect(100., 100., 100., 100.), + clip_id, + spatial_id), + rect(100., 100., 100., 100.), + ColorF::new(0.0, 0.0, 1.0, 1.0), + ); + + if should_try_and_fail { + builder.save(); + let clip_id = builder.define_clip_rect( + &SpaceAndClipInfo { spatial_id, clip_id }, + rect(80., 80., 90., 90.), + ); + let space_and_clip = SpaceAndClipInfo { + spatial_id, + clip_id + }; + builder.push_rect( + &self.make_common_properties_with_clip_and_spatial( + rect(110., 110., 50., 50.), + clip_id, + spatial_id), + rect(110., 110., 50., 50.), + ColorF::new(0.0, 1.0, 0.0, 1.0), + ); + builder.push_shadow( + &space_and_clip, + Shadow { + offset: LayoutVector2D::new(1.0, 1.0), + blur_radius: 1.0, + color: ColorF::new(0.0, 0.0, 0.0, 1.0), + }, + true, + ); + let info = CommonItemProperties { + clip_rect: rect(110., 110., 50., 2.), + clip_id, + spatial_id, + flags: PrimitiveFlags::default(), + }; + builder.push_line( + &info, + &info.clip_rect, + 0.0, LineOrientation::Horizontal, + &ColorF::new(0.0, 0.0, 0.0, 1.0), + LineStyle::Solid, + ); + builder.restore(); + } + + { + builder.save(); + let clip_id = builder.define_clip_rect( + &SpaceAndClipInfo { spatial_id, clip_id }, + rect(80., 80., 100., 100.), + ); + builder.push_rect( + &self.make_common_properties_with_clip_and_spatial( + rect(150., 150., 100., 100.), + clip_id, + spatial_id), + rect(150., 150., 100., 100.), + ColorF::new(0.0, 0.0, 1.0, 1.0), + ); + builder.clear_save(); + } + + let txn = Transaction::new(); + + self.submit_dl(&mut Epoch(0), layout_size, builder, txn); + + self.render_and_get_pixels(window_rect) + }; + + let first = do_test(false); + let second = do_test(true); + + self.compare_pixels(first, second, window_rect.size); + } + + // regression test for #2769 + // "async scene building: cache collisions from reused picture ids" + fn test_blur_cache(&mut self) { + println!("\tblur cache..."); + let window_size = self.window.get_inner_size(); + + let test_size = FramebufferIntSize::new(400, 400); + let window_rect = FramebufferIntRect::new( + point2(0, window_size.height - test_size.height), + test_size, + ); + let layout_size = LayoutSize::new(400., 400.); + + let mut do_test = |shadow_is_red| { + let mut builder = DisplayListBuilder::new(self.wrench.root_pipeline_id); + let shadow_color = if shadow_is_red { + ColorF::new(1.0, 0.0, 0.0, 1.0) + } else { + ColorF::new(0.0, 1.0, 0.0, 1.0) + }; + + builder.push_shadow( + &SpaceAndClipInfo::root_scroll(self.wrench.root_pipeline_id), + Shadow { + offset: LayoutVector2D::new(1.0, 1.0), + blur_radius: 1.0, + color: shadow_color, + }, + true, + ); + let info = self.make_common_properties(rect(110., 110., 50., 2.)); + builder.push_line( + &info, + &info.clip_rect, + 0.0, LineOrientation::Horizontal, + &ColorF::new(0.0, 0.0, 0.0, 1.0), + LineStyle::Solid, + ); + builder.pop_all_shadows(); + + let txn = Transaction::new(); + self.submit_dl(&mut Epoch(0), layout_size, builder, txn); + + self.render_and_get_pixels(window_rect) + }; + + let first = do_test(false); + let second = do_test(true); + + assert_ne!(first, second); + } + + fn test_capture(&mut self) { + println!("\tcapture..."); + let path = "../captures/test"; + let layout_size = LayoutSize::new(400., 400.); + let dim = self.window.get_inner_size(); + let window_rect = FramebufferIntRect::new( + point2(0, dim.height - layout_size.height as i32), + size2(layout_size.width as i32, layout_size.height as i32), + ); + + // 1. render some scene + + let mut txn = Transaction::new(); + let image = self.wrench.api.generate_image_key(); + txn.add_image( + image, + ImageDescriptor::new(1, 1, ImageFormat::BGRA8, ImageDescriptorFlags::IS_OPAQUE), + ImageData::new(vec![0xFF, 0, 0, 0xFF]), + None, + ); + + let mut builder = DisplayListBuilder::new(self.wrench.root_pipeline_id); + + let info = self.make_common_properties(rect(300.0, 70.0, 150.0, 50.0)); + builder.push_image( + &info, + info.clip_rect, + ImageRendering::Auto, + AlphaType::PremultipliedAlpha, + image, + ColorF::WHITE, + ); + + let mut txn = Transaction::new(); + + txn.set_display_list( + Epoch(0), + Some(ColorF::new(1.0, 1.0, 1.0, 1.0)), + layout_size, + builder.finalize(), + false, + ); + txn.generate_frame(0); + + self.wrench.api.send_transaction(self.wrench.document_id, txn); + + let pixels0 = self.render_and_get_pixels(window_rect); + + // 2. capture it + self.wrench.api.save_capture(path.into(), CaptureBits::all()); + + // 3. set a different scene + + builder = DisplayListBuilder::new(self.wrench.root_pipeline_id); + + let mut txn = Transaction::new(); + txn.set_display_list( + Epoch(1), + Some(ColorF::new(1.0, 0.0, 0.0, 1.0)), + layout_size, + builder.finalize(), + false, + ); + self.wrench.api.send_transaction(self.wrench.document_id, txn); + + // 4. load the first one + + let mut documents = self.wrench.api.load_capture(path.into(), None); + let captured = documents.swap_remove(0); + + // 5. render the built frame and compare + let pixels1 = self.render_and_get_pixels(window_rect); + self.compare_pixels(pixels0.clone(), pixels1, window_rect.size); + + // 6. rebuild the scene and compare again + let mut txn = Transaction::new(); + txn.set_root_pipeline(captured.root_pipeline_id.unwrap()); + txn.generate_frame(0); + self.wrench.api.send_transaction(captured.document_id, txn); + let pixels2 = self.render_and_get_pixels(window_rect); + self.compare_pixels(pixels0, pixels2, window_rect.size); + } + + fn test_zero_height_window(&mut self) { + println!("\tzero height test..."); + + let layout_size = LayoutSize::new(120.0, 0.0); + let window_size = DeviceIntSize::new(layout_size.width as i32, layout_size.height as i32); + let doc_id = self.wrench.api.add_document(window_size); + + let mut builder = DisplayListBuilder::new(self.wrench.root_pipeline_id); + let info = self.make_common_properties(LayoutRect::new(LayoutPoint::zero(), + LayoutSize::new(100.0, 100.0))); + builder.push_rect( + &info, + info.clip_rect, + ColorF::new(0.0, 1.0, 0.0, 1.0), + ); + + let mut txn = Transaction::new(); + txn.set_root_pipeline(self.wrench.root_pipeline_id); + txn.set_display_list( + Epoch(1), + Some(ColorF::new(1.0, 0.0, 0.0, 1.0)), + layout_size, + builder.finalize(), + false, + ); + txn.generate_frame(0); + self.wrench.api.send_transaction(doc_id, txn); + + // Ensure we get a notification from rendering the above, even though + // there are zero visible pixels + assert!(self.rx.recv().unwrap() == NotifierEvent::WakeUp { composite_needed: true }); + } + + + fn test_hit_testing(&mut self) { + println!("\thit testing test..."); + + let layout_size = LayoutSize::new(400., 400.); + let mut builder = DisplayListBuilder::new(self.wrench.root_pipeline_id); + + // Add a rectangle that covers the entire scene. + let info = self.make_common_properties(LayoutRect::new(LayoutPoint::zero(), layout_size)); + builder.push_hit_test( + &info, + (0, 1), + ); + + // Add a simple 100x100 rectangle at 100,0. + let info = self.make_common_properties(LayoutRect::new( + LayoutPoint::new(100., 0.), + LayoutSize::new(100., 100.) + )); + builder.push_hit_test( + &info, + (0, 2), + ); + + let space_and_clip = SpaceAndClipInfo::root_scroll(self.wrench.root_pipeline_id); + + let make_rounded_complex_clip = |rect: &LayoutRect, radius: f32| -> ComplexClipRegion { + ComplexClipRegion::new( + *rect, + BorderRadius::uniform_size(LayoutSize::new(radius, radius)), + ClipMode::Clip + ) + }; + + // Add a rectangle that is clipped by a rounded rect clip item. + let rect = LayoutRect::new(LayoutPoint::new(100., 100.), LayoutSize::new(100., 100.)); + let temp_clip_id = builder.define_clip_rounded_rect( + &space_and_clip, + make_rounded_complex_clip(&rect, 20.), + ); + builder.push_hit_test( + &CommonItemProperties { + clip_rect: rect, + clip_id: temp_clip_id, + spatial_id: space_and_clip.spatial_id, + flags: PrimitiveFlags::default(), + }, + (0, 4), + ); + + // Add a rectangle that is clipped by a ClipChain containing a rounded rect. + let rect = LayoutRect::new(LayoutPoint::new(200., 100.), LayoutSize::new(100., 100.)); + let clip_id = builder.define_clip_rounded_rect( + &space_and_clip, + make_rounded_complex_clip(&rect, 20.), + ); + let clip_chain_id = builder.define_clip_chain(None, vec![clip_id]); + builder.push_hit_test( + &CommonItemProperties { + clip_rect: rect, + clip_id: ClipId::ClipChain(clip_chain_id), + spatial_id: space_and_clip.spatial_id, + flags: PrimitiveFlags::default(), + }, + (0, 5), + ); + + let mut epoch = Epoch(0); + let txn = Transaction::new(); + self.submit_dl(&mut epoch, layout_size, builder, txn); + + // We render to ensure that the hit tester is up to date with the current scene. + self.rx.recv().unwrap(); + self.wrench.render(); + + let hit_test = |point: WorldPoint| -> HitTestResult { + self.wrench.api.hit_test( + self.wrench.document_id, + None, + point, + ) + }; + + let assert_hit_test = |point: WorldPoint, tags: Vec<ItemTag>| { + let result = hit_test(point); + assert_eq!(result.items.len(), tags.len()); + + for (hit_test_item, item_b) in result.items.iter().zip(tags.iter()) { + assert_eq!(hit_test_item.tag, *item_b); + } + }; + + // We should not have any hits outside the boundaries of the scene. + assert_hit_test(WorldPoint::new(-10., -10.), Vec::new()); + assert_hit_test(WorldPoint::new(-10., 10.), Vec::new()); + assert_hit_test(WorldPoint::new(450., 450.), Vec::new()); + assert_hit_test(WorldPoint::new(100., 450.), Vec::new()); + + // The top left corner of the scene should only contain the background. + assert_hit_test(WorldPoint::new(50., 50.), vec![(0, 1)]); + + // The middle of the normal rectangle should be hit. + assert_hit_test(WorldPoint::new(150., 50.), vec![(0, 2), (0, 1)]); + + let test_rounded_rectangle = |point: WorldPoint, size: WorldSize, tag: ItemTag| { + // The cut out corners of the rounded rectangle should not be hit. + let top_left = point + WorldVector2D::new(5., 5.); + let bottom_right = point + size.to_vector() - WorldVector2D::new(5., 5.); + + assert_hit_test( + WorldPoint::new(point.x + (size.width / 2.), point.y + (size.height / 2.)), + vec![tag, (0, 1)] + ); + + assert_hit_test(top_left, vec![(0, 1)]); + assert_hit_test(WorldPoint::new(bottom_right.x, top_left.y), vec![(0, 1)]); + assert_hit_test(WorldPoint::new(top_left.x, bottom_right.y), vec![(0, 1)]); + assert_hit_test(bottom_right, vec![(0, 1)]); + }; + + test_rounded_rectangle(WorldPoint::new(100., 100.), WorldSize::new(100., 100.), (0, 4)); + test_rounded_rectangle(WorldPoint::new(200., 100.), WorldSize::new(100., 100.), (0, 5)); + } + + fn test_clear_cache(&mut self) { + println!("\tclear cache test..."); + + self.wrench.api.send_message(ApiMsg::DebugCommand(DebugCommand::ClearCaches(ClearCache::all()))); + + let layout_size = LayoutSize::new(400., 400.); + let builder = DisplayListBuilder::new(self.wrench.root_pipeline_id); + + let txn = Transaction::new(); + let mut epoch = Epoch(0); + self.submit_dl(&mut epoch, layout_size, builder, txn); + + self.rx.recv().unwrap(); + self.wrench.render(); + } +} diff --git a/gfx/wr/wrench/src/reftest.rs b/gfx/wr/wrench/src/reftest.rs new file mode 100644 index 0000000000..912a51647b --- /dev/null +++ b/gfx/wr/wrench/src/reftest.rs @@ -0,0 +1,997 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +use crate::{WindowWrapper, NotifierEvent}; +use base64; +use semver; +use image::load as load_piston_image; +use image::png::PNGEncoder; +use image::{ColorType, ImageFormat}; +use crate::parse_function::parse_function; +use crate::png::save_flipped; +use std::{cmp, env}; +use std::fmt::{Display, Error, Formatter}; +use std::fs::File; +use std::io::{BufRead, BufReader}; +use std::path::{Path, PathBuf}; +use std::process::Command; +use std::sync::mpsc::Receiver; +use webrender::RenderResults; +use webrender::api::*; +use webrender::render_api::*; +use webrender::api::units::*; +use crate::wrench::{Wrench, WrenchThing}; +use crate::yaml_frame_reader::YamlFrameReader; + + +const OPTION_DISABLE_SUBPX: &str = "disable-subpixel"; +const OPTION_DISABLE_AA: &str = "disable-aa"; +const OPTION_DISABLE_DUAL_SOURCE_BLENDING: &str = "disable-dual-source-blending"; +const OPTION_ALLOW_MIPMAPS: &str = "allow-mipmaps"; + +pub struct ReftestOptions { + // These override values that are lower. + pub allow_max_difference: usize, + pub allow_num_differences: usize, +} + +impl ReftestOptions { + pub fn default() -> Self { + ReftestOptions { + allow_max_difference: 0, + allow_num_differences: 0, + } + } +} + +#[derive(Debug, Copy, Clone)] +pub enum ReftestOp { + /// Expect that the images match the reference + Equal, + /// Expect that the images *don't* match the reference + NotEqual, + /// Expect that drawing the reference at different tiles sizes gives the same pixel exact result. + Accurate, + /// Expect that drawing the reference at different tiles sizes gives a *different* pixel exact result. + Inaccurate, +} + +impl Display for ReftestOp { + fn fmt(&self, f: &mut Formatter) -> Result<(), Error> { + write!( + f, + "{}", + match *self { + ReftestOp::Equal => "==".to_owned(), + ReftestOp::NotEqual => "!=".to_owned(), + ReftestOp::Accurate => "**".to_owned(), + ReftestOp::Inaccurate => "!*".to_owned(), + } + ) + } +} + +#[derive(Debug)] +enum ExtraCheck { + DrawCalls(usize), + AlphaTargets(usize), + ColorTargets(usize), +} + +impl ExtraCheck { + fn run(&self, results: &[RenderResults]) -> bool { + match *self { + ExtraCheck::DrawCalls(x) => + x == results.last().unwrap().stats.total_draw_calls, + ExtraCheck::AlphaTargets(x) => + x == results.last().unwrap().stats.alpha_target_count, + ExtraCheck::ColorTargets(x) => + x == results.last().unwrap().stats.color_target_count, + } + } +} + +pub struct RefTestFuzzy { + max_difference: usize, + num_differences: usize, +} + +pub struct Reftest { + op: ReftestOp, + test: Vec<PathBuf>, + reference: PathBuf, + font_render_mode: Option<FontRenderMode>, + fuzziness: Vec<RefTestFuzzy>, + extra_checks: Vec<ExtraCheck>, + disable_dual_source_blending: bool, + allow_mipmaps: bool, + zoom_factor: f32, + force_subpixel_aa_where_possible: Option<bool>, +} + +impl Reftest { + /// Check the positive case (expecting equality) and report details if different + fn check_and_report_equality_failure( + &self, + comparison: ReftestImageComparison, + test: &ReftestImage, + reference: &ReftestImage, + ) -> bool { + match comparison { + ReftestImageComparison::Equal => { + true + } + ReftestImageComparison::NotEqual { difference_histogram, max_difference, count_different } => { + // Each entry in the sorted self.fuzziness list represents a bucket which + // allows at most num_differences pixels with a difference of at most + // max_difference -- but with the caveat that a difference which is small + // enough to be less than a max_difference of an earlier bucket, must be + // counted against that bucket. + // + // Thus the test will fail if the number of pixels with a difference + // > fuzzy[j-1].max_difference and <= fuzzy[j].max_difference + // exceeds fuzzy[j].num_differences. + // + // (For the first entry, consider fuzzy[j-1] to allow zero pixels of zero + // difference). + // + // For example, say we have this histogram of differences: + // + // | [0] [1] [2] [3] [4] [5] [6] ... [255] + // ------+------------------------------------------ + // Hist. | 0 3 2 1 6 2 0 ... 0 + // + // Ie. image comparison found 3 pixels that differ by 1, 2 that differ by 2, etc. + // (Note that entry 0 is always zero, we don't count matching pixels.) + // + // First we calculate an inclusive prefix sum: + // + // | [0] [1] [2] [3] [4] [5] [6] ... [255] + // ------+------------------------------------------ + // Hist. | 0 3 2 1 6 2 0 ... 0 + // Sum | 0 3 5 6 12 14 14 ... 14 + // + // Let's say the fuzzy statements are: + // Fuzzy( 2, 6 ) -- allow up to 6 pixels that differ by 2 or less + // Fuzzy( 4, 8 ) -- allow up to 8 pixels that differ by 4 or less _but_ + // also by more than 2 (= by 3 or 4). + // + // The first check is Sum[2] <= max 6 which passes: 5 <= 6. + // The second check is Sum[4] - Sum[2] <= max 8 which passes: 12-5 <= 8. + // Finally we check if there are any pixels that exceed the max difference (4) + // by checking Sum[255] - Sum[4] which shows there are 14-12 == 2 so we fail. + + let prefix_sum = difference_histogram.iter() + .scan(0, |sum, i| { *sum += i; Some(*sum) }) + .collect::<Vec<_>>(); + + // check each fuzzy statement for violations. + assert_eq!(0, difference_histogram[0]); + assert_eq!(0, prefix_sum[0]); + + // loop invariant: this is the max_difference of the previous iteration's 'fuzzy' + let mut previous_max_diff = 0; + + // loop invariant: this is the number of pixels to ignore as they have been counted + // against previous iterations' fuzzy statements. + let mut previous_sum_fail = 0; // == prefix_sum[previous_max_diff] + + let mut is_failing = false; + let mut fail_text = String::new(); + + for fuzzy in &self.fuzziness { + let fuzzy_max_difference = cmp::min(255, fuzzy.max_difference); + let num_differences = prefix_sum[fuzzy_max_difference] - previous_sum_fail; + if num_differences > fuzzy.num_differences { + fail_text.push_str( + &format!("{} differences > {} and <= {} (allowed {}); ", + num_differences, + previous_max_diff, fuzzy_max_difference, + fuzzy.num_differences)); + is_failing = true; + } + previous_max_diff = fuzzy_max_difference; + previous_sum_fail = prefix_sum[previous_max_diff]; + } + // do we have any pixels with a difference above the highest allowed + // max difference? if so, we fail the test: + let num_differences = prefix_sum[255] - previous_sum_fail; + if num_differences > 0 { + fail_text.push_str( + &format!("{} num_differences > {} and <= {} (allowed {}); ", + num_differences, + previous_max_diff, 255, + 0)); + is_failing = true; + } + + if is_failing { + println!( + "{} | {} | {}: {}, {}: {} | {}", + "REFTEST TEST-UNEXPECTED-FAIL", + self, + "image comparison, max difference", + max_difference, + "number of differing pixels", + count_different, + fail_text, + ); + println!("REFTEST IMAGE 1 (TEST): {}", test.clone().create_data_uri()); + println!( + "REFTEST IMAGE 2 (REFERENCE): {}", + reference.clone().create_data_uri() + ); + println!("REFTEST TEST-END | {}", self); + + false + } else { + true + } + } + } + } + + /// Report details of the negative case + fn report_unexpected_equality(&self) { + println!("REFTEST TEST-UNEXPECTED-FAIL | {} | image comparison", self); + println!("REFTEST TEST-END | {}", self); + } +} + +impl Display for Reftest { + fn fmt(&self, f: &mut Formatter) -> Result<(), Error> { + let paths: Vec<String> = self.test.iter().map(|t| t.display().to_string()).collect(); + write!( + f, + "{} {} {}", + paths.join(", "), + self.op, + self.reference.display() + ) + } +} + +#[derive(Clone)] +pub struct ReftestImage { + pub data: Vec<u8>, + pub size: DeviceIntSize, +} + +#[derive(Debug, Clone)] +pub enum ReftestImageComparison { + Equal, + NotEqual { + /// entry[j] = number of pixels with a difference of exactly j + difference_histogram: Vec<usize>, + max_difference: usize, + count_different: usize, + }, +} + +impl ReftestImage { + pub fn compare(&self, other: &ReftestImage) -> ReftestImageComparison { + assert_eq!(self.size, other.size); + assert_eq!(self.data.len(), other.data.len()); + assert_eq!(self.data.len() % 4, 0); + + let mut histogram = [0usize; 256]; + let mut count = 0; + let mut max = 0; + + for (a, b) in self.data.chunks(4).zip(other.data.chunks(4)) { + if a != b { + let pixel_max = a.iter() + .zip(b.iter()) + .map(|(x, y)| (*x as isize - *y as isize).abs() as usize) + .max() + .unwrap(); + + count += 1; + assert!(pixel_max < 256, "pixel values are not 8 bit, update the histogram binning code"); + // deliberately avoid counting pixels that match -- + // histogram[0] stays at zero. + // this helps our prefix sum later during analysis to + // only count actual differences. + histogram[pixel_max as usize] += 1; + max = cmp::max(max, pixel_max); + } + } + + if count != 0 { + ReftestImageComparison::NotEqual { + difference_histogram: histogram.to_vec(), + max_difference: max, + count_different: count, + } + } else { + ReftestImageComparison::Equal + } + } + + pub fn create_data_uri(mut self) -> String { + let width = self.size.width; + let height = self.size.height; + + // flip image vertically (texture is upside down) + let orig_pixels = self.data.clone(); + let stride = width as usize * 4; + for y in 0 .. height as usize { + let dst_start = y * stride; + let src_start = (height as usize - y - 1) * stride; + let src_slice = &orig_pixels[src_start .. src_start + stride]; + (&mut self.data[dst_start .. dst_start + stride]) + .clone_from_slice(&src_slice[.. stride]); + } + + let mut png: Vec<u8> = vec![]; + { + let encoder = PNGEncoder::new(&mut png); + encoder + .encode(&self.data[..], width as u32, height as u32, ColorType::Rgba8) + .expect("Unable to encode PNG!"); + } + let png_base64 = base64::encode(&png); + format!("data:image/png;base64,{}", png_base64) + } +} + +struct ReftestManifest { + reftests: Vec<Reftest>, +} +impl ReftestManifest { + fn new(manifest: &Path, environment: &ReftestEnvironment, options: &ReftestOptions) -> ReftestManifest { + let dir = manifest.parent().unwrap(); + let f = + File::open(manifest).expect(&format!("couldn't open manifest: {}", manifest.display())); + let file = BufReader::new(&f); + + let mut reftests = Vec::new(); + + for line in file.lines() { + let l = line.unwrap(); + + // strip the comments + let s = &l[0 .. l.find('#').unwrap_or(l.len())]; + let s = s.trim(); + if s.is_empty() { + continue; + } + + let tokens: Vec<&str> = s.split_whitespace().collect(); + + let mut fuzziness = Vec::new(); + let mut op = None; + let mut font_render_mode = None; + let mut extra_checks = vec![]; + let mut disable_dual_source_blending = false; + let mut zoom_factor = 1.0; + let mut allow_mipmaps = false; + let mut force_subpixel_aa_where_possible = None; + + let mut parse_command = |token: &str| -> bool { + match token { + function if function.starts_with("zoom(") => { + let (_, args, _) = parse_function(function); + zoom_factor = args[0].parse().unwrap(); + } + function if function.starts_with("force_subpixel_aa_where_possible(") => { + let (_, args, _) = parse_function(function); + force_subpixel_aa_where_possible = Some(args[0].parse().unwrap()); + } + function if function.starts_with("fuzzy-range(") || + function.starts_with("fuzzy-range-if(") => { + let (_, mut args, _) = parse_function(function); + if function.starts_with("fuzzy-range-if(") { + if !environment.parse_condition(args.remove(0)).expect("unknown condition") { + return true; + } + fuzziness.clear(); + } + let num_range = args.len() / 2; + for range in 0..num_range { + let mut max = args[range * 2 + 0]; + let mut num = args[range * 2 + 1]; + if max.starts_with("<=") { // trim_start_matches would allow <=<=123 + max = &max[2..]; + } + if num.starts_with("*") { + num = &num[1..]; + } + let max_difference = max.parse().unwrap(); + let num_differences = num.parse().unwrap(); + fuzziness.push(RefTestFuzzy { max_difference, num_differences }); + } + } + function if function.starts_with("fuzzy(") || + function.starts_with("fuzzy-if(") => { + let (_, mut args, _) = parse_function(function); + if function.starts_with("fuzzy-if(") { + if !environment.parse_condition(args.remove(0)).expect("unknown condition") { + return true; + } + fuzziness.clear(); + } + let max_difference = args[0].parse().unwrap(); + let num_differences = args[1].parse().unwrap(); + assert!(fuzziness.is_empty()); // if this fires, consider fuzzy-range instead + fuzziness.push(RefTestFuzzy { max_difference, num_differences }); + } + function if function.starts_with("draw_calls(") => { + let (_, args, _) = parse_function(function); + extra_checks.push(ExtraCheck::DrawCalls(args[0].parse().unwrap())); + } + function if function.starts_with("alpha_targets(") => { + let (_, args, _) = parse_function(function); + extra_checks.push(ExtraCheck::AlphaTargets(args[0].parse().unwrap())); + } + function if function.starts_with("color_targets(") => { + let (_, args, _) = parse_function(function); + extra_checks.push(ExtraCheck::ColorTargets(args[0].parse().unwrap())); + } + options if options.starts_with("options(") => { + let (_, args, _) = parse_function(options); + if args.iter().any(|arg| arg == &OPTION_DISABLE_SUBPX) { + font_render_mode = Some(FontRenderMode::Alpha); + } + if args.iter().any(|arg| arg == &OPTION_DISABLE_AA) { + font_render_mode = Some(FontRenderMode::Mono); + } + if args.iter().any(|arg| arg == &OPTION_DISABLE_DUAL_SOURCE_BLENDING) { + disable_dual_source_blending = true; + } + if args.iter().any(|arg| arg == &OPTION_ALLOW_MIPMAPS) { + allow_mipmaps = true; + } + } + _ => return false, + } + return true; + }; + + let mut paths = vec![]; + for (i, token) in tokens.iter().enumerate() { + match *token { + "include" => { + assert!(i == 0, "include must be by itself"); + let include = dir.join(tokens[1]); + + reftests.append( + &mut ReftestManifest::new(include.as_path(), environment, options).reftests, + ); + + break; + } + "==" => { + op = Some(ReftestOp::Equal); + } + "!=" => { + op = Some(ReftestOp::NotEqual); + } + "**" => { + op = Some(ReftestOp::Accurate); + } + "!*" => { + op = Some(ReftestOp::Inaccurate); + } + cond if cond.starts_with("if(") => { + let (_, args, _) = parse_function(cond); + if environment.parse_condition(args[0]).expect("unknown condition") { + for command in &args[1..] { + parse_command(command); + } + } + } + command if parse_command(command) => {} + _ => { + match environment.parse_condition(*token) { + Some(true) => {} + Some(false) => break, + _ => paths.push(dir.join(*token)), + } + } + } + } + + // Don't try to add tests for include lines. + let op = match op { + Some(op) => op, + None => { + assert!(paths.is_empty(), format!("paths = {:?}", paths)); + continue; + } + }; + + // The reference is the last path provided. If multiple paths are + // passed for the test, they render sequentially before being + // compared to the reference, which is useful for testing + // invalidation. + let reference = paths.pop().unwrap(); + let test = paths; + + if environment.platform == "android" { + // Add some fuzz on mobile as we do for non-wrench reftests. + // First remove the ranges with difference <= 2, otherwise they might cause the + // test to fail before the new range is picked up. + fuzziness.retain(|fuzzy| fuzzy.max_difference > 2); + fuzziness.push(RefTestFuzzy { max_difference: 2, num_differences: std::usize::MAX }); + } + + // to avoid changing the meaning of existing tests, the case of + // only a single (or no) 'fuzzy' keyword means we use the max + // of that fuzzy and options.allow_.. (we don't want that to + // turn into a test that allows fuzzy.allow_ *plus* options.allow_): + match fuzziness.len() { + 0 => fuzziness.push(RefTestFuzzy { + max_difference: options.allow_max_difference, + num_differences: options.allow_num_differences }), + 1 => { + let mut fuzzy = &mut fuzziness[0]; + fuzzy.max_difference = cmp::max(fuzzy.max_difference, options.allow_max_difference); + fuzzy.num_differences = cmp::max(fuzzy.num_differences, options.allow_num_differences); + }, + _ => { + // ignore options, use multiple fuzzy keywords instead. make sure + // the list is sorted to speed up counting violations. + fuzziness.sort_by(|a, b| a.max_difference.cmp(&b.max_difference)); + for pair in fuzziness.windows(2) { + if pair[0].max_difference == pair[1].max_difference { + println!("Warning: repeated fuzzy of max_difference {} ignored.", + pair[1].max_difference); + } + } + } + } + + reftests.push(Reftest { + op, + test, + reference, + font_render_mode, + fuzziness, + extra_checks, + disable_dual_source_blending, + allow_mipmaps, + zoom_factor, + force_subpixel_aa_where_possible, + }); + } + + ReftestManifest { reftests: reftests } + } + + fn find(&self, prefix: &Path) -> Vec<&Reftest> { + self.reftests + .iter() + .filter(|x| { + x.test.iter().any(|t| t.starts_with(prefix)) || x.reference.starts_with(prefix) + }) + .collect() + } +} + +struct YamlRenderOutput { + image: ReftestImage, + results: RenderResults, +} + +struct ReftestEnvironment { + pub platform: &'static str, + pub version: Option<semver::Version>, + pub mode: &'static str, +} + +impl ReftestEnvironment { + fn new(wrench: &Wrench, window: &WindowWrapper) -> Self { + Self { + platform: Self::platform(wrench, window), + version: Self::version(wrench, window), + mode: Self::mode(), + } + } + + fn has(&self, condition: &str) -> bool { + if self.platform == condition || self.mode == condition { + return true; + } + match (&self.version, &semver::VersionReq::parse(condition)) { + (Some(v), Ok(r)) => { + if r.matches(v) { + return true; + } + }, + _ => (), + }; + let envkey = format!("WRENCH_REFTEST_CONDITION_{}", condition.to_uppercase()); + env::var(envkey).is_ok() + } + + fn platform(_wrench: &Wrench, window: &WindowWrapper) -> &'static str { + if window.is_software() { + "swgl" + } else if cfg!(target_os = "windows") { + "win" + } else if cfg!(target_os = "linux") { + "linux" + } else if cfg!(target_os = "macos") { + "mac" + } else if cfg!(target_os = "android") { + "android" + } else { + "other" + } + } + + fn version(_wrench: &Wrench, window: &WindowWrapper) -> Option<semver::Version> { + if window.is_software() { + None + } else if cfg!(target_os = "macos") { + use std::str; + let version_bytes = Command::new("defaults") + .arg("read") + .arg("loginwindow") + .arg("SystemVersionStampAsString") + .output() + .expect("Failed to get macOS version") + .stdout; + let mut version_string = str::from_utf8(&version_bytes) + .expect("Failed to read macOS version") + .trim() + .to_string(); + // On some machines this produces just the major.minor and on + // some machines this gives major.minor.patch. But semver requires + // the patch so we fake one if it's not there. + if version_string.chars().filter(|c| *c == '.').count() == 1 { + version_string.push_str(".0"); + } + Some(semver::Version::parse(&version_string) + .expect(&format!("Failed to parse macOS version {}", version_string))) + } else { + None + } + } + + fn mode() -> &'static str { + if cfg!(debug_assertions) { + "debug" + } else { + "release" + } + } + + fn parse_condition(&self, token: &str) -> Option<bool> { + match token { + platform if platform.starts_with("skip_on(") => { + // e.g. skip_on(android,debug) will skip only when + // running on a debug android build. + let (_, args, _) = parse_function(platform); + Some(!args.iter().all(|arg| self.has(arg))) + } + platform if platform.starts_with("env(") => { + // non-negated version of skip_on for nested conditions + let (_, args, _) = parse_function(platform); + Some(args.iter().all(|arg| self.has(arg))) + } + platform if platform.starts_with("platform(") => { + let (_, args, _) = parse_function(platform); + // Skip due to platform not matching + Some(args.iter().any(|arg| arg == &self.platform)) + } + op if op.starts_with("not(") => { + let (_, args, _) = parse_function(op); + Some(!self.parse_condition(args[0]).expect("unknown condition")) + } + op if op.starts_with("or(") => { + let (_, args, _) = parse_function(op); + Some(args.iter().any(|arg| self.parse_condition(arg).expect("unknown condition"))) + } + op if op.starts_with("and(") => { + let (_, args, _) = parse_function(op); + Some(args.iter().all(|arg| self.parse_condition(arg).expect("unknown condition"))) + } + _ => None, + } + } +} + +pub struct ReftestHarness<'a> { + wrench: &'a mut Wrench, + window: &'a mut WindowWrapper, + rx: &'a Receiver<NotifierEvent>, + environment: ReftestEnvironment, +} +impl<'a> ReftestHarness<'a> { + pub fn new(wrench: &'a mut Wrench, window: &'a mut WindowWrapper, rx: &'a Receiver<NotifierEvent>) -> Self { + let environment = ReftestEnvironment::new(wrench, window); + ReftestHarness { wrench, window, rx, environment } + } + + pub fn run(mut self, base_manifest: &Path, reftests: Option<&Path>, options: &ReftestOptions) -> usize { + let manifest = ReftestManifest::new(base_manifest, &self.environment, options); + let reftests = manifest.find(reftests.unwrap_or(&PathBuf::new())); + + let mut total_passing = 0; + let mut failing = Vec::new(); + + for t in reftests { + if self.run_reftest(t) { + total_passing += 1; + } else { + failing.push(t); + } + } + + println!( + "REFTEST INFO | {} passing, {} failing", + total_passing, + failing.len() + ); + + if !failing.is_empty() { + println!("\nReftests with unexpected results:"); + + for reftest in &failing { + println!("\t{}", reftest); + } + } + + failing.len() + } + + fn run_reftest(&mut self, t: &Reftest) -> bool { + let test_name = t.to_string(); + println!("REFTEST {}", test_name); + profile_scope!("wrench reftest", text: &test_name); + + self.wrench + .api + .send_debug_cmd( + DebugCommand::ClearCaches(ClearCache::all()) + ); + + let quality_settings = match t.force_subpixel_aa_where_possible { + Some(force_subpixel_aa_where_possible) => { + QualitySettings { + force_subpixel_aa_where_possible, + } + } + None => { + QualitySettings::default() + } + }; + + self.wrench.set_quality_settings(quality_settings); + self.wrench.set_page_zoom(ZoomFactor::new(t.zoom_factor)); + + if t.disable_dual_source_blending { + self.wrench + .api + .send_debug_cmd( + DebugCommand::EnableDualSourceBlending(false) + ); + } + + let window_size = self.window.get_inner_size(); + let reference_image = match t.reference.extension().unwrap().to_str().unwrap() { + "yaml" => None, + "png" => Some(self.load_image(t.reference.as_path(), ImageFormat::Png)), + other => panic!("Unknown reftest extension: {}", other), + }; + let test_size = reference_image.as_ref().map_or(window_size, |img| img.size); + + // The reference can be smaller than the window size, in which case + // we only compare the intersection. + // + // Note also that, when we have multiple test scenes in sequence, we + // want to test the picture caching machinery. But since picture caching + // only takes effect after the result has been the same several frames in + // a row, we need to render the scene multiple times. + let mut images = vec![]; + let mut results = vec![]; + + match t.op { + ReftestOp::Equal | ReftestOp::NotEqual => { + // For equality tests, render each test image and store result + for filename in t.test.iter() { + let output = self.render_yaml( + &filename, + test_size, + t.font_render_mode, + t.allow_mipmaps, + ); + images.push(output.image); + results.push(output.results); + } + } + ReftestOp::Accurate | ReftestOp::Inaccurate => { + // For accuracy tests, render the reference yaml at an arbitrary series + // of tile sizes, and compare to the reference drawn at normal tile size. + let tile_sizes = [ + DeviceIntSize::new(128, 128), + DeviceIntSize::new(256, 256), + DeviceIntSize::new(512, 512), + ]; + + for tile_size in &tile_sizes { + self.wrench + .api + .send_debug_cmd( + DebugCommand::SetPictureTileSize(Some(*tile_size)) + ); + + let output = self.render_yaml( + &t.reference, + test_size, + t.font_render_mode, + t.allow_mipmaps, + ); + images.push(output.image); + results.push(output.results); + } + + self.wrench + .api + .send_debug_cmd( + DebugCommand::SetPictureTileSize(None) + ); + } + } + + let reference = match reference_image { + Some(image) => { + let save_all_png = false; // flip to true to update all the tests! + if save_all_png { + let img = images.last().unwrap(); + save_flipped(&t.reference, img.data.clone(), img.size); + } + image + } + None => { + let output = self.render_yaml( + &t.reference, + test_size, + t.font_render_mode, + t.allow_mipmaps, + ); + output.image + } + }; + + if t.disable_dual_source_blending { + self.wrench + .api + .send_debug_cmd( + DebugCommand::EnableDualSourceBlending(true) + ); + } + + for extra_check in t.extra_checks.iter() { + if !extra_check.run(&results) { + println!( + "REFTEST TEST-UNEXPECTED-FAIL | {} | Failing Check: {:?} | Actual Results: {:?}", + t, + extra_check, + results, + ); + println!("REFTEST TEST-END | {}", t); + return false; + } + } + + match t.op { + ReftestOp::Equal => { + // Ensure that the final image matches the reference + let test = images.pop().unwrap(); + let comparison = test.compare(&reference); + t.check_and_report_equality_failure( + comparison, + &test, + &reference, + ) + } + ReftestOp::NotEqual => { + // Ensure that the final image *doesn't* match the reference + let test = images.pop().unwrap(); + let comparison = test.compare(&reference); + match comparison { + ReftestImageComparison::Equal => { + t.report_unexpected_equality(); + false + } + ReftestImageComparison::NotEqual { .. } => { + true + } + } + } + ReftestOp::Accurate => { + // Ensure that *all* images match the reference + for test in images.drain(..) { + let comparison = test.compare(&reference); + + if !t.check_and_report_equality_failure( + comparison, + &test, + &reference, + ) { + return false; + } + } + + true + } + ReftestOp::Inaccurate => { + // Ensure that at least one of the images doesn't match the reference + let all_same = images.iter().all(|image| { + match image.compare(&reference) { + ReftestImageComparison::Equal => true, + ReftestImageComparison::NotEqual { .. } => false, + } + }); + + if all_same { + t.report_unexpected_equality(); + } + + !all_same + } + } + } + + fn load_image(&mut self, filename: &Path, format: ImageFormat) -> ReftestImage { + let file = BufReader::new(File::open(filename).unwrap()); + let img_raw = load_piston_image(file, format).unwrap(); + let img = img_raw.flipv().to_rgba(); + let size = img.dimensions(); + ReftestImage { + data: img.into_raw(), + size: DeviceIntSize::new(size.0 as i32, size.1 as i32), + } + } + + fn render_yaml( + &mut self, + filename: &Path, + size: DeviceIntSize, + font_render_mode: Option<FontRenderMode>, + allow_mipmaps: bool, + ) -> YamlRenderOutput { + let mut reader = YamlFrameReader::new(filename); + reader.set_font_render_mode(font_render_mode); + reader.allow_mipmaps(allow_mipmaps); + reader.do_frame(self.wrench); + + self.wrench.api.flush_scene_builder(); + + // wait for the frame + self.rx.recv().unwrap(); + let results = self.wrench.render(); + + let window_size = self.window.get_inner_size(); + assert!( + size.width <= window_size.width && + size.height <= window_size.height, + format!("size={:?} ws={:?}", size, window_size) + ); + + // taking the bottom left sub-rectangle + let rect = FramebufferIntRect::new( + FramebufferIntPoint::new(0, window_size.height - size.height), + FramebufferIntSize::new(size.width, size.height), + ); + let pixels = self.wrench.renderer.read_pixels_rgba8(rect); + self.window.swap_buffers(); + + let write_debug_images = false; + if write_debug_images { + let debug_path = filename.with_extension("yaml.png"); + save_flipped(debug_path, pixels.clone(), size); + } + + reader.deinit(self.wrench); + + YamlRenderOutput { + image: ReftestImage { data: pixels, size }, + results, + } + } +} diff --git a/gfx/wr/wrench/src/test_invalidation.rs b/gfx/wr/wrench/src/test_invalidation.rs new file mode 100644 index 0000000000..badcfae8cf --- /dev/null +++ b/gfx/wr/wrench/src/test_invalidation.rs @@ -0,0 +1,129 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +use crate::NotifierEvent; +use crate::WindowWrapper; +use std::path::PathBuf; +use std::sync::mpsc::Receiver; +use crate::wrench::{Wrench, WrenchThing}; +use crate::yaml_frame_reader::YamlFrameReader; +use webrender::{PictureCacheDebugInfo, TileDebugInfo}; +use webrender::api::units::*; + +pub struct TestHarness<'a> { + wrench: &'a mut Wrench, + window: &'a mut WindowWrapper, + rx: Receiver<NotifierEvent>, +} + +struct RenderResult { + pc_debug: PictureCacheDebugInfo, + composite_needed: bool, +} + +// Convenience method to build a picture rect +fn pr(x: f32, y: f32, w: f32, h: f32) -> PictureRect { + PictureRect::new( + PicturePoint::new(x, y), + PictureSize::new(w, h), + ) +} + +impl<'a> TestHarness<'a> { + pub fn new( + wrench: &'a mut Wrench, + window: &'a mut WindowWrapper, + rx: Receiver<NotifierEvent> + ) -> Self { + TestHarness { + wrench, + window, + rx, + } + } + + /// Main entry point for invalidation tests + pub fn run( + mut self, + ) { + // List all invalidation tests here + self.test_basic(); + self.test_composite_nop(); + } + + /// Simple validation / proof of concept of invalidation testing + fn test_basic( + &mut self, + ) { + // Render basic.yaml, ensure that the valid/dirty rects are as expected + let results = self.render_yaml("basic"); + let tile_info = results.pc_debug.slice(0).tile(0, 0).as_dirty(); + assert_eq!( + tile_info.local_valid_rect, + pr(100.0, 100.0, 500.0, 100.0), + ); + assert_eq!( + tile_info.local_dirty_rect, + pr(100.0, 100.0, 500.0, 100.0), + ); + + // Render it again and ensure the tile was considered valid (no rasterization was done) + let results = self.render_yaml("basic"); + assert_eq!(*results.pc_debug.slice(0).tile(0, 0), TileDebugInfo::Valid); + } + + /// Ensure WR detects composites are needed for position changes within a single tile. + fn test_composite_nop( + &mut self, + ) { + // Render composite_nop_1.yaml, ensure that the valid/dirty rects are as expected + let results = self.render_yaml("composite_nop_1"); + let tile_info = results.pc_debug.slice(0).tile(0, 0).as_dirty(); + assert_eq!( + tile_info.local_valid_rect, + pr(100.0, 100.0, 100.0, 100.0), + ); + assert_eq!( + tile_info.local_dirty_rect, + pr(100.0, 100.0, 100.0, 100.0), + ); + + // Render composite_nop_2.yaml, ensure that the valid/dirty rects are as expected + let results = self.render_yaml("composite_nop_2"); + let tile_info = results.pc_debug.slice(0).tile(0, 0).as_dirty(); + assert_eq!( + tile_info.local_valid_rect, + pr(100.0, 120.0, 100.0, 100.0), + ); + assert_eq!( + tile_info.local_dirty_rect, + pr(100.0, 120.0, 100.0, 100.0), + ); + + // Main part of this test - ensure WR detects a composite is required in this case + assert!(results.composite_needed); + } + + /// Render a YAML file, and return the picture cache debug info + fn render_yaml( + &mut self, + filename: &str, + ) -> RenderResult { + let path = format!("invalidation/{}.yaml", filename); + let mut reader = YamlFrameReader::new(&PathBuf::from(path)); + + reader.do_frame(self.wrench); + let composite_needed = match self.rx.recv().unwrap() { + NotifierEvent::WakeUp { composite_needed } => composite_needed, + NotifierEvent::ShutDown => unreachable!(), + }; + let results = self.wrench.render(); + self.window.swap_buffers(); + + RenderResult { + pc_debug: results.picture_cache_debug, + composite_needed, + } + } +} diff --git a/gfx/wr/wrench/src/wrench.rs b/gfx/wr/wrench/src/wrench.rs new file mode 100644 index 0000000000..058aefbca3 --- /dev/null +++ b/gfx/wr/wrench/src/wrench.rs @@ -0,0 +1,682 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + + +use crate::blob; +use crossbeam::sync::chase_lev; +#[cfg(windows)] +use dwrote; +#[cfg(all(unix, not(target_os = "android")))] +use font_loader::system_fonts; +use winit::EventsLoopProxy; +use std::collections::HashMap; +use std::path::PathBuf; +use std::sync::{Arc, Mutex}; +use std::sync::mpsc::Receiver; +use time; +use webrender; +use webrender::api::*; +use webrender::render_api::*; +use webrender::api::units::*; +use webrender::{DebugFlags, RenderResults, ShaderPrecacheFlags}; +use crate::{WindowWrapper, NotifierEvent}; + +// TODO(gw): This descriptor matches what we currently support for fonts +// but is quite a mess. We should at least document and +// use better types for things like the style and stretch. +#[derive(Debug, Clone, Hash, PartialEq, Eq)] +pub enum FontDescriptor { + Path { path: PathBuf, font_index: u32 }, + Family { name: String }, + Properties { + family: String, + weight: u32, + style: u32, + stretch: u32, + }, +} + +struct NotifierData { + events_loop_proxy: Option<EventsLoopProxy>, + frames_notified: u32, + timing_receiver: chase_lev::Stealer<time::SteadyTime>, + verbose: bool, +} + +impl NotifierData { + fn new( + events_loop_proxy: Option<EventsLoopProxy>, + timing_receiver: chase_lev::Stealer<time::SteadyTime>, + verbose: bool, + ) -> Self { + NotifierData { + events_loop_proxy, + frames_notified: 0, + timing_receiver, + verbose, + } + } +} + +struct Notifier(Arc<Mutex<NotifierData>>); + +impl Notifier { + fn update(&self, check_document: bool) { + let mut data = self.0.lock(); + let data = data.as_mut().unwrap(); + if check_document { + match data.timing_receiver.steal() { + chase_lev::Steal::Data(last_timing) => { + data.frames_notified += 1; + if data.verbose && data.frames_notified == 600 { + let elapsed = time::SteadyTime::now() - last_timing; + println!( + "frame latency (consider queue depth here): {:3.6} ms", + elapsed.num_microseconds().unwrap() as f64 / 1000. + ); + data.frames_notified = 0; + } + } + _ => { + println!("Notified of frame, but no frame was ready?"); + } + } + } + + if let Some(ref _elp) = data.events_loop_proxy { + #[cfg(not(target_os = "android"))] + let _ = _elp.wakeup(); + } + } +} + +impl RenderNotifier for Notifier { + fn clone(&self) -> Box<dyn RenderNotifier> { + Box::new(Notifier(self.0.clone())) + } + + fn wake_up(&self, _composite_needed: bool) { + self.update(false); + } + + fn new_frame_ready(&self, _: DocumentId, + scrolled: bool, + _composite_needed: bool, + _render_time: Option<u64>) { + self.update(!scrolled); + } +} + +pub trait WrenchThing { + fn next_frame(&mut self); + fn prev_frame(&mut self); + fn do_frame(&mut self, _: &mut Wrench) -> u32; +} + +impl WrenchThing for CapturedDocument { + fn next_frame(&mut self) {} + fn prev_frame(&mut self) {} + fn do_frame(&mut self, wrench: &mut Wrench) -> u32 { + match self.root_pipeline_id.take() { + Some(root_pipeline_id) => { + // skip the first frame - to not overwrite the loaded one + let mut txn = Transaction::new(); + txn.set_root_pipeline(root_pipeline_id); + wrench.api.send_transaction(self.document_id, txn); + } + None => { + wrench.refresh(); + } + } + 0 + } +} + +pub struct CapturedSequence { + root: PathBuf, + frame: usize, + frame_set: Vec<(u32, u32)>, +} + +impl CapturedSequence { + pub fn new(root: PathBuf, scene_start: u32, frame_start: u32) -> Self { + // Build set of a scene and frame IDs. + let mut scene = scene_start; + let mut frame = frame_start; + let mut frame_set = Vec::new(); + while Self::scene_root(&root, scene).as_path().is_dir() { + while Self::frame_root(&root, scene, frame).as_path().is_dir() { + frame_set.push((scene, frame)); + frame += 1; + } + scene += 1; + frame = 1; + } + + assert!(!frame_set.is_empty()); + + Self { + root, + frame: 0, + frame_set, + } + } + + fn scene_root(root: &PathBuf, scene: u32) -> PathBuf { + let path = format!("scenes/{:05}", scene); + root.join(path) + } + + fn frame_root(root: &PathBuf, scene: u32, frame: u32) -> PathBuf { + let path = format!("scenes/{:05}/frames/{:05}", scene, frame); + root.join(path) + } +} + +impl WrenchThing for CapturedSequence { + fn next_frame(&mut self) { + if self.frame + 1 < self.frame_set.len() { + self.frame += 1; + } + } + + fn prev_frame(&mut self) { + if self.frame > 0 { + self.frame -= 1; + } + } + + fn do_frame(&mut self, wrench: &mut Wrench) -> u32 { + let mut documents = wrench.api.load_capture(self.root.clone(), Some(self.frame_set[self.frame])); + println!("loaded {:?} from {:?}", + documents.iter().map(|cd| cd.document_id).collect::<Vec<_>>(), + self.frame_set[self.frame]); + let captured = documents.swap_remove(0); + wrench.document_id = captured.document_id; + self.frame as u32 + } +} + +pub struct Wrench { + window_size: DeviceIntSize, + pub device_pixel_ratio: f32, + page_zoom_factor: ZoomFactor, + + pub renderer: webrender::Renderer, + pub api: RenderApi, + pub document_id: DocumentId, + pub root_pipeline_id: PipelineId, + + window_title_to_set: Option<String>, + + graphics_api: webrender::GraphicsApiInfo, + + pub rebuild_display_lists: bool, + pub verbose: bool, + + pub frame_start_sender: chase_lev::Worker<time::SteadyTime>, + + pub callbacks: Arc<Mutex<blob::BlobCallbacks>>, +} + +impl Wrench { + pub fn new( + window: &mut WindowWrapper, + proxy: Option<EventsLoopProxy>, + shader_override_path: Option<PathBuf>, + use_optimized_shaders: bool, + dp_ratio: f32, + size: DeviceIntSize, + do_rebuild: bool, + no_subpixel_aa: bool, + verbose: bool, + no_scissor: bool, + no_batch: bool, + precache_shaders: bool, + disable_dual_source_blending: bool, + zoom_factor: f32, + chase_primitive: webrender::ChasePrimitive, + dump_shader_source: Option<String>, + notifier: Option<Box<dyn RenderNotifier>>, + ) -> Self { + println!("Shader override path: {:?}", shader_override_path); + + let mut debug_flags = DebugFlags::ECHO_DRIVER_MESSAGES; + debug_flags.set(DebugFlags::DISABLE_BATCHING, no_batch); + let callbacks = Arc::new(Mutex::new(blob::BlobCallbacks::new())); + + let precache_flags = if precache_shaders { + ShaderPrecacheFlags::FULL_COMPILE + } else { + ShaderPrecacheFlags::empty() + }; + + let opts = webrender::RendererOptions { + device_pixel_ratio: dp_ratio, + resource_override_path: shader_override_path, + use_optimized_shaders, + enable_subpixel_aa: !no_subpixel_aa, + debug_flags, + enable_clear_scissor: !no_scissor, + max_recorded_profiles: 16, + precache_flags, + blob_image_handler: Some(Box::new(blob::CheckerboardRenderer::new(callbacks.clone()))), + chase_primitive, + testing: true, + max_texture_size: Some(8196), // Needed for rawtest::test_resize_image. + allow_dual_source_blending: !disable_dual_source_blending, + allow_advanced_blend_equation: true, + dump_shader_source, + // SWGL doesn't support the GL_ALWAYS depth comparison function used by + // `clear_caches_with_quads`, but scissored clears work well. + clear_caches_with_quads: !window.is_software(), + ..Default::default() + }; + + // put an Awakened event into the queue to kick off the first frame + if let Some(ref _elp) = proxy { + #[cfg(not(target_os = "android"))] + let _ = _elp.wakeup(); + } + + let (timing_sender, timing_receiver) = chase_lev::deque(); + let notifier = notifier.unwrap_or_else(|| { + let data = Arc::new(Mutex::new(NotifierData::new(proxy, timing_receiver, verbose))); + Box::new(Notifier(data)) + }); + + let (renderer, sender) = webrender::Renderer::new( + window.clone_gl(), + notifier, + opts, + None, + ).unwrap(); + + let api = sender.create_api(); + let document_id = api.add_document(size); + + let graphics_api = renderer.get_graphics_api_info(); + let zoom_factor = ZoomFactor::new(zoom_factor); + + let mut wrench = Wrench { + window_size: size, + + renderer, + api, + document_id, + window_title_to_set: None, + + rebuild_display_lists: do_rebuild, + verbose, + device_pixel_ratio: dp_ratio, + page_zoom_factor: ZoomFactor::new(0.0), + + root_pipeline_id: PipelineId(0, 0), + + graphics_api, + frame_start_sender: timing_sender, + + callbacks, + }; + + wrench.set_page_zoom(zoom_factor); + wrench.set_title("start"); + let mut txn = Transaction::new(); + txn.set_root_pipeline(wrench.root_pipeline_id); + wrench.api.send_transaction(wrench.document_id, txn); + + wrench + } + + pub fn set_quality_settings(&mut self, settings: QualitySettings) { + let mut txn = Transaction::new(); + txn.set_quality_settings(settings); + self.api.send_transaction(self.document_id, txn); + } + + pub fn get_page_zoom(&self) -> ZoomFactor { + self.page_zoom_factor + } + + pub fn set_page_zoom(&mut self, zoom_factor: ZoomFactor) { + if self.page_zoom_factor.get() != zoom_factor.get() { + self.page_zoom_factor = zoom_factor; + let mut txn = Transaction::new(); + txn.set_page_zoom(self.page_zoom_factor); + self.api.send_transaction(self.document_id, txn); + self.set_title(""); + } + } + + pub fn layout_simple_ascii( + &mut self, + font_key: FontKey, + instance_key: FontInstanceKey, + text: &str, + size: f32, + origin: LayoutPoint, + flags: FontInstanceFlags, + ) -> (Vec<u32>, Vec<LayoutPoint>, LayoutRect) { + // Map the string codepoints to glyph indices in this font. + // Just drop any glyph that isn't present in this font. + let indices: Vec<u32> = self.api + .get_glyph_indices(font_key, text) + .iter() + .filter_map(|idx| *idx) + .collect(); + + // Retrieve the metrics for each glyph. + let metrics = self.api.get_glyph_dimensions(instance_key, indices.clone()); + + let mut bounding_rect = LayoutRect::zero(); + let mut positions = Vec::new(); + + let mut cursor = origin; + let direction = if flags.contains(FontInstanceFlags::TRANSPOSE) { + LayoutVector2D::new( + 0.0, + if flags.contains(FontInstanceFlags::FLIP_Y) { -1.0 } else { 1.0 }, + ) + } else { + LayoutVector2D::new( + if flags.contains(FontInstanceFlags::FLIP_X) { -1.0 } else { 1.0 }, + 0.0, + ) + }; + for metric in metrics { + positions.push(cursor); + + match metric { + Some(metric) => { + let glyph_rect = LayoutRect::new( + LayoutPoint::new(cursor.x + metric.left as f32, cursor.y - metric.top as f32), + LayoutSize::new(metric.width as f32, metric.height as f32) + ); + bounding_rect = bounding_rect.union(&glyph_rect); + cursor += direction * metric.advance; + } + None => { + // Extract the advances from the metrics. The get_glyph_dimensions API + // has a limitation that it can't currently get dimensions for non-renderable + // glyphs (e.g. spaces), so just use a rough estimate in that case. + let space_advance = size / 3.0; + cursor += direction * space_advance; + } + } + } + + // The platform font implementations don't always handle + // the exact dimensions used when subpixel AA is enabled + // on glyphs. As a workaround, inflate the bounds by + // 2 pixels on either side, to give a slightly less + // tight fitting bounding rect. + let bounding_rect = bounding_rect.inflate(2.0, 2.0); + + (indices, positions, bounding_rect) + } + + pub fn set_title(&mut self, extra: &str) { + self.window_title_to_set = Some(format!( + "Wrench: {} ({}x zoom={}) - {} - {}", + extra, + self.device_pixel_ratio, + self.page_zoom_factor.get(), + self.graphics_api.renderer, + self.graphics_api.version + )); + } + + pub fn take_title(&mut self) -> Option<String> { + self.window_title_to_set.take() + } + + pub fn should_rebuild_display_lists(&self) -> bool { + self.rebuild_display_lists + } + + pub fn window_size_f32(&self) -> LayoutSize { + LayoutSize::new( + self.window_size.width as f32, + self.window_size.height as f32, + ) + } + + #[cfg(target_os = "windows")] + pub fn font_key_from_native_handle(&mut self, descriptor: &NativeFontHandle) -> FontKey { + let key = self.api.generate_font_key(); + let mut txn = Transaction::new(); + txn.add_native_font(key, descriptor.clone()); + self.api.send_transaction(self.document_id, txn); + key + } + + #[cfg(target_os = "windows")] + pub fn font_key_from_name(&mut self, font_name: &str) -> FontKey { + self.font_key_from_properties( + font_name, + dwrote::FontWeight::Regular.to_u32(), + dwrote::FontStyle::Normal.to_u32(), + dwrote::FontStretch::Normal.to_u32(), + ) + } + + #[cfg(target_os = "windows")] + pub fn font_key_from_properties( + &mut self, + family: &str, + weight: u32, + style: u32, + stretch: u32, + ) -> FontKey { + let weight = dwrote::FontWeight::from_u32(weight); + let style = dwrote::FontStyle::from_u32(style); + let stretch = dwrote::FontStretch::from_u32(stretch); + let desc = dwrote::FontDescriptor { + family_name: family.to_owned(), + weight, + style, + stretch, + }; + let system_fc = dwrote::FontCollection::system(); + if let Some(font) = system_fc.get_font_from_descriptor(&desc) { + let face = font.create_font_face(); + let files = face.get_files(); + if files.len() == 1 { + if let Some(path) = files[0].get_font_file_path() { + return self.font_key_from_native_handle(&NativeFontHandle { + path, + index: face.get_index(), + }); + } + } + } + panic!("failed loading font from properties {:?}", desc) + } + + #[cfg(all(unix, not(target_os = "android")))] + pub fn font_key_from_properties( + &mut self, + family: &str, + _weight: u32, + _style: u32, + _stretch: u32, + ) -> FontKey { + let property = system_fonts::FontPropertyBuilder::new() + .family(family) + .build(); + let (font, index) = system_fonts::get(&property).unwrap(); + self.font_key_from_bytes(font, index as u32) + } + + #[cfg(target_os = "android")] + pub fn font_key_from_properties( + &mut self, + _family: &str, + _weight: u32, + _style: u32, + _stretch: u32, + ) -> FontKey { + unimplemented!() + } + + #[cfg(all(unix, not(target_os = "android")))] + pub fn font_key_from_name(&mut self, font_name: &str) -> FontKey { + let property = system_fonts::FontPropertyBuilder::new() + .family(font_name) + .build(); + let (font, index) = system_fonts::get(&property).unwrap(); + self.font_key_from_bytes(font, index as u32) + } + + #[cfg(target_os = "android")] + pub fn font_key_from_name(&mut self, _font_name: &str) -> FontKey { + unimplemented!() + } + + pub fn font_key_from_bytes(&mut self, bytes: Vec<u8>, index: u32) -> FontKey { + let key = self.api.generate_font_key(); + let mut txn = Transaction::new(); + txn.add_raw_font(key, bytes, index); + self.api.send_transaction(self.document_id, txn); + key + } + + pub fn add_font_instance(&mut self, + font_key: FontKey, + size: f32, + flags: FontInstanceFlags, + render_mode: Option<FontRenderMode>, + bg_color: Option<ColorU>, + synthetic_italics: SyntheticItalics, + ) -> FontInstanceKey { + let key = self.api.generate_font_instance_key(); + let mut txn = Transaction::new(); + let mut options: FontInstanceOptions = Default::default(); + options.flags |= flags; + if let Some(render_mode) = render_mode { + options.render_mode = render_mode; + } + if let Some(bg_color) = bg_color { + options.bg_color = bg_color; + } + options.synthetic_italics = synthetic_italics; + txn.add_font_instance(key, font_key, size, Some(options), None, Vec::new()); + self.api.send_transaction(self.document_id, txn); + key + } + + #[allow(dead_code)] + pub fn delete_font_instance(&mut self, key: FontInstanceKey) { + let mut txn = Transaction::new(); + txn.delete_font_instance(key); + self.api.send_transaction(self.document_id, txn); + } + + pub fn update(&mut self, dim: DeviceIntSize) { + if dim != self.window_size { + self.window_size = dim; + } + } + + pub fn begin_frame(&mut self) { + self.frame_start_sender.push(time::SteadyTime::now()); + } + + pub fn send_lists( + &mut self, + frame_number: u32, + display_lists: Vec<(PipelineId, BuiltDisplayList)>, + scroll_offsets: &HashMap<ExternalScrollId, LayoutPoint>, + ) { + let root_background_color = Some(ColorF::new(1.0, 1.0, 1.0, 1.0)); + + let mut txn = Transaction::new(); + for display_list in display_lists { + txn.set_display_list( + Epoch(frame_number), + root_background_color, + self.window_size_f32(), + display_list, + false, + ); + } + + for (id, offset) in scroll_offsets { + txn.scroll_node_with_id(*offset, *id, ScrollClamping::NoClamping); + } + + txn.generate_frame(0); + self.api.send_transaction(self.document_id, txn); + } + + pub fn get_frame_profiles( + &mut self, + ) -> (Vec<webrender::CpuProfile>, Vec<webrender::GpuProfile>) { + self.renderer.get_frame_profiles() + } + + pub fn render(&mut self) -> RenderResults { + self.renderer.update(); + let _ = self.renderer.flush_pipeline_info(); + self.renderer + .render(self.window_size, 0) + .expect("errors encountered during render!") + } + + pub fn refresh(&mut self) { + self.begin_frame(); + let mut txn = Transaction::new(); + txn.generate_frame(0); + self.api.send_transaction(self.document_id, txn); + } + + pub fn show_onscreen_help(&mut self) { + let help_lines = [ + "Esc - Quit", + "H - Toggle help", + "R - Toggle recreating display items each frame", + "P - Toggle profiler", + "O - Toggle showing intermediate targets", + "I - Toggle showing texture caches", + "B - Toggle showing alpha primitive rects", + "V - Toggle showing overdraw", + "G - Toggle showing gpu cache updates", + "S - Toggle compact profiler", + "Q - Toggle GPU queries for time and samples", + "M - Trigger memory pressure event", + "T - Save CPU profile to a file", + "C - Save a capture to captures/wrench/", + "X - Do a hit test at the current cursor position", + "Y - Clear all caches", + ]; + + let color_and_offset = [(ColorF::BLACK, 2.0), (ColorF::WHITE, 0.0)]; + self.renderer.device.begin_frame(); // next line might compile shaders: + let dr = self.renderer.debug_renderer().unwrap(); + + for ref co in &color_and_offset { + let x = self.device_pixel_ratio * (15.0 + co.1); + let mut y = self.device_pixel_ratio * (15.0 + co.1 + dr.line_height()); + for ref line in &help_lines { + dr.add_text(x, y, line, co.0.into(), None); + y += self.device_pixel_ratio * dr.line_height(); + } + } + self.renderer.device.end_frame(); + } + + pub fn shut_down(self, rx: Receiver<NotifierEvent>) { + self.api.shut_down(true); + + loop { + match rx.recv() { + Ok(NotifierEvent::ShutDown) => { break; } + Ok(_) => {} + Err(e) => { panic!("Did not shut down properly: {:?}.", e); } + } + } + + self.renderer.deinit(); + } +} diff --git a/gfx/wr/wrench/src/yaml_frame_reader.rs b/gfx/wr/wrench/src/yaml_frame_reader.rs new file mode 100644 index 0000000000..2b8034a3ee --- /dev/null +++ b/gfx/wr/wrench/src/yaml_frame_reader.rs @@ -0,0 +1,2245 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +use clap; +use euclid::SideOffsets2D; +use gleam::gl; +use image; +use image::GenericImageView; +use crate::parse_function::parse_function; +use crate::premultiply::premultiply; +use std::collections::HashMap; +use std::fs::File; +use std::io::Read; +use std::path::{Path, PathBuf}; +use std::usize; +use webrender::api::*; +use webrender::render_api::*; +use webrender::api::units::*; +use crate::wrench::{FontDescriptor, Wrench, WrenchThing}; +use crate::yaml_helper::{StringEnum, YamlHelper, make_perspective}; +use yaml_rust::{Yaml, YamlLoader}; +use crate::PLATFORM_DEFAULT_FACE_NAME; + +macro_rules! try_intersect { + ($first: expr, $second: expr) => { + if let Some(rect) = ($first).intersection($second) { + rect + } else { + warn!("skipping item with non-intersecting bounds and clip_rect"); + return; + }; + } +} + +fn rsrc_path(item: &Yaml, aux_dir: &PathBuf) -> PathBuf { + let filename = item.as_str().unwrap(); + let mut file = aux_dir.clone(); + file.push(filename); + file +} + +impl FontDescriptor { + fn from_yaml(item: &Yaml, aux_dir: &PathBuf) -> FontDescriptor { + if !item["family"].is_badvalue() { + FontDescriptor::Properties { + family: item["family"].as_str().unwrap().to_owned(), + weight: item["weight"].as_i64().unwrap_or(400) as u32, + style: item["style"].as_i64().unwrap_or(0) as u32, + stretch: item["stretch"].as_i64().unwrap_or(5) as u32, + } + } else if !item["font"].is_badvalue() { + let path = rsrc_path(&item["font"], aux_dir); + FontDescriptor::Path { + path, + font_index: item["font-index"].as_i64().unwrap_or(0) as u32, + } + } else { + FontDescriptor::Family { + name: PLATFORM_DEFAULT_FACE_NAME.to_string(), + } + } + } +} + +struct LocalExternalImageHandler { + texture_ids: Vec<(gl::GLuint, ImageDescriptor)>, +} + +impl LocalExternalImageHandler { + pub fn new() -> LocalExternalImageHandler { + LocalExternalImageHandler { + texture_ids: Vec::new(), + } + } + + fn init_gl_texture( + id: gl::GLuint, + gl_target: gl::GLuint, + format_desc: webrender::FormatDesc, + width: gl::GLint, + height: gl::GLint, + bytes: &[u8], + gl: &dyn gl::Gl, + ) { + gl.bind_texture(gl_target, id); + gl.tex_parameter_i(gl_target, gl::TEXTURE_MAG_FILTER, gl::LINEAR as gl::GLint); + gl.tex_parameter_i(gl_target, gl::TEXTURE_MIN_FILTER, gl::LINEAR as gl::GLint); + gl.tex_parameter_i(gl_target, gl::TEXTURE_WRAP_S, gl::CLAMP_TO_EDGE as gl::GLint); + gl.tex_parameter_i(gl_target, gl::TEXTURE_WRAP_T, gl::CLAMP_TO_EDGE as gl::GLint); + gl.tex_image_2d( + gl_target, + 0, + format_desc.internal as gl::GLint, + width, + height, + 0, + format_desc.external, + format_desc.pixel_type, + Some(bytes), + ); + gl.bind_texture(gl_target, 0); + } + + pub fn add_image(&mut self, + device: &webrender::Device, + desc: ImageDescriptor, + target: ImageBufferKind, + image_data: ImageData, + ) -> ImageData { + let (image_id, channel_idx) = match image_data { + ImageData::Raw(ref data) => { + let gl = device.gl(); + let texture_ids = gl.gen_textures(1); + let format_desc = if desc.format == ImageFormat::BGRA8 { + // Force BGRA8 data to RGBA8 layout to avoid potential + // need for usage of texture-swizzle. + webrender::FormatDesc { + external: gl::BGRA, + .. device.gl_describe_format(ImageFormat::RGBA8) + } + } else { + device.gl_describe_format(desc.format) + }; + + LocalExternalImageHandler::init_gl_texture( + texture_ids[0], + webrender::get_gl_target(target), + format_desc, + desc.size.width as gl::GLint, + desc.size.height as gl::GLint, + &data, + gl, + ); + self.texture_ids.push((texture_ids[0], desc)); + (ExternalImageId((self.texture_ids.len() - 1) as u64), 0) + }, + _ => panic!("unsupported!"), + }; + + ImageData::External( + ExternalImageData { + id: image_id, + channel_index: channel_idx, + image_type: ExternalImageType::TextureHandle(target) + } + ) + } +} + +impl ExternalImageHandler for LocalExternalImageHandler { + fn lock( + &mut self, + key: ExternalImageId, + _channel_index: u8, + _rendering: ImageRendering, + ) -> ExternalImage { + let (id, desc) = self.texture_ids[key.0 as usize]; + ExternalImage { + uv: TexelRect::new(0.0, 0.0, desc.size.width as f32, desc.size.height as f32), + source: ExternalImageSource::NativeTexture(id), + } + } + fn unlock(&mut self, _key: ExternalImageId, _channel_index: u8) {} +} + +fn broadcast<T: Clone>(base_vals: &[T], num_items: usize) -> Vec<T> { + if base_vals.len() == num_items { + return base_vals.to_vec(); + } + + assert_eq!( + num_items % base_vals.len(), + 0, + "Cannot broadcast {} elements into {}", + base_vals.len(), + num_items + ); + + let mut vals = vec![]; + loop { + if vals.len() == num_items { + break; + } + vals.extend_from_slice(base_vals); + } + vals +} + +enum CheckerboardKind { + BlackGrey, + BlackTransparent, +} + +fn generate_checkerboard_image( + border: u32, + tile_x_size: u32, + tile_y_size: u32, + tile_x_count: u32, + tile_y_count: u32, + kind: CheckerboardKind, +) -> (ImageDescriptor, ImageData) { + let width = 2 * border + tile_x_size * tile_x_count; + let height = 2 * border + tile_y_size * tile_y_count; + let mut pixels = Vec::new(); + + for y in 0 .. height { + for x in 0 .. width { + if y < border || y >= (height - border) || + x < border || x >= (width - border) { + pixels.push(0); + pixels.push(0); + pixels.push(0xff); + pixels.push(0xff); + } else { + let xon = ((x - border) % (2 * tile_x_size)) < tile_x_size; + let yon = ((y - border) % (2 * tile_y_size)) < tile_y_size; + match kind { + CheckerboardKind::BlackGrey => { + let value = if xon ^ yon { 0xff } else { 0x7f }; + pixels.push(value); + pixels.push(value); + pixels.push(value); + pixels.push(0xff); + } + CheckerboardKind::BlackTransparent => { + let value = if xon ^ yon { 0xff } else { 0x00 }; + pixels.push(value); + pixels.push(value); + pixels.push(value); + pixels.push(value); + } + } + } + } + } + + ( + ImageDescriptor::new(width as i32, height as i32, ImageFormat::BGRA8, ImageDescriptorFlags::IS_OPAQUE), + ImageData::new(pixels), + ) +} + +fn generate_xy_gradient_image(w: u32, h: u32) -> (ImageDescriptor, ImageData) { + let mut pixels = Vec::with_capacity((w * h * 4) as usize); + for y in 0 .. h { + for x in 0 .. w { + let grid = if x % 100 < 3 || y % 100 < 3 { 0.9 } else { 1.0 }; + pixels.push((y as f32 / h as f32 * 255.0 * grid) as u8); + pixels.push(0); + pixels.push((x as f32 / w as f32 * 255.0 * grid) as u8); + pixels.push(255); + } + } + + ( + ImageDescriptor::new(w as i32, h as i32, ImageFormat::BGRA8, ImageDescriptorFlags::IS_OPAQUE), + ImageData::new(pixels), + ) +} + +fn generate_solid_color_image( + r: u8, + g: u8, + b: u8, + a: u8, + w: u32, + h: u32, +) -> (ImageDescriptor, ImageData) { + let buf_size = (w * h * 4) as usize; + let mut pixels = Vec::with_capacity(buf_size); + // Unsafely filling the buffer is horrible. Unfortunately doing this idiomatically + // is terribly slow in debug builds to the point that reftests/image/very-big.yaml + // takes more than 20 seconds to run on a recent laptop. + unsafe { + pixels.set_len(buf_size); + let color: u32 = ::std::mem::transmute([b, g, r, a]); + let mut ptr: *mut u32 = ::std::mem::transmute(&mut pixels[0]); + let end = ptr.offset((w * h) as isize); + while ptr < end { + *ptr = color; + ptr = ptr.offset(1); + } + } + + let mut flags = ImageDescriptorFlags::empty(); + if a == 255 { + flags |= ImageDescriptorFlags::IS_OPAQUE; + } + + ( + ImageDescriptor::new(w as i32, h as i32, ImageFormat::BGRA8, flags), + ImageData::new(pixels), + ) +} + + + +fn is_image_opaque(format: ImageFormat, bytes: &[u8]) -> bool { + match format { + ImageFormat::BGRA8 | + ImageFormat::RGBA8 => { + let mut is_opaque = true; + for i in 0 .. (bytes.len() / 4) { + if bytes[i * 4 + 3] != 255 { + is_opaque = false; + break; + } + } + is_opaque + } + ImageFormat::RG8 => true, + ImageFormat::RG16 => true, + ImageFormat::R8 => false, + ImageFormat::R16 => false, + ImageFormat::RGBAF32 | + ImageFormat::RGBAI32 => unreachable!(), + } +} + +pub struct YamlFrameReader { + yaml_path: PathBuf, + aux_dir: PathBuf, + frame_count: u32, + + display_lists: Vec<(PipelineId, BuiltDisplayList)>, + + include_only: Vec<String>, + + watch_source: bool, + list_resources: bool, + + /// A HashMap of offsets which specify what scroll offsets particular + /// scroll layers should be initialized with. + scroll_offsets: HashMap<ExternalScrollId, LayoutPoint>, + next_external_scroll_id: u64, + + image_map: HashMap<(PathBuf, Option<i64>), (ImageKey, LayoutSize)>, + + fonts: HashMap<FontDescriptor, FontKey>, + font_instances: HashMap<(FontKey, FontSize, FontInstanceFlags, Option<ColorU>, SyntheticItalics), FontInstanceKey>, + font_render_mode: Option<FontRenderMode>, + allow_mipmaps: bool, + + /// A HashMap that allows specifying a numeric id for clip and clip chains in YAML + /// and having each of those ids correspond to a unique ClipId. + user_clip_id_map: HashMap<u64, ClipId>, + user_spatial_id_map: HashMap<u64, SpatialId>, + + clip_id_stack: Vec<ClipId>, + spatial_id_stack: Vec<SpatialId>, + + requested_frame: usize, + built_frame: usize, + + yaml_string: String, + keyframes: Option<Yaml>, + + external_image_handler: Option<Box<LocalExternalImageHandler>>, +} + +impl YamlFrameReader { + pub fn new(yaml_path: &Path) -> YamlFrameReader { + YamlFrameReader { + watch_source: false, + list_resources: false, + yaml_path: yaml_path.to_owned(), + aux_dir: yaml_path.parent().unwrap().to_owned(), + frame_count: 0, + display_lists: Vec::new(), + include_only: vec![], + scroll_offsets: HashMap::new(), + fonts: HashMap::new(), + font_instances: HashMap::new(), + font_render_mode: None, + allow_mipmaps: false, + image_map: HashMap::new(), + user_clip_id_map: HashMap::new(), + user_spatial_id_map: HashMap::new(), + clip_id_stack: Vec::new(), + spatial_id_stack: Vec::new(), + yaml_string: String::new(), + requested_frame: 0, + built_frame: usize::MAX, + keyframes: None, + external_image_handler: Some(Box::new(LocalExternalImageHandler::new())), + next_external_scroll_id: 1000, // arbitrary to easily see in logs which are implicit + } + } + + pub fn deinit(mut self, wrench: &mut Wrench) { + let mut txn = Transaction::new(); + + for (_, font_instance) in self.font_instances.drain() { + txn.delete_font_instance(font_instance); + } + + for (_, font) in self.fonts.drain() { + txn.delete_font(font); + } + + wrench.api.send_transaction(wrench.document_id, txn); + } + + fn top_space_and_clip(&self) -> SpaceAndClipInfo { + SpaceAndClipInfo { + spatial_id: *self.spatial_id_stack.last().unwrap(), + clip_id: *self.clip_id_stack.last().unwrap(), + } + } + + pub fn yaml_path(&self) -> &PathBuf { + &self.yaml_path + } + + pub fn new_from_args(args: &clap::ArgMatches) -> YamlFrameReader { + let yaml_file = args.value_of("INPUT").map(|s| PathBuf::from(s)).unwrap(); + + let mut y = YamlFrameReader::new(&yaml_file); + + y.keyframes = args.value_of("keyframes").map(|path| { + let mut file = File::open(&path).unwrap(); + let mut keyframes_string = String::new(); + file.read_to_string(&mut keyframes_string).unwrap(); + YamlLoader::load_from_str(&keyframes_string) + .expect("Failed to parse keyframes file") + .pop() + .unwrap() + }); + y.list_resources = args.is_present("list-resources"); + y.watch_source = args.is_present("watch"); + y.include_only = args.values_of("include") + .map(|v| v.map(|s| s.to_owned()).collect()) + .unwrap_or(vec![]); + y + } + + pub fn reset(&mut self) { + self.scroll_offsets.clear(); + self.display_lists.clear(); + } + + fn build(&mut self, wrench: &mut Wrench) { + let mut yaml_doc = YamlLoader::load_from_str(&self.yaml_string) + .expect("Failed to parse YAML file"); + assert_eq!(yaml_doc.len(), 1); + + self.reset(); + + let yaml = yaml_doc.pop().unwrap(); + if let Some(pipelines) = yaml["pipelines"].as_vec() { + for pipeline in pipelines { + self.build_pipeline(wrench, pipeline["id"].as_pipeline_id().unwrap(), pipeline); + } + } + + assert!(!yaml["root"].is_badvalue(), "Missing root stacking context"); + let root_pipeline_id = wrench.root_pipeline_id; + self.build_pipeline(wrench, root_pipeline_id, &yaml["root"]); + + // If replaying the same frame during interactive use, the frame gets rebuilt, + // but the external image handler has already been consumed by the renderer. + if let Some(external_image_handler) = self.external_image_handler.take() { + wrench.renderer.set_external_image_handler(external_image_handler); + } + } + + fn build_pipeline( + &mut self, + wrench: &mut Wrench, + pipeline_id: PipelineId, + yaml: &Yaml + ) { + // Don't allow referencing clips between pipelines for now. + self.user_clip_id_map.clear(); + self.user_spatial_id_map.clear(); + self.clip_id_stack.clear(); + self.clip_id_stack.push(ClipId::root(pipeline_id)); + self.spatial_id_stack.clear(); + self.spatial_id_stack.push(SpatialId::root_scroll_node(pipeline_id)); + + let mut builder = DisplayListBuilder::new(pipeline_id); + let mut info = CommonItemProperties { + clip_rect: LayoutRect::zero(), + clip_id: ClipId::invalid(), + spatial_id: SpatialId::new(0, PipelineId::dummy()), + flags: PrimitiveFlags::default(), + }; + self.add_stacking_context_from_yaml(&mut builder, wrench, yaml, true, &mut info); + self.display_lists.push(builder.finalize()); + + assert_eq!(self.clip_id_stack.len(), 1); + assert_eq!(self.spatial_id_stack.len(), 1); + } + + fn to_complex_clip_region(&mut self, item: &Yaml) -> ComplexClipRegion { + let rect = item["rect"] + .as_rect() + .expect("Complex clip entry must have rect"); + let radius = item["radius"] + .as_border_radius() + .unwrap_or(BorderRadius::zero()); + let mode = item["clip-mode"] + .as_clip_mode() + .unwrap_or(ClipMode::Clip); + ComplexClipRegion::new(rect, radius, mode) + } + + fn to_complex_clip_regions(&mut self, item: &Yaml) -> Vec<ComplexClipRegion> { + match *item { + Yaml::Array(ref array) => array + .iter() + .map(|entry| self.to_complex_clip_region(entry)) + .collect(), + Yaml::BadValue => vec![], + _ => { + println!("Unable to parse complex clip region {:?}", item); + vec![] + } + } + } + + fn to_sticky_offset_bounds(&mut self, item: &Yaml) -> StickyOffsetBounds { + match *item { + Yaml::Array(ref array) => StickyOffsetBounds::new( + array[0].as_f32().unwrap_or(0.0), + array[1].as_f32().unwrap_or(0.0), + ), + _ => StickyOffsetBounds::new(0.0, 0.0), + } + } + + fn to_clip_id(&self, item: &Yaml, pipeline_id: PipelineId) -> Option<ClipId> { + match *item { + Yaml::Integer(value) => Some(self.user_clip_id_map[&(value as u64)]), + Yaml::String(ref id_string) if id_string == "root_clip" => + Some(ClipId::root(pipeline_id)), + _ => None, + } + } + + fn to_spatial_id(&self, item: &Yaml, pipeline_id: PipelineId) -> SpatialId { + match *item { + Yaml::Integer(value) => self.user_spatial_id_map[&(value as u64)], + Yaml::String(ref id_string) if id_string == "root-reference-frame" => + SpatialId::root_reference_frame(pipeline_id), + Yaml::String(ref id_string) if id_string == "root-scroll-node" => + SpatialId::root_scroll_node(pipeline_id), + _ => { + println!("Unable to parse SpatialId {:?}", item); + SpatialId::root_reference_frame(pipeline_id) + } + } + } + + fn add_clip_id_mapping(&mut self, numeric_id: u64, real_id: ClipId) { + assert_ne!(numeric_id, 0, "id=0 is reserved for the root clip"); + self.user_clip_id_map.insert(numeric_id, real_id); + } + + fn add_spatial_id_mapping(&mut self, numeric_id: u64, real_id: SpatialId) { + assert_ne!(numeric_id, 0, "id=0 is reserved for the root reference frame"); + assert_ne!(numeric_id, 1, "id=1 is reserved for the root scroll node"); + self.user_spatial_id_map.insert(numeric_id, real_id); + } + + fn to_clip_and_scroll_info( + &self, + item: &Yaml, + pipeline_id: PipelineId + ) -> (Option<ClipId>, Option<SpatialId>) { + // Note: this is tricky. In the old code the single ID could be used either way + // for clip/scroll. In the new code we are trying to reflect that and not break + // all the reftests. Ultimately we'd want the clip and scroll nodes to be + // provided separately in YAML. + match *item { + Yaml::BadValue => (None, None), + Yaml::Array(ref array) if array.len() == 2 => { + let scroll_id = self.to_spatial_id(&array[0], pipeline_id); + let clip_id = self.to_clip_id(&array[1], pipeline_id); + (clip_id, Some(scroll_id)) + } + Yaml::String(ref id_string) if id_string == "root-reference-frame" => { + let scroll_id = SpatialId::root_reference_frame(pipeline_id); + let clip_id = ClipId::root(pipeline_id); + (Some(clip_id), Some(scroll_id)) + } + Yaml::String(ref id_string) if id_string == "root-scroll-node" => { + let scroll_id = SpatialId::root_scroll_node(pipeline_id); + (None, Some(scroll_id)) + } + Yaml::String(ref id_string) if id_string == "root_clip" => { + let clip_id = ClipId::root(pipeline_id); + (Some(clip_id), None) + } + Yaml::Integer(value) => { + let scroll_id = self.user_spatial_id_map + .get(&(value as u64)) + .cloned(); + let clip_id = self.user_clip_id_map + .get(&(value as u64)) + .cloned(); + assert!(scroll_id.is_some() || clip_id.is_some(), + "clip-and-scroll index not found: {}", value); + (clip_id, scroll_id) + } + _ => { + println!("Unable to parse clip/scroll {:?}", item); + (None, None) + } + } + } + + fn to_hit_testing_tag(&self, item: &Yaml) -> Option<ItemTag> { + match *item { + Yaml::Array(ref array) if array.len() == 2 => { + match (array[0].as_i64(), array[1].as_i64()) { + (Some(first), Some(second)) => Some((first as u64, second as u16)), + _ => None, + } + } + _ => None, + } + + } + + fn add_or_get_image( + &mut self, + file: &Path, + tiling: Option<i64>, + item: &Yaml, + wrench: &mut Wrench, + ) -> (ImageKey, LayoutSize) { + let key = (file.to_owned(), tiling); + if let Some(k) = self.image_map.get(&key) { + return *k; + } + + if self.list_resources { println!("{}", file.to_string_lossy()); } + let (descriptor, image_data) = match image::open(file) { + Ok(image) => { + let (image_width, image_height) = image.dimensions(); + let (format, bytes) = match image { + image::DynamicImage::ImageLuma8(_) => { + (ImageFormat::R8, image.to_bytes()) + } + image::DynamicImage::ImageRgba8(_) => { + let mut pixels = image.to_bytes(); + premultiply(pixels.as_mut_slice()); + (ImageFormat::BGRA8, pixels) + } + image::DynamicImage::ImageRgb8(_) => { + let bytes = image.to_bytes(); + let mut pixels = Vec::with_capacity(image_width as usize * image_height as usize * 4); + for bgr in bytes.chunks(3) { + pixels.extend_from_slice(&[ + bgr[2], + bgr[1], + bgr[0], + 0xff + ]); + } + (ImageFormat::BGRA8, pixels) + } + _ => panic!("We don't support whatever your crazy image type is, come on"), + }; + let mut flags = ImageDescriptorFlags::empty(); + if is_image_opaque(format, &bytes[..]) { + flags |= ImageDescriptorFlags::IS_OPAQUE; + } + if self.allow_mipmaps { + flags |= ImageDescriptorFlags::ALLOW_MIPMAPS; + } + let descriptor = ImageDescriptor::new( + image_width as i32, + image_height as i32, + format, + flags, + ); + let data = ImageData::new(bytes); + (descriptor, data) + } + _ => { + // This is a hack but it is convenient when generating test cases and avoids + // bloating the repository. + match parse_function( + file.components() + .last() + .unwrap() + .as_os_str() + .to_str() + .unwrap(), + ) { + ("xy-gradient", args, _) => generate_xy_gradient_image( + args.get(0).unwrap_or(&"1000").parse::<u32>().unwrap(), + args.get(1).unwrap_or(&"1000").parse::<u32>().unwrap(), + ), + ("solid-color", args, _) => generate_solid_color_image( + args.get(0).unwrap_or(&"255").parse::<u8>().unwrap(), + args.get(1).unwrap_or(&"255").parse::<u8>().unwrap(), + args.get(2).unwrap_or(&"255").parse::<u8>().unwrap(), + args.get(3).unwrap_or(&"255").parse::<u8>().unwrap(), + args.get(4).unwrap_or(&"1000").parse::<u32>().unwrap(), + args.get(5).unwrap_or(&"1000").parse::<u32>().unwrap(), + ), + (name @ "transparent-checkerboard", args, _) | + (name @ "checkerboard", args, _) => { + let border = args.get(0).unwrap_or(&"4").parse::<u32>().unwrap(); + + let (x_size, y_size, x_count, y_count) = match args.len() { + 3 => { + let size = args.get(1).unwrap_or(&"32").parse::<u32>().unwrap(); + let count = args.get(2).unwrap_or(&"8").parse::<u32>().unwrap(); + (size, size, count, count) + } + 5 => { + let x_size = args.get(1).unwrap_or(&"32").parse::<u32>().unwrap(); + let y_size = args.get(2).unwrap_or(&"32").parse::<u32>().unwrap(); + let x_count = args.get(3).unwrap_or(&"8").parse::<u32>().unwrap(); + let y_count = args.get(4).unwrap_or(&"8").parse::<u32>().unwrap(); + (x_size, y_size, x_count, y_count) + } + _ => { + panic!("invalid checkerboard function"); + } + }; + + let kind = if name == "transparent-checkerboard" { + CheckerboardKind::BlackTransparent + } else { + CheckerboardKind::BlackGrey + }; + + generate_checkerboard_image( + border, + x_size, + y_size, + x_count, + y_count, + kind, + ) + } + _ => { + panic!("Failed to load image {:?}", file.to_str()); + } + } + } + }; + let tiling = tiling.map(|tile_size| tile_size as u16); + let image_key = wrench.api.generate_image_key(); + let mut txn = Transaction::new(); + + let external = item["external"].as_bool().unwrap_or(false); + if external { + // This indicates we want to simulate an external texture, + // ensure it gets created as such + let external_target = match item["external-target"].as_str() { + Some(ref s) => match &s[..] { + "2d" => ImageBufferKind::Texture2D, + "array" => ImageBufferKind::Texture2DArray, + "rect" => ImageBufferKind::TextureRect, + _ => panic!("Unsupported external texture target."), + } + None => { + ImageBufferKind::Texture2D + } + }; + + let external_image_data = + self.external_image_handler.as_mut().unwrap().add_image( + &wrench.renderer.device, + descriptor, + external_target, + image_data + ); + txn.add_image(image_key, descriptor, external_image_data, tiling); + } else { + txn.add_image(image_key, descriptor, image_data, tiling); + } + + wrench.api.send_transaction(wrench.document_id, txn); + let val = ( + image_key, + LayoutSize::new(descriptor.size.width as f32, descriptor.size.height as f32), + ); + self.image_map.insert(key, val); + val + } + + fn get_or_create_font(&mut self, desc: FontDescriptor, wrench: &mut Wrench) -> FontKey { + let list_resources = self.list_resources; + *self.fonts + .entry(desc.clone()) + .or_insert_with(|| match desc { + FontDescriptor::Path { + ref path, + font_index, + } => { + if list_resources { println!("{}", path.to_string_lossy()); } + let mut file = File::open(path).expect("Couldn't open font file"); + let mut bytes = vec![]; + file.read_to_end(&mut bytes) + .expect("failed to read font file"); + wrench.font_key_from_bytes(bytes, font_index) + } + FontDescriptor::Family { ref name } => wrench.font_key_from_name(name), + FontDescriptor::Properties { + ref family, + weight, + style, + stretch, + } => wrench.font_key_from_properties(family, weight, style, stretch), + }) + } + + pub fn allow_mipmaps(&mut self, allow_mipmaps: bool) { + self.allow_mipmaps = allow_mipmaps; + } + + pub fn set_font_render_mode(&mut self, render_mode: Option<FontRenderMode>) { + self.font_render_mode = render_mode; + } + + fn get_or_create_font_instance( + &mut self, + font_key: FontKey, + size: f32, + bg_color: Option<ColorU>, + flags: FontInstanceFlags, + synthetic_italics: SyntheticItalics, + wrench: &mut Wrench, + ) -> FontInstanceKey { + let font_render_mode = self.font_render_mode; + + *self.font_instances + .entry((font_key, size.into(), flags, bg_color, synthetic_italics)) + .or_insert_with(|| { + wrench.add_font_instance( + font_key, + size, + flags, + font_render_mode, + bg_color, + synthetic_italics, + ) + }) + } + + fn to_image_mask(&mut self, item: &Yaml, wrench: &mut Wrench) -> Option<ImageMask> { + if item.as_hash().is_none() { + return None; + } + + let tiling = item["tile-size"].as_i64(); + + let (image_key, image_dims) = match item["image"].as_str() { + Some(filename) => { + if filename == "invalid" { + (ImageKey::DUMMY, LayoutSize::new(100.0, 100.0)) + } else { + let mut file = self.aux_dir.clone(); + file.push(filename); + self.add_or_get_image(&file, tiling, item, wrench) + } + } + None => { + warn!("No image provided for the image-mask!"); + return None; + } + }; + + let image_rect = item["rect"] + .as_rect() + .unwrap_or(LayoutRect::new(LayoutPoint::zero(), image_dims)); + let image_repeat = item["repeat"].as_bool().expect("Expected boolean"); + Some(ImageMask { + image: image_key, + rect: image_rect, + repeat: image_repeat, + }) + } + + fn to_gradient(&mut self, dl: &mut DisplayListBuilder, item: &Yaml) -> Gradient { + let start = item["start"].as_point().expect("gradient must have start"); + let end = item["end"].as_point().expect("gradient must have end"); + let stops = item["stops"] + .as_vec() + .expect("gradient must have stops") + .chunks(2) + .map(|chunk| { + GradientStop { + offset: chunk[0] + .as_force_f32() + .expect("gradient stop offset is not f32"), + color: chunk[1] + .as_colorf() + .expect("gradient stop color is not color"), + } + }) + .collect::<Vec<_>>(); + let extend_mode = if item["repeat"].as_bool().unwrap_or(false) { + ExtendMode::Repeat + } else { + ExtendMode::Clamp + }; + + dl.create_gradient(start, end, stops, extend_mode) + } + + fn to_radial_gradient(&mut self, dl: &mut DisplayListBuilder, item: &Yaml) -> RadialGradient { + let center = item["center"].as_point().expect("radial gradient must have center"); + let radius = item["radius"].as_size().expect("radial gradient must have a radius"); + let stops = item["stops"] + .as_vec() + .expect("radial gradient must have stops") + .chunks(2) + .map(|chunk| { + GradientStop { + offset: chunk[0] + .as_force_f32() + .expect("gradient stop offset is not f32"), + color: chunk[1] + .as_colorf() + .expect("gradient stop color is not color"), + } + }) + .collect::<Vec<_>>(); + let extend_mode = if item["repeat"].as_bool().unwrap_or(false) { + ExtendMode::Repeat + } else { + ExtendMode::Clamp + }; + + dl.create_radial_gradient(center, radius, stops, extend_mode) + } + + fn to_conic_gradient(&mut self, dl: &mut DisplayListBuilder, item: &Yaml) -> ConicGradient { + let center = item["center"].as_point().expect("conic gradient must have center"); + let angle = item["angle"].as_force_f32().expect("conic gradient must have an angle"); + let stops = item["stops"] + .as_vec() + .expect("conic gradient must have stops") + .chunks(2) + .map(|chunk| { + GradientStop { + offset: chunk[0] + .as_force_f32() + .expect("gradient stop offset is not f32"), + color: chunk[1] + .as_colorf() + .expect("gradient stop color is not color"), + } + }) + .collect::<Vec<_>>(); + let extend_mode = if item["repeat"].as_bool().unwrap_or(false) { + ExtendMode::Repeat + } else { + ExtendMode::Clamp + }; + + dl.create_conic_gradient(center, angle, stops, extend_mode) + } + + fn handle_rect( + &mut self, + dl: &mut DisplayListBuilder, + item: &Yaml, + info: &CommonItemProperties, + ) { + let bounds_key = if item["type"].is_badvalue() { + "rect" + } else { + "bounds" + }; + + let bounds = self.resolve_rect(&item[bounds_key]); + let color = self.resolve_colorf(&item["color"], ColorF::BLACK); + dl.push_rect(&info, bounds, color); + } + + fn handle_clear_rect( + &mut self, + dl: &mut DisplayListBuilder, + item: &Yaml, + info: &CommonItemProperties, + ) { + let bounds = item["bounds"].as_rect().expect("clear-rect type must have bounds"); + dl.push_clear_rect(&info, bounds); + } + + fn handle_hit_test( + &mut self, + dl: &mut DisplayListBuilder, + item: &Yaml, + info: &mut CommonItemProperties, + ) { + info.clip_rect = try_intersect!( + item["bounds"].as_rect().expect("hit-test type must have bounds"), + &info.clip_rect + ); + + if let Some(tag) = self.to_hit_testing_tag(&item["hit-testing-tag"]) { + dl.push_hit_test( + &info, + tag, + ); + } + } + + fn handle_line( + &mut self, + dl: &mut DisplayListBuilder, + item: &Yaml, + info: &mut CommonItemProperties, + ) { + let color = item["color"].as_colorf().unwrap_or(ColorF::BLACK); + let orientation = item["orientation"] + .as_str() + .and_then(LineOrientation::from_str) + .expect("line must have orientation"); + let style = item["style"] + .as_str() + .and_then(LineStyle::from_str) + .expect("line must have style"); + + let wavy_line_thickness = if let LineStyle::Wavy = style { + item["thickness"].as_f32().expect("wavy lines must have a thickness") + } else { + 0.0 + }; + + let area; + if item["baseline"].is_badvalue() { + let bounds_key = if item["type"].is_badvalue() { + "rect" + } else { + "bounds" + }; + + area = item[bounds_key] + .as_rect() + .expect("line type must have bounds"); + } else { + // Legacy line representation + let baseline = item["baseline"].as_f32().expect("line must have baseline"); + let start = item["start"].as_f32().expect("line must have start"); + let end = item["end"].as_f32().expect("line must have end"); + let width = item["width"].as_f32().expect("line must have width"); + + area = match orientation { + LineOrientation::Horizontal => { + LayoutRect::new(LayoutPoint::new(start, baseline), + LayoutSize::new(end - start, width)) + } + LineOrientation::Vertical => { + LayoutRect::new(LayoutPoint::new(baseline, start), + LayoutSize::new(width, end - start)) + } + }; + } + + dl.push_line( + &info, + &area, + wavy_line_thickness, + orientation, + &color, + style, + ); + } + + fn handle_gradient( + &mut self, + dl: &mut DisplayListBuilder, + item: &Yaml, + info: &mut CommonItemProperties, + ) { + let bounds_key = if item["type"].is_badvalue() { + "gradient" + } else { + "bounds" + }; + let bounds = item[bounds_key] + .as_rect() + .expect("gradient must have bounds"); + + let gradient = self.to_gradient(dl, item); + let tile_size = item["tile-size"].as_size().unwrap_or(bounds.size); + let tile_spacing = item["tile-spacing"].as_size().unwrap_or(LayoutSize::zero()); + + dl.push_gradient( + &info, + bounds, + gradient, + tile_size, + tile_spacing + ); + } + + fn handle_radial_gradient( + &mut self, + dl: &mut DisplayListBuilder, + item: &Yaml, + info: &mut CommonItemProperties, + ) { + let bounds_key = if item["type"].is_badvalue() { + "radial-gradient" + } else { + "bounds" + }; + let bounds = item[bounds_key] + .as_rect() + .expect("radial gradient must have bounds"); + let gradient = self.to_radial_gradient(dl, item); + let tile_size = item["tile-size"].as_size().unwrap_or(bounds.size); + let tile_spacing = item["tile-spacing"].as_size().unwrap_or(LayoutSize::zero()); + + dl.push_radial_gradient( + &info, + bounds, + gradient, + tile_size, + tile_spacing, + ); + } + + fn handle_conic_gradient( + &mut self, + dl: &mut DisplayListBuilder, + item: &Yaml, + info: &mut CommonItemProperties, + ) { + let bounds_key = if item["type"].is_badvalue() { + "conic-gradient" + } else { + "bounds" + }; + let bounds = item[bounds_key] + .as_rect() + .expect("conic gradient must have bounds"); + let gradient = self.to_conic_gradient(dl, item); + let tile_size = item["tile-size"].as_size().unwrap_or(bounds.size); + let tile_spacing = item["tile-spacing"].as_size().unwrap_or(LayoutSize::zero()); + + dl.push_conic_gradient( + &info, + bounds, + gradient, + tile_size, + tile_spacing, + ); + } + + fn handle_border( + &mut self, + dl: &mut DisplayListBuilder, + wrench: &mut Wrench, + item: &Yaml, + info: &mut CommonItemProperties, + ) { + let bounds_key = if item["type"].is_badvalue() { + "border" + } else { + "bounds" + }; + let bounds = item[bounds_key].as_rect().expect("borders must have bounds"); + let widths = item["width"] + .as_vec_f32() + .expect("borders must have width(s)"); + let widths = broadcast(&widths, 4); + let widths = LayoutSideOffsets::new(widths[0], widths[3], widths[2], widths[1]); + let border_details = if let Some(border_type) = item["border-type"].as_str() { + match border_type { + "normal" => { + let colors = item["color"] + .as_vec_colorf() + .expect("borders must have color(s)"); + let styles = item["style"] + .as_vec_string() + .expect("borders must have style(s)"); + let styles = styles + .iter() + .map(|s| match s.as_str() { + "none" => BorderStyle::None, + "solid" => BorderStyle::Solid, + "double" => BorderStyle::Double, + "dotted" => BorderStyle::Dotted, + "dashed" => BorderStyle::Dashed, + "hidden" => BorderStyle::Hidden, + "ridge" => BorderStyle::Ridge, + "inset" => BorderStyle::Inset, + "outset" => BorderStyle::Outset, + "groove" => BorderStyle::Groove, + s => { + panic!("Unknown border style '{}'", s); + } + }) + .collect::<Vec<BorderStyle>>(); + let radius = item["radius"] + .as_border_radius() + .unwrap_or(BorderRadius::zero()); + + let colors = broadcast(&colors, 4); + let styles = broadcast(&styles, 4); + + let top = BorderSide { + color: colors[0], + style: styles[0], + }; + let right = BorderSide { + color: colors[1], + style: styles[1], + }; + let bottom = BorderSide { + color: colors[2], + style: styles[2], + }; + let left = BorderSide { + color: colors[3], + style: styles[3], + }; + let do_aa = item["do_aa"].as_bool().unwrap_or(true); + Some(BorderDetails::Normal(NormalBorder { + top, + left, + bottom, + right, + radius, + do_aa, + })) + } + "image" | "gradient" | "radial-gradient" | "conic-gradient" => { + let image_width = item["image-width"] + .as_i64() + .unwrap_or(bounds.size.width as i64); + let image_height = item["image-height"] + .as_i64() + .unwrap_or(bounds.size.height as i64); + let fill = item["fill"].as_bool().unwrap_or(false); + + let slice = item["slice"].as_vec_u32(); + let slice = match slice { + Some(slice) => broadcast(&slice, 4), + None => vec![widths.top as u32, widths.left as u32, widths.bottom as u32, widths.right as u32], + }; + + let outset = item["outset"] + .as_vec_f32() + .expect("border must have outset"); + let outset = broadcast(&outset, 4); + let repeat_horizontal = match item["repeat-horizontal"] + .as_str() + .unwrap_or("stretch") + { + "stretch" => RepeatMode::Stretch, + "repeat" => RepeatMode::Repeat, + "round" => RepeatMode::Round, + "space" => RepeatMode::Space, + s => panic!("Unknown box border image repeat mode {}", s), + }; + let repeat_vertical = match item["repeat-vertical"] + .as_str() + .unwrap_or("stretch") + { + "stretch" => RepeatMode::Stretch, + "repeat" => RepeatMode::Repeat, + "round" => RepeatMode::Round, + "space" => RepeatMode::Space, + s => panic!("Unknown box border image repeat mode {}", s), + }; + let source = match border_type { + "image" => { + let file = rsrc_path(&item["image-source"], &self.aux_dir); + let (image_key, _) = self + .add_or_get_image(&file, None, item, wrench); + NinePatchBorderSource::Image(image_key) + } + "gradient" => { + let gradient = self.to_gradient(dl, item); + NinePatchBorderSource::Gradient(gradient) + } + "radial-gradient" => { + let gradient = self.to_radial_gradient(dl, item); + NinePatchBorderSource::RadialGradient(gradient) + } + "conic-gradient" => { + let gradient = self.to_conic_gradient(dl, item); + NinePatchBorderSource::ConicGradient(gradient) + } + _ => unreachable!("Unexpected border type"), + }; + + Some(BorderDetails::NinePatch(NinePatchBorder { + source, + width: image_width as i32, + height: image_height as i32, + slice: SideOffsets2D::new(slice[0] as i32, slice[1] as i32, slice[2] as i32, slice[3] as i32), + fill, + repeat_horizontal, + repeat_vertical, + outset: SideOffsets2D::new(outset[0], outset[1], outset[2], outset[3]), + })) + } + _ => { + println!("Unable to parse border {:?}", item); + None + } + } + } else { + println!("Unable to parse border {:?}", item); + None + }; + if let Some(details) = border_details { + dl.push_border(&info, bounds, widths, details); + } + } + + fn handle_box_shadow( + &mut self, + dl: &mut DisplayListBuilder, + item: &Yaml, + info: &mut CommonItemProperties, + ) { + let bounds_key = if item["type"].is_badvalue() { + "box-shadow" + } else { + "bounds" + }; + let bounds = item[bounds_key] + .as_rect() + .expect("box shadow must have bounds"); + let box_bounds = item["box-bounds"].as_rect().unwrap_or(bounds); + let offset = self.resolve_vector(&item["offset"], LayoutVector2D::zero()); + let color = item["color"] + .as_colorf() + .unwrap_or(ColorF::new(0.0, 0.0, 0.0, 1.0)); + let blur_radius = item["blur-radius"].as_force_f32().unwrap_or(0.0); + let spread_radius = item["spread-radius"].as_force_f32().unwrap_or(0.0); + let border_radius = item["border-radius"] + .as_border_radius() + .unwrap_or(BorderRadius::zero()); + let clip_mode = if let Some(mode) = item["clip-mode"].as_str() { + match mode { + "outset" => BoxShadowClipMode::Outset, + "inset" => BoxShadowClipMode::Inset, + s => panic!("Unknown box shadow clip mode {}", s), + } + } else { + BoxShadowClipMode::Outset + }; + + dl.push_box_shadow( + &info, + box_bounds, + offset, + color, + blur_radius, + spread_radius, + border_radius, + clip_mode, + ); + } + + fn handle_yuv_image( + &mut self, + dl: &mut DisplayListBuilder, + wrench: &mut Wrench, + item: &Yaml, + info: &mut CommonItemProperties, + ) { + // TODO(gw): Support other YUV color depth and spaces. + let color_depth = ColorDepth::Color8; + let color_space = YuvColorSpace::Rec709; + let color_range = ColorRange::Limited; + + let yuv_data = match item["format"].as_str().expect("no format supplied") { + "planar" => { + let y_path = rsrc_path(&item["src-y"], &self.aux_dir); + let (y_key, _) = self.add_or_get_image(&y_path, None, item, wrench); + + let u_path = rsrc_path(&item["src-u"], &self.aux_dir); + let (u_key, _) = self.add_or_get_image(&u_path, None, item, wrench); + + let v_path = rsrc_path(&item["src-v"], &self.aux_dir); + let (v_key, _) = self.add_or_get_image(&v_path, None, item, wrench); + + YuvData::PlanarYCbCr(y_key, u_key, v_key) + } + "nv12" => { + let y_path = rsrc_path(&item["src-y"], &self.aux_dir); + let (y_key, _) = self.add_or_get_image(&y_path, None, item, wrench); + + let uv_path = rsrc_path(&item["src-uv"], &self.aux_dir); + let (uv_key, _) = self.add_or_get_image(&uv_path, None, item, wrench); + + YuvData::NV12(y_key, uv_key) + } + "interleaved" => { + let yuv_path = rsrc_path(&item["src"], &self.aux_dir); + let (yuv_key, _) = self.add_or_get_image(&yuv_path, None, item, wrench); + + YuvData::InterleavedYCbCr(yuv_key) + } + _ => { + panic!("unexpected yuv format"); + } + }; + + let bounds = item["bounds"].as_vec_f32().unwrap(); + let bounds = LayoutRect::new( + LayoutPoint::new(bounds[0], bounds[1]), + LayoutSize::new(bounds[2], bounds[3]), + ); + + dl.push_yuv_image( + &info, + bounds, + yuv_data, + color_depth, + color_space, + color_range, + ImageRendering::Auto, + ); + } + + fn handle_image( + &mut self, + dl: &mut DisplayListBuilder, + wrench: &mut Wrench, + item: &Yaml, + info: &mut CommonItemProperties, + ) { + let filename = &item[if item["type"].is_badvalue() { + "image" + } else { + "src" + }]; + let tiling = item["tile-size"].as_i64(); + let file = rsrc_path(filename, &self.aux_dir); + let (image_key, image_dims) = + self.add_or_get_image(&file, tiling, item, wrench); + + let bounds_raws = item["bounds"].as_vec_f32().unwrap(); + let bounds = if bounds_raws.len() == 2 { + LayoutRect::new(LayoutPoint::new(bounds_raws[0], bounds_raws[1]), image_dims) + } else if bounds_raws.len() == 4 { + LayoutRect::new( + LayoutPoint::new(bounds_raws[0], bounds_raws[1]), + LayoutSize::new(bounds_raws[2], bounds_raws[3]), + ) + } else { + panic!( + "image expected 2 or 4 values in bounds, got '{:?}'", + item["bounds"] + ); + }; + let rendering = match item["rendering"].as_str() { + Some("auto") | None => ImageRendering::Auto, + Some("crisp-edges") => ImageRendering::CrispEdges, + Some("pixelated") => ImageRendering::Pixelated, + Some(_) => panic!( + "ImageRendering can be auto, crisp-edges, or pixelated -- got {:?}", + item + ), + }; + let alpha_type = match item["alpha-type"].as_str() { + Some("premultiplied-alpha") | None => AlphaType::PremultipliedAlpha, + Some("alpha") => AlphaType::Alpha, + Some(_) => panic!( + "AlphaType can be premultiplied-alpha or alpha -- got {:?}", + item + ), + }; + let stretch_size = item["stretch-size"].as_size(); + let tile_spacing = item["tile-spacing"].as_size(); + if stretch_size.is_none() && tile_spacing.is_none() { + dl.push_image( + &info, + bounds, + rendering, + alpha_type, + image_key, + ColorF::WHITE, + ); + } else { + dl.push_repeating_image( + &info, + bounds, + stretch_size.unwrap_or(image_dims), + tile_spacing.unwrap_or(LayoutSize::zero()), + rendering, + alpha_type, + image_key, + ColorF::WHITE, + ); + } + } + + fn handle_text( + &mut self, + dl: &mut DisplayListBuilder, + wrench: &mut Wrench, + item: &Yaml, + info: &mut CommonItemProperties, + ) { + let size = item["size"].as_pt_to_f32().unwrap_or(16.0); + let color = item["color"].as_colorf().unwrap_or(ColorF::BLACK); + let bg_color = item["bg-color"].as_colorf().map(|c| c.into()); + let synthetic_italics = if let Some(angle) = item["synthetic-italics"].as_f32() { + SyntheticItalics::from_degrees(angle) + } else if item["synthetic-italics"].as_bool().unwrap_or(false) { + SyntheticItalics::enabled() + } else { + SyntheticItalics::disabled() + }; + + let mut flags = FontInstanceFlags::empty(); + if item["synthetic-bold"].as_bool().unwrap_or(false) { + flags |= FontInstanceFlags::SYNTHETIC_BOLD; + } + if item["embedded-bitmaps"].as_bool().unwrap_or(false) { + flags |= FontInstanceFlags::EMBEDDED_BITMAPS; + } + if item["transpose"].as_bool().unwrap_or(false) { + flags |= FontInstanceFlags::TRANSPOSE; + } + if item["flip-x"].as_bool().unwrap_or(false) { + flags |= FontInstanceFlags::FLIP_X; + } + if item["flip-y"].as_bool().unwrap_or(false) { + flags |= FontInstanceFlags::FLIP_Y; + } + + assert!( + item["blur-radius"].is_badvalue(), + "text no longer has a blur radius, use PushShadow and PopAllShadows" + ); + + let desc = FontDescriptor::from_yaml(item, &self.aux_dir); + let font_key = self.get_or_create_font(desc, wrench); + let font_instance_key = self.get_or_create_font_instance(font_key, + size, + bg_color, + flags, + synthetic_italics, + wrench); + + assert!( + !(item["glyphs"].is_badvalue() && item["text"].is_badvalue()), + "text item had neither text nor glyphs!" + ); + + let (glyphs, rect) = if item["text"].is_badvalue() { + // if glyphs are specified, then the glyph positions can have the + // origin baked in. + let origin = item["origin"] + .as_point() + .unwrap_or(LayoutPoint::new(0.0, 0.0)); + let glyph_indices = item["glyphs"].as_vec_u32().unwrap(); + let glyph_offsets = item["offsets"].as_vec_f32().unwrap(); + assert_eq!(glyph_offsets.len(), glyph_indices.len() * 2); + + let glyphs = glyph_indices + .iter() + .enumerate() + .map(|k| { + GlyphInstance { + index: *k.1, + // In the future we want to change the API to be relative, eliminating this + point: LayoutPoint::new( + origin.x + glyph_offsets[k.0 * 2], + origin.y + glyph_offsets[k.0 * 2 + 1], + ), + } + }) + .collect::<Vec<_>>(); + // TODO(gw): We could optionally use the WR API to query glyph dimensions + // here and calculate the bounding region here if we want to. + let rect = item["bounds"] + .as_rect() + .expect("Text items with glyphs require bounds [for now]"); + (glyphs, rect) + } else { + let text = item["text"].as_str().unwrap(); + let origin = item["origin"] + .as_point() + .expect("origin required for text without glyphs"); + let (glyph_indices, glyph_positions, bounds) = wrench.layout_simple_ascii( + font_key, + font_instance_key, + text, + size, + origin, + flags, + ); + + let glyphs = glyph_indices + .iter() + .zip(glyph_positions) + .map(|arg| { + let gi = GlyphInstance { + index: *arg.0 as u32, + point: arg.1, + }; + gi + }) + .collect::<Vec<_>>(); + (glyphs, bounds) + }; + + dl.push_text( + &info, + rect, + &glyphs, + font_instance_key, + color, + None, + ); + } + + fn handle_iframe( + &mut self, + dl: &mut DisplayListBuilder, + item: &Yaml, + info: &mut CommonItemProperties, + ) { + let bounds = item["bounds"].as_rect().expect("iframe must have bounds"); + let pipeline_id = item["id"].as_pipeline_id().unwrap(); + let ignore = item["ignore_missing_pipeline"].as_bool().unwrap_or(true); + dl.push_iframe( + bounds, + info.clip_rect, + &SpaceAndClipInfo { + spatial_id: info.spatial_id, + clip_id: info.clip_id + }, + pipeline_id, + ignore + ); + } + + fn get_complex_clip_for_item(&mut self, yaml: &Yaml) -> Option<ComplexClipRegion> { + let complex_clip = &yaml["complex-clip"]; + if complex_clip.is_badvalue() { + return None; + } + Some(self.to_complex_clip_region(complex_clip)) + } + + fn get_item_type_from_yaml(item: &Yaml) -> &str { + let shorthands = [ + "rect", + "image", + "text", + "glyphs", + "box-shadow", // Note: box_shadow shorthand check has to come before border. + "border", + "gradient", + "radial-gradient", + "conic-gradient" + ]; + + for shorthand in shorthands.iter() { + if !item[*shorthand].is_badvalue() { + return shorthand; + } + } + item["type"].as_str().unwrap_or("unknown") + } + + fn add_display_list_items_from_yaml( + &mut self, + dl: &mut DisplayListBuilder, + wrench: &mut Wrench, + yaml: &Yaml, + ) { + // A very large number (but safely far away from finite limits of f32) + let big_number = 1.0e30; + // A rect that should in practical terms serve as a no-op for clipping + let full_clip = LayoutRect::new( + LayoutPoint::new(-big_number / 2.0, -big_number / 2.0), + LayoutSize::new(big_number, big_number)); + + for item in yaml.as_vec().unwrap() { + let item_type = Self::get_item_type_from_yaml(item); + + // We never skip stacking contexts and reference frames because + // they are structural elements of the display list. + if item_type != "stacking-context" && + item_type != "reference-frame" && + self.include_only.contains(&item_type.to_owned()) { + continue; + } + + let (set_clip_id, set_scroll_id) = self.to_clip_and_scroll_info( + &item["clip-and-scroll"], + dl.pipeline_id + ); + if let Some(clip_id) = set_clip_id { + self.clip_id_stack.push(clip_id); + } + if let Some(scroll_id) = set_scroll_id { + self.spatial_id_stack.push(scroll_id); + } + + let complex_clip = self.get_complex_clip_for_item(item); + let clip_rect = item["clip-rect"].as_rect().unwrap_or(full_clip); + + let mut pushed_clip = false; + if let Some(complex_clip) = complex_clip { + match item_type { + "clip" | "clip-chain" | "scroll-frame" => {}, + _ => { + let id = dl.define_clip_rounded_rect( + &self.top_space_and_clip(), + complex_clip, + ); + self.clip_id_stack.push(id); + pushed_clip = true; + } + } + } + + let space_and_clip = self.top_space_and_clip(); + let mut flags = PrimitiveFlags::default(); + if let Some(is_backface_visible) = item["backface-visible"].as_bool() { + if is_backface_visible { + flags.insert(PrimitiveFlags::IS_BACKFACE_VISIBLE); + } else { + flags.remove(PrimitiveFlags::IS_BACKFACE_VISIBLE); + } + } + if let Some(is_scrollbar_container) = item["scrollbar-container"].as_bool() { + if is_scrollbar_container { + flags.insert(PrimitiveFlags::IS_SCROLLBAR_CONTAINER); + } else { + flags.remove(PrimitiveFlags::IS_SCROLLBAR_CONTAINER); + } + } + if let Some(prefer_compositor_surface) = item["prefer-compositor-surface"].as_bool() { + if prefer_compositor_surface { + flags.insert(PrimitiveFlags::PREFER_COMPOSITOR_SURFACE); + } else { + flags.remove(PrimitiveFlags::PREFER_COMPOSITOR_SURFACE); + } + } + + let mut info = CommonItemProperties { + clip_rect, + clip_id: space_and_clip.clip_id, + spatial_id: space_and_clip.spatial_id, + flags, + }; + + match item_type { + "rect" => self.handle_rect(dl, item, &mut info), + "hit-test" => self.handle_hit_test(dl, item, &mut info), + "clear-rect" => self.handle_clear_rect(dl, item, &mut info), + "line" => self.handle_line(dl, item, &mut info), + "image" => self.handle_image(dl, wrench, item, &mut info), + "yuv-image" => self.handle_yuv_image(dl, wrench, item, &mut info), + "text" | "glyphs" => self.handle_text(dl, wrench, item, &mut info), + "scroll-frame" => self.handle_scroll_frame(dl, wrench, item), + "sticky-frame" => self.handle_sticky_frame(dl, wrench, item), + "clip" => self.handle_clip(dl, wrench, item), + "clip-chain" => self.handle_clip_chain(dl, item), + "border" => self.handle_border(dl, wrench, item, &mut info), + "gradient" => self.handle_gradient(dl, item, &mut info), + "radial-gradient" => self.handle_radial_gradient(dl, item, &mut info), + "conic-gradient" => self.handle_conic_gradient(dl, item, &mut info), + "box-shadow" => self.handle_box_shadow(dl, item, &mut info), + "iframe" => self.handle_iframe(dl, item, &mut info), + "stacking-context" => { + self.add_stacking_context_from_yaml(dl, wrench, item, false, &mut info) + } + "reference-frame" => self.handle_reference_frame(dl, wrench, item), + "shadow" => self.handle_push_shadow(dl, item, &mut info), + "pop-all-shadows" => self.handle_pop_all_shadows(dl), + "backdrop-filter" => self.handle_backdrop_filter(dl, item, &mut info), + _ => println!("Skipping unknown item type: {:?}", item), + } + + if pushed_clip { + self.clip_id_stack.pop().unwrap(); + } + if set_clip_id.is_some() { + self.clip_id_stack.pop().unwrap(); + } + if set_scroll_id.is_some() { + self.spatial_id_stack.pop().unwrap(); + } + } + } + + fn handle_scroll_frame( + &mut self, + dl: &mut DisplayListBuilder, + wrench: &mut Wrench, + yaml: &Yaml, + ) { + let clip_rect = yaml["bounds"] + .as_rect() + .expect("scroll frame must have a bounds"); + let content_size = yaml["content-size"].as_size().unwrap_or(clip_rect.size); + let content_rect = LayoutRect::new(clip_rect.origin, content_size); + let external_scroll_offset = yaml["external-scroll-offset"].as_vector().unwrap_or(LayoutVector2D::zero()); + + let numeric_id = yaml["id"].as_i64().map(|id| id as u64); + + let external_id = ExternalScrollId(self.next_external_scroll_id, dl.pipeline_id); + self.next_external_scroll_id += 1; + + if let Some(size) = yaml["scroll-offset"].as_point() { + self.scroll_offsets.insert(external_id, LayoutPoint::new(size.x, size.y)); + } + + let space_and_clip = dl.define_scroll_frame( + &self.top_space_and_clip(), + external_id, + content_rect, + clip_rect, + ScrollSensitivity::ScriptAndInputEvents, + external_scroll_offset, + ); + if let Some(numeric_id) = numeric_id { + self.add_spatial_id_mapping(numeric_id, space_and_clip.spatial_id); + self.add_clip_id_mapping(numeric_id, space_and_clip.clip_id); + } + + if !yaml["items"].is_badvalue() { + self.spatial_id_stack.push(space_and_clip.spatial_id); + self.clip_id_stack.push(space_and_clip.clip_id); + self.add_display_list_items_from_yaml(dl, wrench, &yaml["items"]); + self.clip_id_stack.pop().unwrap(); + self.spatial_id_stack.pop().unwrap(); + } + } + + fn handle_sticky_frame( + &mut self, + dl: &mut DisplayListBuilder, + wrench: &mut Wrench, + yaml: &Yaml, + ) { + let bounds = yaml["bounds"].as_rect().expect("sticky frame must have a bounds"); + let numeric_id = yaml["id"].as_i64().map(|id| id as u64); + + let real_id = dl.define_sticky_frame( + *self.spatial_id_stack.last().unwrap(), + bounds, + SideOffsets2D::new( + yaml["margin-top"].as_f32(), + yaml["margin-right"].as_f32(), + yaml["margin-bottom"].as_f32(), + yaml["margin-left"].as_f32(), + ), + self.to_sticky_offset_bounds(&yaml["vertical-offset-bounds"]), + self.to_sticky_offset_bounds(&yaml["horizontal-offset-bounds"]), + yaml["previously-applied-offset"].as_vector().unwrap_or(LayoutVector2D::zero()), + ); + + if let Some(numeric_id) = numeric_id { + self.add_spatial_id_mapping(numeric_id, real_id); + } + + if !yaml["items"].is_badvalue() { + self.spatial_id_stack.push(real_id); + self.add_display_list_items_from_yaml(dl, wrench, &yaml["items"]); + self.spatial_id_stack.pop().unwrap(); + } + } + + fn resolve_binding<'a>( + &'a self, + yaml: &'a Yaml, + ) -> &'a Yaml { + if let Some(ref keyframes) = self.keyframes { + if let Some(s) = yaml.as_str() { + let prefix: &str = "key("; + let suffix: &str = ")"; + if s.starts_with(prefix) && s.ends_with(suffix) { + let key = &s[prefix.len() .. s.len() - 1]; + return &keyframes[key][self.requested_frame]; + } + } + } + + yaml + } + + fn resolve_colorf( + &self, + yaml: &Yaml, + default: ColorF, + ) -> ColorF { + self.resolve_binding(yaml) + .as_colorf() + .unwrap_or(default) + } + + fn resolve_rect( + &self, + yaml: &Yaml, + ) -> LayoutRect { + self.resolve_binding(yaml) + .as_rect() + .expect(&format!("invalid rect {:?}", yaml)) + } + + fn resolve_vector( + &self, + yaml: &Yaml, + default: LayoutVector2D, + ) -> LayoutVector2D { + self.resolve_binding(yaml) + .as_vector() + .unwrap_or(default) + } + + fn handle_push_shadow( + &mut self, + dl: &mut DisplayListBuilder, + yaml: &Yaml, + info: &mut CommonItemProperties, + ) { + let blur_radius = yaml["blur-radius"].as_f32().unwrap_or(0.0); + let offset = yaml["offset"].as_vector().unwrap_or(LayoutVector2D::zero()); + let color = yaml["color"].as_colorf().unwrap_or(ColorF::BLACK); + + dl.push_shadow( + &SpaceAndClipInfo { spatial_id: info.spatial_id, clip_id: info.clip_id }, + Shadow { + blur_radius, + offset, + color, + }, + true, + ); + } + + fn handle_pop_all_shadows(&mut self, dl: &mut DisplayListBuilder) { + dl.pop_all_shadows(); + } + + fn handle_clip_chain(&mut self, builder: &mut DisplayListBuilder, yaml: &Yaml) { + let numeric_id = yaml["id"].as_i64().expect("clip chains must have an id"); + let clip_ids: Vec<ClipId> = yaml["clips"] + .as_vec_u64() + .unwrap_or_default() + .iter() + .map(|id| self.user_clip_id_map[id]) + .collect(); + + let parent = self.to_clip_id(&yaml["parent"], builder.pipeline_id); + let parent = match parent { + Some(ClipId::ClipChain(clip_chain_id)) => Some(clip_chain_id), + Some(_) => panic!("Tried to create a ClipChain with a non-ClipChain parent"), + None => None, + }; + + let real_id = builder.define_clip_chain(parent, clip_ids); + self.add_clip_id_mapping(numeric_id as u64, ClipId::ClipChain(real_id)); + } + + fn handle_clip(&mut self, dl: &mut DisplayListBuilder, wrench: &mut Wrench, yaml: &Yaml) { + let numeric_id = yaml["id"].as_i64(); + let complex_clips = self.to_complex_clip_regions(&yaml["complex"]); + let mut space_and_clip = self.top_space_and_clip(); + + if let Some(clip_rect) = yaml["bounds"].as_rect() { + space_and_clip.clip_id = dl.define_clip_rect( + &space_and_clip, + clip_rect, + ); + } + + if let Some(image_mask) = self.to_image_mask(&yaml["image-mask"], wrench) { + space_and_clip.clip_id = dl.define_clip_image_mask( + &space_and_clip, + image_mask, + ); + } + + for complex_clip in complex_clips { + space_and_clip.clip_id = dl.define_clip_rounded_rect( + &space_and_clip, + complex_clip, + ); + } + + if let Some(numeric_id) = numeric_id { + self.add_clip_id_mapping(numeric_id as u64, space_and_clip.clip_id); + self.add_spatial_id_mapping(numeric_id as u64, space_and_clip.spatial_id); + } + + if !yaml["items"].is_badvalue() { + self.clip_id_stack.push(space_and_clip.clip_id); + self.add_display_list_items_from_yaml(dl, wrench, &yaml["items"]); + self.clip_id_stack.pop().unwrap(); + } + } + + fn push_reference_frame( + &mut self, + dl: &mut DisplayListBuilder, + wrench: &mut Wrench, + yaml: &Yaml, + ) -> SpatialId { + let default_bounds = LayoutRect::new(LayoutPoint::zero(), wrench.window_size_f32()); + let bounds = yaml["bounds"].as_rect().unwrap_or(default_bounds); + let default_transform_origin = LayoutPoint::new( + bounds.origin.x + bounds.size.width * 0.5, + bounds.origin.y + bounds.size.height * 0.5, + ); + + let transform_style = yaml["transform-style"] + .as_transform_style() + .unwrap_or(TransformStyle::Flat); + + let transform_origin = yaml["transform-origin"] + .as_point() + .unwrap_or(default_transform_origin); + + let perspective_origin = yaml["perspective-origin"] + .as_point() + .unwrap_or(default_transform_origin); + + assert!( + yaml["transform"].is_badvalue() || + yaml["perspective"].is_badvalue(), + "Should have one of either transform or perspective" + ); + + let reference_frame_kind = if !yaml["perspective"].is_badvalue() { + ReferenceFrameKind::Perspective { scrolling_relative_to: None } + } else { + ReferenceFrameKind::Transform + }; + + let transform = yaml["transform"] + .as_transform(&transform_origin); + + let perspective = match yaml["perspective"].as_f32() { + Some(value) if value != 0.0 => { + Some(make_perspective(perspective_origin, value as f32)) + } + Some(..) => None, + _ => yaml["perspective"].as_matrix4d(), + }; + + let reference_frame_id = dl.push_reference_frame( + bounds.origin, + *self.spatial_id_stack.last().unwrap(), + transform_style, + transform.or_else(|| perspective).unwrap_or_default().into(), + reference_frame_kind, + ); + + let numeric_id = yaml["id"].as_i64(); + if let Some(numeric_id) = numeric_id { + self.add_spatial_id_mapping(numeric_id as u64, reference_frame_id); + } + + reference_frame_id + } + + fn handle_reference_frame( + &mut self, + dl: &mut DisplayListBuilder, + wrench: &mut Wrench, + yaml: &Yaml, + ) { + let real_id = self.push_reference_frame(dl, wrench, yaml); + self.spatial_id_stack.push(real_id); + + if !yaml["items"].is_badvalue() { + self.add_display_list_items_from_yaml(dl, wrench, &yaml["items"]); + } + + self.spatial_id_stack.pop().unwrap(); + dl.pop_reference_frame(); + } + + fn add_stacking_context_from_yaml( + &mut self, + dl: &mut DisplayListBuilder, + wrench: &mut Wrench, + yaml: &Yaml, + is_root: bool, + info: &mut CommonItemProperties, + ) { + let default_bounds = LayoutRect::new(LayoutPoint::zero(), wrench.window_size_f32()); + let mut bounds = yaml["bounds"].as_rect().unwrap_or(default_bounds); + + let reference_frame_id = if !yaml["transform"].is_badvalue() || + !yaml["perspective"].is_badvalue() { + let reference_frame_id = self.push_reference_frame(dl, wrench, yaml); + self.spatial_id_stack.push(reference_frame_id); + bounds.origin = LayoutPoint::zero(); + Some(reference_frame_id) + } else { + None + }; + + let clip_node_id = self.to_clip_id(&yaml["clip-node"], dl.pipeline_id); + + let transform_style = yaml["transform-style"] + .as_transform_style() + .unwrap_or(TransformStyle::Flat); + let mix_blend_mode = yaml["mix-blend-mode"] + .as_mix_blend_mode() + .unwrap_or(MixBlendMode::Normal); + let raster_space = yaml["raster-space"] + .as_raster_space() + .unwrap_or(RasterSpace::Screen); + let is_backdrop_root = yaml["backdrop-root"].as_bool().unwrap_or(false); + let is_blend_container = yaml["blend-container"].as_bool().unwrap_or(false); + + if is_root { + if let Some(size) = yaml["scroll-offset"].as_point() { + let external_id = ExternalScrollId(0, dl.pipeline_id); + self.scroll_offsets.insert(external_id, LayoutPoint::new(size.x, size.y)); + } + } + + let filters = yaml["filters"].as_vec_filter_op().unwrap_or(vec![]); + let filter_datas = yaml["filter-datas"].as_vec_filter_data().unwrap_or(vec![]); + let filter_primitives = yaml["filter-primitives"].as_vec_filter_primitive().unwrap_or(vec![]); + + let mut flags = StackingContextFlags::empty(); + if is_backdrop_root { + flags |= StackingContextFlags::IS_BACKDROP_ROOT; + } + if is_blend_container { + flags |= StackingContextFlags::IS_BLEND_CONTAINER; + } + + dl.push_stacking_context( + bounds.origin, + *self.spatial_id_stack.last().unwrap(), + info.flags, + clip_node_id, + transform_style, + mix_blend_mode, + &filters, + &filter_datas, + &filter_primitives, + raster_space, + flags, + ); + + if !yaml["items"].is_badvalue() { + self.add_display_list_items_from_yaml(dl, wrench, &yaml["items"]); + } + + dl.pop_stacking_context(); + + if reference_frame_id.is_some() { + self.spatial_id_stack.pop().unwrap(); + dl.pop_reference_frame(); + } + } + + fn handle_backdrop_filter( + &mut self, + dl: &mut DisplayListBuilder, + item: &Yaml, + info: &mut CommonItemProperties, + ) { + info.clip_rect = try_intersect!( + self.resolve_rect(&item["bounds"]), + &info.clip_rect + ); + + let filters = item["filters"].as_vec_filter_op().unwrap_or(vec![]); + let filter_datas = item["filter-datas"].as_vec_filter_data().unwrap_or(vec![]); + let filter_primitives = item["filter-primitives"].as_vec_filter_primitive().unwrap_or(vec![]); + + dl.push_backdrop_filter( + &info, + &filters, + &filter_datas, + &filter_primitives, + ); + } +} + +impl WrenchThing for YamlFrameReader { + fn do_frame(&mut self, wrench: &mut Wrench) -> u32 { + let mut should_build_yaml = false; + + // If YAML isn't read yet, or watching source file, reload from disk. + if self.yaml_string.is_empty() || self.watch_source { + let mut file = File::open(&self.yaml_path) + .unwrap_or_else(|_| panic!("YAML '{:?}' doesn't exist", self.yaml_path)); + self.yaml_string.clear(); + file.read_to_string(&mut self.yaml_string).unwrap(); + should_build_yaml = true; + } + + // Evaluate conditions that require parsing the YAML. + if self.built_frame != self.requested_frame { + // Requested frame has changed + should_build_yaml = true; + } + + // Build the DL from YAML if required + if should_build_yaml { + self.build(wrench); + } + + // Determine whether to send a new DL, or just refresh. + if should_build_yaml || wrench.should_rebuild_display_lists() { + wrench.begin_frame(); + wrench.send_lists( + self.frame_count, + self.display_lists.clone(), + &self.scroll_offsets, + ); + } else { + wrench.refresh(); + } + + self.frame_count += 1; + self.frame_count + } + + fn next_frame(&mut self) { + let mut max_frame_count = 0; + if let Some(ref keyframes) = self.keyframes { + for (_, values) in keyframes.as_hash().unwrap() { + max_frame_count = max_frame_count.max(values.as_vec().unwrap().len()); + } + } + if self.requested_frame + 1 < max_frame_count { + self.requested_frame += 1; + } + } + + fn prev_frame(&mut self) { + if self.requested_frame > 0 { + self.requested_frame -= 1; + } + } +} diff --git a/gfx/wr/wrench/src/yaml_helper.rs b/gfx/wr/wrench/src/yaml_helper.rs new file mode 100644 index 0000000000..dc55b1e860 --- /dev/null +++ b/gfx/wr/wrench/src/yaml_helper.rs @@ -0,0 +1,806 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +use euclid::{Angle, Size2D}; +use crate::parse_function::parse_function; +use std::f32; +use std::str::FromStr; +use webrender::api::*; +use webrender::api::units::*; +use yaml_rust::{Yaml, YamlLoader}; + +pub trait YamlHelper { + fn as_f32(&self) -> Option<f32>; + fn as_force_f32(&self) -> Option<f32>; + fn as_vec_f32(&self) -> Option<Vec<f32>>; + fn as_vec_u32(&self) -> Option<Vec<u32>>; + fn as_vec_u64(&self) -> Option<Vec<u64>>; + fn as_pipeline_id(&self) -> Option<PipelineId>; + fn as_rect(&self) -> Option<LayoutRect>; + fn as_size(&self) -> Option<LayoutSize>; + fn as_point(&self) -> Option<LayoutPoint>; + fn as_vector(&self) -> Option<LayoutVector2D>; + fn as_matrix4d(&self) -> Option<LayoutTransform>; + fn as_transform(&self, transform_origin: &LayoutPoint) -> Option<LayoutTransform>; + fn as_colorf(&self) -> Option<ColorF>; + fn as_vec_colorf(&self) -> Option<Vec<ColorF>>; + fn as_px_to_f32(&self) -> Option<f32>; + fn as_pt_to_f32(&self) -> Option<f32>; + fn as_vec_string(&self) -> Option<Vec<String>>; + fn as_border_radius_component(&self) -> LayoutSize; + fn as_border_radius(&self) -> Option<BorderRadius>; + fn as_transform_style(&self) -> Option<TransformStyle>; + fn as_raster_space(&self) -> Option<RasterSpace>; + fn as_clip_mode(&self) -> Option<ClipMode>; + fn as_mix_blend_mode(&self) -> Option<MixBlendMode>; + fn as_filter_op(&self) -> Option<FilterOp>; + fn as_vec_filter_op(&self) -> Option<Vec<FilterOp>>; + fn as_filter_data(&self) -> Option<FilterData>; + fn as_vec_filter_data(&self) -> Option<Vec<FilterData>>; + fn as_filter_input(&self) -> Option<FilterPrimitiveInput>; + fn as_filter_primitive(&self) -> Option<FilterPrimitive>; + fn as_vec_filter_primitive(&self) -> Option<Vec<FilterPrimitive>>; + fn as_color_space(&self) -> Option<ColorSpace>; +} + +fn string_to_color(color: &str) -> Option<ColorF> { + match color { + "red" => Some(ColorF::new(1.0, 0.0, 0.0, 1.0)), + "green" => Some(ColorF::new(0.0, 1.0, 0.0, 1.0)), + "blue" => Some(ColorF::new(0.0, 0.0, 1.0, 1.0)), + "white" => Some(ColorF::new(1.0, 1.0, 1.0, 1.0)), + "black" => Some(ColorF::new(0.0, 0.0, 0.0, 1.0)), + "yellow" => Some(ColorF::new(1.0, 1.0, 0.0, 1.0)), + "transparent" => Some(ColorF::new(1.0, 1.0, 1.0, 0.0)), + s => { + let items: Vec<f32> = s.split_whitespace() + .map(|s| f32::from_str(s).unwrap()) + .collect(); + if items.len() == 3 { + Some(ColorF::new( + items[0] / 255.0, + items[1] / 255.0, + items[2] / 255.0, + 1.0, + )) + } else if items.len() == 4 { + Some(ColorF::new( + items[0] / 255.0, + items[1] / 255.0, + items[2] / 255.0, + items[3], + )) + } else { + None + } + } + } +} + +pub trait StringEnum: Sized { + fn from_str(_: &str) -> Option<Self>; + fn as_str(&self) -> &'static str; +} + +macro_rules! define_string_enum { + ($T:ident, [ $( $y:ident = $x:expr ),* ]) => { + impl StringEnum for $T { + fn from_str(text: &str) -> Option<$T> { + match text { + $( $x => Some($T::$y), )* + _ => { + println!("Unrecognized {} value '{}'", stringify!($T), text); + None + } + } + } + fn as_str(&self) -> &'static str { + match *self { + $( $T::$y => $x, )* + } + } + } + } +} + +define_string_enum!(TransformStyle, [Flat = "flat", Preserve3D = "preserve-3d"]); + +define_string_enum!( + MixBlendMode, + [ + Normal = "normal", + Multiply = "multiply", + Screen = "screen", + Overlay = "overlay", + Darken = "darken", + Lighten = "lighten", + ColorDodge = "color-dodge", + ColorBurn = "color-burn", + HardLight = "hard-light", + SoftLight = "soft-light", + Difference = "difference", + Exclusion = "exclusion", + Hue = "hue", + Saturation = "saturation", + Color = "color", + Luminosity = "luminosity" + ] +); + +define_string_enum!( + LineOrientation, + [Horizontal = "horizontal", Vertical = "vertical"] +); + +define_string_enum!( + LineStyle, + [ + Solid = "solid", + Dotted = "dotted", + Dashed = "dashed", + Wavy = "wavy" + ] +); + +define_string_enum!(ClipMode, [Clip = "clip", ClipOut = "clip-out"]); + +define_string_enum!( + ComponentTransferFuncType, + [ + Identity = "Identity", + Table = "Table", + Discrete = "Discrete", + Linear = "Linear", + Gamma = "Gamma" + ] +); + +define_string_enum!( + ColorSpace, + [ + Srgb = "srgb", + LinearRgb = "linear-rgb" + ] +); + +// Rotate around `axis` by `degrees` angle +fn make_rotation( + origin: &LayoutPoint, + degrees: f32, + axis_x: f32, + axis_y: f32, + axis_z: f32, +) -> LayoutTransform { + let pre_transform = LayoutTransform::translation(-origin.x, -origin.y, -0.0); + let post_transform = LayoutTransform::translation(origin.x, origin.y, 0.0); + + let theta = 2.0f32 * f32::consts::PI - degrees.to_radians(); + let transform = + LayoutTransform::identity().pre_rotate(axis_x, axis_y, axis_z, Angle::radians(theta)); + + pre_transform.then(&transform).then(&post_transform) +} + +pub fn make_perspective( + origin: LayoutPoint, + perspective: f32, +) -> LayoutTransform { + let pre_transform = LayoutTransform::translation(-origin.x, -origin.y, -0.0); + let post_transform = LayoutTransform::translation(origin.x, origin.y, 0.0); + let transform = LayoutTransform::perspective(perspective); + pre_transform.then(&transform).then(&post_transform) +} + +// Create a skew matrix, specified in degrees. +fn make_skew( + skew_x: f32, + skew_y: f32, +) -> LayoutTransform { + let alpha = Angle::radians(skew_x.to_radians()); + let beta = Angle::radians(skew_y.to_radians()); + LayoutTransform::skew(alpha, beta) +} + +impl YamlHelper for Yaml { + fn as_f32(&self) -> Option<f32> { + match *self { + Yaml::Integer(iv) => Some(iv as f32), + Yaml::Real(ref sv) => f32::from_str(sv.as_str()).ok(), + _ => None, + } + } + + fn as_force_f32(&self) -> Option<f32> { + match *self { + Yaml::Integer(iv) => Some(iv as f32), + Yaml::String(ref sv) | Yaml::Real(ref sv) => f32::from_str(sv.as_str()).ok(), + _ => None, + } + } + + fn as_vec_f32(&self) -> Option<Vec<f32>> { + match *self { + Yaml::String(ref s) | Yaml::Real(ref s) => s.split_whitespace() + .map(|v| f32::from_str(v)) + .collect::<Result<Vec<_>, _>>() + .ok(), + Yaml::Array(ref v) => v.iter() + .map(|v| match *v { + Yaml::Integer(k) => Ok(k as f32), + Yaml::String(ref k) | Yaml::Real(ref k) => f32::from_str(k).map_err(|_| false), + _ => Err(false), + }) + .collect::<Result<Vec<_>, _>>() + .ok(), + Yaml::Integer(k) => Some(vec![k as f32]), + _ => None, + } + } + + fn as_vec_u32(&self) -> Option<Vec<u32>> { + if let Some(v) = self.as_vec() { + Some(v.iter().map(|v| v.as_i64().unwrap() as u32).collect()) + } else { + None + } + } + + fn as_vec_u64(&self) -> Option<Vec<u64>> { + if let Some(v) = self.as_vec() { + Some(v.iter().map(|v| v.as_i64().unwrap() as u64).collect()) + } else { + None + } + } + + fn as_pipeline_id(&self) -> Option<PipelineId> { + if let Some(v) = self.as_vec() { + let a = v.get(0).and_then(|v| v.as_i64()).map(|v| v as u32); + let b = v.get(1).and_then(|v| v.as_i64()).map(|v| v as u32); + match (a, b) { + (Some(a), Some(b)) if v.len() == 2 => Some(PipelineId(a, b)), + _ => None, + } + } else { + None + } + } + + fn as_px_to_f32(&self) -> Option<f32> { + self.as_force_f32() + } + + fn as_pt_to_f32(&self) -> Option<f32> { + self.as_force_f32().map(|fv| fv * 16. / 12.) + } + + fn as_rect(&self) -> Option<LayoutRect> { + if self.is_badvalue() { + return None; + } + + if let Some(nums) = self.as_vec_f32() { + if nums.len() == 4 { + return Some(LayoutRect::new( + LayoutPoint::new(nums[0], nums[1]), + LayoutSize::new(nums[2], nums[3]), + )); + } + } + + None + } + + fn as_size(&self) -> Option<LayoutSize> { + if self.is_badvalue() { + return None; + } + + if let Some(nums) = self.as_vec_f32() { + if nums.len() == 2 { + return Some(LayoutSize::new(nums[0], nums[1])); + } + } + + None + } + + fn as_point(&self) -> Option<LayoutPoint> { + if self.is_badvalue() { + return None; + } + + if let Some(nums) = self.as_vec_f32() { + if nums.len() == 2 { + return Some(LayoutPoint::new(nums[0], nums[1])); + } + } + + None + } + + fn as_vector(&self) -> Option<LayoutVector2D> { + self.as_point().map(|p| p.to_vector()) + } + + fn as_matrix4d(&self) -> Option<LayoutTransform> { + if let Some(nums) = self.as_vec_f32() { + assert_eq!(nums.len(), 16, "expected 16 floats, got '{:?}'", self); + Some(LayoutTransform::new( + nums[0], nums[1], nums[2], nums[3], + nums[4], nums[5], nums[6], nums[7], + nums[8], nums[9], nums[10], nums[11], + nums[12], nums[13], nums[14], nums[15], + )) + } else { + None + } + } + + fn as_transform(&self, transform_origin: &LayoutPoint) -> Option<LayoutTransform> { + if let Some(transform) = self.as_matrix4d() { + return Some(transform); + } + + match *self { + Yaml::String(ref string) => { + let mut slice = string.as_str(); + let mut transform = LayoutTransform::identity(); + while !slice.is_empty() { + let (function, ref args, reminder) = parse_function(slice); + slice = reminder; + let mx = match function { + "translate" if args.len() >= 2 => { + let z = args.get(2).and_then(|a| a.parse().ok()).unwrap_or(0.); + LayoutTransform::translation( + args[0].parse().unwrap(), + args[1].parse().unwrap(), + z, + ) + } + "rotate" | "rotate-z" if args.len() == 1 => { + make_rotation(transform_origin, args[0].parse().unwrap(), 0.0, 0.0, 1.0) + } + "rotate-x" if args.len() == 1 => { + make_rotation(transform_origin, args[0].parse().unwrap(), 1.0, 0.0, 0.0) + } + "rotate-y" if args.len() == 1 => { + make_rotation(transform_origin, args[0].parse().unwrap(), 0.0, 1.0, 0.0) + } + "scale" if args.len() >= 1 => { + let x = args[0].parse().unwrap(); + // Default to uniform X/Y scale if Y unspecified. + let y = args.get(1).and_then(|a| a.parse().ok()).unwrap_or(x); + // Default to no Z scale if unspecified. + let z = args.get(2).and_then(|a| a.parse().ok()).unwrap_or(1.0); + LayoutTransform::scale(x, y, z) + } + "scale-x" if args.len() == 1 => { + LayoutTransform::scale(args[0].parse().unwrap(), 1.0, 1.0) + } + "scale-y" if args.len() == 1 => { + LayoutTransform::scale(1.0, args[0].parse().unwrap(), 1.0) + } + "scale-z" if args.len() == 1 => { + LayoutTransform::scale(1.0, 1.0, args[0].parse().unwrap()) + } + "skew" if args.len() >= 1 => { + // Default to no Y skew if unspecified. + let skew_y = args.get(1).and_then(|a| a.parse().ok()).unwrap_or(0.0); + make_skew(args[0].parse().unwrap(), skew_y) + } + "skew-x" if args.len() == 1 => { + make_skew(args[0].parse().unwrap(), 0.0) + } + "skew-y" if args.len() == 1 => { + make_skew(0.0, args[0].parse().unwrap()) + } + "perspective" if args.len() == 1 => { + LayoutTransform::perspective(args[0].parse().unwrap()) + } + _ => { + println!("unknown function {}", function); + break; + } + }; + transform = transform.then(&mx); + } + Some(transform) + } + Yaml::Array(ref array) => { + let transform = array.iter().fold( + LayoutTransform::identity(), + |u, yaml| match yaml.as_transform(transform_origin) { + Some(ref transform) => transform.then(&u), + None => u, + }, + ); + Some(transform) + } + Yaml::BadValue => None, + _ => { + println!("unknown transform {:?}", self); + None + } + } + } + + fn as_colorf(&self) -> Option<ColorF> { + if let Some(mut nums) = self.as_vec_f32() { + assert!( + nums.len() == 3 || nums.len() == 4, + "color expected a color name, or 3-4 floats; got '{:?}'", + self + ); + + if nums.len() == 3 { + nums.push(1.0); + } + assert!(nums[3] >= 0.0 && nums[3] <= 1.0, + "alpha value should be in the 0-1 range, got {:?}", + nums[3]); + return Some(ColorF::new( + nums[0] / 255.0, + nums[1] / 255.0, + nums[2] / 255.0, + nums[3], + )); + } + + if let Some(s) = self.as_str() { + string_to_color(s) + } else { + None + } + } + + fn as_vec_colorf(&self) -> Option<Vec<ColorF>> { + if let Some(v) = self.as_vec() { + Some(v.iter().map(|v| v.as_colorf().unwrap()).collect()) + } else if let Some(color) = self.as_colorf() { + Some(vec![color]) + } else { + None + } + } + + fn as_vec_string(&self) -> Option<Vec<String>> { + if let Some(v) = self.as_vec() { + Some(v.iter().map(|v| v.as_str().unwrap().to_owned()).collect()) + } else if let Some(s) = self.as_str() { + Some(vec![s.to_owned()]) + } else { + None + } + } + + fn as_border_radius_component(&self) -> LayoutSize { + if let Yaml::Integer(integer) = *self { + return LayoutSize::new(integer as f32, integer as f32); + } + self.as_size().unwrap_or(Size2D::zero()) + } + + fn as_border_radius(&self) -> Option<BorderRadius> { + if let Some(size) = self.as_size() { + return Some(BorderRadius::uniform_size(size)); + } + + match *self { + Yaml::BadValue => None, + Yaml::String(ref s) | Yaml::Real(ref s) => { + let fv = f32::from_str(s).unwrap(); + Some(BorderRadius::uniform(fv)) + } + Yaml::Integer(v) => Some(BorderRadius::uniform(v as f32)), + Yaml::Array(ref array) if array.len() == 4 => { + let top_left = array[0].as_border_radius_component(); + let top_right = array[1].as_border_radius_component(); + let bottom_left = array[2].as_border_radius_component(); + let bottom_right = array[3].as_border_radius_component(); + Some(BorderRadius { + top_left, + top_right, + bottom_left, + bottom_right, + }) + } + Yaml::Hash(_) => { + let top_left = self["top-left"].as_border_radius_component(); + let top_right = self["top-right"].as_border_radius_component(); + let bottom_left = self["bottom-left"].as_border_radius_component(); + let bottom_right = self["bottom-right"].as_border_radius_component(); + Some(BorderRadius { + top_left, + top_right, + bottom_left, + bottom_right, + }) + } + _ => { + panic!("Invalid border radius specified: {:?}", self); + } + } + } + + fn as_transform_style(&self) -> Option<TransformStyle> { + self.as_str().and_then(|x| StringEnum::from_str(x)) + } + + fn as_raster_space(&self) -> Option<RasterSpace> { + self.as_str().and_then(|s| { + match parse_function(s) { + ("screen", _, _) => { + Some(RasterSpace::Screen) + } + ("local", ref args, _) if args.len() == 1 => { + Some(RasterSpace::Local(args[0].parse().unwrap())) + } + f => { + panic!("error parsing raster space {:?}", f); + } + } + }) + } + + fn as_mix_blend_mode(&self) -> Option<MixBlendMode> { + self.as_str().and_then(|x| StringEnum::from_str(x)) + } + + fn as_clip_mode(&self) -> Option<ClipMode> { + self.as_str().and_then(|x| StringEnum::from_str(x)) + } + + fn as_filter_op(&self) -> Option<FilterOp> { + if let Some(s) = self.as_str() { + match parse_function(s) { + ("identity", _, _) => { + Some(FilterOp::Identity) + } + ("component-transfer", _, _) => { + Some(FilterOp::ComponentTransfer) + } + ("blur", ref args, _) if args.len() == 2 => { + Some(FilterOp::Blur(args[0].parse().unwrap(), args[1].parse().unwrap())) + } + ("brightness", ref args, _) if args.len() == 1 => { + Some(FilterOp::Brightness(args[0].parse().unwrap())) + } + ("contrast", ref args, _) if args.len() == 1 => { + Some(FilterOp::Contrast(args[0].parse().unwrap())) + } + ("grayscale", ref args, _) if args.len() == 1 => { + Some(FilterOp::Grayscale(args[0].parse().unwrap())) + } + ("hue-rotate", ref args, _) if args.len() == 1 => { + Some(FilterOp::HueRotate(args[0].parse().unwrap())) + } + ("invert", ref args, _) if args.len() == 1 => { + Some(FilterOp::Invert(args[0].parse().unwrap())) + } + ("opacity", ref args, _) if args.len() == 1 => { + let amount: f32 = args[0].parse().unwrap(); + Some(FilterOp::Opacity(amount.into(), amount)) + } + ("saturate", ref args, _) if args.len() == 1 => { + Some(FilterOp::Saturate(args[0].parse().unwrap())) + } + ("sepia", ref args, _) if args.len() == 1 => { + Some(FilterOp::Sepia(args[0].parse().unwrap())) + } + ("srgb-to-linear", _, _) => Some(FilterOp::SrgbToLinear), + ("linear-to-srgb", _, _) => Some(FilterOp::LinearToSrgb), + ("drop-shadow", ref args, _) if args.len() == 3 => { + let str = format!("---\noffset: {}\nblur-radius: {}\ncolor: {}\n", args[0], args[1], args[2]); + let mut yaml_doc = YamlLoader::load_from_str(&str).expect("Failed to parse drop-shadow"); + let yaml = yaml_doc.pop().unwrap(); + Some(FilterOp::DropShadow(Shadow { + offset: yaml["offset"].as_vector().unwrap(), + blur_radius: yaml["blur-radius"].as_f32().unwrap(), + color: yaml["color"].as_colorf().unwrap() + })) + } + ("color-matrix", ref args, _) if args.len() == 20 => { + let m: Vec<f32> = args.iter().map(|f| f.parse().unwrap()).collect(); + let mut matrix: [f32; 20] = [0.0; 20]; + matrix.clone_from_slice(&m); + Some(FilterOp::ColorMatrix(matrix)) + } + ("flood", ref args, _) if args.len() == 1 => { + let str = format!("---\ncolor: {}\n", args[0]); + let mut yaml_doc = YamlLoader::load_from_str(&str).expect("Failed to parse flood"); + let yaml = yaml_doc.pop().unwrap(); + Some(FilterOp::Flood(yaml["color"].as_colorf().unwrap())) + } + (_, _, _) => None, + } + } else { + None + } + } + + fn as_vec_filter_op(&self) -> Option<Vec<FilterOp>> { + if let Some(v) = self.as_vec() { + Some(v.iter().map(|x| x.as_filter_op().unwrap()).collect()) + } else { + self.as_filter_op().map(|op| vec![op]) + } + } + + fn as_filter_data(&self) -> Option<FilterData> { + // Parse an array with five entries. First entry is an array of func types (4). + // The remaining entries are arrays of floats. + if let Yaml::Array(ref array) = *self { + if array.len() != 5 { + panic!("Invalid filter data specified, base array doesn't have five entries: {:?}", self); + } + if let Some(func_types_p) = array[0].as_vec_string() { + if func_types_p.len() != 4 { + panic!("Invalid filter data specified, func type array doesn't have five entries: {:?}", self); + } + let func_types: Vec<ComponentTransferFuncType> = + func_types_p.into_iter().map(|x| { match StringEnum::from_str(&x) { + Some(y) => y, + None => panic!("Invalid filter data specified, invalid func type name: {:?}", self), + }}).collect(); + if let Some(r_values_p) = array[1].as_vec_f32() { + if let Some(g_values_p) = array[2].as_vec_f32() { + if let Some(b_values_p) = array[3].as_vec_f32() { + if let Some(a_values_p) = array[4].as_vec_f32() { + let filter_data = FilterData { + func_r_type: func_types[0], + r_values: r_values_p, + func_g_type: func_types[1], + g_values: g_values_p, + func_b_type: func_types[2], + b_values: b_values_p, + func_a_type: func_types[3], + a_values: a_values_p, + }; + return Some(filter_data) + } + } + } + } + } + } + None + } + + fn as_filter_input(&self) -> Option<FilterPrimitiveInput> { + if let Some(input) = self.as_str() { + match input { + "original" => Some(FilterPrimitiveInput::Original), + "previous" => Some(FilterPrimitiveInput::Previous), + _ => None, + } + } else if let Some(index) = self.as_i64() { + if index >= 0 { + Some(FilterPrimitiveInput::OutputOfPrimitiveIndex(index as usize)) + } else { + panic!("Filter input index cannot be negative"); + } + } else { + panic!("Invalid filter input"); + } + } + + fn as_vec_filter_data(&self) -> Option<Vec<FilterData>> { + if let Some(v) = self.as_vec() { + Some(v.iter().map(|x| x.as_filter_data().unwrap()).collect()) + } else { + self.as_filter_data().map(|data| vec![data]) + } + } + + fn as_filter_primitive(&self) -> Option<FilterPrimitive> { + if let Some(filter_type) = self["type"].as_str() { + let kind = match filter_type { + "identity" => { + FilterPrimitiveKind::Identity(IdentityPrimitive { + input: self["in"].as_filter_input().unwrap(), + }) + } + "blend" => { + FilterPrimitiveKind::Blend(BlendPrimitive { + input1: self["in1"].as_filter_input().unwrap(), + input2: self["in2"].as_filter_input().unwrap(), + mode: self["blend-mode"].as_mix_blend_mode().unwrap(), + }) + } + "flood" => { + FilterPrimitiveKind::Flood(FloodPrimitive { + color: self["color"].as_colorf().unwrap(), + }) + } + "blur" => { + FilterPrimitiveKind::Blur(BlurPrimitive { + input: self["in"].as_filter_input().unwrap(), + width: self["width"].as_f32().unwrap(), + height: self["height"].as_f32().unwrap(), + }) + } + "opacity" => { + FilterPrimitiveKind::Opacity(OpacityPrimitive { + input: self["in"].as_filter_input().unwrap(), + opacity: self["opacity"].as_f32().unwrap(), + }) + } + "color-matrix" => { + let m: Vec<f32> = self["matrix"].as_vec_f32().unwrap(); + let mut matrix: [f32; 20] = [0.0; 20]; + matrix.clone_from_slice(&m); + + FilterPrimitiveKind::ColorMatrix(ColorMatrixPrimitive { + input: self["in"].as_filter_input().unwrap(), + matrix, + }) + } + "drop-shadow" => { + FilterPrimitiveKind::DropShadow(DropShadowPrimitive { + input: self["in"].as_filter_input().unwrap(), + shadow: Shadow { + offset: self["offset"].as_vector().unwrap(), + color: self["color"].as_colorf().unwrap(), + blur_radius: self["radius"].as_f32().unwrap(), + } + }) + } + "component-transfer" => { + FilterPrimitiveKind::ComponentTransfer(ComponentTransferPrimitive { + input: self["in"].as_filter_input().unwrap(), + }) + } + "offset" => { + FilterPrimitiveKind::Offset(OffsetPrimitive { + input: self["in"].as_filter_input().unwrap(), + offset: self["offset"].as_vector().unwrap(), + }) + } + "composite" => { + let operator = match self["operator"].as_str().unwrap() { + "over" => CompositeOperator::Over, + "in" => CompositeOperator::In, + "out" => CompositeOperator::Out, + "atop" => CompositeOperator::Atop, + "xor" => CompositeOperator::Xor, + "lighter" => CompositeOperator::Lighter, + "arithmetic" => { + let k_vals = self["k-values"].as_vec_f32().unwrap(); + assert!(k_vals.len() == 4, "Must be 4 k values for arithmetic composite operator"); + let k_vals = [k_vals[0], k_vals[1], k_vals[2], k_vals[3]]; + CompositeOperator::Arithmetic(k_vals) + } + _ => panic!("Invalid composite operator"), + }; + FilterPrimitiveKind::Composite(CompositePrimitive { + input1: self["in1"].as_filter_input().unwrap(), + input2: self["in2"].as_filter_input().unwrap(), + operator, + }) + } + _ => return None, + }; + + Some(FilterPrimitive { + kind, + color_space: self["color-space"].as_color_space().unwrap_or(ColorSpace::LinearRgb), + }) + } else { + None + } + } + + fn as_vec_filter_primitive(&self) -> Option<Vec<FilterPrimitive>> { + if let Some(v) = self.as_vec() { + Some(v.iter().map(|x| x.as_filter_primitive().unwrap()).collect()) + } else { + self.as_filter_primitive().map(|data| vec![data]) + } + } + + fn as_color_space(&self) -> Option<ColorSpace> { + self.as_str().and_then(|x| StringEnum::from_str(x)) + } +} |