aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--jnlp-files/jogl-applet-runner-newt-gears-normal.html32
-rw-r--r--jnlp-files/jogl-applet-runner-newt-gears-special.html40
-rw-r--r--jnlp-files/jogl-applet-runner-newt.jnlp26
-rw-r--r--jnlp-files/jogl-applet-version.html (renamed from jnlp-files/jogl-applet-version-jnlp.html)0
-rw-r--r--jnlp-files/jogl-test-applets.html29
-rwxr-xr-xsrc/newt/classes/com/jogamp/newt/awt/applet/JOGLNewtApplet1Run.java160
-rwxr-xr-xsrc/newt/classes/com/jogamp/newt/awt/applet/JOGLNewtAppletBase.java242
-rw-r--r--www/index.html16
8 files changed, 542 insertions, 3 deletions
diff --git a/jnlp-files/jogl-applet-runner-newt-gears-normal.html b/jnlp-files/jogl-applet-runner-newt-gears-normal.html
new file mode 100644
index 000000000..126ebea08
--- /dev/null
+++ b/jnlp-files/jogl-applet-runner-newt-gears-normal.html
@@ -0,0 +1,32 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+<html>
+<head>
+<title>JOGL NEWT JNLP Applet Runner - GearsES2 - normal</title>
+</head>
+<body BGCOLOR="#ffffff">
+
+<P>
+
+<applet width=200 height=200>
+ <param name="java_arguments" value="-Dsun.java2d.noddraw=true">
+ <param name="gl_event_listener_class" value="com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2">
+ <param name="gl_profile" value="GL2">
+ <param name="gl_swap_interval" value="1">
+ <param name="gl_debug" value="false">
+ <param name="gl_trace" value="false">
+ <param name="jnlp_href" value="jogl-applet-runner-newt.jnlp">
+</applet>Hello Gears !
+
+</P>
+<P>
+JOGL NEWT JNLP Applet Runner Special Keys:<br>
+<ul>
+ <li> d - toggle decoration </li>
+ <li> f - toggle fullscreen </li>
+ <li> r - in/out browser window </li>
+ <li> a - on/off always-on-top </li>
+</ul>
+</P>
+
+</body>
+</html>
diff --git a/jnlp-files/jogl-applet-runner-newt-gears-special.html b/jnlp-files/jogl-applet-runner-newt-gears-special.html
new file mode 100644
index 000000000..3472e62ec
--- /dev/null
+++ b/jnlp-files/jogl-applet-runner-newt-gears-special.html
@@ -0,0 +1,40 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+<html>
+<head>
+<title>JOGL NEWT JNLP Applet Runner - GearsES2 - special</title>
+</head>
+<body BGCOLOR="#ffffff">
+
+<P>
+
+<applet width=1 height=1>
+ <param name="java_arguments" value="-Dsun.java2d.noddraw=true">
+ <param name="gl_event_listener_class" value="com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2">
+ <param name="gl_profile" value="GL2">
+ <param name="gl_swap_interval" value="1">
+ <param name="gl_undecorated" value="true">
+ <param name="gl_opaque" value="false">
+ <param name="gl_alwaysontop" value="true">
+ <param name="gl_dx" value="10">
+ <param name="gl_dy" value="0">
+ <param name="gl_width" value="200">
+ <param name="gl_height" value="200">
+ <param name="gl_debug" value="false">
+ <param name="gl_trace" value="false">
+ <param name="jnlp_href" value="jogl-applet-runner-newt.jnlp">
+</applet>Hello Gears !
+
+</P>
+<P>
+JOGL NEWT JNLP Applet Runner Special Keys:<br>
+<ul>
+ <li> d - toggle decoration </li>
+ <li> f - toggle fullscreen </li>
+ <li> r - in/out browser window </li>
+ <li> a - on/off always-on-top </li>
+</ul>
+</P>
+
+
+</body>
+</html>
diff --git a/jnlp-files/jogl-applet-runner-newt.jnlp b/jnlp-files/jogl-applet-runner-newt.jnlp
new file mode 100644
index 000000000..77f8c32c0
--- /dev/null
+++ b/jnlp-files/jogl-applet-runner-newt.jnlp
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<jnlp codebase="JOGL_CODEBASE_TAG" href="jogl-applet-runner-newt.jnlp" version="JOGAMP_VERSION">
+ <information>
+ <title>JOGL JNLP Applet Runner NEWT</title>
+ <vendor>JogAmp Community</vendor>
+ <homepage href="http://jogamp.org/"/>
+ <description>JOGL JNLP Applet Runner NEWT</description>
+ <offline-allowed/>
+ </information>
+ <update check="background" policy="always"/>
+
+ <resources>
+ <j2se href="http://java.sun.com/products/autodl/j2se" version="1.4+"/>
+ <property name="sun.java2d.noddraw" value="true"/>
+ <jar href="jar/jogl.test.jar" main="true"/>
+ <jar href="jar/junit.jar" />
+ <extension name="jogl-all-awt" href="JOGL_CODEBASE_TAG/jogl-all-awt.jnlp" />
+ </resources>
+
+ <applet-desc
+ name="JOGLNewtApplet2Run-Applet"
+ main-class="com.jogamp.newt.awt.applet.JOGLNewtApplet1Run"
+ width="200"
+ height="200">
+ </applet-desc>
+</jnlp>
diff --git a/jnlp-files/jogl-applet-version-jnlp.html b/jnlp-files/jogl-applet-version.html
index 316ce2fcc..316ce2fcc 100644
--- a/jnlp-files/jogl-applet-version-jnlp.html
+++ b/jnlp-files/jogl-applet-version.html
diff --git a/jnlp-files/jogl-test-applets.html b/jnlp-files/jogl-test-applets.html
new file mode 100644
index 000000000..60e8f8fe3
--- /dev/null
+++ b/jnlp-files/jogl-test-applets.html
@@ -0,0 +1,29 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+<html>
+<head>
+<title>JOGL Test Applets</title>
+</head>
+<body>
+
+<H2> Test page for JOGL Applets </H2>
+
+<p>
+<H3> Version </H3>
+<ul>
+ <li><a href="jogl-applet-version.html">Applet (JNLP/Launcher)</a></li>
+ <li><a href="jogl-applet-version-lancheronly.html">Applet (Launcher Only)</a></li>
+ <li><a href="jogl-application-version.jnlp">Application</a></li>
+</ul>
+</p>
+
+
+<p>
+<H3> AWT JNLP Applet's using native NEWT (JOGL NEWT Applet Launcher)</H3>
+<ul>
+ <li><a href="jogl-applet-runner-newt-gears-normal.html">GearsES2 in Applet Area (normal)</a></li>
+ <li><a href="jogl-applet-runner-newt-gears-special.html">GearsES2 translucent over pager (special)</a></li>
+</ul>
+</p>
+
+</body>
+</html>
diff --git a/src/newt/classes/com/jogamp/newt/awt/applet/JOGLNewtApplet1Run.java b/src/newt/classes/com/jogamp/newt/awt/applet/JOGLNewtApplet1Run.java
new file mode 100755
index 000000000..64ac66504
--- /dev/null
+++ b/src/newt/classes/com/jogamp/newt/awt/applet/JOGLNewtApplet1Run.java
@@ -0,0 +1,160 @@
+package com.jogamp.newt.awt.applet;
+
+import java.applet.*;
+import java.awt.Container;
+import java.awt.event.MouseListener;
+import java.awt.event.MouseMotionListener;
+import java.awt.event.KeyListener;
+
+import javax.media.opengl.*;
+import com.jogamp.newt.awt.NewtCanvasAWT;
+import com.jogamp.newt.opengl.GLWindow;
+import java.awt.BorderLayout;
+
+/**
+ * Simple GLEventListener deployment as an applet using JOGL. This demo must be
+ * referenced from a web page via an &lt;applet&gt; tag.
+ *
+ * <p>
+ * Example of an applet tag using GearsES2 within the applet area (normal case):
+ * <pre>
+ &lt;applet width=100 height=100&gt;
+ &lt;param name="java_arguments" value="-Dsun.java2d.noddraw=true"&gt;
+ &lt;param name="gl_event_listener_class" value="com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2"&gt;
+ &lt;param name="gl_profile" value="GL2"&gt;
+ &lt;param name="gl_swap_interval" value="1"&gt;
+ &lt;param name="gl_debug" value="false"&gt;
+ &lt;param name="gl_trace" value="false"&gt;
+ &lt;param name="jnlp_href" value="jogl-newt-applet-runner.jnlp"&gt;
+ &lt;/applet&gt;Hello Gears !
+ * </pre>
+ * </p>
+ *
+ * <p>
+ * Example of an applet tag using GearsES2 in an undecorated, translucent and always-on-top window:
+ * <pre>
+ &lt;applet width=1 height=1&gt;
+ &lt;param name="java_arguments" value="-Dsun.java2d.noddraw=true"&gt;
+ &lt;param name="gl_event_listener_class" value="com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2"&gt;
+ &lt;param name="gl_profile" value="GL2"&gt;
+ &lt;param name="gl_swap_interval" value="1"&gt;
+ &lt;param name="gl_undecorated" value="true"&gt;
+ &lt;param name="gl_alwaysontop" value="true"&gt;
+ &lt;param name="gl_opaque" value="false"&gt;
+ &lt;param name="gl_dx" value="10"&gt;
+ &lt;param name="gl_dy" value="0"&gt;
+ &lt;param name="gl_width" value="100"&gt;
+ &lt;param name="gl_height" value="100"&gt;
+ &lt;param name="gl_debug" value="false"&gt;
+ &lt;param name="gl_trace" value="false"&gt;
+ &lt;param name="jnlp_href" value="jogl-newt-applet-runner.jnlp"&gt;
+ &lt;/applet&gt;Hello Gears !
+ * </pre>
+ * </p>
+ */
+@SuppressWarnings("serial")
+public class JOGLNewtApplet1Run extends Applet {
+ GLWindow glWindow;
+ NewtCanvasAWT newtCanvasAWT;
+ JOGLNewtAppletBase base;
+ /** if valid glStandalone:=true (own window) ! */
+ int glXd=Integer.MAX_VALUE, glYd=Integer.MAX_VALUE, glWidth=Integer.MAX_VALUE, glHeight=Integer.MAX_VALUE;
+ boolean glStandalone = false;
+
+ public void init() {
+ if(!(this instanceof Container)) {
+ throw new RuntimeException("This Applet is not a AWT Container");
+ }
+ Container container = (Container) this; // have to think about that, we may use a Container
+
+ String glEventListenerClazzName=null;
+ String glProfileName=null;
+ int glSwapInterval=0;
+ boolean glDebug=false;
+ boolean glTrace=false;
+ boolean glUndecorated=false;
+ boolean glAlwaysOnTop=false;
+ boolean glOpaque=true;
+ try {
+ glEventListenerClazzName = getParameter("gl_event_listener_class");
+ glProfileName = getParameter("gl_profile");
+ glSwapInterval = JOGLNewtAppletBase.str2Int(getParameter("gl_swap_interval"), glSwapInterval);
+ glDebug = JOGLNewtAppletBase.str2Bool(getParameter("gl_debug"), glDebug);
+ glTrace = JOGLNewtAppletBase.str2Bool(getParameter("gl_trace"), glTrace);
+ glUndecorated = JOGLNewtAppletBase.str2Bool(getParameter("gl_undecorated"), glUndecorated);
+ glAlwaysOnTop = JOGLNewtAppletBase.str2Bool(getParameter("gl_alwaysontop"), glAlwaysOnTop);
+ glOpaque = JOGLNewtAppletBase.str2Bool(getParameter("gl_opaque"), glOpaque);
+ glXd = JOGLNewtAppletBase.str2Int(getParameter("gl_dx"), glXd);
+ glYd = JOGLNewtAppletBase.str2Int(getParameter("gl_dy"), glYd);
+ glWidth = JOGLNewtAppletBase.str2Int(getParameter("gl_width"), glWidth);
+ glHeight = JOGLNewtAppletBase.str2Int(getParameter("gl_height"), glHeight);
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ if(null==glEventListenerClazzName) {
+ throw new RuntimeException("No applet parameter 'gl_event_listener_class'");
+ }
+ glStandalone = Integer.MAX_VALUE>glXd && Integer.MAX_VALUE>glYd && Integer.MAX_VALUE>glWidth && Integer.MAX_VALUE>glHeight;
+
+ base = new JOGLNewtAppletBase(glEventListenerClazzName,
+ glSwapInterval,
+ glDebug,
+ glTrace);
+
+ try {
+ GLProfile.initSingleton(false);
+ GLCapabilities caps = new GLCapabilities(GLProfile.get(glProfileName));
+ caps.setBackgroundOpaque(glOpaque);
+ glWindow = GLWindow.create(caps);
+ glWindow.setUndecorated(glUndecorated);
+ glWindow.setAlwaysOnTop(glAlwaysOnTop);
+ if(glStandalone) {
+ newtCanvasAWT = null;
+ } else {
+ newtCanvasAWT = new NewtCanvasAWT(glWindow);
+ container.setLayout(new BorderLayout());
+ container.add(newtCanvasAWT, BorderLayout.CENTER);
+ }
+ base.init(glWindow);
+ if(base.isValid()) {
+ GLEventListener glEventListener = base.getGLEventListener();
+
+ if(glEventListener instanceof MouseListener) {
+ addMouseListener((MouseListener)glEventListener);
+ }
+ if(glEventListener instanceof MouseMotionListener) {
+ addMouseMotionListener((MouseMotionListener)glEventListener);
+ }
+ if(glEventListener instanceof KeyListener) {
+ addKeyListener((KeyListener)glEventListener);
+ }
+ }
+ } catch (Throwable t) {
+ throw new RuntimeException(t);
+ }
+ }
+
+ public void start() {
+ if(glStandalone) {
+ glWindow.setSize(glWidth, glHeight);
+ final java.awt.Point p0 = this.getLocationOnScreen();
+ glWindow.setPosition(p0.x+glXd, p0.y+glYd);
+ }
+ base.start();
+ }
+
+ public void stop() {
+ base.stop();
+ }
+
+ public void destroy() {
+ glWindow.setVisible(false); // hide 1st
+ if(!glStandalone) {
+ glWindow.reparentWindow(null); // get out of newtCanvasAWT
+ this.remove(newtCanvasAWT); // remove newtCanvasAWT
+ }
+ base.destroy(); // destroy glWindow unrecoverable
+ base=null;
+ }
+}
+
diff --git a/src/newt/classes/com/jogamp/newt/awt/applet/JOGLNewtAppletBase.java b/src/newt/classes/com/jogamp/newt/awt/applet/JOGLNewtAppletBase.java
new file mode 100755
index 000000000..97142b32b
--- /dev/null
+++ b/src/newt/classes/com/jogamp/newt/awt/applet/JOGLNewtAppletBase.java
@@ -0,0 +1,242 @@
+package com.jogamp.newt.awt.applet;
+
+import java.lang.reflect.*;
+
+import javax.media.nativewindow.NativeWindow;
+import javax.media.opengl.*;
+import com.jogamp.opengl.util.*;
+
+import com.jogamp.newt.event.*;
+import com.jogamp.newt.opengl.GLWindow;
+
+/** Shows how to deploy an applet using JOGL. This demo must be
+ referenced from a web page via an &lt;applet&gt; tag. */
+
+public class JOGLNewtAppletBase extends WindowAdapter implements KeyListener, MouseListener, GLEventListener {
+ String glEventListenerClazzName;
+ int glSwapInterval;
+ boolean glDebug;
+ boolean glTrace;
+
+ GLEventListener glEventListener = null;
+ GLWindow glWindow = null;
+ Animator glAnimator=null;
+ boolean isValid = false;
+ NativeWindow awtParent;
+
+ public JOGLNewtAppletBase(String glEventListenerClazzName,
+ int glSwapInterval,
+ boolean glDebug,
+ boolean glTrace) {
+
+ this.glEventListenerClazzName=glEventListenerClazzName;
+ this.glSwapInterval=glSwapInterval;
+ this.glDebug = glDebug;
+ this.glTrace = glTrace;
+ }
+
+ public GLEventListener getGLEventListener() { return glEventListener; }
+ public GLWindow getGLWindow() { return glWindow; }
+ public Animator getGLAnimator() { return glAnimator; }
+ public boolean isValid() { return isValid; }
+
+ public static boolean str2Bool(String str, boolean def) {
+ if(null==str) return def;
+ try {
+ return Boolean.valueOf(str).booleanValue();
+ } catch (Exception ex) { ex.printStackTrace(); }
+ return def;
+ }
+
+ public static int str2Int(String str, int def) {
+ if(null==str) return def;
+ try {
+ return Integer.parseInt(str);
+ } catch (Exception ex) { ex.printStackTrace(); }
+ return def;
+ }
+
+ public static GLEventListener createInstance(String clazzName) {
+ Object instance = null;
+
+ try {
+ Class<?> clazz = Class.forName(clazzName);
+ instance = clazz.newInstance();
+ } catch (Throwable t) {
+ t.printStackTrace();
+ throw new RuntimeException("Error while instantiating demo: "+clazzName);
+ }
+ if( null == instance ) {
+ throw new RuntimeException("Null GLEventListener: "+clazzName);
+ }
+ if( !(instance instanceof GLEventListener) ) {
+ throw new RuntimeException("Not a GLEventListener: "+clazzName);
+ }
+ return (GLEventListener) instance;
+ }
+
+ public static boolean setField(Object instance, String fieldName, Object value) {
+ try {
+ Field f = instance.getClass().getField(fieldName);
+ if(f.getType().isInstance(value)) {
+ f.set(instance, value);
+ return true;
+ } else {
+ System.out.println(instance.getClass()+" '"+fieldName+"' field not assignable with "+value.getClass()+", it's a: "+f.getType());
+ }
+ } catch (NoSuchFieldException nsfe) {
+ System.out.println(instance.getClass()+" has no '"+fieldName+"' field");
+ } catch (Throwable t) {
+ t.printStackTrace();
+ }
+ return false;
+ }
+
+ public void init(GLWindow glWindow) {
+ init(Thread.currentThread().getThreadGroup(), glWindow);
+ }
+
+ public void init(ThreadGroup tg, GLWindow glWindow) {
+ this.glWindow = glWindow;
+
+ glEventListener = createInstance(glEventListenerClazzName);
+
+ try {
+ if(!setField(glEventListener, "window", glWindow)) {
+ setField(glEventListener, "glWindow", glWindow);
+ }
+
+ glWindow.addGLEventListener(this);
+ glWindow.addGLEventListener(glEventListener);
+
+ if(glEventListener instanceof WindowListener) {
+ glWindow.addWindowListener((WindowListener)glEventListener);
+ }
+ glWindow.addWindowListener(this);
+
+ if(glEventListener instanceof MouseListener) {
+ glWindow.addMouseListener((MouseListener)glEventListener);
+ }
+ glWindow.addMouseListener(this);
+
+ if(glEventListener instanceof KeyListener) {
+ glWindow.addKeyListener((KeyListener)glEventListener);
+ }
+ glWindow.addKeyListener(this);
+
+ glWindow.setUpdateFPSFrames(FPSCounter.DEFAULT_FRAMES_PER_INTERVAL, System.err);
+
+ // glAnimator = new FPSAnimator(canvas, 60);
+ glAnimator = new Animator(tg, glWindow);
+ } catch (Throwable t) {
+ throw new RuntimeException(t);
+ }
+ isValid = true;
+ }
+
+ public void start() {
+ if(isValid) {
+ glWindow.setVisible(true);
+ glAnimator.start();
+ awtParent = glWindow.getParent();
+ }
+ }
+
+ public void stop() {
+ if(null!=glAnimator) {
+ glAnimator.stop();
+ glWindow.setVisible(false);
+ }
+ }
+
+ public void destroy() {
+ isValid = false;
+ if(null!=glAnimator) {
+ glAnimator.stop();
+ glAnimator.remove(glWindow);
+ glAnimator=null;
+ }
+ if(null!=glWindow) {
+ glWindow.destroy();
+ glWindow=null;
+ }
+ }
+
+ // ***********************************************************************************
+ // ***********************************************************************************
+ // ***********************************************************************************
+
+ public void init(GLAutoDrawable drawable) {
+ GL _gl = drawable.getGL();
+
+ if(glDebug) {
+ try {
+ _gl = _gl.getContext().setGL( GLPipelineFactory.create("javax.media.opengl.Debug", null, _gl, null) );
+ } catch (Exception e) {e.printStackTrace();}
+ }
+
+ if(glTrace) {
+ try {
+ // Trace ..
+ _gl = _gl.getContext().setGL( GLPipelineFactory.create("javax.media.opengl.Trace", null, _gl, new Object[] { System.err } ) );
+ } catch (Exception e) {e.printStackTrace();}
+ }
+
+ if(glSwapInterval>=0) {
+ _gl.setSwapInterval(glSwapInterval);
+ }
+ }
+ public void reshape(GLAutoDrawable drawable, int x, int y, int width, int height) {
+ }
+ public void display(GLAutoDrawable drawable) {
+ }
+ public void dispose(GLAutoDrawable drawable) {
+ }
+
+ // ***********************************************************************************
+ // ***********************************************************************************
+ // ***********************************************************************************
+
+ public void keyPressed(KeyEvent e) {
+ }
+ public void keyReleased(KeyEvent e) {
+ }
+ public void keyTyped(KeyEvent e) {
+ if(e.getKeyChar()=='d') {
+ glWindow.setUndecorated(!glWindow.isUndecorated());
+ } if(e.getKeyChar()=='f') {
+ glWindow.setFullscreen(!glWindow.isFullscreen());
+ } else if(e.getKeyChar()=='a') {
+ glWindow.setAlwaysOnTop(!glWindow.isAlwaysOnTop());
+ } else if(e.getKeyChar()=='r' && null!=awtParent) {
+ if(null == glWindow.getParent()) {
+ glWindow.reparentWindow(awtParent);
+ } else {
+ glWindow.reparentWindow(null);
+ }
+ }
+ }
+
+ // ***********************************************************************************
+ // ***********************************************************************************
+ // ***********************************************************************************
+
+ public void mouseClicked(MouseEvent e) {
+ }
+ public void mouseEntered(MouseEvent e) {
+ }
+ public void mouseExited(MouseEvent e) {
+ }
+ public void mousePressed(MouseEvent e) {
+ }
+ public void mouseReleased(MouseEvent e) {
+ }
+ public void mouseMoved(MouseEvent e) {
+ }
+ public void mouseDragged(MouseEvent e) {
+ }
+ public void mouseWheelMoved(MouseEvent e) {
+ }
+
+}
+
diff --git a/www/index.html b/www/index.html
index 2ae8643df..0911395b0 100644
--- a/www/index.html
+++ b/www/index.html
@@ -73,9 +73,19 @@
It integrates with the AWT and Swing widget sets, as well with custom windowing toolkits using the NativeWindow API.
It is part of a suite of open-source technologies initiated by the Game Technology Group at Sun Microsystems.
</p>
- <p>
- Quick Version Info [ <a href="../../deployment/jogamp-current/applet-version-jnlp.html">Applet</a>,
- <a href="../../deployment/jogamp-current/application-version.jnlp">Application</a> ]
+ <p> Quick Version Info:
+ <ul>
+ <li>Current Version [ <a href="../../deployment/jogamp-current/jogl-applet-version.html">Applet</a>,
+ <a href="../../deployment/jogamp-current/jogl-application-version.jnlp">Application</a> ]</li>
+ <li>Next Version [ <a href="../../deployment/jogamp-next/jogl-applet-version.html">Applet</a>,
+ <a href="../../deployment/jogamp-next/jogl-application-version.jnlp">Application</a> ]</li>
+ </ul>
+ </p>
+ <p> Some JOGL Test Applets:
+ <ul>
+ <li><a href="../../deployment/jogamp-current/jogl-test-applets.html">Current Version</a></li>
+ <li><a href="../../deployment/jogamp-next/jogl-test-applets.html">Next Version</a></li>
+ </ul>
</p>
<p>
Please see the <a href="../../jogl-demos/www">JOGL demos</a> for illustrations of