diff --git a/android/app/src/main/java/io/github/artcraftandroid/procraft/ui/Icons.kt b/android/app/src/main/java/io/github/artcraftandroid/procraft/ui/Icons.kt
index 53fde9ef..4a75c3bc 100644
--- a/android/app/src/main/java/io/github/artcraftandroid/procraft/ui/Icons.kt
+++ b/android/app/src/main/java/io/github/artcraftandroid/procraft/ui/Icons.kt
@@ -89,6 +89,7 @@ object PcIcons {
"Linear Burn" to ours("blend-linear-burn", 26f, "M14.35 6.44L14.27 6.49L12.12 10.46L12.03 10.64L11.91 11.02L11.85 11.41L11.84 11.61L11.87 12L11.96 12.39L12.03 12.57L12.21 12.93L12.32 13.09L12.58 13.4L12.88 13.65L13.22 13.86L13.4 13.94L13.78 14.07L14.17 14.13L14.37 14.14L14.57 14.13L14.96 14.07L15.34 13.94L15.52 13.86L15.86 13.65L16.16 13.4L16.42 13.09L16.62 12.76L16.71 12.57L16.83 12.2L16.89 11.81L16.9 11.61L16.89 11.41L16.83 11.02L16.78 10.82L16.62 10.46L14.47 6.49L14.42 6.45ZM14.39 10.4L14.47 10.45L15.25 12.04L15.33 12.26L15.36 12.49L15.35 12.64L15.28 12.87L15.17 13.07L15.07 13.19L14.95 13.29L14.75 13.4L14.6 13.45L14.37 13.48L14.22 13.46L13.99 13.4L13.79 13.29L13.67 13.19L13.57 13.07L13.46 12.87L13.41 12.72L13.38 12.49L13.41 12.26L13.49 12.04L14.27 10.45L14.32 10.41ZM18.69 16.23L18.84 16.13L18.95 16L19.01 15.89L19.04 15.78L19.04 15.6L18.99 15.43L18.93 15.33L18.85 15.24L18.71 15.13L18.54 15.08L18.42 15.07L18.3 15.09L14.37 15.99L10.44 15.09L10.32 15.07L10.2 15.08L10.09 15.11L9.93 15.2L9.81 15.33L9.73 15.48L9.7 15.6L9.7 15.78L9.76 15.95L9.86 16.09L9.95 16.17L10.11 16.25L11.67 16.61L10.16 16.96L10 17.02L9.86 17.13L9.76 17.28L9.7 17.45L9.7 17.62L9.73 17.74L9.78 17.85L9.84 17.94L9.93 18.03L10.03 18.09L10.14 18.13L10.26 18.15L10.38 18.15L14.37 17.23L18.3 18.14L18.42 18.15L18.54 18.14L18.71 18.09L18.85 17.99L18.93 17.9L19.01 17.74L19.04 17.62L19.04 17.45L18.98 17.28L18.88 17.13L18.79 17.05L18.63 16.97L17.07 16.61Z"),
"Darker Color" to ours("blend-darker-color", 26f, "M21.73 6.38L21.63 6.03L21.45 5.7L21.21 5.41L20.92 5.17L20.59 4.99L20.24 4.89L19.87 4.85L7.67 4.85L7.3 4.89L6.95 4.99L6.62 5.17L6.33 5.41L6.09 5.7L5.91 6.03L5.81 6.38L5.77 6.75L5.77 18.95L5.81 19.32L5.91 19.67L6.09 20L6.33 20.29L6.62 20.53L6.95 20.71L7.3 20.81L7.67 20.85L19.87 20.85L20.24 20.81L20.59 20.71L20.92 20.53L21.21 20.29L21.45 20L21.63 19.67L21.73 19.32L21.77 18.95L21.77 6.75ZM8.77 11.94L8.57 11.67L8.46 11.36L8.44 11.14L8.46 10.91L8.57 10.6L8.77 10.33L8.94 10.19L9.14 10.08L9.47 10L9.69 10L9.91 10.04L10.12 10.13L10.39 10.33L13.77 13.71L17.15 10.33L17.42 10.13L17.63 10.04L17.96 9.99L18.29 10.04L18.5 10.13L18.77 10.33L18.91 10.5L19.05 10.8L19.1 11.02L19.1 11.25L19.05 11.47L18.91 11.77L18.77 11.94L14.58 16.13L14.4 16.28L14.21 16.38L13.88 16.46L13.66 16.46L13.44 16.42L13.23 16.33L13.04 16.21Z"),
"Normal" to ours("blend-normal", 26f, "M21.92 12.8L21.88 12.01L21.76 11.22L21.57 10.45L21.3 9.7L20.96 8.98L20.55 8.3L20.08 7.66L19.55 7.07L18.96 6.54L18.32 6.07L17.64 5.66L16.92 5.32L16.17 5.05L15.4 4.86L14.61 4.74L13.82 4.7L13.03 4.74L12.24 4.86L11.47 5.05L10.72 5.32L10 5.66L9.32 6.07L8.68 6.54L8.09 7.07L7.56 7.66L7.09 8.3L6.68 8.98L6.34 9.7L6.07 10.45L5.88 11.22L5.76 12.01L5.72 12.8L5.76 13.59L5.88 14.38L6.07 15.15L6.34 15.9L6.68 16.62L7.09 17.3L7.56 17.94L8.09 18.53L8.68 19.06L9.32 19.53L10 19.94L10.72 20.28L11.47 20.55L12.24 20.74L13.03 20.86L13.82 20.9L14.61 20.86L15.4 20.74L16.17 20.55L16.92 20.28L17.64 19.94L18.32 19.53L18.96 19.06L19.55 18.53L20.08 17.94L20.55 17.3L20.96 16.62L21.3 15.9L21.57 15.15L21.76 14.38L21.88 13.59Z"),
+ "Greater" to ours("blend-greater", 26f, "M12.1 7.02L11.53 6.99L10.96 7.02L10.4 7.1L9.84 7.24L9.31 7.43L8.79 7.68L8.3 7.97L7.84 8.31L7.42 8.69L7.04 9.11L6.7 9.57L6.41 10.06L6.16 10.58L5.97 11.11L5.83 11.67L5.75 12.23L5.72 12.8L5.75 13.37L5.83 13.93L5.97 14.49L6.16 15.02L6.41 15.54L6.7 16.03L7.04 16.49L7.42 16.91L7.84 17.29L8.3 17.63L8.79 17.92L9.31 18.17L9.84 18.36L10.4 18.5L10.96 18.58L11.53 18.61L12.1 18.58L12.66 18.5L13.12 18.39L12.6 18.08L12.24 17.82L11.92 17.55L11.38 17.02L10.71 16.94L10.3 16.84L9.91 16.7L9.54 16.53L9.18 16.31L8.85 16.07L8.54 15.79L8.26 15.48L8.02 15.15L7.8 14.79L7.63 14.42L7.49 14.03L7.39 13.62L7.33 13.21L7.3 12.8L7.33 12.39L7.39 11.98L7.49 11.57L7.63 11.18L7.8 10.81L8.02 10.45L8.26 10.12L8.54 9.81L8.85 9.53L9.18 9.29L9.54 9.07L9.91 8.9L10.3 8.76L10.71 8.66L11.38 8.58L11.92 8.05L12.24 7.78L12.6 7.52L13.12 7.21L12.66 7.1ZM21.92 12.8L21.87 12.04L21.72 11.3L21.61 10.93L21.32 10.23L21.14 9.89L20.72 9.26L20.22 8.69L19.94 8.43L19.34 7.97L19.01 7.77L18.68 7.59L17.98 7.3L17.61 7.19L16.87 7.04L16.11 6.99L15.73 7L15.35 7.04L14.61 7.19L13.89 7.43L13.54 7.59L12.88 7.97L12.57 8.19L12 8.69L11.74 8.97L11.5 9.26L11.08 9.89L10.74 10.58L10.61 10.93L10.41 11.67L10.35 12.04L10.3 12.8L10.31 13.18L10.35 13.56L10.5 14.3L10.74 15.02L10.9 15.37L11.28 16.03L11.5 16.34L12 16.91L12.28 17.17L12.88 17.63L13.2 17.83L13.54 18.01L14.24 18.3L14.61 18.41L15.35 18.56L15.73 18.6L16.49 18.6L17.24 18.5L17.61 18.41L17.98 18.3L18.68 18.01L19.01 17.83L19.65 17.41L19.94 17.17L20.48 16.63L20.94 16.03L21.14 15.71L21.48 15.02L21.61 14.67L21.72 14.3L21.87 13.56Z"),
"Lighten" to ours("blend-lighten", 26f, "M14.89 3.81L14.76 3.53L14.55 3.3L14.28 3.13L13.97 3.06L13.66 3.07L13.37 3.18L13.11 3.37L12.98 3.53L12.88 3.71L12.82 3.91L12.8 4.12L12.8 6.44L12.82 6.65L12.88 6.85L13.04 7.12L13.19 7.27L13.46 7.43L13.66 7.49L13.87 7.51L14.08 7.49L14.28 7.43L14.46 7.33L14.63 7.2L14.76 7.03L14.86 6.85L14.92 6.65L14.94 6.44L14.94 4.12ZM20.99 7.18L21.1 6.89L21.11 6.58L21.04 6.27L20.94 6.09L20.8 5.92L20.55 5.74L20.26 5.63L19.94 5.62L19.64 5.69L19.45 5.79L19.29 5.92L17.65 7.56L17.52 7.73L17.42 7.91L17.34 8.21L17.34 8.42L17.42 8.73L17.52 8.91L17.65 9.08L17.81 9.21L18 9.31L18.2 9.37L18.41 9.39L18.62 9.37L18.82 9.31L19 9.21L19.16 9.08L20.8 7.44ZM8.2 5.74L7.9 5.63L7.59 5.62L7.28 5.69L7.01 5.85L6.87 6L6.75 6.18L6.64 6.47L6.63 6.79L6.7 7.09L6.8 7.27L6.94 7.44L8.58 9.08L8.74 9.21L8.92 9.31L9.23 9.38L9.44 9.38L9.74 9.31L9.93 9.21L10.09 9.08L10.22 8.91L10.32 8.73L10.38 8.53L10.4 8.32L10.38 8.11L10.32 7.91L10.22 7.73L10.09 7.56L8.45 5.92ZM4.82 11.83L4.54 11.97L4.31 12.18L4.15 12.45L4.07 12.75L4.09 13.07L4.19 13.36L4.38 13.61L4.54 13.75L4.73 13.85L4.93 13.91L5.13 13.93L7.45 13.93L7.66 13.91L7.86 13.85L8.13 13.68L8.34 13.45L8.44 13.27L8.5 13.07L8.52 12.86L8.5 12.65L8.44 12.45L8.34 12.26L8.21 12.1L8.05 11.97L7.86 11.87L7.66 11.81L7.45 11.79L5.13 11.79ZM17.79 11.67L17.66 11.29L17.49 10.92L17.28 10.58L17.04 10.26L16.77 9.96L16.47 9.69L16.15 9.45L15.8 9.24L15.44 9.07L15.06 8.93L14.67 8.84L14.27 8.78L13.87 8.76L13.47 8.78L13.07 8.84L12.68 8.93L12.3 9.07L11.94 9.24L11.59 9.45L11.27 9.69L10.97 9.96L10.7 10.26L10.46 10.58L10.25 10.92L10.08 11.29L9.95 11.67L9.85 12.06L9.79 12.46L9.77 12.86L9.79 13.26L9.85 13.66L9.95 14.05L10.08 14.43L10.25 14.79L10.46 15.14L10.7 15.46L10.97 15.76L11.27 16.03L11.59 16.27L11.94 16.47L12.3 16.65L12.68 16.78L13.07 16.88L13.47 16.94L13.87 16.96L14.27 16.94L14.67 16.88L15.06 16.78L15.44 16.65L15.8 16.47L16.15 16.27L16.47 16.03L16.77 15.76L17.04 15.46L17.28 15.14L17.49 14.79L17.66 14.43L17.79 14.05L17.89 13.66L17.95 13.26L17.97 12.86L17.95 12.46L17.89 12.06ZM22.92 13.88L23.2 13.75L23.43 13.54L23.59 13.27L23.67 12.96L23.67 12.75L23.63 12.55L23.49 12.26L23.28 12.03L23.01 11.87L22.81 11.81L22.61 11.79L20.29 11.79L20.08 11.81L19.88 11.87L19.61 12.03L19.4 12.26L19.3 12.45L19.24 12.65L19.22 12.86L19.24 13.07L19.3 13.27L19.4 13.45L19.53 13.61L19.69 13.75L19.88 13.85L20.08 13.91L20.29 13.93L22.61 13.93ZM6.75 18.53L6.64 18.83L6.63 19.14L6.7 19.44L6.87 19.71L7.1 19.92L7.38 20.06L7.59 20.1L7.8 20.1L8.1 20.02L8.29 19.92L8.45 19.79L10.09 18.15L10.22 17.99L10.32 17.8L10.4 17.5L10.4 17.29L10.32 16.99L10.22 16.8L10.09 16.64L9.93 16.51L9.74 16.41L9.54 16.35L9.33 16.33L9.12 16.35L8.92 16.41L8.74 16.51L8.58 16.64L6.94 18.28ZM19.64 20.02L19.94 20.1L20.26 20.08L20.55 19.98L20.8 19.79L20.99 19.54L21.1 19.24L21.11 18.93L21.04 18.63L20.94 18.44L20.8 18.28L19.16 16.64L19 16.51L18.72 16.37L18.51 16.33L18.3 16.33L18 16.41L17.81 16.51L17.65 16.64L17.52 16.8L17.42 16.99L17.36 17.19L17.34 17.4L17.36 17.6L17.42 17.8L17.52 17.99L17.65 18.15L19.29 19.79L19.45 19.92ZM12.88 22L13.04 22.27L13.28 22.48L13.56 22.62L13.87 22.66L14.18 22.62L14.46 22.48L14.7 22.27L14.86 22L14.92 21.8L14.94 21.59L14.94 19.28L14.92 19.07L14.86 18.87L14.7 18.6L14.46 18.39L14.28 18.29L14.08 18.23L13.87 18.21L13.66 18.23L13.46 18.29L13.28 18.39L13.11 18.52L12.98 18.68L12.88 18.87L12.82 19.07L12.8 19.28L12.8 21.59L12.82 21.8Z"),
"Screen" to ours("blend-screen", 26f, "M14.82 5.08L14.69 4.92L14.52 4.78L14.34 4.68L14.13 4.62L13.92 4.6L13.71 4.62L13.5 4.68L13.32 4.78L13.15 4.92L13.02 5.08L12.92 5.27L12.86 5.47L12.83 5.69L12.86 5.9L12.92 6.1L13.02 6.29L13.15 6.45L13.32 6.59L13.5 6.69L13.71 6.75L13.92 6.77L14.13 6.75L14.34 6.69L14.52 6.59L14.69 6.45L14.82 6.29L14.92 6.1L14.98 5.9L15.01 5.69L14.98 5.47L14.92 5.27ZM19.78 7.14L19.65 6.97L19.48 6.84L19.3 6.74L19.09 6.68L18.88 6.65L18.67 6.68L18.46 6.74L18.28 6.84L18.11 6.97L17.98 7.14L17.88 7.32L17.82 7.53L17.79 7.74L17.82 7.95L17.88 8.16L17.98 8.34L18.11 8.51L18.28 8.64L18.46 8.74L18.67 8.8L18.88 8.83L19.09 8.8L19.3 8.74L19.48 8.64L19.65 8.51L19.78 8.34L19.88 8.16L19.94 7.95L19.97 7.74L19.94 7.53L19.88 7.32ZM9.86 7.14L9.73 6.97L9.56 6.84L9.38 6.74L9.17 6.68L8.96 6.65L8.75 6.68L8.54 6.74L8.36 6.84L8.19 6.97L8.06 7.14L7.96 7.32L7.9 7.53L7.87 7.74L7.9 7.95L7.96 8.16L8.06 8.34L8.19 8.51L8.36 8.64L8.54 8.74L8.75 8.8L8.96 8.83L9.17 8.8L9.38 8.74L9.56 8.64L9.73 8.51L9.86 8.34L9.96 8.16L10.02 7.95L10.05 7.74L10.02 7.53L9.96 7.32ZM17.89 12.18L17.79 11.66L17.62 11.17L17.51 10.93L17.25 10.47L16.93 10.06L16.75 9.87L16.36 9.52L16.15 9.37L15.69 9.11L15.45 9L14.96 8.83L14.7 8.77L14.18 8.7L13.92 8.69L13.66 8.7L13.14 8.77L12.88 8.83L12.39 9L11.92 9.23L11.69 9.37L11.48 9.52L11.09 9.87L10.74 10.26L10.59 10.47L10.45 10.7L10.22 11.17L10.05 11.66L9.99 11.92L9.92 12.44L9.91 12.7L9.95 13.22L9.99 13.48L10.12 13.99L10.22 14.23L10.45 14.7L10.59 14.93L10.74 15.14L11.09 15.53L11.48 15.88L11.69 16.03L12.15 16.29L12.39 16.4L12.88 16.57L13.14 16.63L13.4 16.67L13.92 16.71L14.44 16.67L14.7 16.63L14.96 16.57L15.45 16.4L15.92 16.17L16.15 16.03L16.56 15.71L16.75 15.53L16.93 15.34L17.25 14.93L17.39 14.7L17.62 14.23L17.79 13.74L17.85 13.48L17.89 13.22L17.93 12.7ZM21.84 12.1L21.7 11.93L21.54 11.8L21.35 11.7L21.15 11.64L20.93 11.61L20.72 11.64L20.52 11.7L20.33 11.8L20.17 11.93L20.03 12.1L19.93 12.28L19.87 12.49L19.85 12.7L19.87 12.91L19.93 13.12L20.03 13.3L20.17 13.47L20.33 13.6L20.52 13.7L20.72 13.76L20.93 13.79L21.15 13.76L21.35 13.7L21.54 13.6L21.7 13.47L21.84 13.3L21.94 13.12L22 12.91L22.02 12.7L22 12.49L21.94 12.28ZM7.81 12.1L7.67 11.93L7.51 11.8L7.32 11.7L7.12 11.64L6.91 11.61L6.69 11.64L6.49 11.7L6.3 11.8L6.14 11.93L6 12.1L5.9 12.28L5.84 12.49L5.82 12.7L5.84 12.91L5.9 13.12L6 13.3L6.14 13.47L6.3 13.6L6.49 13.7L6.69 13.76L6.91 13.79L7.12 13.76L7.32 13.7L7.51 13.6L7.67 13.47L7.81 13.3L7.91 13.12L7.97 12.91L7.99 12.7L7.97 12.49L7.91 12.28ZM9.86 17.06L9.73 16.89L9.56 16.76L9.38 16.66L9.17 16.6L8.96 16.57L8.75 16.6L8.54 16.66L8.36 16.76L8.19 16.89L8.06 17.06L7.96 17.24L7.9 17.45L7.87 17.66L7.9 17.87L7.96 18.08L8.06 18.26L8.19 18.43L8.36 18.56L8.54 18.66L8.75 18.72L8.96 18.75L9.17 18.72L9.38 18.66L9.56 18.56L9.73 18.43L9.86 18.26L9.96 18.08L10.02 17.87L10.05 17.66L10.02 17.45L9.96 17.24ZM19.65 16.89L19.48 16.76L19.3 16.66L19.09 16.6L18.88 16.57L18.67 16.6L18.46 16.66L18.28 16.76L18.11 16.89L17.98 17.06L17.88 17.24L17.82 17.45L17.79 17.66L17.82 17.87L17.88 18.08L17.98 18.26L18.11 18.43L18.28 18.56L18.46 18.66L18.67 18.72L18.88 18.75L19.09 18.72L19.3 18.66L19.48 18.56L19.65 18.43L19.78 18.26L19.88 18.08L19.94 17.87L19.97 17.66L19.94 17.45L19.88 17.24L19.78 17.06ZM14.69 18.95L14.52 18.81L14.34 18.71L14.13 18.65L13.92 18.63L13.71 18.65L13.5 18.71L13.32 18.81L13.15 18.95L13.02 19.11L12.92 19.3L12.86 19.5L12.83 19.71L12.86 19.93L12.92 20.13L13.02 20.32L13.15 20.48L13.32 20.62L13.5 20.72L13.71 20.78L13.92 20.8L14.13 20.78L14.34 20.72L14.52 20.62L14.69 20.48L14.82 20.32L14.92 20.13L14.98 19.93L15.01 19.71L14.98 19.5L14.92 19.3L14.82 19.11Z"),
"Color Dodge" to ours("blend-color-dodge", 26f, "M13.72 4.98L12.07 11.04L6.07 12.66L6 12.71L5.98 12.77L6.01 12.85L6.07 12.88L12.07 14.5L13.69 20.5L13.72 20.56L13.8 20.59L13.88 20.56L13.91 20.5L15.53 14.5L21.53 12.88L21.59 12.85L21.62 12.77L21.59 12.69L21.53 12.66L15.53 11.04L13.91 5.04L13.88 4.98L13.8 4.95Z"),
diff --git a/assets/icons/procraft/blend-greater.svg b/assets/icons/procraft/blend-greater.svg
new file mode 100644
index 00000000..7051ff7e
--- /dev/null
+++ b/assets/icons/procraft/blend-greater.svg
@@ -0,0 +1,4 @@
+
diff --git a/assets/icons/slots.tsv b/assets/icons/slots.tsv
index 6c51d6a3..432567b5 100644
--- a/assets/icons/slots.tsv
+++ b/assets/icons/slots.tsv
@@ -213,6 +213,7 @@ blend-color-burn 26 26 7.56 4.8 21.47 20.5
blend-linear-burn 26 26 9.7 4.85 19.04 19.74
blend-darker-color 26 26 5.77 4.85 21.77 20.85
blend-normal 26 26 5.72 4.7 21.92 20.9
+blend-greater 26 26 5.72 4.7 21.92 20.9
blend-lighten 26 26 4.07 2.81 23.67 22.91
blend-screen 26 26 5.82 4.6 22.02 20.8
blend-color-dodge 26 26 5.96 4.95 21.64 20.59
diff --git a/crates/core/src/tests.rs b/crates/core/src/tests.rs
index 48aaff16..de2379c0 100644
--- a/crates/core/src/tests.rs
+++ b/crates/core/src/tests.rs
@@ -774,7 +774,7 @@ fn merge_duplicate_blend_and_locks() {
assert_eq!(s.layers().len(), 2);
assert!(s.set_layer_blend(copy, procraft_engine::document::BlendMode::Multiply.id()));
assert!(!s.set_layer_blend(copy, 999));
- assert_eq!(crate::layers::blend_modes().len(), 27);
+ assert_eq!(crate::layers::blend_modes().len(), 28);
assert!(s.merge_down(copy));
assert_eq!(s.layers().len(), 1);
// red multiplied by red is still red
diff --git a/crates/engine/src/document.rs b/crates/engine/src/document.rs
index d5253c8d..0efd7938 100644
--- a/crates/engine/src/document.rs
+++ b/crates/engine/src/document.rs
@@ -38,12 +38,13 @@ pub enum BlendMode {
Saturation,
Color,
Luminosity,
+ Greater,
}
impl BlendMode {
/// Every mode, in the order the layer panel lists them (grouped: darken, normal, lighten,
/// contrast, difference, colour).
- pub const ALL: [BlendMode; 27] = [
+ pub const ALL: [BlendMode; 28] = [
BlendMode::Multiply,
BlendMode::Darken,
BlendMode::Shade,
@@ -71,10 +72,11 @@ impl BlendMode {
BlendMode::Saturation,
BlendMode::Color,
BlendMode::Luminosity,
+ BlendMode::Greater,
];
/// The highest of the modes' numbers.
- pub const MAX_ID: u32 = 26;
+ pub const MAX_ID: u32 = 30;
/// The renderer's number for the mode (stable: shaders switch on it).
pub fn id(self) -> u32 {
@@ -106,6 +108,7 @@ impl BlendMode {
BlendMode::Color => 24,
BlendMode::Luminosity => 25,
BlendMode::Shade => 26,
+ BlendMode::Greater => 30,
}
}
@@ -142,6 +145,7 @@ impl BlendMode {
BlendMode::Saturation => "Saturation",
BlendMode::Color => "Color",
BlendMode::Luminosity => "Luminosity",
+ BlendMode::Greater => "Greater",
}
}
}
diff --git a/crates/engine/src/formats.rs b/crates/engine/src/formats.rs
index fba68aff..f0239657 100644
--- a/crates/engine/src/formats.rs
+++ b/crates/engine/src/formats.rs
@@ -407,6 +407,8 @@ fn blend_key(mode: BlendMode) -> &'static [u8; 4] {
BlendMode::Saturation => b"sat ",
BlendMode::Color => b"colr",
BlendMode::Luminosity => b"lum ",
+ // procreate has not "greater", "normal" is the nearest
+ BlendMode::Greater => b"norm",
}
}
diff --git a/crates/engine/src/native.rs b/crates/engine/src/native.rs
index 1d7bf3be..5f089f5a 100644
--- a/crates/engine/src/native.rs
+++ b/crates/engine/src/native.rs
@@ -1629,6 +1629,11 @@ mod tests {
#[test]
fn every_blend_mode_has_its_number() {
for m in BlendMode::ALL {
+ // Procreate has no Greater mode: it saves as Normal
+ if m == BlendMode::Greater {
+ assert_eq!(blend_from(blend_to(m)), BlendMode::Normal);
+ continue;
+ }
assert_eq!(blend_from(blend_to(m)), m, "{m:?}");
}
assert_eq!(
diff --git a/crates/engine/src/studio.rs b/crates/engine/src/studio.rs
index bf6acd4a..411d3e03 100644
--- a/crates/engine/src/studio.rs
+++ b/crates/engine/src/studio.rs
@@ -318,8 +318,8 @@ impl Brush {
// blend modes are kept by number (as the layers' are numbered; a grain's own and behind
// past them)
"blend_mode" | "burnt_blend" => {
- let id = value.round().clamp(0.0, BRUSH_BEHIND as f32);
- let known = id <= BlendMode::MAX_ID as f32 || id == BRUSH_BEHIND as f32;
+ let id = value.round().clamp(0.0, BlendMode::MAX_ID as f32);
+ let known = BlendMode::from_id(id as u32).is_some() || id == BRUSH_BEHIND as f32;
self.extra.insert(key.to_owned(), if known { id } else { 0.0 });
}
// the grain's and a dual brush's second's: a layer mode or the grain's own heights
diff --git a/crates/gpu/src/canvas.rs b/crates/gpu/src/canvas.rs
index 5ce465bd..8ba9e019 100644
--- a/crates/gpu/src/canvas.rs
+++ b/crates/gpu/src/canvas.rs
@@ -286,6 +286,11 @@ impl StrokeStyle {
}
}
+ fn brush_blend(value: f32) -> u32 {
+ let id = value.round().clamp(0.0, BlendMode::MAX_ID as f32) as u32;
+ if BlendMode::from_id(id).is_some() || id == BRUSH_BEHIND { id } else { 0 }
+ }
+
/// A stroke drawn with `brush`'s shape, grain and rendering.
pub fn for_brush(
brush: &Brush,
@@ -329,10 +334,10 @@ impl StrokeStyle {
grade: if wet { brush.setting("wet_grade").clamp(-1.0, 1.0) } else { 0.0 },
blur: if wet { brush.setting("wet_blur").clamp(0.0, 1.0) } else { 0.0 },
wet_jitter: if wet { brush.setting("wet_jitter").clamp(0.0, 1.0) } else { 0.0 },
- blend: brush.setting("blend_mode").round().clamp(0.0, BRUSH_BEHIND as f32) as u32,
+ blend: Self::brush_blend(brush.setting("blend_mode")),
blur_jitter: if wet { brush.setting("wet_blur_jitter").clamp(0.0, 1.0) } else { 0.0 },
grain_blend: brush.setting("grain_blend").round().clamp(0.0, GRAIN_LINEAR_HEIGHT as f32) as u32,
- burnt_blend: brush.setting("burnt_blend").round().clamp(0.0, BRUSH_BEHIND as f32) as u32,
+ burnt_blend: Self::brush_blend(brush.setting("burnt_blend")),
// a brush's rotation turns its grain the other way to the shaders' angle
// the editors' turn of the image, the whole grain with it (the rotation control is
// each stamp's own: `Stamp::grain_turn`)
diff --git a/crates/gpu/src/shaders/blend.wgsl b/crates/gpu/src/shaders/blend.wgsl
index 685f34b3..c76ffce5 100644
--- a/crates/gpu/src/shaders/blend.wgsl
+++ b/crates/gpu/src/shaders/blend.wgsl
@@ -220,9 +220,40 @@ fn blend(b: vec4, s: vec4, mode: u32) -> vec4 {
if (mode == 29u) {
return b + s * (1.0 - b.a);
}
+ if (mode == 30u) {
+ return blend_greater(b, s);
+ }
let cb = unpremultiply(b);
let cs = unpremultiply(s);
let mixed = clamp(blend_rgb(cb, cs, mode), vec3(0.0), vec3(1.0));
let rgb = s.a * (1.0 - b.a) * cs + s.a * b.a * mixed + (1.0 - s.a) * b.rgb;
return vec4(rgb, s.a + b.a * (1.0 - s.a));
}
+
+// Standard Greater/Max Alpha Blend for premultiplied targets
+fn blend_greater(b: vec4, s: vec4) -> vec4 {
+ let dA = b.a;
+ let sa = s.a;
+
+ // Early exit if background is fully opaque or source is completely transparent
+ if (dA >= 1.0 || sa <= 0.0) {
+ return b;
+ }
+
+ // Target alpha is determined by the greater of the two layers
+ let target_a = max(dA, sa);
+
+ // Unpremultiply both inputs to operate in straight (unassociated) color space
+ let color_b = select(vec3(0.0), b.rgb / dA, dA > 0.0);
+ let color_s = select(vec3(0.0), s.rgb / sa, sa > 0.0);
+
+ // Calculate normalized weight based on relative alpha contribution
+ let total_a = dA + sa;
+ let weight = select(0.5, sa / total_a, total_a > 0.0);
+
+ // Blend in straight RGB space
+ let blended_rgb = mix(color_b, color_s, weight);
+
+ // Re-premultiply by the target alpha for output consistency
+ return vec4(blended_rgb * target_a, target_a);
+}
diff --git a/crates/gpu/src/shaders/composite.wgsl b/crates/gpu/src/shaders/composite.wgsl
index 1b8eeb7b..42894b92 100644
--- a/crates/gpu/src/shaders/composite.wgsl
+++ b/crates/gpu/src/shaders/composite.wgsl
@@ -281,7 +281,7 @@ fn unsquared(c: vec4) -> vec4 {
// the layer's)
fn stroke_into(b: vec4, s: vec4) -> vec4 {
let mode = lu.stroke_blend & 255u;
- if ((lu.stroke_blend & STROKE_LUMINANCE) == 0u || mode == 26u || mode == 29u || s.a <= 0.0) {
+ if ((lu.stroke_blend & STROKE_LUMINANCE) == 0u || mode == 26u || mode == 29u || mode == 30u || s.a <= 0.0) {
return blend(b, s, mode);
}
let cb = unpremultiply(b);
@@ -290,4 +290,3 @@ fn stroke_into(b: vec4, s: vec4) -> vec4 {
let full = vec4((1.0 - b.a) * cs + b.a * mixed, 1.0);
return unsquared(mix(squared(b), squared(full), s.a));
}
-
diff --git a/desktop/src/icons.rs b/desktop/src/icons.rs
index e774d56f..cbdec8e8 100644
--- a/desktop/src/icons.rs
+++ b/desktop/src/icons.rs
@@ -144,6 +144,9 @@ pub const BLEND_GLYPHS: &[(&str, Icon)] = &[
] }),
("Normal", Icon { name: "blend-normal", width: 26.0, height: 26.0, parts: &[
Part { d: "M21.92 12.8L21.88 12.01L21.76 11.22L21.57 10.45L21.3 9.7L20.96 8.98L20.55 8.3L20.08 7.66L19.55 7.07L18.96 6.54L18.32 6.07L17.64 5.66L16.92 5.32L16.17 5.05L15.4 4.86L14.61 4.74L13.82 4.7L13.03 4.74L12.24 4.86L11.47 5.05L10.72 5.32L10 5.66L9.32 6.07L8.68 6.54L8.09 7.07L7.56 7.66L7.09 8.3L6.68 8.98L6.34 9.7L6.07 10.45L5.88 11.22L5.76 12.01L5.72 12.8L5.76 13.59L5.88 14.38L6.07 15.15L6.34 15.9L6.68 16.62L7.09 17.3L7.56 17.94L8.09 18.53L8.68 19.06L9.32 19.53L10 19.94L10.72 20.28L11.47 20.55L12.24 20.74L13.03 20.86L13.82 20.9L14.61 20.86L15.4 20.74L16.17 20.55L16.92 20.28L17.64 19.94L18.32 19.53L18.96 19.06L19.55 18.53L20.08 17.94L20.55 17.3L20.96 16.62L21.3 15.9L21.57 15.15L21.76 14.38L21.88 13.59Z", stroke: 0.0, fill: true, even_odd: true },
+] }),
+ ("Greater", Icon { name: "blend-greater", width: 26.0, height: 26.0, parts: &[
+ Part { d: "M12.1 7.02L11.53 6.99L10.96 7.02L10.4 7.1L9.84 7.24L9.31 7.43L8.79 7.68L8.3 7.97L7.84 8.31L7.42 8.69L7.04 9.11L6.7 9.57L6.41 10.06L6.16 10.58L5.97 11.11L5.83 11.67L5.75 12.23L5.72 12.8L5.75 13.37L5.83 13.93L5.97 14.49L6.16 15.02L6.41 15.54L6.7 16.03L7.04 16.49L7.42 16.91L7.84 17.29L8.3 17.63L8.79 17.92L9.31 18.17L9.84 18.36L10.4 18.5L10.96 18.58L11.53 18.61L12.1 18.58L12.66 18.5L13.12 18.39L12.6 18.08L12.24 17.82L11.92 17.55L11.38 17.02L10.71 16.94L10.3 16.84L9.91 16.7L9.54 16.53L9.18 16.31L8.85 16.07L8.54 15.79L8.26 15.48L8.02 15.15L7.8 14.79L7.63 14.42L7.49 14.03L7.39 13.62L7.33 13.21L7.3 12.8L7.33 12.39L7.39 11.98L7.49 11.57L7.63 11.18L7.8 10.81L8.02 10.45L8.26 10.12L8.54 9.81L8.85 9.53L9.18 9.29L9.54 9.07L9.91 8.9L10.3 8.76L10.71 8.66L11.38 8.58L11.92 8.05L12.24 7.78L12.6 7.52L13.12 7.21L12.66 7.1ZM21.92 12.8L21.87 12.04L21.72 11.3L21.61 10.93L21.32 10.23L21.14 9.89L20.72 9.26L20.22 8.69L19.94 8.43L19.34 7.97L19.01 7.77L18.68 7.59L17.98 7.3L17.61 7.19L16.87 7.04L16.11 6.99L15.73 7L15.35 7.04L14.61 7.19L13.89 7.43L13.54 7.59L12.88 7.97L12.57 8.19L12 8.69L11.74 8.97L11.5 9.26L11.08 9.89L10.74 10.58L10.61 10.93L10.41 11.67L10.35 12.04L10.3 12.8L10.31 13.18L10.35 13.56L10.5 14.3L10.74 15.02L10.9 15.37L11.28 16.03L11.5 16.34L12 16.91L12.28 17.17L12.88 17.63L13.2 17.83L13.54 18.01L14.24 18.3L14.61 18.41L15.35 18.56L15.73 18.6L16.49 18.6L17.24 18.5L17.61 18.41L17.98 18.3L18.68 18.01L19.01 17.83L19.65 17.41L19.94 17.17L20.48 16.63L20.94 16.03L21.14 15.71L21.48 15.02L21.61 14.67L21.72 14.3L21.87 13.56Z", stroke: 0.0, fill: true, even_odd: true },
] }),
("Lighten", Icon { name: "blend-lighten", width: 26.0, height: 26.0, parts: &[
Part { d: "M14.89 3.81L14.76 3.53L14.55 3.3L14.28 3.13L13.97 3.06L13.66 3.07L13.37 3.18L13.11 3.37L12.98 3.53L12.88 3.71L12.82 3.91L12.8 4.12L12.8 6.44L12.82 6.65L12.88 6.85L13.04 7.12L13.19 7.27L13.46 7.43L13.66 7.49L13.87 7.51L14.08 7.49L14.28 7.43L14.46 7.33L14.63 7.2L14.76 7.03L14.86 6.85L14.92 6.65L14.94 6.44L14.94 4.12ZM20.99 7.18L21.1 6.89L21.11 6.58L21.04 6.27L20.94 6.09L20.8 5.92L20.55 5.74L20.26 5.63L19.94 5.62L19.64 5.69L19.45 5.79L19.29 5.92L17.65 7.56L17.52 7.73L17.42 7.91L17.34 8.21L17.34 8.42L17.42 8.73L17.52 8.91L17.65 9.08L17.81 9.21L18 9.31L18.2 9.37L18.41 9.39L18.62 9.37L18.82 9.31L19 9.21L19.16 9.08L20.8 7.44ZM8.2 5.74L7.9 5.63L7.59 5.62L7.28 5.69L7.01 5.85L6.87 6L6.75 6.18L6.64 6.47L6.63 6.79L6.7 7.09L6.8 7.27L6.94 7.44L8.58 9.08L8.74 9.21L8.92 9.31L9.23 9.38L9.44 9.38L9.74 9.31L9.93 9.21L10.09 9.08L10.22 8.91L10.32 8.73L10.38 8.53L10.4 8.32L10.38 8.11L10.32 7.91L10.22 7.73L10.09 7.56L8.45 5.92ZM4.82 11.83L4.54 11.97L4.31 12.18L4.15 12.45L4.07 12.75L4.09 13.07L4.19 13.36L4.38 13.61L4.54 13.75L4.73 13.85L4.93 13.91L5.13 13.93L7.45 13.93L7.66 13.91L7.86 13.85L8.13 13.68L8.34 13.45L8.44 13.27L8.5 13.07L8.52 12.86L8.5 12.65L8.44 12.45L8.34 12.26L8.21 12.1L8.05 11.97L7.86 11.87L7.66 11.81L7.45 11.79L5.13 11.79ZM17.79 11.67L17.66 11.29L17.49 10.92L17.28 10.58L17.04 10.26L16.77 9.96L16.47 9.69L16.15 9.45L15.8 9.24L15.44 9.07L15.06 8.93L14.67 8.84L14.27 8.78L13.87 8.76L13.47 8.78L13.07 8.84L12.68 8.93L12.3 9.07L11.94 9.24L11.59 9.45L11.27 9.69L10.97 9.96L10.7 10.26L10.46 10.58L10.25 10.92L10.08 11.29L9.95 11.67L9.85 12.06L9.79 12.46L9.77 12.86L9.79 13.26L9.85 13.66L9.95 14.05L10.08 14.43L10.25 14.79L10.46 15.14L10.7 15.46L10.97 15.76L11.27 16.03L11.59 16.27L11.94 16.47L12.3 16.65L12.68 16.78L13.07 16.88L13.47 16.94L13.87 16.96L14.27 16.94L14.67 16.88L15.06 16.78L15.44 16.65L15.8 16.47L16.15 16.27L16.47 16.03L16.77 15.76L17.04 15.46L17.28 15.14L17.49 14.79L17.66 14.43L17.79 14.05L17.89 13.66L17.95 13.26L17.97 12.86L17.95 12.46L17.89 12.06ZM22.92 13.88L23.2 13.75L23.43 13.54L23.59 13.27L23.67 12.96L23.67 12.75L23.63 12.55L23.49 12.26L23.28 12.03L23.01 11.87L22.81 11.81L22.61 11.79L20.29 11.79L20.08 11.81L19.88 11.87L19.61 12.03L19.4 12.26L19.3 12.45L19.24 12.65L19.22 12.86L19.24 13.07L19.3 13.27L19.4 13.45L19.53 13.61L19.69 13.75L19.88 13.85L20.08 13.91L20.29 13.93L22.61 13.93ZM6.75 18.53L6.64 18.83L6.63 19.14L6.7 19.44L6.87 19.71L7.1 19.92L7.38 20.06L7.59 20.1L7.8 20.1L8.1 20.02L8.29 19.92L8.45 19.79L10.09 18.15L10.22 17.99L10.32 17.8L10.4 17.5L10.4 17.29L10.32 16.99L10.22 16.8L10.09 16.64L9.93 16.51L9.74 16.41L9.54 16.35L9.33 16.33L9.12 16.35L8.92 16.41L8.74 16.51L8.58 16.64L6.94 18.28ZM19.64 20.02L19.94 20.1L20.26 20.08L20.55 19.98L20.8 19.79L20.99 19.54L21.1 19.24L21.11 18.93L21.04 18.63L20.94 18.44L20.8 18.28L19.16 16.64L19 16.51L18.72 16.37L18.51 16.33L18.3 16.33L18 16.41L17.81 16.51L17.65 16.64L17.52 16.8L17.42 16.99L17.36 17.19L17.34 17.4L17.36 17.6L17.42 17.8L17.52 17.99L17.65 18.15L19.29 19.79L19.45 19.92ZM12.88 22L13.04 22.27L13.28 22.48L13.56 22.62L13.87 22.66L14.18 22.62L14.46 22.48L14.7 22.27L14.86 22L14.92 21.8L14.94 21.59L14.94 19.28L14.92 19.07L14.86 18.87L14.7 18.6L14.46 18.39L14.28 18.29L14.08 18.23L13.87 18.21L13.66 18.23L13.46 18.29L13.28 18.39L13.11 18.52L12.98 18.68L12.88 18.87L12.82 19.07L12.8 19.28L12.8 21.59L12.82 21.8Z", stroke: 0.0, fill: true, even_odd: true },
diff --git a/docs/icons/STYLE_GUIDE.md b/docs/icons/STYLE_GUIDE.md
index ebdc3fd7..501ad681 100644
--- a/docs/icons/STYLE_GUIDE.md
+++ b/docs/icons/STYLE_GUIDE.md
@@ -255,4 +255,5 @@ Screen a disc ringed with dots; Color Dodge a sparkle; Add a plus in a ring; Sof
Hard Light a spotlight, Vivid Light a bolt, Linear Light a torch, Pin Light a thumbtack; Hard Mix
four squares; Subtract a minus, Divide a division sign; Hue the colour wheel, Saturation a drop
filled halfway, Color three overlapping circles, Luminosity a disc half solid on the slant; Behind
-a solid sheet behind an outline; Height an arrow standing on a base, Linear Height a ramp.
+a solid sheet behind an outline; Height an arrow standing on a base, Linear Height a ramp. Greater
+a solid disc in front of a ring.
diff --git a/tools/icons/draw_icons.py b/tools/icons/draw_icons.py
index 80817848..77e3d358 100644
--- a/tools/icons/draw_icons.py
+++ b/tools/icons/draw_icons.py
@@ -1550,6 +1550,13 @@ def half_disc():
return unary_union([solid, ring(12, 12, 8.1, 1.8)])
+def greater():
+ """Greater: the more opaque of two discs — the solid one covers the outline."""
+ front = Point(14.6, 12.0).buffer(DISC_R, quad_segs=24)
+ back = ring(9.4, 12.0, DISC_R - 0.9, 1.8).difference(front.buffer(GAP / 2))
+ return unary_union([back, front])
+
+
def behind():
"""Behind: a solid sheet behind a sheet's outline."""
front = soft(box(3.0, 9.0, 15.0, 21.0), 1.4)
@@ -1569,7 +1576,7 @@ def ramp():
BLENDS = {'multiply': overlap_dark, 'darken': darken, 'shade': sunset, 'color-burn': flame, 'linear-burn': campfire,
- 'darker-color': darker_colour, 'normal': lambda: Point(12, 12).buffer(8.0, quad_segs=32),
+ 'darker-color': darker_colour, 'normal': lambda: Point(12, 12).buffer(8.0, quad_segs=32), 'greater': greater,
'lighten': sun_object, 'screen': dim_sun, 'color-dodge': lambda: star(12, 12, 10.0, 0.3), 'add': plus_in_ring,
'lighter-color': lighter_colour, 'overlay': overlap_rings, 'soft-light': lamp, 'hard-light': spotlight,
'vivid-light': flash, 'linear-light': torch, 'pin-light': thumbtack, 'hard-mix': four_squares,