private static void WriteFootprintCommon(BinaryWriter writer, PcbPrimitive primitive, CoordPoint?location = null)
 {
     writer.Write(primitive.Layer.ToByte());
     writer.Write((ushort)primitive.Flags);
     writer.Write(Enumerable.Repeat((byte)0xff, 10).ToArray());
     if (location != null)
     {
         WriteCoordPoint(writer, location.Value);
     }
 }
 private void WriteFootprintCommonParametersAndOutline(BinaryWriter writer, PcbPrimitive primitive,
                                                       ParameterCollection parameters, IList <CoordPoint> outline)
 {
     WriteBlock(writer, w =>
     {
         WriteFootprintCommon(w, primitive);
         w.Write(0);       // TODO: Unknown
         w.Write((byte)0); // TODO: Unknown
         WriteBlock(w, wb => WriteParameters(wb, parameters));
         w.Write(outline.Count);
         foreach (var coord in outline)
         {
             // oddly enough polygonal features are stored using double precision
             // but still employ the same units as standard Coords, which means
             // the extra precision is not needed
             w.Write((double)coord.X.ToInt32());
             w.Write((double)coord.Y.ToInt32());
         }
     });
 }
        private ParameterCollection ReadFootprintCommonParametersAndOutline(BinaryReader reader, PcbPrimitive primitive,
                                                                            List <CoordPoint> outline)
        {
            ParameterCollection parameters = null;

            ReadBlock(reader, recordSize =>
            {
                ReadFootprintCommon(reader, primitive);
                reader.ReadUInt32(); // TODO: Unknown
                reader.ReadByte();   // TODO: Unknown
                parameters      = ReadBlock(reader, size => ReadParameters(reader, size));
                var outlineSize = reader.ReadUInt32();
                for (int i = 0; i < outlineSize; ++i)
                {
                    // oddly enough polygonal features are stored using double precision
                    // but still employ the same units as standard Coords, which means
                    // the extra precision is not needed
                    Coord x = (int)reader.ReadDouble();
                    Coord y = (int)reader.ReadDouble();
                    outline.Add(new CoordPoint(x, y));
                }
            });
            return(parameters);
        }
        /// <summary>
        /// Reads a PCB component footprint stored in the given <paramref name="sectionKey"/>,
        /// </summary>
        /// <param name="sectionKey">
        /// Section storage key where to look for the component footprint parameters and data.
        /// </param>
        /// <returns></returns>
        private PcbComponent ReadFootprint(string sectionKey)
        {
            var footprintStorage = Cf.TryGetStorage(sectionKey) ?? throw new ArgumentException($"Footprint resource not found: {sectionKey}");

            BeginContext(sectionKey);

            var recordCount = ReadHeader(footprintStorage);

            var component = new PcbComponent();

            ReadFootprintParameters(footprintStorage, component);

            var wideStrings = ReadWideStrings(footprintStorage);

            using (var reader = footprintStorage.GetStream("Data").GetBinaryReader())
            {
                AssertValue(nameof(component.Pattern), component.Pattern, ReadStringBlock(reader));

                int ndxRecord = 0;
                while (reader.BaseStream.Position < reader.BaseStream.Length)
                {
                    if (ndxRecord > recordCount)
                    {
                        EmitWarning("Number of existing records exceed the header's record count");
                    }

                    // save the stream position so we can later recover the raw component data
                    var primitiveStartPosition = reader.BaseStream.Position;

                    PcbPrimitive element  = null;
                    var          objectId = (PcbPrimitiveObjectId)reader.ReadByte();
                    BeginContext(objectId.ToString());
                    switch (objectId)
                    {
                    case PcbPrimitiveObjectId.Arc:
                        element = ReadFootprintArc(reader);
                        break;

                    case PcbPrimitiveObjectId.Pad:
                        element = ReadFootprintPad(reader);
                        break;

                    case PcbPrimitiveObjectId.Via:
                        element = ReadFootprintVia(reader);
                        break;

                    case PcbPrimitiveObjectId.Track:
                        element = ReadFootprintTrack(reader);
                        break;

                    case PcbPrimitiveObjectId.Text:
                        element = ReadFootprintString(reader, wideStrings);
                        break;

                    case PcbPrimitiveObjectId.Fill:
                        element = ReadFootprintFill(reader);
                        break;

                    case PcbPrimitiveObjectId.Region:
                        element = ReadFootprintRegion(reader);
                        break;

                    case PcbPrimitiveObjectId.ComponentBody:
                        element = ReadFootprintComponentBody(reader);
                        break;

                    default:
                        // otherwise we attempt to skip the actual primitive data but still
                        // create a basic instance with just the raw data for debugging
                        element = ReadFootprintUknown(reader, objectId);
                        break;
                    }

                    element.SetRawData(ExtractStreamData(reader, primitiveStartPosition, reader.BaseStream.Position));

                    component.Primitives.Add(element);

                    EndContext();
                    ndxRecord++;
                }
            }

            ReadUniqueIdPrimitiveInformation(footprintStorage, component);

            EndContext();

            return(component);
        }
 private void ReadFootprintCommon(BinaryReader reader, PcbPrimitive primitive)
 {
     primitive.Layer = reader.ReadByte();
     primitive.Flags = (PcbFlags)reader.ReadUInt16();
     Assert10FFbytes(reader);
 }