示例#1
0
        static uint[] decodeRgbIcon(byte[] payload, CSize size)
        {
            // https://devblogs.microsoft.com/oldnewthing/20101019-00/?p=12503
            int totalPixels = size.cx * size.cy;

            int maskLineDwords  = (size.cx + 31) / 32;
            int maskStrideBytes = maskLineDwords * 4;
            int bytesMask       = size.cy * maskStrideBytes;

            int cbHeader = Marshal.SizeOf <BITMAPINFOHEADER>();

            if (payload.Length != (totalPixels * 4) + bytesMask + cbHeader)
            {
                throw new ArgumentException("Size doesn't match");
            }

            uint[] result = new uint[totalPixels];

            // Copy the RGB values
            payload.AsSpan()
            .Slice(cbHeader, totalPixels * 4)
            .castSpan <uint>()
            .CopyTo(result.AsSpan());

            // Apply the alpha mask, it's 1 bit / pixel.
            ReadOnlySpan <byte> mask = payload.AsSpan().Slice(cbHeader + totalPixels * 4);

            applyMask(result.AsSpan(), size, mask, maskStrideBytes);
            return(result);
        }
        public void InputEndsTooEarlyAndRestartsFromUtf32()
        {
            uint[] codepoints1 = TextEncoderTestHelper.GenerateValidUtf32CodePoints(TextEncoderConstants.DataLength);
            uint[] codepoints2 = TextEncoderTestHelper.GenerateValidUtf32CodePoints(TextEncoderConstants.DataLength);

            uint[] inputAll = new uint[codepoints1.Length + codepoints2.Length];
            Array.Copy(codepoints1, inputAll, codepoints1.Length);
            Array.Copy(codepoints2, 0, inputAll, codepoints1.Length, codepoints2.Length);

            ReadOnlySpan <byte> expected = Text.Encoding.Convert(Text.Encoding.UTF32, Text.Encoding.UTF8, MemoryMarshal.AsBytes(inputAll.AsSpan()).ToArray());
            Span <byte>         output   = new byte[expected.Length];

            ReadOnlySpan <byte> input = MemoryMarshal.AsBytes(inputAll.AsSpan(0, codepoints1.Length));

            input = input.Slice(0, input.Length - 2); // Strip a couple bytes from last good code point
            Assert.Equal(OperationStatus.NeedMoreData, Encodings.Utf32.ToUtf8(input, output, out int consumed, out int written));
            Assert.True(input.Length > consumed, "Consumed too many bytes [first half]");
            Assert.NotEqual(expected.Length, written);
            Assert.True(expected.Slice(0, written).SequenceEqual(output.Slice(0, written)), "Invalid output sequence [first half]");

            input    = MemoryMarshal.AsBytes(inputAll.AsSpan()).Slice(consumed);
            expected = expected.Slice(written);
            Assert.Equal(OperationStatus.Done, Encodings.Utf32.ToUtf8(input, output, out consumed, out written));
            Assert.Equal(input.Length, consumed);
            Assert.Equal(expected.Length, written);
            Assert.True(expected.SequenceEqual(output.Slice(0, written)), "Invalid output sequence [second half]");
        }
示例#3
0
        public async Task TestLongCompatibility(int length, bool bigTiff)
        {
            uint[] refData = new uint[length];
            new Random(42).NextBytes(MemoryMarshal.AsBytes(refData.AsSpan()));

            using Stream stream = await GenerateTiffAsync(bigTiff, async ifd =>
            {
                await ifd.WriteTagAsync((TiffTag) 0x1234, TiffValueCollection.UnsafeWrap(refData));
            });

            await using (TiffFileReader reader = await TiffFileReader.OpenAsync(stream, leaveOpen: true))
            {
                TiffImageFileDirectory ifd = await reader.ReadImageFileDirectoryAsync();

                TiffFieldReader fieldReader = await reader.CreateFieldReaderAsync();

                TiffImageFileDirectoryEntry entry = ifd.FindEntry((TiffTag)0x1234);
                Assert.Equal((TiffTag)0x1234, entry.Tag);

                // Byte
                await TestInvalidConversionAsync <byte>(fieldReader, entry, nameof(fieldReader.ReadByteFieldAsync), refData.Length);

                // SSbyte
                await TestInvalidConversionAsync <sbyte>(fieldReader, entry, nameof(fieldReader.ReadSByteFieldAsync), refData.Length);

                // Short
                await TestInvalidConversionAsync <ushort>(fieldReader, entry, nameof(fieldReader.ReadShortFieldAsync), refData.Length);

                // SShort
                await TestInvalidConversionAsync <short>(fieldReader, entry, nameof(fieldReader.ReadSShortFieldAsync), refData.Length);

                // Long
                await TestValidConversionAsync(fieldReader, entry, nameof(fieldReader.ReadLongFieldAsync), refData);

                // SLong
                await TestValidConversionAsync(fieldReader, entry, nameof(fieldReader.ReadSLongFieldAsync), Array.ConvertAll(refData, v => (int)v));

                // Float
                await TestInvalidConversionAsync <float>(fieldReader, entry, nameof(fieldReader.ReadFloatFieldAsync), refData.Length);

                // Double
                await TestInvalidConversionAsync <double>(fieldReader, entry, nameof(fieldReader.ReadDoubleFieldAsync), refData.Length);

                // Rational
                await TestValidConversionAsync(fieldReader, entry, nameof(fieldReader.ReadRationalFieldAsync), Array.ConvertAll(refData, v => new TiffRational(v, 1)));

                // SRational
                await TestValidConversionAsync(fieldReader, entry, nameof(fieldReader.ReadSRationalFieldAsync), Array.ConvertAll(refData, v => new TiffSRational((int)v, 1)));
            }
        }
示例#4
0
        static Crc()
        {
            var tmpTable = new uint[MaxSlice][];

            for (uint i = 0; i < MaxSlice; i++)
            {
                tmpTable[i] = new uint[256];
            }

            uint crc;

            for (uint i = 0; i < 256; i++)
            {
                crc = i << 24;

                for (uint j = 0; j < 8; j++)
                {
                    uint x     = crc & (1u << 31);
                    uint shift = x != 0 ? Polynomial : 0;
                    crc = (crc << 1) ^ shift;
                }
                tmpTable[0][i] = crc;
            }

            for (uint i = 0; i < 256; i++)
            {
                for (uint j = 1; j < MaxSlice; j++)
                {
                    uint x = tmpTable[0][(tmpTable[j - 1][i] >> 24) & 0xFF];
                    tmpTable[j][i] = x ^ (tmpTable[j - 1][i] << 8);
                }
            }

            // reversing the tables makes the slicing-by-x loop slightly faster
            // as it can access the table data linearly
            tmpTable.AsSpan().Reverse();

            for (int i = 0; i < MaxSlice; i++)
            {
                tmpTable[i].CopyTo(_lookupTable.AsSpan(i * 256, 256));
            }
        }
 public void IterationTest(int length)
 {
     uint[] array = new uint[length];
     array.AsSpan().Fill(uint.MaxValue);
     using (NativeList <uint> nativeList = new(array))
     {
         for (int i = 0; i < nativeList.Count; i++)
         {
             Assert.Equal(uint.MaxValue, nativeList[i]);
         }
         for (uint i = 0; i < nativeList.Count; i++)
         {
             Assert.Equal(uint.MaxValue, nativeList[i]);
         }
         foreach (uint u in nativeList)
         {
             Assert.Equal(uint.MaxValue, u);
         }
     }
 }
示例#6
0
            static void CreateC(ReadOnlySpan <uint> origC,
                                int mod,
                                out ReadOnlySpan <uint> c,
                                out ReadOnlySpan <uint> ic)
            {
                var cc = new uint[origC.Length + 1];

                origC.CopyTo(cc.AsSpan(1));
                cc[0] = (uint)(mod - 1);
                c     = cc;

                ic = new uint[1] {
                    1
                };
                var t = 1;

                while (t < c.Length)
                {
                    t = Math.Min(t << 1, c.Length);
                    var current = ConvolutionAnyMod.Convolution(c[..t], ic, mod).AsSpan();
        public void SortTest()
        {
            const int listLength = 32000;

            var list = new uint[listLength];
            var listStuff = new uint[listLength];
            Random random = new Random();
            
            for (int i = 0; i < listLength; i++)
            {
                list[i] = (uint) random.Next(0, int.MaxValue);
                listStuff[i] = 0;
            }

            var compareList = new uint[listLength];
            
            Array.Copy(list, compareList, listLength);

            Array.Sort(compareList);
            list.AsSpan().Sort(listStuff.AsSpan(), 0, false);

            list.Should().BeEquivalentTo(compareList);
        }
示例#8
0
        /// <summary>
        /// Create or updates the reflection for this shader
        /// </summary>
        /// <param name="effectReflection">the reflection from the hlsl</param>
        /// <param name="stage">the shader pipeline stage</param>
        private void CreateReflection(EffectReflection effectReflection, ShaderStage stage)
        {
            int currentProgram;

            GL.GetInteger(GetPName.CurrentProgram, out currentProgram);
            GL.UseProgram(ProgramId);

            int uniformBlockCount;

            GL.GetProgram(ProgramId, ProgramPropertyARB.ActiveUniformBlocks, out uniformBlockCount);

            var validConstantBuffers = new bool[effectReflection.ConstantBuffers.Count];

            for (uint uniformBlockIndex = 0; uniformBlockIndex < uniformBlockCount; ++uniformBlockIndex)
            {
                // TODO: get previous name to find te actual constant buffer in the reflexion
                GL.GetActiveUniformBlockName(ProgramId, uniformBlockIndex, 1024, out var constantBufferNameLength, out string constantBufferName);

                var constantBufferDescriptionIndex = effectReflection.ConstantBuffers.FindIndex(x => x.Name == constantBufferName);
                if (constantBufferDescriptionIndex == -1)
                {
                    reflectionResult.Error($"Unable to find the constant buffer description [{constantBufferName}]");
                    return;
                }
                var constantBufferIndex = effectReflection.ResourceBindings.FindIndex(x => x.RawName == constantBufferName);
                if (constantBufferIndex == -1)
                {
                    reflectionResult.Error($"Unable to find the constant buffer [{constantBufferName}]");
                    return;
                }

                var constantBufferDescription = effectReflection.ConstantBuffers[constantBufferDescriptionIndex];
                var constantBuffer            = effectReflection.ResourceBindings[constantBufferIndex];

                GL.GetActiveUniformBlock(ProgramId, uniformBlockIndex, UniformBlockPName.UniformBlockDataSize, out constantBufferDescription.Size);

                int uniformCount;
                GL.GetActiveUniformBlock(ProgramId, uniformBlockIndex, UniformBlockPName.UniformBlockActiveUniforms, out uniformCount);

                // set the binding
                GL.UniformBlockBinding(ProgramId, uniformBlockIndex, uniformBlockIndex);

                // Read uniforms desc
                var uniformIndices = new uint[uniformCount];
                var uniformOffsets = new int[uniformCount];
                var uniformTypes   = new int[uniformCount];
                var uniformNames   = new string[uniformCount];
                GL.GetActiveUniformBlock(ProgramId, uniformBlockIndex, UniformBlockPName.UniformBlockActiveUniformIndices, MemoryMarshal.Cast <uint, int>(uniformIndices.AsSpan()));
                GL.GetActiveUniforms(ProgramId, (uint)uniformIndices.Length, uniformIndices, UniformPName.UniformOffset, uniformOffsets);
                GL.GetActiveUniforms(ProgramId, (uint)uniformIndices.Length, uniformIndices, UniformPName.UniformType, uniformTypes);

                for (int uniformIndex = 0; uniformIndex < uniformIndices.Length; ++uniformIndex)
                {
                    uniformNames[uniformIndex] = GL.GetActiveUniform(ProgramId, uniformIndices[uniformIndex], out var uniformSize, out var uniformType);
                }

                // Reoder by offset
                var indexMapping = uniformIndices.Select((x, i) => new UniformMergeInfo {
                    Offset = uniformOffsets[i], Type = (UniformType)uniformTypes[i], Name = uniformNames[i], NextOffset = 0
                }).OrderBy(x => x.Offset).ToArray();
                indexMapping.Last().NextOffset = constantBufferDescription.Size;

                // Fill next offsets
                for (int i = 1; i < indexMapping.Length; ++i)
                {
                    indexMapping[i - 1].NextOffset = indexMapping[i].Offset;
                }

                // Group arrays/structures into one variable (std140 layout is enough for offset determinism inside arrays/structures)
                indexMapping = indexMapping.GroupBy(x =>
                {
                    // Use only first part of name (ignore structure/array part)
                    var name = x.Name;
                    if (name.Contains("."))
                    {
                        name = name.Substring(0, name.IndexOf('.'));
                    }
                    if (name.Contains("["))
                    {
                        name = name.Substring(0, name.IndexOf('['));
                    }
                    return(name);
                })
                               .Select(x =>
                {
                    var result        = x.First();
                    result.NextOffset = x.Last().NextOffset;

                    // Check weither it's an array or a struct
                    int dotIndex   = result.Name.IndexOf('.');
                    int arrayIndex = result.Name.IndexOf('[');

                    if (x.Count() > 1 && arrayIndex == -1 && dotIndex == -1)
                    {
                        throw new InvalidOperationException();
                    }

                    // TODO: Type processing

                    result.Name = x.Key;
                    return(result);
                }).ToArray();

                foreach (var variableIndexGroup in indexMapping)
                {
                    var variableIndex = -1;
                    for (var tentativeIndex = 0; tentativeIndex < constantBufferDescription.Members.Length; ++tentativeIndex)
                    {
                        if (constantBufferDescription.Members[tentativeIndex].RawName == variableIndexGroup.Name)
                        {
                            variableIndex = tentativeIndex;
                            break;
                        }
                    }

                    if (variableIndex == -1)
                    {
                        reflectionResult.Error($"Unable to find uniform [{variableIndexGroup.Name}] in constant buffer [{constantBufferName}]");
                        continue;
                    }
                    var variable = constantBufferDescription.Members[variableIndex];
                    variable.Type.Type = GetTypeFromActiveUniformType(variableIndexGroup.Type);
                    variable.Offset    = variableIndexGroup.Offset;
                    variable.Size      = variableIndexGroup.NextOffset - variableIndexGroup.Offset;

                    constantBufferDescription.Members[variableIndex] = variable;
                }

                constantBufferDescription.Type = ConstantBufferType.ConstantBuffer;

                constantBuffer.SlotCount = 1; // constant buffers are not arrays
                constantBuffer.SlotStart = (int)uniformBlockIndex;
                constantBuffer.Stage     = stage;

                // store the new values
                validConstantBuffers[constantBufferDescriptionIndex]             = true;
                effectReflection.ConstantBuffers[constantBufferDescriptionIndex] = constantBufferDescription;
                effectReflection.ResourceBindings[constantBufferIndex]           = constantBuffer;
            }
//#endif

            // Remove unecessary cbuffer and resource bindings

            // Register textures, samplers, etc...
            //TODO: (?) non texture/buffer uniform outside of a block
            {
                // Register "NoSampler", required by HLSL=>GLSL translation to support HLSL such as texture.Load().
                var noSampler = new EffectResourceBindingDescription {
                    KeyInfo = { KeyName = "NoSampler" }, RawName = "NoSampler", Class = EffectParameterClass.Sampler, SlotStart = -1, SlotCount = 1
                };
                Reflection.ResourceBindings.Add(noSampler);

                int activeUniformCount;
                GL.GetProgram(ProgramId, ProgramPropertyARB.ActiveUniforms, out activeUniformCount);
#if !STRIDE_GRAPHICS_API_OPENGLES
                var uniformTypes   = new int[activeUniformCount];
                var uniformIndices = new uint[activeUniformCount];
                for (uint i = 0; i < uniformIndices.Length; ++i)
                {
                    uniformIndices[i] = i;
                }
                GL.GetActiveUniforms(ProgramId, (uint)activeUniformCount, uniformIndices, UniformPName.UniformType, uniformTypes);
#endif

                int textureUnitCount = 0;

                const int sbCapacity = 128;
                var       sb         = new StringBuilder(sbCapacity);

                for (uint activeUniformIndex = 0; activeUniformIndex < activeUniformCount; ++activeUniformIndex)
                {
                    var uniformName = GL.GetActiveUniform(ProgramId, activeUniformIndex, out var uniformCount, out var uniformType);

#if STRIDE_GRAPHICS_API_OPENGLES
                    //this is a special OpenglES case , it is declared as built in uniform, and the driver will take care of it, we just need to ignore it here
                    if (uniformName.StartsWith("gl_DepthRange"))
                    {
                        continue;
                    }
#endif

                    switch (uniformType)
                    {
                    case UniformType.Sampler1D:
                    case UniformType.Sampler1DShadow:
                    case UniformType.IntSampler1D:
                    case UniformType.UnsignedIntSampler1D:

                    case UniformType.SamplerBuffer:
                    case UniformType.UnsignedIntSamplerBuffer:
                    case UniformType.IntSamplerBuffer:
                    case UniformType.Sampler2D:
                    case UniformType.Sampler2DShadow:
                    case UniformType.Sampler3D:     // TODO: remove Texture3D that is not available in OpenGL ES 2
                    case UniformType.SamplerCube:
                    case UniformType.IntSampler2D:
                    case UniformType.IntSampler3D:
                    case UniformType.IntSamplerCube:
                    case UniformType.UnsignedIntSampler2D:
                    case UniformType.UnsignedIntSampler3D:
                    case UniformType.UnsignedIntSamplerCube:
                        var uniformIndex = GL.GetUniformLocation(ProgramId, uniformName);

                        // Temporary way to scan which texture and sampler created this texture_sampler variable (to fix with new HLSL2GLSL converter)

                        var startIndex             = -1;
                        var textureReflectionIndex = -1;
                        var samplerReflectionIndex = -1;
                        do
                        {
                            int middlePart  = uniformName.IndexOf('_', startIndex + 1);
                            var textureName = middlePart != -1 ? uniformName.Substring(0, middlePart) : uniformName;
                            var samplerName = middlePart != -1 ? uniformName.Substring(middlePart + 1) : null;

                            textureReflectionIndex =
                                effectReflection.ResourceBindings.FindIndex(x => x.RawName == textureName);
                            samplerReflectionIndex =
                                effectReflection.ResourceBindings.FindIndex(x => x.RawName == samplerName);

                            if (textureReflectionIndex != -1 && samplerReflectionIndex != -1)
                            {
                                break;
                            }

                            startIndex = middlePart;
                        } while (startIndex != -1);

                        if (startIndex == -1 || textureReflectionIndex == -1 || samplerReflectionIndex == -1)
                        {
                            reflectionResult.Error($"Unable to find sampler and texture corresponding to [{uniformName}]");
                            continue;     // Error
                        }

                        var textureReflection = effectReflection.ResourceBindings[textureReflectionIndex];
                        var samplerReflection = effectReflection.ResourceBindings[samplerReflectionIndex];

                        // Contrary to Direct3D, samplers and textures are part of the same object in OpenGL
                        // Since we are exposing the Direct3D representation, a single sampler parameter key can be used for several textures, a single texture can be used with several samplers.
                        // When such a case is detected, we need to duplicate the resource binding.
                        textureReflectionIndex = GetReflexionIndex(textureReflection, textureReflectionIndex, effectReflection.ResourceBindings);
                        samplerReflectionIndex = GetReflexionIndex(samplerReflection, samplerReflectionIndex, effectReflection.ResourceBindings);

                        // Update texture uniform mapping
                        GL.Uniform1(uniformIndex, textureUnitCount);

                        textureReflection.Stage = stage;
                        //textureReflection.Param.RawName = uniformName;
                        textureReflection.Type      = GetTypeFromActiveUniformType(uniformType);
                        textureReflection.Class     = EffectParameterClass.ShaderResourceView;
                        textureReflection.SlotStart = textureUnitCount;
                        textureReflection.SlotCount = 1;     // TODO: texture arrays

                        samplerReflection.Stage     = stage;
                        samplerReflection.Class     = EffectParameterClass.Sampler;
                        samplerReflection.SlotStart = textureUnitCount;
                        samplerReflection.SlotCount = 1;     // TODO: texture arrays

                        effectReflection.ResourceBindings[textureReflectionIndex] = textureReflection;
                        effectReflection.ResourceBindings[samplerReflectionIndex] = samplerReflection;

                        Textures.Add(new Texture(textureUnitCount));

                        textureUnitCount++;
                        break;
                    }
                }

                // Remove any optimized resource binding
                effectReflection.ResourceBindings.RemoveAll(x => x.SlotStart == -1);
                effectReflection.ConstantBuffers = effectReflection.ConstantBuffers.Where((cb, i) => validConstantBuffers[i]).ToList();
            }

            GL.UseProgram((uint)currentProgram);
        }
示例#9
0
        public static bool Save(string filename, int w, int h, byte[] data)
        {
            const byte iComponentCount = 3;

            using var outStream = new FileStream(filename, FileMode.Create, FileAccess.Write, FileShare.ReadWrite);
            if (!outStream.CanWrite)
            {
                return(false);
            }

            using var binaryWriter = new BinaryWriter(outStream);

            // write BMP-Header
            binaryWriter.Write("BM".AsSpan()); // all BMP-Files start with "BM"
            var header = new uint[3];
            var rowPad = 4 - (w * 8 * iComponentCount % 32 / 8);

            if (rowPad == 4)
            {
                rowPad = 0;
            }
            header[0] = (uint)(54 + (w * h * iComponentCount) + (rowPad * h)); // filesize = 54 (header) + sizeX * sizeY * numChannels
            header[1] = 0;                                                     // reserved = 0 (4 Bytes)
            header[2] = 54;                                                    // File offset to Raster Data
            binaryWriter.Write(MemoryMarshal.AsBytes(header.AsSpan()));
            // write BMP-Info-Header
            var infoHeader = new uint[10];

            infoHeader[0] = 40;      // size of info header
            infoHeader[1] = (uint)w; // Bitmap Width
            infoHeader[2] = (uint)h; //uint32_t(-(int32_t)h); // Bitmap Height (negative to flip image)
            infoHeader[3] = (uint)(1 + (65536 * 8 * iComponentCount));
            // first 2 bytes=Number of Planes (=1) next 2 bytes=BPP
            infoHeader[4] = 0;      // compression (0 = none)
            infoHeader[5] = 0;      // compressed file size (0 if no compression)
            infoHeader[6] = 11810;  // horizontal resolution: Pixels/meter (11810 = 300 dpi)
            infoHeader[7] = 11810;  // vertical resolution: Pixels/meter (11810 = 300 dpi)
            infoHeader[8] = 0;      // Number of actually used colors
            infoHeader[9] = 0;      // Number of important colors  0 = all
            binaryWriter.Write(MemoryMarshal.AsBytes(infoHeader.AsSpan()));

            // data in BMP is stored BGR, so convert scalar BGR
            var pData = new byte[iComponentCount * w * h];

            uint i = 0;

            for (uint y = 0; y < h; ++y)
            {
                for (uint x = 0; x < w; ++x)
                {
                    var r = data[(4 * (x + (y * w))) + 0];
                    var g = data[(4 * (x + (y * w))) + 1];
                    var b = data[(4 * (x + (y * w))) + 2];
                    var a = data[(4 * (x + (y * w))) + 3];

                    pData[i++] = b;
                    pData[i++] = g;
                    pData[i++] = r;
                    if (iComponentCount == 4)
                    {
                        pData[i++] = a;
                    }
                }
            }

            // write data (pad if necessary)
            if (rowPad == 0)
            {
                binaryWriter.Write(pData);
            }
            else
            {
                var zeroes = new[] { byte.MinValue, byte.MinValue, byte.MinValue,
                                     byte.MinValue, byte.MinValue, byte.MinValue,
                                     byte.MinValue, byte.MinValue, byte.MinValue };
                for (var l = 0; l < h; l++)
                {
                    var seq = new ReadOnlySequence <byte>(pData).Slice(iComponentCount * l * w, iComponentCount * w);
                    foreach (var item in seq)
                    {
                        binaryWriter.Write(item.Span);
                    }
                    binaryWriter.Write(zeroes.AsSpan()[..rowPad]);
示例#10
0
        static uint[] decodeMonochromeIcon(byte[] payload, CSize size)
        {
            int totalPixels = size.cx * size.cy;

            int maskLineDwords  = (size.cx + 31) / 32;
            int maskStrideBytes = maskLineDwords * 4;
            int bytesMask       = size.cy * maskStrideBytes;

            int cbHeader = Marshal.SizeOf <BITMAPINFOHEADER>();

            // 8 is the color table, immediately after the header
            if (payload.Length != cbHeader + (bytesMask * 2) + 8)
            {
                throw new ArgumentException("Size doesn't match");
            }

            uint[]      result     = new uint[totalPixels];
            Span <uint> colorTable = stackalloc uint[2];

            payload.AsSpan()
            .Slice(cbHeader, 8)
            .castSpan <uint>()
            .CopyTo(colorTable);

            ReadOnlySpan <byte> bitmap = payload.AsSpan()
                                         .Slice(cbHeader + 8, bytesMask);

            if (0 == (size.cx % 8))
            {
                if (0 == (size.cx % 32))
                {
                    // No padding whatsoever
                    int destOffset = 0;
                    for (int i = 0; i < bitmap.Length; i++, destOffset += 8)
                    {
                        decodeMonochrome(result, colorTable, destOffset, bitmap[i]);
                    }
                }
                else
                {
                    // There is padding, but it's whole count of bytes
                    int maskBytesPerLine = size.cx / 8;
                    int sourceOffset     = 0;
                    int destOffset       = 0;
                    for (int y = 0; y < size.cy; y++, sourceOffset += maskStrideBytes)
                    {
                        for (int x = 0; x < maskBytesPerLine; x++, destOffset += 8)
                        {
                            decodeMonochrome(result, colorTable, destOffset, bitmap[sourceOffset + x]);
                        }
                    }
                }
            }
            else
            {
                // There is padding, and the last few pixels have less than 8 payload bits per line.
                throw new NotImplementedException("The library only supports cursors with width being a multiple of 8px");
            }

            // Apply the alpha mask, it's 1 bit / pixel.
            ReadOnlySpan <byte> mask = payload.AsSpan().Slice(cbHeader + 8 + bytesMask, bytesMask);

            applyMask(result.AsSpan(), size, mask, maskStrideBytes);
            return(result);
        }
示例#11
0
        //[InlineData(TextEncoderTestHelper.SupportedEncoding.FromUtf32)] // Open issue: https://github.com/dotnet/corefxlab/issues/1513
        public void InputBufferEndsTooEarlyAndRestart(TextEncoderTestHelper.SupportedEncoding from)
        {
            string inputString1 = TextEncoderTestHelper.GenerateValidStringEndsWithHighStartsWithLow(TextEncoderConstants.DataLength, false);
            string inputString2 = inputString1 + TextEncoderTestHelper.GenerateValidStringEndsWithHighStartsWithLow(TextEncoderConstants.DataLength, true);

            byte[] inputUtf8Bytes1   = TextEncoderTestHelper.GenerateValidUtf8BytesEndsWithHighStartsWithLow(TextEncoderConstants.DataLength, false);
            byte[] tempForUtf8Bytes2 = TextEncoderTestHelper.GenerateValidUtf8BytesEndsWithHighStartsWithLow(TextEncoderConstants.DataLength, true);
            byte[] inputUtf8Bytes2   = new byte[inputUtf8Bytes1.Length + tempForUtf8Bytes2.Length];
            Array.Copy(inputUtf8Bytes1, inputUtf8Bytes2, inputUtf8Bytes1.Length);
            Array.Copy(tempForUtf8Bytes2, 0, inputUtf8Bytes2, inputUtf8Bytes1.Length, tempForUtf8Bytes2.Length);

            uint[] inputUtf32Bytes1   = TextEncoderTestHelper.GenerateValidUtf32EndsWithHighStartsWithLow(TextEncoderConstants.DataLength, false);
            uint[] tempForUtf32Bytes2 = TextEncoderTestHelper.GenerateValidUtf32EndsWithHighStartsWithLow(TextEncoderConstants.DataLength, true);
            uint[] inputUtf32Bytes2   = new uint[inputUtf32Bytes1.Length + tempForUtf32Bytes2.Length];
            Array.Copy(inputUtf32Bytes1, inputUtf32Bytes2, inputUtf32Bytes1.Length);
            Array.Copy(tempForUtf32Bytes2, 0, inputUtf32Bytes2, inputUtf32Bytes1.Length, tempForUtf32Bytes2.Length);

            byte[] uint32Bytes1    = TextEncoderTestHelper.GenerateValidBytesUtf32EndsWithHighStartsWithLow(TextEncoderConstants.DataLength, false);
            byte[] tempUint32Bytes = TextEncoderTestHelper.GenerateValidBytesUtf32EndsWithHighStartsWithLow(TextEncoderConstants.DataLength, true);
            byte[] uint32Bytes2    = new byte[uint32Bytes1.Length + tempUint32Bytes.Length];
            Array.Copy(uint32Bytes1, uint32Bytes2, uint32Bytes1.Length);
            Array.Copy(tempUint32Bytes, 0, uint32Bytes2, uint32Bytes1.Length, tempUint32Bytes.Length);

            byte[]      expectedBytes;
            Span <byte> encodedBytes;

            int charactersConsumed1;
            int charactersConsumed2;

            int bytesWritten1;
            int bytesWritten2;

            switch (from)
            {
            case TextEncoderTestHelper.SupportedEncoding.FromUtf8:
                expectedBytes = Text.Encoding.Convert(testEncoder, testEncoder, inputUtf8Bytes2);
                ReadOnlySpan <byte> firstUtf8  = inputUtf8Bytes1;
                ReadOnlySpan <byte> secondUtf8 = inputUtf8Bytes2;
                encodedBytes = new Span <byte>(new byte[expectedBytes.Length]);
                Assert.False(utf8.TryEncode(firstUtf8, encodedBytes, out charactersConsumed1, out bytesWritten1));
                Assert.True(utf8.TryEncode(secondUtf8.Slice(charactersConsumed1), encodedBytes.Slice(bytesWritten1), out charactersConsumed2, out bytesWritten2));
                break;

            case TextEncoderTestHelper.SupportedEncoding.FromUtf16:
                byte[] inputStringUtf16 = testEncoderUnicode.GetBytes(inputString2);
                expectedBytes = Text.Encoding.Convert(testEncoderUnicode, testEncoder, inputStringUtf16);
                ReadOnlySpan <char> firstUtf16  = inputString1.AsSpan();
                ReadOnlySpan <char> secondUtf16 = inputString2.AsSpan();
                encodedBytes = new Span <byte>(new byte[expectedBytes.Length]);
                Assert.False(utf8.TryEncode(firstUtf16, encodedBytes, out charactersConsumed1, out bytesWritten1));
                Assert.True(utf8.TryEncode(secondUtf16.Slice(charactersConsumed1), encodedBytes.Slice(bytesWritten1), out charactersConsumed2, out bytesWritten2));
                break;

            case TextEncoderTestHelper.SupportedEncoding.FromString:         // Open issue: https://github.com/dotnet/corefxlab/issues/1515
                /*inputStringUtf16 = testEncoderUnicode.GetBytes(inputString2);
                 * expectedBytes = Text.Encoding.Convert(testEncoderUnicode, testEncoder, inputStringUtf16);
                 * string firstInputStr = inputString1;
                 * string secondInputStr = inputString2;
                 * encodedBytes = new Span<byte>(new byte[expectedBytes.Length]);
                 * Assert.False(utf8.TryEncode(firstInputStr, encodedBytes, out bytesWritten1));
                 * Assert.True(utf8.TryEncode(secondInputStr.Substring(charactersConsumed1), encodedBytes.Slice(bytesWritten1), out bytesWritten1));*/
                return;

            case TextEncoderTestHelper.SupportedEncoding.FromUtf32:
            default:
                expectedBytes = Text.Encoding.Convert(testEncoderUtf32, testEncoder, uint32Bytes2);
                ReadOnlySpan <uint> firstInput  = inputUtf32Bytes1.AsSpan();
                ReadOnlySpan <uint> secondInput = inputUtf32Bytes2.AsSpan();
                encodedBytes = new Span <byte>(new byte[TextEncoderTestHelper.GetUtf8ByteCount(inputUtf32Bytes2)]);
                Assert.False(utf8.TryEncode(firstInput, encodedBytes, out charactersConsumed1, out bytesWritten1));
                Assert.True(utf8.TryEncode(secondInput.Slice(charactersConsumed1), encodedBytes.Slice(bytesWritten1), out charactersConsumed2, out bytesWritten2));
                break;
            }

            Assert.Equal(TextEncoderConstants.DataLength * 2, charactersConsumed1 + charactersConsumed2);
            Assert.Equal(expectedBytes.Length, bytesWritten1 + bytesWritten2);
            Assert.True(expectedBytes.AsSpan().SequenceEqual(encodedBytes));
        }