View Javadoc

1   /*
2    *  MicroEmulator
3    *  Copyright (C) 2002 Bartek Teodorczyk <barteo@barteo.net>
4    *
5    *  This library is free software; you can redistribute it and/or
6    *  modify it under the terms of the GNU Lesser General Public
7    *  License as published by the Free Software Foundation; either
8    *  version 2.1 of the License, or (at your option) any later version.
9    *
10   *  This library is distributed in the hope that it will be useful,
11   *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12   *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13   *  Lesser General Public License for more details.
14   *
15   *  You should have received a copy of the GNU Lesser General Public
16   *  License along with this library; if not, write to the Free Software
17   *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
18   */
19  
20  package org.microemu.device.swt;
21  
22  import java.io.ByteArrayInputStream;
23  import java.io.IOException;
24  import java.io.InputStream;
25  import java.net.URL;
26  import java.util.Enumeration;
27  import java.util.Hashtable;
28  import java.util.Vector;
29  
30  import javax.microedition.lcdui.Canvas;
31  import javax.microedition.lcdui.Displayable;
32  import javax.microedition.lcdui.Image;
33  import javax.microedition.lcdui.game.Sprite;
34  
35  import org.eclipse.swt.graphics.Font;
36  import org.eclipse.swt.graphics.ImageData;
37  import org.eclipse.swt.graphics.RGB;
38  import org.microemu.DisplayAccess;
39  import org.microemu.EmulatorContext;
40  import org.microemu.MIDletAccess;
41  import org.microemu.MIDletBridge;
42  import org.microemu.app.ui.swt.ImageFilter;
43  import org.microemu.app.ui.swt.SwtDeviceComponent;
44  import org.microemu.app.ui.swt.SwtGraphics;
45  import org.microemu.app.util.IOUtils;
46  import org.microemu.device.Device;
47  import org.microemu.device.DeviceFactory;
48  import org.microemu.device.InputMethod;
49  import org.microemu.device.MutableImage;
50  import org.microemu.device.impl.Button;
51  import org.microemu.device.impl.Color;
52  import org.microemu.device.impl.DeviceDisplayImpl;
53  import org.microemu.device.impl.PositionedImage;
54  import org.microemu.device.impl.Rectangle;
55  import org.microemu.device.impl.Shape;
56  import org.microemu.device.impl.SoftButton;
57  
58  
59  public class SwtDeviceDisplay implements DeviceDisplayImpl 
60  {
61      EmulatorContext context;
62  
63  	Rectangle displayRectangle;
64  	Rectangle displayPaintable;
65  
66  	boolean isColor;
67  	int numColors;
68      int numAlphaLevels;
69      
70  	Color backgroundColor;
71  	Color foregroundColor;
72  
73  	PositionedImage mode123Image;
74  	PositionedImage modeAbcUpperImage;
75  	PositionedImage modeAbcLowerImage;
76  
77  	public SwtDeviceDisplay(EmulatorContext context) 
78  	{
79  		this.context = context;
80  	}
81  
82  
83  	public MutableImage getDisplayImage()
84  	{
85  		return context.getDisplayComponent().getDisplayImage();
86  	}
87  
88  
89  	public int getHeight() 
90  	{
91  		return displayPaintable.height;
92  	}
93  
94  
95  	public int getWidth() 
96  	{
97  		return displayPaintable.width;
98  	}
99  
100 
101 	public int getFullHeight() 
102 	{
103 		return displayRectangle.height;
104 	}
105 
106 
107 	public int getFullWidth() 
108 	{
109 		return displayRectangle.width;
110 	}
111 
112 
113 	public boolean isColor() 
114 	{
115 		return isColor;
116 	}
117 	
118 	
119     public boolean isFullScreenMode() 
120     { 
121     	MIDletAccess ma = MIDletBridge.getMIDletAccess();
122     	if (ma == null) {
123     		return false;
124     	} else {
125     		DisplayAccess da = ma.getDisplayAccess();
126     		if (da == null) {
127     			return false;
128     		} else {
129     			return da.isFullScreenMode();
130     		}
131     	}
132     }
133 
134 
135     public int numAlphaLevels() 
136     {
137         return numAlphaLevels;
138     }
139 
140     
141     public int numColors() 
142 	{
143 		return numColors;
144 	}
145 
146 
147 	public void paintControls(SwtGraphics g) 
148 	{
149 		Device device = DeviceFactory.getDevice();
150 		
151 		g.setBackground(g.getColor(new RGB(
152 				backgroundColor.getRed(), 
153 				backgroundColor.getGreen(), 
154 				backgroundColor.getBlue())));
155 		g.fillRectangle(0, 0, displayRectangle.width, displayPaintable.y);
156 		g.fillRectangle(0, displayPaintable.y, 
157 				displayPaintable.x, displayPaintable.height);
158 		g.fillRectangle(displayPaintable.x + displayPaintable.width, displayPaintable.y,
159 				displayRectangle.width - displayPaintable.x - displayPaintable.width, displayPaintable.height);
160 		g.fillRectangle(0, displayPaintable.y + displayPaintable.height,
161 				displayRectangle.width, displayRectangle.height - displayPaintable.y - displayPaintable.height);
162 
163 		g.setForeground(g.getColor(new RGB(
164 				foregroundColor.getRed(), 
165 				foregroundColor.getGreen(), 
166 				foregroundColor.getBlue())));
167 		for (Enumeration s = device.getSoftButtons().elements(); s.hasMoreElements();) {
168 			((SwtSoftButton) s.nextElement()).paint(g);
169 		}
170 
171 		int inputMode = device.getInputMethod().getInputMode();
172 		if (inputMode == InputMethod.INPUT_123) {
173 			g.drawImage(((SwtImmutableImage) mode123Image.getImage()).getImage(), 
174 			        mode123Image.getRectangle().x, mode123Image.getRectangle().y);
175 		} else if (inputMode == InputMethod.INPUT_ABC_UPPER) {
176 			g.drawImage(((SwtImmutableImage) modeAbcUpperImage.getImage()).getImage(), 
177 			        modeAbcUpperImage.getRectangle().x, modeAbcUpperImage.getRectangle().y);
178 		} else if (inputMode == InputMethod.INPUT_ABC_LOWER) {
179 			g.drawImage(((SwtImmutableImage) modeAbcLowerImage.getImage()).getImage(), 
180 			        modeAbcLowerImage.getRectangle().x, modeAbcLowerImage.getRectangle().y);
181 		}
182 	}
183 
184 	
185 	public void paintDisplayable(SwtGraphics g, int x, int y, int width, int height) 
186 	{
187 		MIDletAccess ma = MIDletBridge.getMIDletAccess();
188 		if (ma == null) {
189 			return;
190 		}
191 		DisplayAccess da = ma.getDisplayAccess();
192 		if (da == null) {
193 			return;
194 		}
195 		Displayable current = da.getCurrent();
196 		if (current == null) {
197 			return;
198 		}
199 
200 		g.setForeground(g.getColor(new RGB(
201 				foregroundColor.getRed(), 
202 				foregroundColor.getGreen(), 
203 				foregroundColor.getBlue())));
204 
205 		org.eclipse.swt.graphics.Rectangle oldclip = g.getClipping();
206 		if (!(current instanceof Canvas) 
207 				|| ((Canvas) current).getWidth() != displayRectangle.width
208 				|| ((Canvas) current).getHeight() != displayRectangle.height) {
209 			g.translate(displayPaintable.x, displayPaintable.y);
210 		}
211 		g.setClipping(new org.eclipse.swt.graphics.Rectangle(x, y, width, height));
212 		Font oldf = g.getFont();
213 		ma.getDisplayAccess().paint(new SwtDisplayGraphics(g, getDisplayImage()));
214 		g.setFont(oldf);		
215 		if (!(current instanceof Canvas) 
216 				|| ((Canvas) current).getWidth() != displayRectangle.width
217 				|| ((Canvas) current).getHeight() != displayRectangle.height) {
218 			g.translate(-displayPaintable.x, -displayPaintable.y);
219 		}
220 		g.setClipping(oldclip);
221 	}
222 
223 	
224 	public void repaint(int x, int y, int width, int height) 
225 	{
226 		context.getDisplayComponent().repaintRequest(x, y, width, height);
227 	}
228 
229 
230 	public void setScrollDown(boolean state) 
231 	{
232 		Enumeration en = DeviceFactory.getDevice().getSoftButtons().elements();
233 		while (en.hasMoreElements()) {
234 			SoftButton button = (SoftButton) en.nextElement();
235 			if (button.getType() == SoftButton.TYPE_ICON
236 					&& button.getName().equals("down")) {
237 				button.setVisible(state);
238 			}
239 		}
240 	}
241 
242 
243 	public void setScrollUp(boolean state) 
244 	{
245 		Enumeration en = DeviceFactory.getDevice().getSoftButtons().elements();
246 		while (en.hasMoreElements()) {
247 			SoftButton button = (SoftButton) en.nextElement();
248 			if (button.getType() == SoftButton.TYPE_ICON
249 					&& button.getName().equals("up")) {
250 				button.setVisible(state);
251 			}
252 		}
253 	}
254 
255 
256 	public Rectangle getDisplayRectangle() 
257 	{
258 		return displayRectangle;
259 	}
260 
261 
262 	public Rectangle getDisplayPaintable()
263 	{
264 		return displayPaintable;
265 	}
266 
267 	
268 	public Color getBackgroundColor() 
269 	{
270 		return backgroundColor;
271 	}
272 
273 
274 	public Color getForegroundColor() 
275 	{
276 		return foregroundColor;
277 	}
278 	
279 	
280 	public Image createImage(int width, int height) 
281 	{
282 		if (width <= 0 || height <= 0) {
283 			throw new IllegalArgumentException();
284 		}
285 
286 		return new SwtMutableImage(width, height);
287 	}
288 
289 	
290 	public Image createImage(String name) 
291 			throws IOException 
292 	{
293 		return getImage(name);
294 	}
295 
296 	
297 	public Image createImage(javax.microedition.lcdui.Image source) 
298 	{
299 		if (source.isMutable()) {
300 			return new SwtImmutableImage((SwtMutableImage) source);
301 		} else {
302 			return source;
303 		}
304 	}
305 
306 	
307 	public Image createImage(byte[] imageData, int imageOffset, int imageLength) 
308 	{
309 		ByteArrayInputStream is = new ByteArrayInputStream(imageData, imageOffset, imageLength);
310 		try {
311 			return getImage(is);
312 		} catch (IOException ex) {
313 			throw new IllegalArgumentException(ex.toString());
314 		}
315 	}
316 
317     public Image createImage(InputStream is) throws IOException
318     {
319         if (is == null) {
320             throw new IOException();
321         }
322         
323         return getImage(is);
324     }
325 
326 
327     public void setNumAlphaLevels(int i)
328     {
329         numAlphaLevels = i;
330     }
331 
332     /*
333 	 * (non-Javadoc)
334 	 * 
335 	 * @see com.barteo.emulator.device.impl.DeviceDisplayImpl#setNumColors(int)
336 	 */
337     public void setNumColors(int i)
338     {
339         numColors = i;
340     }
341 
342 
343     /* (non-Javadoc)
344      * @see com.barteo.emulator.device.impl.DeviceDisplayImpl#setIsColor(boolean)
345      */
346     public void setIsColor(boolean b)
347     {
348         isColor = b;
349     }
350 
351 
352     /* (non-Javadoc)
353      * @see com.barteo.emulator.device.impl.DeviceDisplayImpl#setBackgroundColor(java.awt.Color)
354      */
355     public void setBackgroundColor(Color color)
356     {
357         backgroundColor = color;
358     }
359 
360 
361     /* (non-Javadoc)
362      * @see com.barteo.emulator.device.impl.DeviceDisplayImpl#setForegroundColor(java.awt.Color)
363      */
364     public void setForegroundColor(Color color)
365     {
366         foregroundColor = color;
367     }
368 
369 
370     /* (non-Javadoc)
371      * @see com.barteo.emulator.device.impl.DeviceDisplayImpl#setDisplayRectangle(java.awt.Rectangle)
372      */
373     public void setDisplayRectangle(Rectangle rectangle)
374     {
375         displayRectangle = rectangle;
376     }
377 
378 
379     /* (non-Javadoc)
380      * @see com.barteo.emulator.device.impl.DeviceDisplayImpl#setDisplayPaintable(java.awt.Rectangle)
381      */
382     public void setDisplayPaintable(Rectangle rectangle)
383     {
384         displayPaintable = rectangle;
385     }
386 
387     /* (non-Javadoc)
388      * @see com.barteo.emulator.device.impl.DeviceDisplayImpl#setMode123Image(com.barteo.emulator.device.impl.PositionedImage)
389      */
390     public void setMode123Image(PositionedImage object)
391     {
392         mode123Image = object;
393     }
394 
395 
396     /* (non-Javadoc)
397      * @see com.barteo.emulator.device.impl.DeviceDisplayImpl#setModeAbcLowerImage(com.barteo.emulator.device.impl.PositionedImage)
398      */
399     public void setModeAbcLowerImage(PositionedImage object)
400     {
401         modeAbcLowerImage = object;
402     }
403 
404 
405     /* (non-Javadoc)
406      * @see com.barteo.emulator.device.impl.DeviceDisplayImpl#setModeAbcUpperImage(com.barteo.emulator.device.impl.PositionedImage)
407      */
408     public void setModeAbcUpperImage(PositionedImage object)
409     {
410         modeAbcUpperImage = object;
411     }
412 
413     
414     public Image createSystemImage(URL url) 
415     		throws IOException 
416 	{
417 		return new SwtImmutableImage(SwtDeviceComponent.createImage(url.openStream()));
418 	}
419 
420     
421 	private Image getImage(String str) 
422 			throws IOException 
423 	{
424 		// TODO not always true, there could be some loading images before
425 		// invoke startApp, right now getCurrentMIDlet returns prevoius MIDlet
426 		Object midlet = MIDletBridge.getCurrentMIDlet();
427 		if (midlet == null) {
428 			midlet = getClass();
429 		}
430 		InputStream is = midlet.getClass().getResourceAsStream(str);
431 
432 		if (is == null) {
433 			throw new IOException(str + " could not be found.");
434 		}
435 		try {
436 			return getImage(is);
437 		} finally {
438 			IOUtils.closeQuietly(is);
439 		}
440 	}
441 
442 	
443 	private Image getImage(InputStream is) 
444 			throws IOException 
445 	{
446 		ImageFilter filter = null;
447 		if (isColor()) {
448 			filter = new RGBImageFilter();
449 		} else {
450 			if (numColors() == 2) {
451 				filter = new BWImageFilter();
452 			} else {
453 				filter = new GrayImageFilter();
454 			}
455 		}
456 
457 		return new SwtImmutableImage(SwtDeviceComponent.createImage(is, filter));
458 	}
459 
460 
461     public Button createButton(String name, Shape shape, int keyCode, String keyName, Hashtable inputToChars)
462     {
463         return new SwtButton(name, shape, keyCode, keyName, inputToChars);
464     }
465 
466 
467     public SoftButton createSoftButton(String name, Shape shape, int keyCode, String keyName, Rectangle paintable, String alignmentName, Vector commands, javax.microedition.lcdui.Font font)
468     {
469         return new SwtSoftButton(name, shape, keyCode, keyName, paintable, alignmentName, commands, font);
470     }
471 
472 
473     public SoftButton createSoftButton(String name, Rectangle paintable, Image normalImage, Image pressedImage)
474     {
475         return new SwtSoftButton(name, paintable, normalImage, pressedImage);
476     }
477 
478 
479     public Image createRGBImage(int[] rgb, int width, int height, boolean processAlpha)
480     {
481         if (rgb == null)
482             throw new NullPointerException();
483         if (width <= 0 || height <= 0)
484             throw new IllegalArgumentException();
485         
486         org.eclipse.swt.graphics.Image img = SwtDeviceComponent.createImage(width, height);
487         ImageData imageData = img.getImageData();
488         
489         if (!processAlpha) {
490             // we should eliminate the transparency info
491             // but can't touch the original array
492             // so we just create another
493             int l = rgb.length;
494             
495             int [] rgbAux = new int[l];
496             for (int i = 0; i < l; i++)
497                 rgbAux[i] = rgb[i] | 0xff000000;
498             rgb = rgbAux;
499         } 
500         
501         
502 
503         for (int y = 0; y < height; y++) {
504         		imageData.setPixels(0, y, width, rgb, y * width);
505         }
506                 
507         // TODO now apply the corresponding filter
508 		ImageFilter filter = null;
509         if (isColor()) {
510         		filter = new RGBImageFilter();
511         } else {
512         		if (numColors() == 2) {
513         			filter = new BWImageFilter();
514         		} else {
515         			filter = new GrayImageFilter();
516         		}
517         }
518 	
519         return new SwtImmutableImage(SwtDeviceComponent.createImage(imageData));
520     }
521 
522 
523     public Image createImage(Image image, int x, int y, int width, int height, int transform)
524     {
525         if (image == null) {
526             throw new NullPointerException();
527         }
528         if (x + width > image.getWidth() || y + height > image.getHeight()
529         			|| width <= 0 || height <= 0 || x < 0 || y < 0) {
530             throw new IllegalArgumentException("Area out of Image");
531         }
532 
533 
534         int [] rgbData = new int[height * width];
535         int [] rgbTransformedData = new int[height * width];
536         if (image instanceof SwtImmutableImage) {
537         		((SwtImmutableImage) image).getRGB(rgbData, 0, width, x, y, width, height);
538         } else {
539         		((SwtMutableImage) image).getRGB(rgbData, 0, width, x, y, width, height);
540         }
541 
542 
543         int colIncr, rowIncr, offset;
544 
545         switch(transform) {
546             case Sprite.TRANS_NONE: {
547                 offset = 0;
548                 colIncr = 1;
549                 rowIncr = 0;
550                 break;
551             }
552             case Sprite.TRANS_ROT90: {
553                 offset = (height - 1) * width;
554                 colIncr = -width;
555                 rowIncr = (height * width) + 1;
556                 int temp = width;
557                 width = height;
558                 height = temp;
559                 break;
560             }
561             case Sprite.TRANS_ROT180: {
562                 offset = (height * width) - 1;
563                 colIncr = -1;
564                 rowIncr =  0;
565                 break;
566             }
567             case Sprite.TRANS_ROT270: {
568                 offset = width - 1;
569                 colIncr = width;
570                 rowIncr =  -(height * width) - 1;
571                 int temp = width;
572                 width = height;
573                 height = temp;
574                 break;
575             }
576             case Sprite.TRANS_MIRROR: {
577                 offset = width - 1;
578                 colIncr = -1;
579                 rowIncr =  width << 1;
580                 break;
581             }
582             case Sprite.TRANS_MIRROR_ROT90: {
583                 offset = (height * width) - 1;
584                 colIncr = -width;
585                 rowIncr = (height * width) - 1;
586                 int temp = width;
587                 width = height;
588                 height = temp;
589                 break;
590             }
591             case Sprite.TRANS_MIRROR_ROT180: {
592                 offset = (height - 1) * width;
593                 colIncr = 1;
594                 rowIncr =  -(width << 1);
595                 break;
596             }
597             case Sprite.TRANS_MIRROR_ROT270: {
598                 offset = 0;
599                 colIncr = width;
600                 rowIncr = -(height * width) + 1;
601                 int temp = width;
602                 width = height;
603                 height = temp;
604                 break;
605             }
606             default:
607                 throw new IllegalArgumentException("Bad transform");
608         }
609 
610         // now the loops!
611         for (int row = 0, i = 0; row < height; row++, offset += rowIncr) {
612             for (int col = 0; col < width; col++, offset += colIncr, i++) {
613                 rgbTransformedData[i] = rgbData[offset];
614             }
615         }
616         // to aid gc
617         rgbData = null;
618         image = null;
619         
620         return createRGBImage(rgbTransformedData, width, height, true);
621     }
622 
623 }