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.*;
import java.time.Duration;
import java.lang.invoke.VarHandle;
import java.lang.invoke.MethodHandles;
// mark point of interest in an animated way
import javax.swing.event.AncestorListener;
import javax.swing.event.AncestorEvent;
import javax.swing.Timer;
import static x30_pkg.x30_util.DynamicObject;
import java.awt.datatransfer.*;
import java.awt.dnd.*;
import java.awt.geom.*;
import java.awt.datatransfer.Transferable;
import java.awt.datatransfer.DataFlavor;
import java.text.*;
import javax.imageio.metadata.*;
import javax.imageio.stream.*;
import java.text.NumberFormat;
import javax.swing.border.*;
import javax.swing.undo.UndoManager;
import java.util.TimeZone;
import java.awt.datatransfer.StringSelection;
import java.text.SimpleDateFormat;
import java.nio.charset.Charset;
import java.awt.datatransfer.UnsupportedFlavorException;
import javax.swing.Icon;
class main {
static void g22markPointAnimation(ImageSurface is, Pt pt) {
is.addOverlay(g -> {
var p = scalePt(pt, is.getZoomX(), is.getZoomY());
double blend = zeroToOneSine(frac(sysSeconds()));
drawSquareAround(g, p, 1, blendColor(blend, Color.green, Color.red));
drawSquareAround(g, p, 2, blendColor(blend, Color.red, Color.green));
drawSquareAround(g, p, 3, blendColor(blend, Color.white, Color.black));
});
repaintEvery(is, 100);
}
static Pt scalePt(Pt p, double scaleX) { return scalePt(p, scaleX, scaleX); }
static Pt scalePt(Pt p, double scaleX, double scaleY) {
return new Pt(iround(p.x*scaleX), iround(p.y*scaleY));
}
static Pt scalePt(double f, Pt p) {
return scalePt(p, f);
}
static Pt scalePt(int w, int h, double f) {
return scalePt(new Pt(w, h), f);
}
static double zeroToOneSine(double x) {
return 0.5*(1+sin(x*(pi()*2)));
}
static double frac(double d) {
return fraction(d);
}
static double sysSeconds() {
return nanosToSeconds(nanoTime());
}
static void drawSquareAround(Graphics2D g, int p_x, int p_y, int radius, Color color) { drawSquareAround(g, pt(p_x, p_y), radius, color); }
static void drawSquareAround(Graphics2D g, Pt p, int radius, Color color) {
drawRect(g, p.x-radius, p.y-radius, radius*2+1, radius*2+1, color);
}
static Color blendColor(Color a, Color b, double bish) {
return blendColors(a, b, bish);
}
static Color blendColor(double bish, Color a, Color b) {
return blendColors(a, b, bish);
}
static A repaintEvery(int ms, A c) {
return awtDoEvery(c, ms, () -> c.repaint());
}
static A repaintEvery(A c, int ms) {
return repaintEvery(ms, c);
}
static int iround(double d) {
return (int) Math.round(d);
}
static int iround(Number n) {
return iround(toDouble(n));
}
static double sin(double x) {
return Math.sin(x);
}
static double pi() {
return Math.PI;
}
static double fraction(double d) {
return d % 1;
}
static double nanosToSeconds(double nanos) {
return nanoSecondsToSeconds(nanos);
}
static long nanoTime() {
return System.nanoTime();
}
static Pt pt(int x, int y) {
return new Pt(x, y);
}
static Pt pt(int x) {
return new Pt(x, x);
}
static void drawRect(BufferedImage image, int x, int y, int w, int h, Color color) {
Graphics2D g = imageGraphics(image);
drawRect(g, x, y, w, h, color);
g.dispose();
}
static void drawRect(Graphics2D g, int x, int y, int w, int h, Color color) {
g.setColor(color);
g.drawRect(x, y, w, h);
}
static void drawRect(Graphics2D g, Color color, Rect r) {
drawRect(g, r, color);
}
static void drawRect(Graphics2D g, Rect r, Color color) {
g.setColor(color);
g.drawRect(r.x, r.y, r.w, r.h);
}
static void drawRect(Graphics2D g, Rect r) {
g.drawRect(r.x, r.y, r.w, r.h);
}
// draw on currentImage()
static void drawRect(int x, int y, int w, int h, Color color) {
drawRect(currentImage(), x, y, w, h, color);
}
static void drawRect(Rect r, Color color) {
drawRect(r.x, r.y, r.w, r.h, color);
}
static void drawRect(BufferedImage image, Rect r, Color c) {
if (r != null) drawRect(image, r.x, r.y, r.w, r.h, c);
}
static Color blendColors(double bish, Color a, Color b) {
return blendColors(a, b, bish);
}
static Color blendColors(Color a, Color b, double bish) {
bish = normalizeTo0to1(bish);
return new Color(
(float) blend(a.getRed()/255.0, b.getRed()/255.0, bish),
(float) blend(a.getGreen()/255.0, b.getGreen()/255.0, bish),
(float) blend(a.getBlue()/255.0, b.getBlue()/255.0, bish));
}
static A awtDoEvery(A component, long delay, Runnable r) {
return awtEvery(component, delay, r);
}
static A awtDoEvery(A component, long delay, long firstDelay, Runnable r) {
return awtEvery(component, delay, firstDelay, r);
}
static void awtDoEvery(RootPaneContainer frame, long delay, Runnable r) {
awtEvery(frame, delay, r);
}
static A awtDoEvery(A component, double delaySeconds, Runnable r) {
return awtEvery(component, delaySeconds, r);
}
static double toDouble(Object o) {
if (o instanceof Number)
return ((Number) o).doubleValue();
if (o instanceof BigInteger)
return ((BigInteger) o).doubleValue();
if (o instanceof String)
return parseDouble((String) o);
if (o == null) return 0.0;
throw fail(o);
}
static double nanoSecondsToSeconds(double nanos) {
return nanos*1e-9;
}
static ThreadLocal imageGraphics_antiAlias = new ThreadLocal();
static Graphics2D imageGraphics(BufferedImage img) {
return !isFalse(imageGraphics_antiAlias.get()) ? antiAliasGraphics(img) : createGraphics(img);
}
static ThreadLocal currentImage_var = new ThreadLocal();
static BufferedImage currentImage() {
return currentImage_var.get();
}
static void currentImage(BufferedImage img) {
currentImage_var.set(img);
}
static double normalizeTo0to1(double x) {
return Math.min(Math.max(x, 0), 1);
}
static int blend(int x, int y, double yish) {
double xish = 1-yish;
return (int) (x*xish+y*yish);
}
static double blend(double x, double y, double yish) {
double xish = 1-yish;
return x*xish+y*yish;
}
static A awtEvery(A component, long delay, Object r) {
swingEvery(component, delay, r);
return component;
}
static A awtEvery(A component, long delay, Runnable r) { return awtEvery(component, delay, delay, r); }
static A awtEvery(A component, long delay, long firstDelay, Runnable r) {
return awtEvery(component, delay, firstDelay, (Object) r);
}
static A awtEvery(A component, long delay, long firstDelay, Object r) {
swingEvery(component, delay, firstDelay, r);
return component;
}
static void awtEvery(RootPaneContainer frame, long delay, Object r) {
swingEvery(frame, delay, r);
}
static A awtEvery(A component, double delaySeconds, Object r) {
return awtEvery(component, toMS(delaySeconds), r);
}
static double parseDouble(String s) {
return empty(s) ? 0.0 : Double.parseDouble(s);
}
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 boolean isFalse(Object o) {
return eq(false, o);
}
static Graphics2D antiAliasGraphics(BufferedImage img) {
return antiAliasOn(createGraphics(img));
}
static Map createGraphics_modulators = synchroIdentityHashMap();
static Graphics2D createGraphics(BufferedImage img) {
Graphics2D g = img.createGraphics();
Object mod = createGraphics_modulators.get(img);
if (mod != null)
callF(mod, g);
return g;
}
// mod: voidfunc(Graphics2D)
static void createGraphics_modulate(BufferedImage img, Object mod) {
mapPut2(createGraphics_modulators, img, mod);
}
static void swingEvery(JComponent component, long delay, Object r) {
installTimer(component, delay, r);
}
static void swingEvery(JComponent component, long delay, long firstDelay, Object r) {
installTimer(component, r, delay, firstDelay);
}
static void swingEvery(RootPaneContainer frame, long delay, Object r) {
installTimer(frame, delay, r);
}
static void swingEvery(RootPaneContainer frame, long delay, long firstDelay, Object r) {
installTimer(frame, delay, firstDelay, r);
}
static long toMS(double seconds) {
return (long) (seconds*1000);
}
static boolean empty(Collection c) { return c == null || c.isEmpty(); }
static boolean empty(Iterable c) { return c == null || !c.iterator().hasNext(); }
static boolean empty(CharSequence s) { return s == null || s.length() == 0; }
static boolean empty(Map map) { return map == null || map.isEmpty(); }
static boolean empty(Object[] o) { return o == null || o.length == 0; }
static boolean empty(BitSet bs) { return bs == null || bs.isEmpty(); }
static boolean empty(Object o) {
if (o instanceof Collection) return empty((Collection) o);
if (o instanceof String) return empty((String) o);
if (o instanceof Map) return empty((Map) o);
if (o instanceof Object[]) return empty((Object[]) o);
if (o instanceof byte[]) return empty((byte[]) o);
if (o == null) return true;
throw fail("unknown type for 'empty': " + getType(o));
}
static boolean empty(Iterator i) { return i == null || !i.hasNext(); }
static boolean empty(double[] a) { return a == null || a.length == 0; }
static boolean empty(float[] a) { return a == null || a.length == 0; }
static boolean empty(int[] a) { return a == null || a.length == 0; }
static boolean empty(long[] a) { return a == null || a.length == 0; }
static boolean empty(byte[] a) { return a == null || a.length == 0; }
static boolean empty(short[] a) { return a == null || a.length == 0; }
static boolean empty(IMultiMap mm) { return mm == null || mm.size() == 0; }
static boolean empty(File f) { return getFileSize(f) == 0; }
static boolean empty(Rect r) { return !(r != null && r.w != 0 && r.h != 0); }
static boolean empty(Chain c) { return c == null; }
static boolean empty(AppendableChain c) { return c == null; }
static RuntimeException asRuntimeException(Throwable t) {
if (t instanceof Error)
_handleError((Error) t);
return t instanceof RuntimeException ? (RuntimeException) t : new RuntimeException(t);
}
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 Graphics2D antiAliasOn(Graphics2D g) {
g.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
return g;
}
static Map synchroIdentityHashMap() {
return synchroMap(new IdentityHashMap());
}
static Map> callF_cache = newDangerousWeakHashMap();
static A callF(F0 f) {
return f == null ? null : f.get();
}
static B callF(F1 f, A a) {
return f == null ? null : f.get(a);
}
static A callF(IF0 f) {
return f == null ? null : f.get();
}
static B callF(IF1 f, A a) {
return f == null ? null : f.get(a);
}
static B callF(A a, IF1 f) {
return f == null ? null : f.get(a);
}
static C callF(IF2 f, A a, B b) {
return f == null ? null : f.get(a, b);
}
static void callF(VF1 f, A a) {
if (f != null) f.get(a);
}
static void callF(A a, IVF1 f) {
if (f != null) f.get(a);
}
static void callF(IVF1 f, A a) {
if (f != null) f.get(a);
}
static Object callF(Runnable r) { { if (r != null) r.run(); } return null; }
static Object callF(Object f, Object... args) {
return safeCallF(f, args);
}
static Object safeCallF(Object f, Object... args) {
if (f instanceof Runnable) {
((Runnable) f).run();
return null;
}
if (f == null) return null;
Class c = f.getClass();
ArrayList methods;
synchronized(callF_cache) {
methods = callF_cache.get(c);
if (methods == null)
methods = callF_makeCache(c);
}
int n = l(methods);
if (n == 0) {
if (f instanceof String)
throw fail("Legacy call: " + f);
throw fail("No get method in " + getClassName(c));
}
if (n == 1) return invokeMethod(methods.get(0), f, args);
for (int i = 0; i < n; i++) {
Method m = methods.get(i);
if (call_checkArgs(m, args, false))
return invokeMethod(m, f, args);
}
throw fail("No matching get method in " + getClassName(c));
}
// used internally
static ArrayList callF_makeCache(Class c) {
ArrayList l = new ArrayList();
Class _c = c;
do {
for (Method m : _c.getDeclaredMethods())
if (m.getName().equals("get")) {
makeAccessible(m);
l.add(m);
}
if (!l.isEmpty()) break;
_c = _c.getSuperclass();
} while (_c != null);
callF_cache.put(c, l);
return l;
}
static void mapPut2(Map map, A key, B value) {
if (map != null && key != null)
if (value != null) map.put(key, value);
else map.remove(key);
}
// first delay = delay
static Timer installTimer(JComponent component, Object r, long delay) {
return installTimer(component, r, delay, delay);
}
// first delay = delay
static Timer installTimer(RootPaneContainer frame, long delay, Object r) {
return installTimer(frame.getRootPane(), r, delay, delay);
}
// first delay = delay
static Timer installTimer(JComponent component, long delay, Object r) {
return installTimer(component, r, delay, delay);
}
static Timer installTimer(JComponent component, long delay, long firstDelay, Object r) {
return installTimer(component, r, delay, firstDelay);
}
static Timer installTimer(final JComponent component, final Object r, final long delay, final long firstDelay) {
return installTimer(component, r, delay, firstDelay, true);
}
static Timer installTimer(final JComponent component, final Object r, final long delay, final long firstDelay, final boolean repeats) {
if (component == null) return null;
return (Timer) swingAndWait(new F0