import java.util.*;
import java.util.zip.*;
import java.util.List;
import java.util.regex.*;
import java.util.concurrent.*;
import java.util.concurrent.atomic.*;
import java.util.concurrent.locks.*;
import java.util.function.*;
import javax.swing.*;
import javax.swing.event.*;
import javax.swing.text.*;
import javax.swing.table.*;
import java.io.*;
import java.net.*;
import java.lang.reflect.*;
import java.lang.ref.*;
import java.lang.management.*;
import java.security.*;
import java.security.spec.*;
import java.awt.*;
import java.awt.event.*;
import java.awt.image.*;
import java.awt.geom.*;
import javax.imageio.*;
import java.math.*;
// drawing the resulting image on img1 gives img2
import java.awt.geom.*;
import static x30_pkg.x30_util.DynamicObject;
class main {
static class ImageDifferenceAsTransparentOverlay implements IFieldsToList{
BufferedImage img1;
BufferedImage img2;
ImageDifferenceAsTransparentOverlay() {}
ImageDifferenceAsTransparentOverlay(BufferedImage img1, BufferedImage img2) {
this.img2 = img2;
this.img1 = img1;}
public String toString() { return shortClassName_dropNumberPrefix(this) + "(" + img1 + ", " + img2 + ")"; }public Object[] _fieldsToList() { return new Object[] {img1, img2}; }
int w, h;
int[] pixels;
int x1, y1, x2, y2; // changed area (inclusive)
GrabbableIntPixels gp1, gp2;
public void run() { try {
if (pixels != null) return;
int w = this.w = img1.getWidth(), h = this.h = img1.getHeight();
assertSameSize(img1, img2);
int[] pixels = this.pixels = new int[w*h];
gp1 = grabbableIntPixels_fastOrSlow(img1);
gp2 = grabbableIntPixels_fastOrSlow(img2);
int iPixels1 = gp1.offset, iPixels2 = gp2.offset;
int[] pixels1 = gp1.data, pixels2 = gp2.data;
int iPixels = 0;
x1 = w; y1 = h; x2 = 0; y2 = 0;
for (int y = 0; y < h; y++) {
for (int x = 0; x < w; x++) {
int pix;
if ((pixels1[iPixels1+x] & 0xFFFFFF)
!= (pix = pixels2[iPixels2+x] & 0xFFFFFF)) {
pixels[iPixels] = pix | 0xFF000000;
if (x < x1) x1 = x;
if (x > x2) x2 = x;
if (y < y1) y1 = y;
if (y > y2) y2 = y;
}
iPixels++;
}
iPixels1 += gp1.scanlineStride;
iPixels2 += gp2.scanlineStride;
}
} catch (Exception __e) { throw rethrow(__e); } }
BufferedImage get() {
run();
return newBufferedImageWithAlpha(w, h, pixels);
}
Rect changedBounds() {
run();
return rectFromPointsInclusive(x1, y1, x2, y2);
}
}
static String shortClassName_dropNumberPrefix(Object o) {
return dropNumberPrefix(shortClassName(o));
}
static void assertSameSize(BufferedImage a, BufferedImage b) {
assertEquals(a.getWidth(), b.getWidth());
assertEquals(a.getHeight(), b.getHeight());
}
static void assertSameSize(WidthAndHeight a, WidthAndHeight b) {
assertEquals(a.getWidth(), b.getWidth());
assertEquals(a.getHeight(), b.getHeight());
}
static GrabbableIntPixels grabbableIntPixels_fastOrSlow(BufferedImage image) { try {
try {
GrabbableIntPixels gp = grabbableIntPixels(image);
if (gp != null) return gp;
} catch (Throwable __e) { printStackTrace(__e); }
// Use pixelGrabber if quick method fails
int w = image.getWidth(), h = image.getHeight();
int[] data = new int[w*h];
PixelGrabber pixelGrabber = new PixelGrabber(image, 0, 0, w, h, data, 0, w);
if (!pixelGrabber.grabPixels())
throw fail("Could not grab pixels");
return new GrabbableIntPixels(data, w, h, 0, w);
} catch (Exception __e) { throw rethrow(__e); } }
static RuntimeException rethrow(Throwable t) {
if (t instanceof Error)
_handleError((Error) t);
throw t instanceof RuntimeException ? (RuntimeException) t : new RuntimeException(t);
}
static RuntimeException rethrow(String msg, Throwable t) {
throw new RuntimeException(msg, t);
}
// get purpose 1: access a list/array/map (safer version of x.get(y))
static A get(List l, int idx) {
return l != null && idx >= 0 && idx < l(l) ? l.get(idx) : null;
}
// seems to conflict with other signatures
/*static B get(Map map, A key) {
ret map != null ? map.get(key) : null;
}*/
static A get(A[] l, int idx) {
return idx >= 0 && idx < l(l) ? l[idx] : null;
}
// default to false
static boolean get(boolean[] l, int idx) {
return idx >= 0 && idx < l(l) ? l[idx] : false;
}
// get purpose 2: access a field by reflection or a map
static Object get(Object o, String field) {
try {
if (o == null) return null;
if (o instanceof Class) return get((Class) o, field);
if (o instanceof Map)
return ((Map) o).get(field);
Field f = getOpt_findField(o.getClass(), field);
if (f != null) {
makeAccessible(f);
return f.get(o);
}
if (o instanceof DynamicObject)
return getOptDynOnly(((DynamicObject) o), field);
} catch (Exception e) {
throw asRuntimeException(e);
}
throw new RuntimeException("Field '" + field + "' not found in " + o.getClass().getName());
}
static Object get_raw(String field, Object o) {
return get_raw(o, field);
}
static Object get_raw(Object o, String field) { try {
if (o == null) return null;
Field f = get_findField(o.getClass(), field);
makeAccessible(f);
return f.get(o);
} catch (Exception __e) { throw rethrow(__e); } }
static Object get(Class c, String field) {
try {
Field f = get_findStaticField(c, field);
makeAccessible(f);
return f.get(null);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
static Field get_findStaticField(Class> c, String field) {
Class _c = c;
do {
for (Field f : _c.getDeclaredFields())
if (f.getName().equals(field) && (f.getModifiers() & java.lang.reflect.Modifier.STATIC) != 0)
return f;
_c = _c.getSuperclass();
} while (_c != null);
throw new RuntimeException("Static field '" + field + "' not found in " + c.getName());
}
static Field get_findField(Class> c, String field) {
Class _c = c;
do {
for (Field f : _c.getDeclaredFields())
if (f.getName().equals(field))
return f;
_c = _c.getSuperclass();
} while (_c != null);
throw new RuntimeException("Field '" + field + "' not found in " + c.getName());
}
static Object get(String field, Object o) {
return get(o, field);
}
static boolean get(BitSet bs, int idx) {
return bs != null && bs.get(idx);
}
static Class run(String progID, String... args) {
Class main = hotwire(progID);
callMain(main, args);
return main;
}
static BufferedImage newBufferedImageWithAlpha(int w, int h, int[] pixels) {
return intArrayToBufferedImage(pixels, w, h);
}
static Rect rectFromPointsInclusive(int x1, int y1, int x2, int y2) {
return rectFromPoints(x1, y1, x2+1, y2+1);
}
static String dropNumberPrefix(String s) {
return dropFirst(s, indexOfNonDigit(s));
}
static String shortClassName(Object o) {
if (o == null) return null;
Class c = o instanceof Class ? (Class) o : o.getClass();
String name = c.getName();
return shortenClassName(name);
}
static A assertEquals(Object x, A y) {
return assertEquals("", x, y);
}
static A assertEquals(String msg, Object x, A y) {
if (assertVerbose()) return assertEqualsVerbose(msg, x, y);
if (!(x == null ? y == null : x.equals(y)))
throw fail((msg != null ? msg + ": " : "") + y + " != " + x);
return y;
}
static Boolean grabbableIntPixels_succeeded;
static boolean grabbableIntPixels_enable = true;
static GrabbableIntPixels grabbableIntPixels(BufferedImage img) {
if (img == null || !grabbableIntPixels_enable) return null;
try {
var result = grabbableIntPixels_impl(img);
grabbableIntPixels_succeeded = result != null;
return result;
} catch (Throwable _e) {
grabbableIntPixels_succeeded = false;
throw rethrow(_e); }
}
static GrabbableIntPixels grabbableIntPixels_impl(BufferedImage img) {
Raster raster = img.getRaster();
SampleModel _sampleModel = raster.getSampleModel();
if (!(_sampleModel instanceof SinglePixelPackedSampleModel)) return null;
SinglePixelPackedSampleModel sampleModel = (SinglePixelPackedSampleModel) _sampleModel;
DataBufferInt dataBuffer = (DataBufferInt) (raster.getDataBuffer());
assertEquals(1, dataBuffer.getNumBanks());
assertEquals(DataBuffer.TYPE_INT, dataBuffer.getDataType());
// Let's at this point assume the raster data is what we
// think it is... (TODO: test on unusual platforms)
int w = img.getWidth(), h = img.getHeight();
int scanlineStride = sampleModel.getScanlineStride();
int[] pixels = dataBuffer.getData();
int offset = dataBuffer.getOffset();
int translateX = raster.getSampleModelTranslateX();
int translateY = raster.getSampleModelTranslateY();
offset += -translateX-translateY*scanlineStride;
return new GrabbableIntPixels(pixels, w, h, offset, scanlineStride);
}
static A printStackTrace(A e) {
// we go to system.out now - system.err is nonsense
if (e != null) print(getStackTrace(e));
return e;
}
static void printStackTrace() {
printStackTrace(new Throwable());
}
static void printStackTrace(String msg) {
printStackTrace(new Throwable(msg));
}
static void printStackTrace(String msg, Throwable e) {
printStackTrace(new Throwable(msg, e));
}
static RuntimeException fail() { throw new RuntimeException("fail"); }
static RuntimeException fail(Throwable e) { throw asRuntimeException(e); }
static RuntimeException fail(Object msg) { throw new RuntimeException(String.valueOf(msg)); }
static RuntimeException fail(Object... objects) { throw new Fail(objects); }
static RuntimeException fail(String msg) { throw new RuntimeException(msg == null ? "" : msg); }
static RuntimeException fail(String msg, Throwable innerException) { throw new RuntimeException(msg, innerException); }
static void _handleError(Error e) {
call(javax(), "_handleError", e);
}
static int l(Object[] a) { return a == null ? 0 : a.length; }
static int l(boolean[] a) { return a == null ? 0 : a.length; }
static int l(byte[] a) { return a == null ? 0 : a.length; }
static int l(short[] a) { return a == null ? 0 : a.length; }
static int l(long[] a) { return a == null ? 0 : a.length; }
static int l(int[] a) { return a == null ? 0 : a.length; }
static int l(float[] a) { return a == null ? 0 : a.length; }
static int l(double[] a) { return a == null ? 0 : a.length; }
static int l(char[] a) { return a == null ? 0 : a.length; }
static int l(Collection c) { return c == null ? 0 : c.size(); }
static int l(Iterator i) { return iteratorCount_int_close(i); } // consumes the iterator && closes it if possible
static int l(Map m) { return m == null ? 0 : m.size(); }
static int l(CharSequence s) { return s == null ? 0 : s.length(); }
static long l(File f) { return f == null ? 0 : f.length(); }
static int l(Object o) {
return o == null ? 0
: o instanceof String ? l((String) o)
: o instanceof Map ? l((Map) o)
: o instanceof Collection ? l((Collection) o)
: o instanceof Object[] ? l((Object[]) o)
: o instanceof boolean[] ? l((boolean[]) o)
: o instanceof byte[] ? l((byte[]) o)
: o instanceof char[] ? l((char[]) o)
: o instanceof short[] ? l((short[]) o)
: o instanceof int[] ? l((int[]) o)
: o instanceof float[] ? l((float[]) o)
: o instanceof double[] ? l((double[]) o)
: o instanceof long[] ? l((long[]) o)
: (Integer) call(o, "size");
}
static Field getOpt_findField(Class> c, String field) {
Class _c = c;
do {
for (Field f : _c.getDeclaredFields())
if (f.getName().equals(field))
return f;
_c = _c.getSuperclass();
} while (_c != null);
return null;
}
static Field makeAccessible(Field f) {
try {
f.setAccessible(true);
} catch (Throwable e) {
// Note: The error reporting only works with Java VM option --illegal-access=deny
vmBus_send("makeAccessible_error", e, f);
}
return f;
}
static Method makeAccessible(Method m) {
try {
m.setAccessible(true);
} catch (Throwable e) {
vmBus_send("makeAccessible_error", e, m);
}
return m;
}
static Constructor makeAccessible(Constructor c) {
try {
c.setAccessible(true);
} catch (Throwable e) {
vmBus_send("makeAccessible_error", e, c);
}
return c;
}
static Object getOptDynOnly(DynamicObject o, String field) {
if (o == null || o.fieldValues == null) return null;
return o.fieldValues.get(field);
}
static RuntimeException asRuntimeException(Throwable t) {
if (t instanceof Error)
_handleError((Error) t);
return t instanceof RuntimeException ? (RuntimeException) t : new RuntimeException(t);
}
// custom mainClass only works with hotwire_here
static Class> hotwire(String src) { return hotwire(src, __1 -> mainClassNameForClassLoader(__1)); }
static Class> hotwire(String src, IF1 calculateMainClass) {
assertFalse(_inCore());
Class j = getJavaX();
if (isAndroid()) {
synchronized(j) { // hopefully this goes well...
List libraries = new ArrayList();
File srcDir = (File) call(j, "transpileMain", src, libraries);
if (srcDir == null)
throw fail("transpileMain returned null (src=" + quote(src) + ")");
Object androidContext = get(j, "androidContext");
return (Class) call(j, "loadx2android", srcDir, src);
}
} else {
Class c = (Class) (call(j, "hotwire", src));
hotwire_copyOver(c);
return c;
}
}
static A callMain(A c, String... args) {
callOpt(c, "main", new Object[] {args});
return c;
}
static void callMain() {
callMain(mc());
}
// from: https://stackoverflow.com/questions/14416107/int-array-to-bufferedimage
// pixels are RGB pixels
static BufferedImage intArrayToBufferedImage(int[] pixels, int w, int h) {
int[] bitMasks = new int[]{0xFF0000, 0xFF00, 0xFF, 0xFF000000};
SinglePixelPackedSampleModel sm = new SinglePixelPackedSampleModel(DataBuffer.TYPE_INT, w, h, bitMasks);
DataBufferInt db = new DataBufferInt(pixels, pixels.length);
WritableRaster wr = Raster.createWritableRaster(sm, db, new Point());
return new BufferedImage(ColorModel.getRGBdefault(), wr, false, null);
}
static Rect rectFromPoints(int x1, int y1, int x2, int y2) {
return pointsRect(x1, y1, x2, y2);
}
static Rect rectFromPoints(Pt a, Pt b) {
return pointsRect(a.x, a.y, b.x, b.y);
}
static String[] dropFirst(int n, String[] a) {
return drop(n, a);
}
static String[] dropFirst(String[] a) {
return drop(1, a);
}
static Object[] dropFirst(Object[] a) {
return drop(1, a);
}
static List dropFirst(List l) {
return dropFirst(1, l);
}
static List dropFirst(int n, Iterable i) { return dropFirst(n, toList(i)); }
static List dropFirst(Iterable i) { return dropFirst(toList(i)); }
static List dropFirst(int n, List l) {
return n <= 0 ? l : new ArrayList(l.subList(Math.min(n, l.size()), l.size()));
}
static List dropFirst(List l, int n) {
return dropFirst(n, l);
}
static String dropFirst(int n, String s) { return substring(s, n); }
static String dropFirst(String s, int n) { return substring(s, n); }
static String dropFirst(String s) { return substring(s, 1); }
static int indexOfNonDigit(String s) {
int n = l(s);
for (int i = 0; i < n; i++)
if (!isDigit(s.charAt(i)))
return i;
return -1;
}
static String shortenClassName(String name) {
if (name == null) return null;
int i = lastIndexOf(name, "$");
if (i < 0) i = lastIndexOf(name, ".");
return i < 0 ? name : substring(name, i+1);
}
static ThreadLocal assertVerbose_value = new ThreadLocal();
static void assertVerbose(boolean b) {
assertVerbose_value.set(b);
}
static boolean assertVerbose() { return isTrue(assertVerbose_value.get()); }
static A assertEqualsVerbose(Object x, A y) {
assertEqualsVerbose((String) null, x, y);
return y;
}
// x = expected, y = actual
static A assertEqualsVerbose(String msg, Object x, A y) {
if (!eq(x, y)) {
throw fail((nempty(msg) ? msg + ": " : "") + "expected: "+ x + ", got: " + y);
} else
print("OK" + (empty(msg) ? "" : " " + msg) + ": " + /*sfu*/(x));
return y;
}
static boolean eq(Object a, Object b) {
return a == b || a != null && b != null && a.equals(b);
}
// a little kludge for stuff like eq(symbol, "$X")
static boolean eq(Symbol a, String b) {
return eq(str(a), b);
}
static String nullIfEmpty(String s) {
return isEmpty(s) ? null : s;
}
static Map nullIfEmpty(Map map) {
return isEmpty(map) ? null : map;
}
static List nullIfEmpty(List l) {
return isEmpty(l) ? null : l;
}
static volatile StringBuffer local_log = new StringBuffer(); // not redirected
static boolean printAlsoToSystemOut = true;
static volatile Appendable print_log = local_log; // might be redirected, e.g. to main bot
// in bytes - will cut to half that
static volatile int print_log_max = 1024*1024;
static volatile int local_log_max = 100*1024;
static boolean print_silent = false; // total mute if set
static Object print_byThread_lock = new Object();
static volatile ThreadLocal