--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/javauis/lcdui_akn/javalcdui/javasrc/javax/microedition/lcdui/Buffer.java Wed Sep 01 12:33:18 2010 +0100
@@ -0,0 +1,584 @@
+/*
+* Copyright (c) 1999 - 2004 Nokia Corporation and/or its subsidiary(-ies).
+* All rights reserved.
+* This component and the accompanying materials are made available
+* under the terms of "Eclipse Public License v1.0"
+* which accompanies this distribution, and is available
+* at the URL "http://www.eclipse.org/legal/epl-v10.html".
+*
+* Initial Contributors:
+* Nokia Corporation - initial contribution.
+*
+* Contributors:
+*
+* Description:
+*
+*/
+
+package javax.microedition.lcdui;
+
+import com.nokia.mj.impl.rt.legacy.NativeError;
+
+/**
+ * Buffer for LCDUI/LCDGR commands.
+ *
+ * Commands placed in buffer consist of a header followed by
+ * optional data. The header is always a 32bit integer in
+ * one of the following two forms.
+ *
+ * An activation header has the ACTIVATE marker (the top bit) set
+ * and contains a component handle in the lower 30 bits.
+ *
+ * A command header has the top four bits clear, and the remaining
+ * 28 bits are divided as follows:
+ *
+ * bits 0-15 contain the command size including the header as the
+ * number of integers (or words) in the buffer occupied by the
+ * commadn.
+ *
+ * bits 16-27 contain an unsigned integer opcode.
+ *
+ */
+final class Buffer
+{
+ private static final int BUFFER_SIZE = 1024; // 4KB buffer
+ private static final int CHAR_BUFFER_SIZE = 128;
+
+ public static final int NOP = 0;
+ public static final int ACTIVATE = (1<<31);
+ public static final int OP_MASK = 0x0FFF;
+
+ /**
+ * JavaUnhand<> mangled pointer to CMIDBuffer
+ */
+ private int iHandle;
+
+ /**
+ * Java side buffer and write pointer.
+ */
+ private int[] iBuffer;
+ private int iCount;
+
+ /**
+ * Tracks current buffer processor to minimize ACTIVATE commands.
+ */
+ private int iCurrent;
+ // index of activation size
+ private int iStart; // index of activation size
+ private char[] iCharBuffer;
+
+
+ /**
+ *
+ */
+ Buffer(Toolkit aToolkit)
+ {
+ iBuffer = new int[BUFFER_SIZE];
+ iCharBuffer = new char[CHAR_BUFFER_SIZE];
+ iCount = 0;
+ iCurrent = -1;
+ iStart = 0;
+ iHandle = NativeError.check(_open(aToolkit.getEventServerHandle()));
+ }
+
+ /**
+ * Sync any pending commands and then shutdown buffer processing
+ */
+ synchronized void close()
+ {
+ if (iHandle <= 0)
+ {
+ return;
+ }
+ sync();
+ _close(iHandle);
+ iHandle = 0;
+ }
+
+ /**
+ *
+ */
+ int getHandle()
+ {
+ if (iHandle <= 0)
+ {
+ throw new RuntimeException("Buffer closed");
+ }
+ return iHandle;
+ }
+
+
+ /**
+ * writes a command with no parameters into the buffer.
+ */
+ final void write(int aHandle, int aCommand)
+ {
+ if (iHandle <= 0)
+ {
+ throw new RuntimeException("Buffer closed");
+ }
+
+ if (aHandle != iCurrent)
+ {
+ deactivate(); // remove existing target
+ activate(aHandle); // set new target - this may cause a flush.
+ }
+
+ // size = 1;
+ final int opc = (aCommand << 16) | 1;
+ ensureSpace(1);
+
+ iBuffer[iCount++] = opc;
+ }
+
+ /**
+ *
+ */
+ final void write(int aHandle, int aCommand, int aArg)
+ {
+ if (iHandle <= 0)
+ {
+ throw new RuntimeException("Buffer closed");
+ }
+
+ if (aHandle != iCurrent)
+ {
+ deactivate(); // remove existing target
+ activate(aHandle); // set new target - this may cause a flush.
+ }
+
+ // size = 2;
+ final int opc = (aCommand << 16) | 2;
+ ensureSpace(2);
+
+ iBuffer[iCount++] = opc;
+ iBuffer[iCount++] = aArg;
+ }
+
+ /**
+ *
+ */
+ final void write(int aHandle, int aCommand, int aArg1, int aArg2)
+ {
+ if (iHandle <= 0)
+ {
+ throw new RuntimeException("Buffer closed");
+ }
+
+ if (aHandle != iCurrent)
+ {
+ deactivate(); // remove existing target
+ activate(aHandle); // set new target - this may cause a flush.
+ }
+
+ // size = 3;
+ final int opc = (aCommand << 16) | 3;
+ ensureSpace(3);
+
+ final int[] buffer = iBuffer;
+ int count = iCount;
+ buffer[count++] = opc;
+ buffer[count++] = aArg1;
+ buffer[count++] = aArg2;
+ iCount = count;
+ }
+
+ /**
+ *
+ */
+ final void write(int aHandle, int aCommand, int aArg1, int aArg2, int aArg3)
+ {
+ if (iHandle <= 0)
+ {
+ throw new RuntimeException("Buffer closed");
+ }
+
+ if (aHandle != iCurrent)
+ {
+ deactivate(); // remove existing target
+ activate(aHandle); // set new target - this may cause a flush.
+ }
+
+ // size = 4;
+ final int opc = (aCommand << 16) | 4;
+ ensureSpace(4);
+
+ final int[] buffer = iBuffer;
+ int count = iCount;
+ buffer[count++] = opc;
+ buffer[count++] = aArg1;
+ buffer[count++] = aArg2;
+ buffer[count++] = aArg3;
+ iCount = count;
+ }
+
+ /**
+ *
+ */
+ final void write(int aHandle, int aCommand, int aArg1, int aArg2,
+ int aArg3, int aArg4)
+ {
+ if (iHandle <= 0)
+ {
+ throw new RuntimeException("Buffer closed");
+ }
+
+ if (aHandle != iCurrent)
+ {
+ deactivate(); // remove existing target
+ activate(aHandle); // set new target - this may cause a flush.
+ }
+
+ // size = 5;
+ final int opc = (aCommand << 16) | 5;
+ ensureSpace(5);
+
+ final int[] buffer = iBuffer;
+ int count = iCount;
+ buffer[count++] = opc;
+ buffer[count++] = aArg1;
+ buffer[count++] = aArg2;
+ buffer[count++] = aArg3;
+ buffer[count++] = aArg4;
+ iCount = count;
+ }
+
+ /**
+ *
+ */
+ final void write(int aHandle, int aCommand, int aArg1, int aArg2,
+ int aArg3, int aArg4, int aArg5)
+ {
+ if (iHandle <= 0)
+ {
+ throw new RuntimeException("Buffer closed");
+ }
+
+ if (aHandle != iCurrent)
+ {
+ deactivate(); // remove existing target
+ activate(aHandle); // set new target - this may cause a flush.
+ }
+
+ // size = 6;
+ final int opc = (aCommand << 16) | 6;
+ ensureSpace(6);
+
+ final int[] buffer = iBuffer;
+ int count = iCount;
+ buffer[count++] = opc;
+ buffer[count++] = aArg1;
+ buffer[count++] = aArg2;
+ buffer[count++] = aArg3;
+ buffer[count++] = aArg4;
+ buffer[count++] = aArg5;
+ iCount = count;
+ }
+
+ /**
+ *
+ */
+ final void write(int aHandle, int aCommand, int aArg1, int aArg2,
+ int aArg3, int aArg4, int aArg5, int aArg6)
+ {
+ if (iHandle <= 0)
+ {
+ throw new RuntimeException("Buffer closed");
+ }
+
+ if (aHandle != iCurrent)
+ {
+ deactivate(); // remove existing target
+ activate(aHandle); // set new target - this may cause a flush.
+ }
+
+ // size = 7;
+ final int opc = (aCommand << 16) | 7;
+ ensureSpace(7);
+
+ final int[] buffer = iBuffer;
+ int count = iCount;
+ buffer[count++] = opc;
+ buffer[count++] = aArg1;
+ buffer[count++] = aArg2;
+ buffer[count++] = aArg3;
+ buffer[count++] = aArg4;
+ buffer[count++] = aArg5;
+ buffer[count++] = aArg6;
+ iCount = count;
+ }
+
+ /**
+ *
+ */
+ final void write(int aHandle, int aCommand, int aArg1, int aArg2,
+ int aArg3, int aArg4, int aArg5, int aArg6, int aArg7)
+ {
+ if (iHandle <= 0)
+ {
+ throw new RuntimeException("Buffer closed");
+ }
+
+ if (aHandle != iCurrent)
+ {
+ deactivate(); // remove existing target
+ activate(aHandle); // set new target - this may cause a flush.
+ }
+
+ // size = 8;
+ final int opc = (aCommand << 16) | 8;
+ ensureSpace(8);
+
+ final int[] buffer = iBuffer;
+ int count = iCount;
+ buffer[count++] = opc;
+ buffer[count++] = aArg1;
+ buffer[count++] = aArg2;
+ buffer[count++] = aArg3;
+ buffer[count++] = aArg4;
+ buffer[count++] = aArg5;
+ buffer[count++] = aArg6;
+ buffer[count++] = aArg7;
+ iCount = count;
+ }
+
+ /**
+ *
+ */
+ final void write(int aHandle, int aCommand, int aArg1, int aArg2,
+ int aArg3, int aArg4, int aArg5, int aArg6, int aArg7,
+ int aArg8, int aArg9)
+ {
+ if (iHandle <= 0)
+ {
+ throw new RuntimeException("Buffer closed");
+ }
+
+ if (aHandle != iCurrent)
+ {
+ deactivate(); // remove existing target
+ activate(aHandle); // set new target - this may cause a flush.
+ }
+
+ // size = 10;
+ final int opc = (aCommand << 16) | 10;
+ ensureSpace(10);
+
+ final int[] buffer = iBuffer;
+ int count = iCount;
+ buffer[count++] = opc;
+ buffer[count++] = aArg1;
+ buffer[count++] = aArg2;
+ buffer[count++] = aArg3;
+ buffer[count++] = aArg4;
+ buffer[count++] = aArg5;
+ buffer[count++] = aArg6;
+ buffer[count++] = aArg7;
+ buffer[count++] = aArg8;
+ buffer[count++] = aArg9;
+ iCount = count;
+ }
+
+ /**
+ * Writes a string command into the buffer, intended to support
+ * Graphics.drawString(), this method also passes three additional
+ * integer parameters.
+ *
+ */
+ final void writeStr(int aHandle, int aCmd, String aString, int aOff,
+ int aLen, int aArg1, int aArg2, int aArg3)
+ {
+ //
+ // Implementation note: We cannot avoid two copies as even a native method
+ // would still have to use GetStringChars() which makes a copy. There is
+ // no equivalent to GetIntArrayRegion.
+ //
+ if (aLen > 0)
+ {
+ final char[] array = (aLen <= CHAR_BUFFER_SIZE ? iCharBuffer : new char[aLen]);
+ aString.getChars(aOff, aOff+aLen, array, 0);
+ writeChars(aHandle, aCmd, array, 0, aLen, aArg1, aArg2, aArg3);
+ }
+ }
+
+ /**
+ * Writes a character array command into the buffer, intended to support
+ * Graphics.drawChars(), this method also passes three additional
+ * integer parameters.
+ */
+ final void writeChars(int aHandle, int aCommand, char[] aChars, int aOff,
+ int aLen, int aArg1, int aArg2, int aArg3)
+ {
+ if (aLen < 1)
+ {
+ return;
+ }
+
+ //
+ // cmd, x, y, anchor, len, char[0..len-1]
+ //
+ final int cmdLen = 4 + ((aLen+1)>>1);
+
+ if (cmdLen < BUFFER_SIZE)
+ {
+ if (iHandle <= 0)
+ {
+ throw new RuntimeException("Buffer closed");
+ }
+
+ if (aHandle != iCurrent)
+ {
+ deactivate(); // remove existing target
+ activate(aHandle); // set new target - this may cause a flush.
+ }
+
+ final int size = cmdLen + 1;
+ final int opc = (aCommand << 16) | size;
+ ensureSpace(size);
+
+ iBuffer[iCount++] = opc;
+ iBuffer[iCount++] = aArg1;
+ iBuffer[iCount++] = aArg2;
+ iBuffer[iCount++] = aArg3;
+
+ writeCharsInLine(aChars, aOff, aLen);
+ }
+ else
+ {
+ // Not enough space in the buffer
+ throw new OutOfMemoryError();
+ //
+ // Possible alternatives:
+ //
+ // 1. Allocate an HBufC, write the chars into it, stick it in the buffer.
+ //
+ // writeCharsOutOfLine();
+ //
+ }
+ }
+
+ /**
+ *
+ */
+ private void writeCharsInLine(char[] aChars, int aOff, int aLen)
+ {
+ final int[] buffer = iBuffer;
+ int count = iCount;
+
+ buffer[count++] = aLen; // | CHAR_DATA_INLINE
+
+ final int wend = aOff + (aLen & ~1);
+
+ while (aOff < wend)
+ {
+ final int ch1 = aChars[aOff++];
+ final int ch2 = aChars[aOff++];
+
+ //
+ // Pack two chars into each int.
+ //
+ // Assumes:
+ //
+ // ints are little endian.
+ // char to int promotion doesn't sign extend
+ //
+
+ buffer[count++] = (ch2 << 16) | ch1;
+ }
+
+ if ((aLen & 1) == 1)
+ {
+ buffer[count++] = aChars[aOff]; // last char in first half-word
+ }
+
+ iCount = count;
+ }
+
+ /**
+ * ensures there is at least aSize words of space remaining in the buffer,
+ * and flushes the buffer if not.
+ */
+ final void ensureSpace(int aSize)
+ {
+ if ((iCount+aSize) > iBuffer.length)
+ {
+ pump();
+ if (aSize > iBuffer.length)
+ {
+ throw new RuntimeException("Insufficient space in buffer for command: " + aSize);
+ }
+ }
+ }
+
+ /**
+ * Flushes buffer and waits for native processing to complete.
+ */
+ final void sync()
+ {
+ synchronized (this)
+ {
+ if (iCount > 0)
+ {
+ deactivate();
+ _flush(iHandle, iBuffer, iCount);
+ iCount=0;
+ iStart=0;
+ iCurrent=-1;
+ }
+ }
+ }
+
+ /**
+ *
+ */
+ private void deactivate()
+ {
+ if (-1 != iCurrent)
+ {
+ iBuffer[iStart] = iCount - iStart - 1;
+ iCurrent = -1;
+ }
+ }
+
+ /**
+ *
+ */
+ private void activate(int aHandle)
+ {
+ if (0 != aHandle)
+ {
+ // flush if insufficient space for activation
+ // command.
+ // RECURSION NOTE: we do not use pump() here
+ // to avoid any risk of recursion.
+ if ((iCount + 2) > iBuffer.length)
+ {
+ sync();
+ }
+
+ iBuffer[ iCount++ ] = (aHandle | ACTIVATE);
+ iCurrent = aHandle;
+ iStart = iCount;
+ iBuffer[ iCount++ ] = 0;
+ }
+ else
+ {
+ throw new RuntimeException("Invalid handle " + aHandle);
+ }
+ }
+
+ /**
+ * Flush the current contents of the buffer and reset the current writer.
+ */
+ private void pump()
+ {
+ final int current = iCurrent;
+ sync();
+ activate(current);
+ }
+
+ private native int _open(int aEventServerHandle);
+ private native void _flush(int aHandle, int[] aBuffer, int aCount);
+ private native void _close(int aHandle);
+}
+