Loading tools/layoutlib/bridge/src/android/graphics/BlendComposite.java +136 −147 Original line number Diff line number Diff line Loading @@ -197,12 +197,14 @@ public final class BlendComposite implements Composite { int[] srcPixel = new int[4]; int[] dstPixel = new int[4]; int[] result = new int[4]; int[] srcPixels = new int[width]; int[] dstPixels = new int[width]; for (int y = 0; y < height; y++) { src.getDataElements(0, y, width, 1, srcPixels); dstIn.getDataElements(0, y, width, 1, dstPixels); if (alpha != 0) { src.getDataElements(0, y, width, 1, srcPixels); for (int x = 0; x < width; x++) { // pixels are stored as INT_ARGB // our arrays are [R, G, B, A] Loading @@ -218,21 +220,31 @@ public final class BlendComposite implements Composite { dstPixel[2] = (pixel ) & 0xFF; dstPixel[3] = (pixel >> 24) & 0xFF; int[] result = blender.blend(srcPixel, dstPixel); result = blender.blend(srcPixel, dstPixel, result); // mixes the result with the opacity dstPixels[x] = ((int) (dstPixel[3] + (result[3] - dstPixel[3]) * alpha) & 0xFF) << 24 | if (alpha == 1) { dstPixels[x] = (result[3] & 0xFF) << 24 | (result[0] & 0xFF) << 16 | (result[1] & 0xFF) << 8 | result[2] & 0xFF; } else { dstPixels[x] = ((int) (dstPixel[3] + (result[3] - dstPixel[3]) * alpha) & 0xFF) << 24 | ((int) (dstPixel[0] + (result[0] - dstPixel[0]) * alpha) & 0xFF) << 16 | ((int) (dstPixel[1] + (result[1] - dstPixel[1]) * alpha) & 0xFF) << 8 | (int) (dstPixel[2] + (result[2] - dstPixel[2]) * alpha) & 0xFF; } } } dstOut.setDataElements(0, y, width, 1, dstPixels); } } } private static abstract class Blender { public abstract int[] blend(int[] src, int[] dst); public abstract int[] blend(int[] src, int[] dst, int[] result); private static void RGBtoHSL(int r, int g, int b, float[] hsl) { float var_R = (r / 255f); Loading Loading @@ -346,56 +358,50 @@ public final class BlendComposite implements Composite { case NORMAL: return new Blender() { @Override public int[] blend(int[] src, int[] dst) { return src; public int[] blend(int[] src, int[] dst, int[] result) { System.arraycopy(src, 0, result, 0, 4); return result; } }; case ADD: return new Blender() { @Override public int[] blend(int[] src, int[] dst) { return new int[] { Math.min(255, src[0] + dst[0]), Math.min(255, src[1] + dst[1]), Math.min(255, src[2] + dst[2]), Math.min(255, src[3] + dst[3]) }; public int[] blend(int[] src, int[] dst, int[] result) { for (int i = 0; i < 4; i++) { result[i] = Math.min(255, src[i] + dst[i]); } return result; } }; case AVERAGE: return new Blender() { @Override public int[] blend(int[] src, int[] dst) { return new int[] { (src[0] + dst[0]) >> 1, (src[1] + dst[1]) >> 1, (src[2] + dst[2]) >> 1, Math.min(255, src[3] + dst[3]) }; public int[] blend(int[] src, int[] dst, int[] result) { for (int i = 0; i < 3; i++) { result[i] = (src[i] + dst[i]) >> 1; } result[3] = Math.min(255, src[3] + dst[3]); return result; } }; case BLUE: return new Blender() { @Override public int[] blend(int[] src, int[] dst) { return new int[] { dst[0], src[1], dst[2], Math.min(255, src[3] + dst[3]) }; public int[] blend(int[] src, int[] dst, int[] result) { System.arraycopy(dst, 0, result, 0, 3); result[3] = Math.min(255, src[3] + dst[3]); return result; } }; case COLOR: return new Blender() { @Override public int[] blend(int[] src, int[] dst) { public int[] blend(int[] src, int[] dst, int[] result) { float[] srcHSL = new float[3]; RGBtoHSL(src[0], src[1], src[2], srcHSL); float[] dstHSL = new float[3]; RGBtoHSL(dst[0], dst[1], dst[2], dstHSL); int[] result = new int[4]; HSLtoRGB(srcHSL[0], srcHSL[1], dstHSL[2], result); result[3] = Math.min(255, src[3] + dst[3]); Loading @@ -405,97 +411,88 @@ public final class BlendComposite implements Composite { case COLOR_BURN: return new Blender() { @Override public int[] blend(int[] src, int[] dst) { return new int[] { src[0] == 0 ? 0 : Math.max(0, 255 - (((255 - dst[0]) << 8) / src[0])), src[1] == 0 ? 0 : Math.max(0, 255 - (((255 - dst[1]) << 8) / src[1])), src[2] == 0 ? 0 : Math.max(0, 255 - (((255 - dst[2]) << 8) / src[2])), Math.min(255, src[3] + dst[3]) }; public int[] blend(int[] src, int[] dst, int[] result) { for (int i = 0; i < 3; i++) { result[i] = src[i] == 0 ? 0 : Math.max(0, 255 - (((255 - dst[i]) << 8) / src[i])); } result[3] = Math.min(255, src[3] + dst[3]); return result; } }; case COLOR_DODGE: return new Blender() { @Override public int[] blend(int[] src, int[] dst) { return new int[] { src[0] == 255 ? 255 : Math.min((dst[0] << 8) / (255 - src[0]), 255), src[1] == 255 ? 255 : Math.min((dst[1] << 8) / (255 - src[1]), 255), src[2] == 255 ? 255 : Math.min((dst[2] << 8) / (255 - src[2]), 255), Math.min(255, src[3] + dst[3]) }; public int[] blend(int[] src, int[] dst, int[] result) { for (int i = 0; i < 3; i++) { result[i] = src[i] == 255 ? 255 : Math.min((dst[i] << 8) / (255 - src[i]), 255); } result[3] = Math.min(255, src[3] + dst[3]); return result; } }; case DARKEN: return new Blender() { @Override public int[] blend(int[] src, int[] dst) { return new int[] { Math.min(src[0], dst[0]), Math.min(src[1], dst[1]), Math.min(src[2], dst[2]), Math.min(255, src[3] + dst[3]) }; public int[] blend(int[] src, int[] dst, int[] result) { for (int i = 0; i < 3; i++) { result[i] = Math.min(src[i], dst[i]); } result[3] = Math.min(255, src[3] + dst[3]); return result; } }; case DIFFERENCE: return new Blender() { @Override public int[] blend(int[] src, int[] dst) { return new int[] { Math.abs(dst[0] - src[0]), Math.abs(dst[1] - src[1]), Math.abs(dst[2] - src[2]), Math.min(255, src[3] + dst[3]) }; public int[] blend(int[] src, int[] dst, int[] result) { for (int i = 0; i < 3; i++) { result[i] = dst[i] + src[i] - (dst[i] * src[i] >> 7); } result[3] = Math.min(255, src[3] + dst[3]); return result; } }; case EXCLUSION: return new Blender() { @Override public int[] blend(int[] src, int[] dst) { return new int[] { dst[0] + src[0] - (dst[0] * src[0] >> 7), dst[1] + src[1] - (dst[1] * src[1] >> 7), dst[2] + src[2] - (dst[2] * src[2] >> 7), Math.min(255, src[3] + dst[3]) }; public int[] blend(int[] src, int[] dst, int[] result) { for (int i = 0; i < 3; i++) { result[i] = dst[i] + src[i] - (dst[i] * src[i] >> 7); } result[3] = Math.min(255, src[3] + dst[3]); return result; } }; case FREEZE: return new Blender() { @Override public int[] blend(int[] src, int[] dst) { return new int[] { src[0] == 0 ? 0 : Math.max(0, 255 - (255 - dst[0]) * (255 - dst[0]) / src[0]), src[1] == 0 ? 0 : Math.max(0, 255 - (255 - dst[1]) * (255 - dst[1]) / src[1]), src[2] == 0 ? 0 : Math.max(0, 255 - (255 - dst[2]) * (255 - dst[2]) / src[2]), Math.min(255, src[3] + dst[3]) }; public int[] blend(int[] src, int[] dst, int[] result) { for (int i = 0; i < 3; i++) { result[i] = src[i] == 0 ? 0 : Math.max(0, 255 - (255 - dst[i]) * (255 - dst[i]) / src[i]); } result[3] = Math.min(255, src[3] + dst[3]); return result; } }; case GLOW: return new Blender() { @Override public int[] blend(int[] src, int[] dst) { return new int[] { dst[0] == 255 ? 255 : Math.min(255, src[0] * src[0] / (255 - dst[0])), dst[1] == 255 ? 255 : Math.min(255, src[1] * src[1] / (255 - dst[1])), dst[2] == 255 ? 255 : Math.min(255, src[2] * src[2] / (255 - dst[2])), Math.min(255, src[3] + dst[3]) }; public int[] blend(int[] src, int[] dst, int[] result) { for (int i = 0; i < 3; i++) { result[i] = dst[i] == 255 ? 255 : Math.min(255, src[i] * src[i] / (255 - dst[i])); } result[3] = Math.min(255, src[3] + dst[3]); return result; } }; case GREEN: return new Blender() { @Override public int[] blend(int[] src, int[] dst) { public int[] blend(int[] src, int[] dst, int[] result) { return new int[] { dst[0], dst[1], Loading @@ -507,7 +504,7 @@ public final class BlendComposite implements Composite { case HARD_LIGHT: return new Blender() { @Override public int[] blend(int[] src, int[] dst) { public int[] blend(int[] src, int[] dst, int[] result) { return new int[] { src[0] < 128 ? dst[0] * src[0] >> 7 : 255 - ((255 - src[0]) * (255 - dst[0]) >> 7), Loading @@ -522,7 +519,7 @@ public final class BlendComposite implements Composite { case HEAT: return new Blender() { @Override public int[] blend(int[] src, int[] dst) { public int[] blend(int[] src, int[] dst, int[] result) { return new int[] { dst[0] == 0 ? 0 : Math.max(0, 255 - (255 - src[0]) * (255 - src[0]) / dst[0]), dst[1] == 0 ? 0 : Math.max(0, 255 - (255 - src[1]) * (255 - src[1]) / dst[1]), Loading @@ -534,13 +531,12 @@ public final class BlendComposite implements Composite { case HUE: return new Blender() { @Override public int[] blend(int[] src, int[] dst) { public int[] blend(int[] src, int[] dst, int[] result) { float[] srcHSL = new float[3]; RGBtoHSL(src[0], src[1], src[2], srcHSL); float[] dstHSL = new float[3]; RGBtoHSL(dst[0], dst[1], dst[2], dstHSL); int[] result = new int[4]; HSLtoRGB(srcHSL[0], dstHSL[1], dstHSL[2], result); result[3] = Math.min(255, src[3] + dst[3]); Loading @@ -550,7 +546,7 @@ public final class BlendComposite implements Composite { case INVERSE_COLOR_BURN: return new Blender() { @Override public int[] blend(int[] src, int[] dst) { public int[] blend(int[] src, int[] dst, int[] result) { return new int[] { dst[0] == 0 ? 0 : Math.max(0, 255 - (((255 - src[0]) << 8) / dst[0])), Loading @@ -565,7 +561,7 @@ public final class BlendComposite implements Composite { case INVERSE_COLOR_DODGE: return new Blender() { @Override public int[] blend(int[] src, int[] dst) { public int[] blend(int[] src, int[] dst, int[] result) { return new int[] { dst[0] == 255 ? 255 : Math.min((src[0] << 8) / (255 - dst[0]), 255), Loading @@ -580,25 +576,23 @@ public final class BlendComposite implements Composite { case LIGHTEN: return new Blender() { @Override public int[] blend(int[] src, int[] dst) { return new int[] { Math.max(src[0], dst[0]), Math.max(src[1], dst[1]), Math.max(src[2], dst[2]), Math.min(255, src[3] + dst[3]) }; public int[] blend(int[] src, int[] dst, int[] result) { for (int i = 0; i < 3; i++) { result[i] = Math.max(src[i], dst[i]); } result[3] = Math.min(255, src[3] + dst[3]); return result; } }; case LUMINOSITY: return new Blender() { @Override public int[] blend(int[] src, int[] dst) { public int[] blend(int[] src, int[] dst, int[] result) { float[] srcHSL = new float[3]; RGBtoHSL(src[0], src[1], src[2], srcHSL); float[] dstHSL = new float[3]; RGBtoHSL(dst[0], dst[1], dst[2], dstHSL); int[] result = new int[4]; HSLtoRGB(dstHSL[0], dstHSL[1], srcHSL[2], result); result[3] = Math.min(255, src[3] + dst[3]); Loading @@ -608,19 +602,18 @@ public final class BlendComposite implements Composite { case MULTIPLY: return new Blender() { @Override public int[] blend(int[] src, int[] dst) { return new int[] { (src[0] * dst[0]) >> 8, (src[1] * dst[1]) >> 8, (src[2] * dst[2]) >> 8, Math.min(255, src[3] + dst[3]) }; public int[] blend(int[] src, int[] dst, int[] result) { for (int i = 0; i < 3; i++) { result[i] = (src[i] * dst[i]) >> 8; } result[3] = Math.min(255, src[3] + dst[3]); return result; } }; case NEGATION: return new Blender() { @Override public int[] blend(int[] src, int[] dst) { public int[] blend(int[] src, int[] dst, int[] result) { return new int[] { 255 - Math.abs(255 - dst[0] - src[0]), 255 - Math.abs(255 - dst[1] - src[1]), Loading @@ -632,22 +625,19 @@ public final class BlendComposite implements Composite { case OVERLAY: return new Blender() { @Override public int[] blend(int[] src, int[] dst) { return new int[] { dst[0] < 128 ? dst[0] * src[0] >> 7 : 255 - ((255 - dst[0]) * (255 - src[0]) >> 7), dst[1] < 128 ? dst[1] * src[1] >> 7 : 255 - ((255 - dst[1]) * (255 - src[1]) >> 7), dst[2] < 128 ? dst[2] * src[2] >> 7 : 255 - ((255 - dst[2]) * (255 - src[2]) >> 7), Math.min(255, src[3] + dst[3]) }; public int[] blend(int[] src, int[] dst, int[] result) { for (int i = 0; i < 3; i++) { result[i] = dst[i] < 128 ? dst[i] * src[i] >> 7 : 255 - ((255 - dst[i]) * (255 - src[i]) >> 7); } result[3] = Math.min(255, src[3] + dst[3]); return result; } }; case RED: return new Blender() { @Override public int[] blend(int[] src, int[] dst) { public int[] blend(int[] src, int[] dst, int[] result) { return new int[] { src[0], dst[1], Loading @@ -659,7 +649,7 @@ public final class BlendComposite implements Composite { case REFLECT: return new Blender() { @Override public int[] blend(int[] src, int[] dst) { public int[] blend(int[] src, int[] dst, int[] result) { return new int[] { src[0] == 255 ? 255 : Math.min(255, dst[0] * dst[0] / (255 - src[0])), src[1] == 255 ? 255 : Math.min(255, dst[1] * dst[1] / (255 - src[1])), Loading @@ -671,13 +661,12 @@ public final class BlendComposite implements Composite { case SATURATION: return new Blender() { @Override public int[] blend(int[] src, int[] dst) { public int[] blend(int[] src, int[] dst, int[] result) { float[] srcHSL = new float[3]; RGBtoHSL(src[0], src[1], src[2], srcHSL); float[] dstHSL = new float[3]; RGBtoHSL(dst[0], dst[1], dst[2], dstHSL); int[] result = new int[4]; HSLtoRGB(dstHSL[0], srcHSL[1], dstHSL[2], result); result[3] = Math.min(255, src[3] + dst[3]); Loading @@ -687,7 +676,7 @@ public final class BlendComposite implements Composite { case SCREEN: return new Blender() { @Override public int[] blend(int[] src, int[] dst) { public int[] blend(int[] src, int[] dst, int[] result) { return new int[] { 255 - ((255 - src[0]) * (255 - dst[0]) >> 8), 255 - ((255 - src[1]) * (255 - dst[1]) >> 8), Loading @@ -699,7 +688,7 @@ public final class BlendComposite implements Composite { case SOFT_BURN: return new Blender() { @Override public int[] blend(int[] src, int[] dst) { public int[] blend(int[] src, int[] dst, int[] result) { return new int[] { dst[0] + src[0] < 256 ? (dst[0] == 255 ? 255 : Loading @@ -720,7 +709,7 @@ public final class BlendComposite implements Composite { case SOFT_DODGE: return new Blender() { @Override public int[] blend(int[] src, int[] dst) { public int[] blend(int[] src, int[] dst, int[] result) { return new int[] { dst[0] + src[0] < 256 ? (src[0] == 255 ? 255 : Loading @@ -743,7 +732,7 @@ public final class BlendComposite implements Composite { case STAMP: return new Blender() { @Override public int[] blend(int[] src, int[] dst) { public int[] blend(int[] src, int[] dst, int[] result) { return new int[] { Math.max(0, Math.min(255, dst[0] + 2 * src[0] - 256)), Math.max(0, Math.min(255, dst[1] + 2 * src[1] - 256)), Loading @@ -755,7 +744,7 @@ public final class BlendComposite implements Composite { case SUBTRACT: return new Blender() { @Override public int[] blend(int[] src, int[] dst) { public int[] blend(int[] src, int[] dst, int[] result) { return new int[] { Math.max(0, src[0] + dst[0] - 256), Math.max(0, src[1] + dst[1] - 256), Loading Loading
tools/layoutlib/bridge/src/android/graphics/BlendComposite.java +136 −147 Original line number Diff line number Diff line Loading @@ -197,12 +197,14 @@ public final class BlendComposite implements Composite { int[] srcPixel = new int[4]; int[] dstPixel = new int[4]; int[] result = new int[4]; int[] srcPixels = new int[width]; int[] dstPixels = new int[width]; for (int y = 0; y < height; y++) { src.getDataElements(0, y, width, 1, srcPixels); dstIn.getDataElements(0, y, width, 1, dstPixels); if (alpha != 0) { src.getDataElements(0, y, width, 1, srcPixels); for (int x = 0; x < width; x++) { // pixels are stored as INT_ARGB // our arrays are [R, G, B, A] Loading @@ -218,21 +220,31 @@ public final class BlendComposite implements Composite { dstPixel[2] = (pixel ) & 0xFF; dstPixel[3] = (pixel >> 24) & 0xFF; int[] result = blender.blend(srcPixel, dstPixel); result = blender.blend(srcPixel, dstPixel, result); // mixes the result with the opacity dstPixels[x] = ((int) (dstPixel[3] + (result[3] - dstPixel[3]) * alpha) & 0xFF) << 24 | if (alpha == 1) { dstPixels[x] = (result[3] & 0xFF) << 24 | (result[0] & 0xFF) << 16 | (result[1] & 0xFF) << 8 | result[2] & 0xFF; } else { dstPixels[x] = ((int) (dstPixel[3] + (result[3] - dstPixel[3]) * alpha) & 0xFF) << 24 | ((int) (dstPixel[0] + (result[0] - dstPixel[0]) * alpha) & 0xFF) << 16 | ((int) (dstPixel[1] + (result[1] - dstPixel[1]) * alpha) & 0xFF) << 8 | (int) (dstPixel[2] + (result[2] - dstPixel[2]) * alpha) & 0xFF; } } } dstOut.setDataElements(0, y, width, 1, dstPixels); } } } private static abstract class Blender { public abstract int[] blend(int[] src, int[] dst); public abstract int[] blend(int[] src, int[] dst, int[] result); private static void RGBtoHSL(int r, int g, int b, float[] hsl) { float var_R = (r / 255f); Loading Loading @@ -346,56 +358,50 @@ public final class BlendComposite implements Composite { case NORMAL: return new Blender() { @Override public int[] blend(int[] src, int[] dst) { return src; public int[] blend(int[] src, int[] dst, int[] result) { System.arraycopy(src, 0, result, 0, 4); return result; } }; case ADD: return new Blender() { @Override public int[] blend(int[] src, int[] dst) { return new int[] { Math.min(255, src[0] + dst[0]), Math.min(255, src[1] + dst[1]), Math.min(255, src[2] + dst[2]), Math.min(255, src[3] + dst[3]) }; public int[] blend(int[] src, int[] dst, int[] result) { for (int i = 0; i < 4; i++) { result[i] = Math.min(255, src[i] + dst[i]); } return result; } }; case AVERAGE: return new Blender() { @Override public int[] blend(int[] src, int[] dst) { return new int[] { (src[0] + dst[0]) >> 1, (src[1] + dst[1]) >> 1, (src[2] + dst[2]) >> 1, Math.min(255, src[3] + dst[3]) }; public int[] blend(int[] src, int[] dst, int[] result) { for (int i = 0; i < 3; i++) { result[i] = (src[i] + dst[i]) >> 1; } result[3] = Math.min(255, src[3] + dst[3]); return result; } }; case BLUE: return new Blender() { @Override public int[] blend(int[] src, int[] dst) { return new int[] { dst[0], src[1], dst[2], Math.min(255, src[3] + dst[3]) }; public int[] blend(int[] src, int[] dst, int[] result) { System.arraycopy(dst, 0, result, 0, 3); result[3] = Math.min(255, src[3] + dst[3]); return result; } }; case COLOR: return new Blender() { @Override public int[] blend(int[] src, int[] dst) { public int[] blend(int[] src, int[] dst, int[] result) { float[] srcHSL = new float[3]; RGBtoHSL(src[0], src[1], src[2], srcHSL); float[] dstHSL = new float[3]; RGBtoHSL(dst[0], dst[1], dst[2], dstHSL); int[] result = new int[4]; HSLtoRGB(srcHSL[0], srcHSL[1], dstHSL[2], result); result[3] = Math.min(255, src[3] + dst[3]); Loading @@ -405,97 +411,88 @@ public final class BlendComposite implements Composite { case COLOR_BURN: return new Blender() { @Override public int[] blend(int[] src, int[] dst) { return new int[] { src[0] == 0 ? 0 : Math.max(0, 255 - (((255 - dst[0]) << 8) / src[0])), src[1] == 0 ? 0 : Math.max(0, 255 - (((255 - dst[1]) << 8) / src[1])), src[2] == 0 ? 0 : Math.max(0, 255 - (((255 - dst[2]) << 8) / src[2])), Math.min(255, src[3] + dst[3]) }; public int[] blend(int[] src, int[] dst, int[] result) { for (int i = 0; i < 3; i++) { result[i] = src[i] == 0 ? 0 : Math.max(0, 255 - (((255 - dst[i]) << 8) / src[i])); } result[3] = Math.min(255, src[3] + dst[3]); return result; } }; case COLOR_DODGE: return new Blender() { @Override public int[] blend(int[] src, int[] dst) { return new int[] { src[0] == 255 ? 255 : Math.min((dst[0] << 8) / (255 - src[0]), 255), src[1] == 255 ? 255 : Math.min((dst[1] << 8) / (255 - src[1]), 255), src[2] == 255 ? 255 : Math.min((dst[2] << 8) / (255 - src[2]), 255), Math.min(255, src[3] + dst[3]) }; public int[] blend(int[] src, int[] dst, int[] result) { for (int i = 0; i < 3; i++) { result[i] = src[i] == 255 ? 255 : Math.min((dst[i] << 8) / (255 - src[i]), 255); } result[3] = Math.min(255, src[3] + dst[3]); return result; } }; case DARKEN: return new Blender() { @Override public int[] blend(int[] src, int[] dst) { return new int[] { Math.min(src[0], dst[0]), Math.min(src[1], dst[1]), Math.min(src[2], dst[2]), Math.min(255, src[3] + dst[3]) }; public int[] blend(int[] src, int[] dst, int[] result) { for (int i = 0; i < 3; i++) { result[i] = Math.min(src[i], dst[i]); } result[3] = Math.min(255, src[3] + dst[3]); return result; } }; case DIFFERENCE: return new Blender() { @Override public int[] blend(int[] src, int[] dst) { return new int[] { Math.abs(dst[0] - src[0]), Math.abs(dst[1] - src[1]), Math.abs(dst[2] - src[2]), Math.min(255, src[3] + dst[3]) }; public int[] blend(int[] src, int[] dst, int[] result) { for (int i = 0; i < 3; i++) { result[i] = dst[i] + src[i] - (dst[i] * src[i] >> 7); } result[3] = Math.min(255, src[3] + dst[3]); return result; } }; case EXCLUSION: return new Blender() { @Override public int[] blend(int[] src, int[] dst) { return new int[] { dst[0] + src[0] - (dst[0] * src[0] >> 7), dst[1] + src[1] - (dst[1] * src[1] >> 7), dst[2] + src[2] - (dst[2] * src[2] >> 7), Math.min(255, src[3] + dst[3]) }; public int[] blend(int[] src, int[] dst, int[] result) { for (int i = 0; i < 3; i++) { result[i] = dst[i] + src[i] - (dst[i] * src[i] >> 7); } result[3] = Math.min(255, src[3] + dst[3]); return result; } }; case FREEZE: return new Blender() { @Override public int[] blend(int[] src, int[] dst) { return new int[] { src[0] == 0 ? 0 : Math.max(0, 255 - (255 - dst[0]) * (255 - dst[0]) / src[0]), src[1] == 0 ? 0 : Math.max(0, 255 - (255 - dst[1]) * (255 - dst[1]) / src[1]), src[2] == 0 ? 0 : Math.max(0, 255 - (255 - dst[2]) * (255 - dst[2]) / src[2]), Math.min(255, src[3] + dst[3]) }; public int[] blend(int[] src, int[] dst, int[] result) { for (int i = 0; i < 3; i++) { result[i] = src[i] == 0 ? 0 : Math.max(0, 255 - (255 - dst[i]) * (255 - dst[i]) / src[i]); } result[3] = Math.min(255, src[3] + dst[3]); return result; } }; case GLOW: return new Blender() { @Override public int[] blend(int[] src, int[] dst) { return new int[] { dst[0] == 255 ? 255 : Math.min(255, src[0] * src[0] / (255 - dst[0])), dst[1] == 255 ? 255 : Math.min(255, src[1] * src[1] / (255 - dst[1])), dst[2] == 255 ? 255 : Math.min(255, src[2] * src[2] / (255 - dst[2])), Math.min(255, src[3] + dst[3]) }; public int[] blend(int[] src, int[] dst, int[] result) { for (int i = 0; i < 3; i++) { result[i] = dst[i] == 255 ? 255 : Math.min(255, src[i] * src[i] / (255 - dst[i])); } result[3] = Math.min(255, src[3] + dst[3]); return result; } }; case GREEN: return new Blender() { @Override public int[] blend(int[] src, int[] dst) { public int[] blend(int[] src, int[] dst, int[] result) { return new int[] { dst[0], dst[1], Loading @@ -507,7 +504,7 @@ public final class BlendComposite implements Composite { case HARD_LIGHT: return new Blender() { @Override public int[] blend(int[] src, int[] dst) { public int[] blend(int[] src, int[] dst, int[] result) { return new int[] { src[0] < 128 ? dst[0] * src[0] >> 7 : 255 - ((255 - src[0]) * (255 - dst[0]) >> 7), Loading @@ -522,7 +519,7 @@ public final class BlendComposite implements Composite { case HEAT: return new Blender() { @Override public int[] blend(int[] src, int[] dst) { public int[] blend(int[] src, int[] dst, int[] result) { return new int[] { dst[0] == 0 ? 0 : Math.max(0, 255 - (255 - src[0]) * (255 - src[0]) / dst[0]), dst[1] == 0 ? 0 : Math.max(0, 255 - (255 - src[1]) * (255 - src[1]) / dst[1]), Loading @@ -534,13 +531,12 @@ public final class BlendComposite implements Composite { case HUE: return new Blender() { @Override public int[] blend(int[] src, int[] dst) { public int[] blend(int[] src, int[] dst, int[] result) { float[] srcHSL = new float[3]; RGBtoHSL(src[0], src[1], src[2], srcHSL); float[] dstHSL = new float[3]; RGBtoHSL(dst[0], dst[1], dst[2], dstHSL); int[] result = new int[4]; HSLtoRGB(srcHSL[0], dstHSL[1], dstHSL[2], result); result[3] = Math.min(255, src[3] + dst[3]); Loading @@ -550,7 +546,7 @@ public final class BlendComposite implements Composite { case INVERSE_COLOR_BURN: return new Blender() { @Override public int[] blend(int[] src, int[] dst) { public int[] blend(int[] src, int[] dst, int[] result) { return new int[] { dst[0] == 0 ? 0 : Math.max(0, 255 - (((255 - src[0]) << 8) / dst[0])), Loading @@ -565,7 +561,7 @@ public final class BlendComposite implements Composite { case INVERSE_COLOR_DODGE: return new Blender() { @Override public int[] blend(int[] src, int[] dst) { public int[] blend(int[] src, int[] dst, int[] result) { return new int[] { dst[0] == 255 ? 255 : Math.min((src[0] << 8) / (255 - dst[0]), 255), Loading @@ -580,25 +576,23 @@ public final class BlendComposite implements Composite { case LIGHTEN: return new Blender() { @Override public int[] blend(int[] src, int[] dst) { return new int[] { Math.max(src[0], dst[0]), Math.max(src[1], dst[1]), Math.max(src[2], dst[2]), Math.min(255, src[3] + dst[3]) }; public int[] blend(int[] src, int[] dst, int[] result) { for (int i = 0; i < 3; i++) { result[i] = Math.max(src[i], dst[i]); } result[3] = Math.min(255, src[3] + dst[3]); return result; } }; case LUMINOSITY: return new Blender() { @Override public int[] blend(int[] src, int[] dst) { public int[] blend(int[] src, int[] dst, int[] result) { float[] srcHSL = new float[3]; RGBtoHSL(src[0], src[1], src[2], srcHSL); float[] dstHSL = new float[3]; RGBtoHSL(dst[0], dst[1], dst[2], dstHSL); int[] result = new int[4]; HSLtoRGB(dstHSL[0], dstHSL[1], srcHSL[2], result); result[3] = Math.min(255, src[3] + dst[3]); Loading @@ -608,19 +602,18 @@ public final class BlendComposite implements Composite { case MULTIPLY: return new Blender() { @Override public int[] blend(int[] src, int[] dst) { return new int[] { (src[0] * dst[0]) >> 8, (src[1] * dst[1]) >> 8, (src[2] * dst[2]) >> 8, Math.min(255, src[3] + dst[3]) }; public int[] blend(int[] src, int[] dst, int[] result) { for (int i = 0; i < 3; i++) { result[i] = (src[i] * dst[i]) >> 8; } result[3] = Math.min(255, src[3] + dst[3]); return result; } }; case NEGATION: return new Blender() { @Override public int[] blend(int[] src, int[] dst) { public int[] blend(int[] src, int[] dst, int[] result) { return new int[] { 255 - Math.abs(255 - dst[0] - src[0]), 255 - Math.abs(255 - dst[1] - src[1]), Loading @@ -632,22 +625,19 @@ public final class BlendComposite implements Composite { case OVERLAY: return new Blender() { @Override public int[] blend(int[] src, int[] dst) { return new int[] { dst[0] < 128 ? dst[0] * src[0] >> 7 : 255 - ((255 - dst[0]) * (255 - src[0]) >> 7), dst[1] < 128 ? dst[1] * src[1] >> 7 : 255 - ((255 - dst[1]) * (255 - src[1]) >> 7), dst[2] < 128 ? dst[2] * src[2] >> 7 : 255 - ((255 - dst[2]) * (255 - src[2]) >> 7), Math.min(255, src[3] + dst[3]) }; public int[] blend(int[] src, int[] dst, int[] result) { for (int i = 0; i < 3; i++) { result[i] = dst[i] < 128 ? dst[i] * src[i] >> 7 : 255 - ((255 - dst[i]) * (255 - src[i]) >> 7); } result[3] = Math.min(255, src[3] + dst[3]); return result; } }; case RED: return new Blender() { @Override public int[] blend(int[] src, int[] dst) { public int[] blend(int[] src, int[] dst, int[] result) { return new int[] { src[0], dst[1], Loading @@ -659,7 +649,7 @@ public final class BlendComposite implements Composite { case REFLECT: return new Blender() { @Override public int[] blend(int[] src, int[] dst) { public int[] blend(int[] src, int[] dst, int[] result) { return new int[] { src[0] == 255 ? 255 : Math.min(255, dst[0] * dst[0] / (255 - src[0])), src[1] == 255 ? 255 : Math.min(255, dst[1] * dst[1] / (255 - src[1])), Loading @@ -671,13 +661,12 @@ public final class BlendComposite implements Composite { case SATURATION: return new Blender() { @Override public int[] blend(int[] src, int[] dst) { public int[] blend(int[] src, int[] dst, int[] result) { float[] srcHSL = new float[3]; RGBtoHSL(src[0], src[1], src[2], srcHSL); float[] dstHSL = new float[3]; RGBtoHSL(dst[0], dst[1], dst[2], dstHSL); int[] result = new int[4]; HSLtoRGB(dstHSL[0], srcHSL[1], dstHSL[2], result); result[3] = Math.min(255, src[3] + dst[3]); Loading @@ -687,7 +676,7 @@ public final class BlendComposite implements Composite { case SCREEN: return new Blender() { @Override public int[] blend(int[] src, int[] dst) { public int[] blend(int[] src, int[] dst, int[] result) { return new int[] { 255 - ((255 - src[0]) * (255 - dst[0]) >> 8), 255 - ((255 - src[1]) * (255 - dst[1]) >> 8), Loading @@ -699,7 +688,7 @@ public final class BlendComposite implements Composite { case SOFT_BURN: return new Blender() { @Override public int[] blend(int[] src, int[] dst) { public int[] blend(int[] src, int[] dst, int[] result) { return new int[] { dst[0] + src[0] < 256 ? (dst[0] == 255 ? 255 : Loading @@ -720,7 +709,7 @@ public final class BlendComposite implements Composite { case SOFT_DODGE: return new Blender() { @Override public int[] blend(int[] src, int[] dst) { public int[] blend(int[] src, int[] dst, int[] result) { return new int[] { dst[0] + src[0] < 256 ? (src[0] == 255 ? 255 : Loading @@ -743,7 +732,7 @@ public final class BlendComposite implements Composite { case STAMP: return new Blender() { @Override public int[] blend(int[] src, int[] dst) { public int[] blend(int[] src, int[] dst, int[] result) { return new int[] { Math.max(0, Math.min(255, dst[0] + 2 * src[0] - 256)), Math.max(0, Math.min(255, dst[1] + 2 * src[1] - 256)), Loading @@ -755,7 +744,7 @@ public final class BlendComposite implements Composite { case SUBTRACT: return new Blender() { @Override public int[] blend(int[] src, int[] dst) { public int[] blend(int[] src, int[] dst, int[] result) { return new int[] { Math.max(0, src[0] + dst[0] - 256), Math.max(0, src[1] + dst[1] - 256), Loading