Exemple #1
0
        /// <summary>
        /// Loads packets from the input stream.  For example, packets are all of the x's in a stroke
        /// </summary>
#endif
        static uint LoadPackets(Stream inputStream, 
                                uint totalBytesInStrokeBlockOfIsfStream, 
#if OLD_ISF
                                Compressor compressor, 
#endif
                                StylusPointDescription stylusPointDescription, 
                                Matrix transform, 
                                out StylusPointCollection stylusPoints)
        {
            stylusPoints = null;

            if (0 == totalBytesInStrokeBlockOfIsfStream)
                return 0;

            uint locallyDecodedBytesRemaining = totalBytesInStrokeBlockOfIsfStream;
            uint localBytesRead;

            // First read the no of packets
            uint pointCount;

            localBytesRead = SerializationHelper.Decode(inputStream, out pointCount);
            if (locallyDecodedBytesRemaining < localBytesRead)
                throw new ArgumentException(StrokeCollectionSerializer.ISFDebugMessage("Invalid ISF data"));

            locallyDecodedBytesRemaining -= localBytesRead;
            if (0 == locallyDecodedBytesRemaining)
                return localBytesRead;

            // Allocate packet properties
            int intsPerPoint = stylusPointDescription.GetInputArrayLengthPerPoint();
            int buttonCount = stylusPointDescription.ButtonCount;
            int buttonIntsPerPoint = (buttonCount > 0 ? 1 : 0);
            int valueIntsPerPoint = intsPerPoint - buttonIntsPerPoint;
            //add one int per point for button data if it exists
            int[] rawPointData = new int[pointCount * intsPerPoint];
            int[] packetDataSet = new int[pointCount];
            

            // copy the rest of the data from the stroke data
            byte[] inputBuffer = new byte[locallyDecodedBytesRemaining];

            // Read the input data into the byte array
            uint bytesRead = StrokeCollectionSerializer.ReliableRead(inputStream, inputBuffer, locallyDecodedBytesRemaining);

            if ( bytesRead != locallyDecodedBytesRemaining )
            {
                // Make sure the bytes read are expected. If not, we should bail out.
                // An exception will be thrown.
                throw new ArgumentException(StrokeCollectionSerializer.ISFDebugMessage("Invalid ISF data"));
            }

            // at this point, we have read all of the bytes remaining in the input
            //      stream's packet block, and while we will keep the bytes remaining
            //      variable for positioning within the local byte buffer, we should
            //      not read from the stream again, or we risk reading into another
            //      ISF tag's block.
            int originalPressureIndex = stylusPointDescription.OriginalPressureIndex;
            for (int i = 0; i < valueIntsPerPoint && locallyDecodedBytesRemaining > 0; i++)
            {
                localBytesRead = locallyDecodedBytesRemaining;
                Compressor.DecompressPacketData(
#if OLD_ISF
                        compressor, 
#endif
                        inputBuffer, 
                        ref localBytesRead, 
                        packetDataSet);

                if (localBytesRead > locallyDecodedBytesRemaining)
                    throw new ArgumentException(StrokeCollectionSerializer.ISFDebugMessage("Invalid ISF data"));

                //
                // packetDataSet is like this:
                // -------------
                // |X|X|X|X|X|X|
                // -------------
                //
                // we need to copy into rawPointData at
                //
                // -------------
                // |X| |X| |X| |
                // -------------
                //
                // additionally, for NormalPressure, if it exists and was 
                // reordered in the StylusPointDescription, we need to account for that here
                //
                int tempi = i;
                if (tempi > 1 && 
                    originalPressureIndex != -1 && 
                    originalPressureIndex != StylusPointDescription.RequiredPressureIndex/*2*/)
                {
                    //
                    // NormalPressure exists in the packet stream and was not at index 2
                    // StylusPointDescription enforces that NormalPressure is at index 2
                    // so we need to copy packet data beyond X and Y into a different location
                    //
                    // take the example of the original StylusPointDescription
                    //  |X|Y|XTilt|YTilt|NormalPressure|Rotation|
                    //
                    // originalPressureIndex is 4, and we know it is now 2
                    // which means that everything before index 4 has been shifted one
                    // and everything after index 4 is still good.  Index 4 should be copied to index 2
                    if (tempi == originalPressureIndex)
                    {
                        tempi = 2;
                    }
                    else if (tempi < originalPressureIndex)
                    {
                        tempi++;
                    }
                }

                locallyDecodedBytesRemaining -= localBytesRead;
                for (int j = 0, x = 0; j < pointCount; j++, x += intsPerPoint)
                {

                    rawPointData[x + tempi] = packetDataSet[j];
                }

                // Move the array elements to point to next set of compressed data
                for (uint u = 0; u < locallyDecodedBytesRemaining; u++)
                {
                    inputBuffer[u] = inputBuffer[u + (int)localBytesRead];
                }
            }

            // Now that we've read packet data, we must read button data if it is there
            byte[] buttonData = null;
            // since the button state is a simple bit value (either down or up), the button state
            // for a series of packets is packed into an array of bits rather than integers
            // For example, if there are 16 packets, and 2 buttons, then 32 bits can be used (e.g. 1 32-bit integer)
            if (0 != locallyDecodedBytesRemaining && buttonCount > 0)
            {
                    // calculate the number of full bytes used for buttons per packet
                    //   Example: 10 buttons would require 1 full byte
                int fullBytesForButtonsPerPacket = buttonCount / Native.BitsPerByte;
                    // calculate the number of bits that spill beyond the full byte boundary
                    //   Example: 10 buttons would require 2 extra bits (8 fit in a full byte)
                int partialBitsForButtonsPerPacket = buttonCount % Native.BitsPerByte;

                // Now figure out how many bytes we need to read for the button data
                localBytesRead = (uint)((buttonCount * pointCount + 7) / Native.BitsPerByte);
                if (localBytesRead > locallyDecodedBytesRemaining)
                {
                    throw new ArgumentException(StrokeCollectionSerializer.ISFDebugMessage("Buffer range is smaller than expected expected size"));
                }
                locallyDecodedBytesRemaining -= localBytesRead;

                int buttonSizeInBytes = (buttonCount + 7)/Native.BitsPerByte;
                buttonData = new byte[pointCount * buttonSizeInBytes];

                // Create a bit reader to unpack the bits from the ISF stream into
                //    loosely packed byte buffer (e.g. button data aligned on full byte
                //    boundaries only)
                BitStreamReader bitReader =
                    new BitStreamReader(inputBuffer, (uint)buttonCount * pointCount);

                // unpack the button data into each packet
                int byteCounter = 0;
                while (!bitReader.EndOfStream)
                {
                    // unpack the fully bytes first
                    for (int fullBytes = 0; fullBytes < fullBytesForButtonsPerPacket; fullBytes++)
                    {
                        buttonData[byteCounter++] = bitReader.ReadByte(Native.BitsPerByte);
                    }
                    // then unpack a single partial byte if necessary
                    if (partialBitsForButtonsPerPacket > 0)
                    {
                        buttonData[byteCounter++] = bitReader.ReadByte((int)partialBitsForButtonsPerPacket);
                    }
                }

                // if the number of bytes allocated != necessary byte amount then an error occurred
                if (byteCounter != buttonData.Length)
                {
                    throw new ArgumentException(StrokeCollectionSerializer.ISFDebugMessage("Button data length not equal to expected length"));
                }

                //
                // set the point data in the raw array
                //
                FillButtonData( (int)pointCount,
                                buttonCount,
                                valueIntsPerPoint, //gives the first button index
                                rawPointData,
                                buttonData);
            }


            stylusPoints = new StylusPointCollection(stylusPointDescription, rawPointData, null, transform);

            // if we read too far into the stream (e.g. the packets were compressed)
            //      then move the stream pointer back to the end of the actual packet
            //      data before returning. This keeps the return value on the function
            //      (representing bytes read) honest and consistent with the stream
            //      position movement in this function.
            if (0 != locallyDecodedBytesRemaining)
            {
                inputStream.Seek(0 - (long)locallyDecodedBytesRemaining, SeekOrigin.Current);
            }

            return totalBytesInStrokeBlockOfIsfStream - locallyDecodedBytesRemaining;
        }
Exemple #2
0
        /// <summary> 
        /// Uncompress
        /// </summary> 
        /// <param name="input"></param> 
        /// <param name="inputIndex"></param>
        /// <returns></returns> 
        internal byte[] Uncompress(byte[] input, int inputIndex)
        {
            //first things first
            Debug.Assert(input != null); 
            Debug.Assert(input.Length > 1);
            Debug.Assert(inputIndex < input.Length); 
            Debug.Assert(inputIndex >= 0); 

            List<byte> output = new List<byte>(); 
            BitStreamWriter writer = new BitStreamWriter(output);
            BitStreamReader reader = new BitStreamReader(input, inputIndex);

            //decode 
            int index = 0, countBytes = 0, start = 0;
            byte byte1 = 0, byte2 = 0; 
 
            _maxMatchLength = FirstMaxMatchLength;
 
            // initialize the ring buffer
            for (index = 0; index < RingBufferLength - _maxMatchLength; index++)
            {
                _ringBuffer[index] = 0; 
            }
 
            //initialize decoding globals 
            _flags = 0;
            _currentRingBufferPosition = RingBufferLength - _maxMatchLength; 
            while (!reader.EndOfStream)
            {
                byte1 = reader.ReadByte(Native.BitsPerByte);
 
                // High order byte counts the number of bits used in the low order
                // byte. 
                if (((_flags >>= 1) & 0x100) == 0) 
                {
                    // Set bit mask describing the next 8 bytes. 
                    _flags = (((int)byte1) | 0xff00);

                    byte1 = reader.ReadByte(Native.BitsPerByte);
                } 

                if ((_flags & 1) != 0) 
                { 
                    // Just store the literal byte in the buffer.
                    writer.Write(byte1, Native.BitsPerByte); 

                    _ringBuffer[_currentRingBufferPosition++] = byte1;
                    _currentRingBufferPosition &= RingBufferLength - 1;
                } 
                else
                { 
                    // Extract the offset and count to copy from the ring buffer. 
                    byte2 = reader.ReadByte(Native.BitsPerByte);
 
                    countBytes = (int)byte2;
                    start = (countBytes & 0xf0) << 4 | (int)byte1;
                    countBytes = (countBytes & 0x0f) + MaxLiteralLength;
 
                    for (index = 0; index <= countBytes; index++)
                    { 
                        byte1 = _ringBuffer[(start + index) & (RingBufferLength - 1)]; 
                        writer.Write(byte1, Native.BitsPerByte);
 
                        _ringBuffer[_currentRingBufferPosition++] = byte1;
                        _currentRingBufferPosition &= RingBufferLength - 1;
                    }
                } 
            }
 
            return output.ToArray(); 
        }