Check-in [755b182ede]

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Image.getGraphics() correctly enables the alpha channel if one is used; Rework GameCanvas to use a raw pixel buffer.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1:755b182ede4da93b0132f53642ba59a5cd38a41e
User & Date: stephanie.gawroriski 2019-06-30 23:29:56
Context
2019-07-01
00:11
Correct bytes being truncated on flush of a PrintStream. check-in: bef523c8ff user: stephanie.gawroriski tags: trunk
2019-06-30
23:29
Image.getGraphics() correctly enables the alpha channel if one is used; Rework GameCanvas to use a raw pixel buffer. check-in: 755b182ede user: stephanie.gawroriski tags: trunk
21:38
Do not read the table of contents offset and entry count in BootLibrary() because it triggers builds in plain SummerCoat. check-in: 84e6aa7adb user: stephanie.gawroriski tags: trunk
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to changelog.mkd.

107
108
109
110
111
112
113

114
115
116
117
118
119
120
       implemented.
     * Fixed crash in text drawing when an empty string is drawn.
     * Fully drawn default fonts.
     * Made all the graphics operations not throw a `TODO`, instead they will
       just draw a placeholder graphic.
     * Moved the graphics drawing operations to another class.
     * Removed the 24 strike font, it was too large.

     * Update the `Display` when a command is added or removed.
     * Use a default title for a `Displayable` if one has not been set, this
       will be in the order of the suite name, the main class, and if those
       are not valid then "SquirrelJME" will be used instead.
     * When a `Displayable` is made current and it is already the current
       displayed item, always set the title since it may have been placed in
       the background by another application calling `setCurrent()`.







>







107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
       implemented.
     * Fixed crash in text drawing when an empty string is drawn.
     * Fully drawn default fonts.
     * Made all the graphics operations not throw a `TODO`, instead they will
       just draw a placeholder graphic.
     * Moved the graphics drawing operations to another class.
     * Removed the 24 strike font, it was too large.
     * Support double buffered `GameCanvas`.
     * Update the `Display` when a command is added or removed.
     * Use a default title for a `Displayable` if one has not been set, this
       will be in the order of the suite name, the main class, and if those
       are not valid then "SquirrelJME" will be used instead.
     * When a `Displayable` is made current and it is already the current
       displayed item, always set the title since it may have been placed in
       the background by another application calling `setCurrent()`.

Changes to runt/apis/midp-lcdui/javax/microedition/lcdui/Image.java.

101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
	{
		// {@squirreljme.error EB28 Cannot get mutable graphic operations for
		// an immutable image.}
		if (!isMutable())
			throw new IllegalStateException("EB28");
		
		// Create
		return new AdvancedGraphics(this._data, false, null, this._width,
			this._height, this._width, 0, 0, 0);
	}
	
	/**
	 * Returns the image height.
	 *
	 * @return The height of the image.







|







101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
	{
		// {@squirreljme.error EB28 Cannot get mutable graphic operations for
		// an immutable image.}
		if (!isMutable())
			throw new IllegalStateException("EB28");
		
		// Create
		return new AdvancedGraphics(this._data, this._alpha, null, this._width,
			this._height, this._width, 0, 0, 0);
	}
	
	/**
	 * Returns the image height.
	 *
	 * @return The height of the image.

Changes to runt/apis/midp-lcdui/javax/microedition/lcdui/game/GameCanvas.java.

6
7
8
9
10
11
12

13
14
15
16
17
18
19
..
51
52
53
54
55
56
57
58
59



60
61
62
63
64
65
66
..
94
95
96
97
98
99
100
101





102
103
104
105
106
107
108
...
113
114
115
116
117
118
119




120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140

141
142
143
144
145
146
147
148


149
150

151



152
153
154



















155
156
157
158
159
160
161
...
162
163
164
165
166
167
168
169
170



















171


172
173
174
175
176
177



178





179
180



181




































// ---------------------------------------------------------------------------
// SquirrelJME is under the GNU General Public License v3+, or later.
// See license.mkd for licensing and copyright information.
// ---------------------------------------------------------------------------

package javax.microedition.lcdui.game;


import cc.squirreljme.runtime.lcdui.gfx.ForwardingGraphics;
import javax.microedition.lcdui.Canvas;
import javax.microedition.lcdui.Graphics;
import javax.microedition.lcdui.Image;

public abstract class GameCanvas
	extends Canvas
................................................................................
	
	/** Are game keys being suppressed?. */
	private volatile boolean _suppressgamekeys;
	
	/** Is the buffer preserved after a flush? */
	private volatile boolean _preservebuffer;
	
	/** The image to draw onto as a double buffer. */
	private volatile Image _image;



	
	/**
	 * Initializes the game canvas.
	 *
	 * The buffer is preserved by default.
	 *
	 * @param __supke If {@code true} then game key events are suppressed.
................................................................................
	/**
	 * Flushes the full off-screen buffer to the display.
	 *
	 * @since 2017/02/08
	 */
	public void flushGraphics()
	{
		flushGraphics(0, 0, getWidth(), getHeight());





	}
	
	/**
	 * Flushes the specified off-screen buffer area to the display.
	 *
	 * @param __x The X position.
	 * @param __y The Y position.
................................................................................
	 */
	public void flushGraphics(int __x, int __y, int __w, int __h)
		throws IllegalStateException
	{
		// Nothing to flush
		if (__w <= 0 || __h <= 0)
			return;




		
		// {@squirreljme.error EB2w Cannot flush the graphics if the buffer
		// is not preserved.}
		if (!this._preservebuffer)
			throw new IllegalStateException("EB2w");
		
		// Just tell the canvas to repaint because it is final and our paint
		// method just draws the backing buffer to the screen
		super.repaint(__x, __y, __w, __h);
	}
	
	/**
	 * This returns the off-screen buffer that is used by the game canvas to
	 * draw.
	 *
	 * @return The graphics object for the off-screen buffer.
	 * @since 2016/10/10
	 */
	protected Graphics getGraphics()
	{
		ForwardingGraphics forwardgfx = this._forwardgfx;

		
		// It is possible for the canvas to change size, as such the image in
		// the background must be recreated for the correct size
		int dw = Math.max(1, getWidth()),
			dh = Math.max(1, getHeight());
		Image image = this._image;
		if (image == null || dw != image.getWidth() || dh != image.getHeight())
		{


			this._image = (image = Image.createImage(dw, dh));
			forwardgfx.forwardGraphics(image.getGraphics());

		}



		
		// Always return the forwarded graphics
		return forwardgfx.forwardPlainGraphics();



















	}
	
	public int getKeyStates()
	{
		throw new todo.TODO();
	}
	
................................................................................
	/**
	 * {@inheritDoc}
	 * @since 2016/10/10
	 */
	@Override
	public void paint(Graphics __g)
	{
		// The default implementation of this method just takes the offscreen
		// buffer and renders it to the canvas



















		Image image = this._image;


		if (image == null)
			return;
		
		// Paint the image to the display
		// Do not worry about using transformations to display it
		__g.drawImage(image, 0, 0, 0);



	}





}
















































>







 







|
|
>
>
>







 







|
>
>
>
>
>







 







>
>
>
>






|
|
<











|
>

<
|
|
|
<
<
|
>
>
|
|
>
|
>
>
>
|
<
<
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







 







|
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>
>
|


<
<
<
>
>
>
|
>
>
>
>
>
|
|
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
..
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
..
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
...
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140

141
142
143
144
145
146
147
148
149
150
151
152
153
154

155
156
157


158
159
160
161
162
163
164
165
166
167
168


169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
...
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228



229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
// ---------------------------------------------------------------------------
// SquirrelJME is under the GNU General Public License v3+, or later.
// See license.mkd for licensing and copyright information.
// ---------------------------------------------------------------------------

package javax.microedition.lcdui.game;

import cc.squirreljme.runtime.lcdui.gfx.AdvancedGraphics;
import cc.squirreljme.runtime.lcdui.gfx.ForwardingGraphics;
import javax.microedition.lcdui.Canvas;
import javax.microedition.lcdui.Graphics;
import javax.microedition.lcdui.Image;

public abstract class GameCanvas
	extends Canvas
................................................................................
	
	/** Are game keys being suppressed?. */
	private volatile boolean _suppressgamekeys;
	
	/** Is the buffer preserved after a flush? */
	private volatile boolean _preservebuffer;
	
	/** The A buffer. */
	private volatile __Buffer__ _bufa;
	
	/** The B buffer. */
	private volatile __Buffer__ _bufb;
	
	/**
	 * Initializes the game canvas.
	 *
	 * The buffer is preserved by default.
	 *
	 * @param __supke If {@code true} then game key events are suppressed.
................................................................................
	/**
	 * Flushes the full off-screen buffer to the display.
	 *
	 * @since 2017/02/08
	 */
	public void flushGraphics()
	{
		// Do nothing if this is not on a display
		if (this.getCurrentDisplay() == null)
			return;
		
		// Flip!
		this.__flip();
	}
	
	/**
	 * Flushes the specified off-screen buffer area to the display.
	 *
	 * @param __x The X position.
	 * @param __y The Y position.
................................................................................
	 */
	public void flushGraphics(int __x, int __y, int __w, int __h)
		throws IllegalStateException
	{
		// Nothing to flush
		if (__w <= 0 || __h <= 0)
			return;
		
		// Do nothing if this is not on a display
		if (this.getCurrentDisplay() == null)
			return;
		
		// {@squirreljme.error EB2w Cannot flush the graphics if the buffer
		// is not preserved.}
		if (!this._preservebuffer)
			throw new IllegalStateException("EB2w");
		
		// Flip!
		this.__flip();

	}
	
	/**
	 * This returns the off-screen buffer that is used by the game canvas to
	 * draw.
	 *
	 * @return The graphics object for the off-screen buffer.
	 * @since 2016/10/10
	 */
	protected Graphics getGraphics()
	{
		// Draw into the B buffer
		__Buffer__ buf = this._bufb;
		

		// Get device size
		int dw = this.getWidth(),
			dh = this.getHeight();


		
		// Force device size into bounds
		if (dw < 1)
			dw = 1;
		if (dh < 1)
			dh = 1;
		
		// Get buffer size
		int bw, bh;
		if (buf != null)
		{


			bw = buf._width;
			bh = buf._height;
		}
		else
			bw = bh = 0;
		
		// Recreate the buffer?
		if (buf == null || bw != dw || bh != dh)
		{
			// Create buffer
			buf = new __Buffer__(dw, dh);
			
			// Store buffer state
			this._bufb = buf;
		}
		
		// Create graphics to wrap it, alpha is not used!
		return new AdvancedGraphics(buf._pixels, false, null,
			dw, dh, dw, 0, 0, 0);
	}
	
	public int getKeyStates()
	{
		throw new todo.TODO();
	}
	
................................................................................
	/**
	 * {@inheritDoc}
	 * @since 2016/10/10
	 */
	@Override
	public void paint(Graphics __g)
	{
		// Whatever is in the A buffer is drawn
		__Buffer__ buf = this._bufa;
		if (buf == null)
			return;
			
		// The fastest way to draw onto the screen is to do a direct draw
		// from the RGB pixel data
		int pw = buf._width;
		__g.drawRGB(buf._pixels, 0, pw, 0, 0, pw, buf._height, false);
	}
	
	/**
	 * Performs the graphics flip.
	 *
	 * @return The flipped graphics.
	 * @since 2019/06/30
	 */
	private final void __flip()
	{
		// Get both buffers
		__Buffer__ bufa = this._bufa,
			bufb = this._bufb;
		
		// If never drawn onto, ignore
		if (bufb == null)
			return;
		



		// Get buffer size
		int bw = bufb._width,
			bh = bufb._height;
		
		// Create buffer to copy to
		if (bufa == null || bufa._width != bw && bufa._height != bh)
		{
			bufa = new __Buffer__(bw, bh);
			this._bufa = bufa;
		}
		
		// Copy pixel data (use System since it may be a memory copy)
		System.arraycopy(bufb._pixels, 0,
			bufa._pixels, 0, bw * bh);
		
		// Signal and wait for refresh
		super.repaint(0, 0, bw, bh);
		super.serviceRepaints();
	}
	
	/**
	 * This represents a single buffer, since this class is double buffered.
	 *
	 * @since 2019/06/30
	 */
	private static final class __Buffer__
	{
		/** The buffer pixels. */
		final int[] _pixels;
		
		/** The width. */
		final int _width;
		
		/** The height. */
		final int _height;
		
		/**
		 * Initializes the buffer.
		 *
		 * @param __w The width.
		 * @param __h The height.
		 * @since 2019/06/30
		 */
		__Buffer__(int __w, int __h)
		{
			this._width = (__w < 1 ? (__w = 1) : __w);
			this._height = (__h < 1 ? (__h = 1) : __h);
			this._pixels = new int[__w * __h];
		}
	}
}