Пример #1
0
        internal Point GetLastTabletPoint()
        {
            int packetLength = StylusPointDescription.GetInputArrayLengthPerPoint();
            int lastXIndex   = _data.Length - packetLength;

            return(new Point(_data[lastXIndex], _data[lastXIndex + 1]));
        }
Пример #2
0
        /// <summary>
        /// Internal ctor called by input with a raw int[]
        /// </summary>
        /// <param name="stylusPointDescription">stylusPointDescription</param>
        /// <param name="rawPacketData">rawPacketData</param>
        /// <param name="tabletToView">tabletToView</param>
        /// <param name="tabletToViewMatrix">tabletToView</param>
        internal StylusPointCollection(StylusPointDescription stylusPointDescription, int[] rawPacketData, GeneralTransform tabletToView, Matrix tabletToViewMatrix)
        {
            if (null == stylusPointDescription)
            {
                throw new ArgumentNullException("stylusPointDescription");
            }
            _stylusPointDescription = stylusPointDescription;

            int lengthPerPoint    = stylusPointDescription.GetInputArrayLengthPerPoint();
            int logicalPointCount = rawPacketData.Length / lengthPerPoint;

            Debug.Assert(0 == rawPacketData.Length % lengthPerPoint, "Invalid assumption about packet length, there shouldn't be any remainder");

            //
            // set our capacity and validate
            //
            ((List <StylusPoint>) this.Items).Capacity = logicalPointCount;
            for (int count = 0, i = 0; count < logicalPointCount; count++, i += lengthPerPoint)
            {
                //first, determine the x, y values by xf-ing them
                Point p = new Point(rawPacketData[i], rawPacketData[i + 1]);
                if (tabletToView != null)
                {
                    tabletToView.TryTransform(p, out p);
                }
                else
                {
                    p = tabletToViewMatrix.Transform(p);
                }

                int  startIndex           = 2;
                bool containsTruePressure = stylusPointDescription.ContainsTruePressure;
                if (containsTruePressure)
                {
                    //don't copy pressure in the int[] for extra data
                    startIndex++;
                }

                int[] data       = null;
                int   dataLength = lengthPerPoint - startIndex;
                if (dataLength > 0)
                {
                    //copy the rest of the data
                    var rawArrayStartIndex = i + startIndex;
                    data = rawPacketData.AsSpan(rawArrayStartIndex, dataLength).ToArray();
                }

                StylusPoint newPoint = new StylusPoint(p.X, p.Y, StylusPoint.DefaultPressure, _stylusPointDescription, data, false, false);
                if (containsTruePressure)
                {
                    //use the algorithm to set pressure in StylusPoint
                    int pressure = rawPacketData[i + 2];
                    newPoint.SetPropertyValue(StylusPointProperties.NormalPressure, pressure);
                }

                //this does not go through our protected virtuals
                ((List <StylusPoint>) this.Items).Add(newPoint);
            }
        }
Пример #3
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;
        }