/* Classe MUAPP 20000409 © alain.marty@wanadoo.fr */ import java.applet.*; import java.awt.*; import java.awt.image.*; public class MUAPP extends Applet { Image image; AudioClip drip; String type_dessin; public void init() { MediaTracker tracker = new MediaTracker( this ); String sss = getParameter( "image" ); image = getImage( getCodeBase(), sss ); tracker.addImage( image, 0 ); try { tracker.waitForAll(); } // try { tracker.waitForID( 0 ); } catch (InterruptedException e ) { showStatus( "Chargement interrompu" ); } drip = getAudioClip( getCodeBase(), "drip.au" ); type_dessin = getParameter( "type_dessin" ); } public void paint( Graphics g ) { if (image != null ) g.drawImage( image, 0, 0, this ); } public boolean mouseUp( Event e, int x, int y ) { drip.play(); new FRAME( type_dessin ); return true; } } class FRAME extends Frame { CANVAS canvas; String sss; public FRAME( String titre ) { super( titre ); sss = titre; setLayout( new BorderLayout() ); Panel controles = new Panel(); canvas = new CANVAS( this ); if (canvas.controles() != null) add( "West", canvas.controles() ); add( "Center", canvas ); pack(); move( 200, 100 ); show(); canvas.requestFocus(); } public boolean action( Event e, Object o ) { canvas.requestFocus(); return canvas.action( e, o ); } public boolean handleEvent( Event e ) { switch( e.id ) { case e.WINDOW_DESTROY: hide(); dispose(); return true; default: return super.handleEvent( e ); } } } class CANVAS extends Canvas implements Runnable { FRAME frame; Label s_calcul = new Label(); TextField s_zoom = new TextField(), s_zx = new TextField(), s_zy = new TextField(); Image image = null; Thread thread = null; DESSIN dessin = null; int w = 0, h = 0; double zoom = 0.5, zx = 0.0, zy = 0.0, K = 1.0; Rectangle r = new Rectangle( 0, 0, 0, 0 ); boolean sketch = false; public CANVAS( FRAME f ) { frame = f; resize( 256, 256 ); setBackground( Color.lightGray ); setForeground( Color.black ); if ( frame.sss.equals( "MANDEL" ) ) dessin = new MANDEL(); else if ( frame.sss.equals( "RAYTRACE" ) ) dessin = new RAYTRACE(); } public void init() { zoom = 0.5; zx = 0.0; zy = 0.0; } public final Panel controles() { Panel p = new Panel(); p.setBackground( Color.lightGray ); p.setLayout( new BorderLayout() ); Panel pan = new Panel(); pan.setLayout( new BorderLayout() ); Panel can = new Panel(); can.setLayout( new GridLayout( 0, 2, 1, 1 ) ); can.add( new Label( "Calcul:", Label.RIGHT )); can.add( s_calcul ); can.add( new Label( "Zoom:", Label.RIGHT )); can.add( s_zoom ); can.add( new Label( "Zx:", Label.RIGHT )); can.add( s_zx ); can.add( new Label( "Zy:", Label.RIGHT )); can.add( s_zy ); can.add( new Button( "Reset" )); can.add( new Button( "Stop" )); can.add( new Button( "<<" )); can.add( new Button( ">>" )); pan.add( "North", can ); Panel dess = dessin.controles(); if (dess != null) pan.add( "South", dess ); p.add( "North", pan ); p.add( "Center", new Label( ":)", Label.RIGHT ) ); return p; } public final void infos() { double d, decim = 10000.0; d = Math.round( zoom*decim ) / decim; s_zoom.setText( new Double( d ).toString() ); d = Math.round( zx*decim ) / decim; s_zx.setText( new Double( d ).toString() ); d = Math.round( zy*decim ) / decim; s_zy.setText( new Double( d ).toString() ); s_calcul.setText( "" ); } public void relancer() { if (thread != null) { thread.stop(); thread = null; } thread = new Thread( this ); thread.start(); } public void update( Graphics g ) { paint( g ); } public void paint( Graphics g ) { Dimension dim = size(); if ( w != dim.width || h != dim.height ) { w = dim.width; h = dim.height; relancer(); } if (image != null) g.drawImage( image, 0, 0, this ); if (sketch) { g.setXORMode( getBackground() ); // getForeground() g.fillRect( r.x, r.y, r.width, r.height ); // g.drawRect(); g.setPaintMode(); } } public boolean mouseDown( Event e, int x, int y ) { this.infos(); dessin.infos(); r.x = x; r.y = y; r.width = r.height = 0; sketch = true; return true; } public boolean mouseDrag( Event e, int x, int y ) { r.width = x - r.x; r.height = y - r.y; if (r.width < 0) { r.x = x; r.width = - r.width; } if (r.height < 0) { r.y = y; r.height = - r.height; } repaint(); return true; } public boolean mouseUp( Event e, int x, int y ) { boolean ok = false; ok = dessin.mouseUp( e, x, y ); // APPEL A DESSIN double K = zoom * (double) Math.min( w/2, h/2 ); int xx = r.x + r.width/2; int yy = r.y + r.height/2; double deltax = (w/2 - xx) / K; double deltay = (h/2 - yy) / K; if ( r.width == 0 || r.height == 0 ) { if ( e.shiftDown()) { zx += deltax; zy += deltay; ok = true; } else { this.infos(); dessin.infos(); } } else if ( xx != w/2 && yy != h/2 ) { zx += deltax; zy += deltay; double coeff = Math.max((double) w / (double) r.width, (double) h / (double) r.height ); zoom *= coeff; ok = true; } if (ok) relancer(); r.x = r.y = r.width = r.height = 0; sketch = false; requestFocus(); // NECESSAIRE !!!!!!!!!! return ok; } public boolean keyDown( Event e, int key ) { boolean ok = false; ok = dessin.keyDown( e, key ); // APPEL A DESSIN switch (key) { case Event.UP: zoom *= 2.0; ok = true; break; case Event.DOWN: zoom /= 2.0; ok = true; break; case ' ': zoom = 0.5; zx = 0.0; zy = 0.0; ok = true; break; } if (ok) relancer(); return ok; } public boolean action( Event e, Object o ) { boolean ok = false; if ( e.target instanceof Button ) { if ( o.equals( "Reset" ) ) { init(); dessin.init(); ok = true; } else if ( o.equals( "Stop" ) ) { if (thread != null) { thread.stop(); thread = null; } requestFocus(); return true; } else if ( o.equals( "<<" ) ) { translater( false ); requestFocus(); return true; } else if ( o.equals( ">>" ) ) { translater( true ); requestFocus(); return true; } } else if ( e.target instanceof Choice ) ok = dessin.action( e, o ); if (ok) { requestFocus(); relancer(); } return ok; } public void run() { long ttt = System.currentTimeMillis(); this.infos(); dessin.infos(); int pixels[] = new int[w*h]; double K = 1.0 / (zoom * (double) Math.min( w/2, h/2 )); int pasMax = 4; for (int pas = pasMax; pas >= 1; pas /=2) { for (int lig = 0; lig < h; lig +=pas) { if ( lig%10 == 0 ) s_calcul.setText( pas + " / " + (lig*100)/h +"%" ); double y = (lig - h/2) * K - zy; for (int col = 0; col < w; col +=pas) { if ( (pas == pasMax) || (lig % (2*pas) != 0) || (col % (2*pas) != 0) ) { double x = (col - w/2) * K - zx; pixels[lig*w + col] = dessin.couleur(x,y); // APPEL A DESSIN } } } thread.yield(); image = null; image = createImage(new MemoryImageSource(w, h, pixels, 0, w)); getGraphics().drawImage( image, 0, 0, this ); } repaint(); // redondant ? pixels = null; ttt = System.currentTimeMillis() - ttt; s_calcul.setText( ttt + " ms" ); } public void translater( boolean sens ) { if (image == null) return; int pix[] = new int[w*h]; PixelGrabber pg = new PixelGrabber( image, 0, 0, w, h, pix, 0, w ); try { pg.grabPixels(); } catch (InterruptedException e) {}; int argb, r, g, b; for (int i = 0; i < w*h; i++) { argb = pix[i]; r = (argb & 0xff0000) >>16; g = (argb & 0xff00) >>8; b = (argb & 0xff); if (sens) { r = (r+16)%255; g = (g+16)%255; b = (b+16)%255; } else { r = (r-16)%255; g = (g-16)%255; b = (b-16)%255; } pix[i] = 0xff000000 | (r<<16) | (g<<8) | b; } image = null; image = createImage(new MemoryImageSource(w, h, pix, 0, w)); pix = null; getGraphics().drawImage( image, 0, 0, this ); } } abstract interface DESSIN { public void init(); public Panel controles(); public void infos(); public boolean keyDown( Event e, int key ); public boolean mouseUp( Event e, double x, double y ); public boolean action( Event e, Object obj ); public int couleur( double x, double y ); }