/// <summary> /// Writes a PCB component footprint. /// </summary> /// <param name="footprint"> /// Component footsprint to be serialized. /// </param> private void WriteFootprint(PcbComponent component) { var sectionKey = GetSectionKeyFromComponentPattern(component.Pattern); var footprintStorage = Cf.RootStorage.GetOrAddStorage(sectionKey); var primitives = component.Primitives.Where(p => !(p is PcbUnknown)); WriteHeader(footprintStorage, primitives.Count()); // record count WriteFootprintParameters(footprintStorage, component); WriteWideStrings(footprintStorage, component); footprintStorage.GetOrAddStream("Data").Write(writer => { WriteStringBlock(writer, component.Pattern); foreach (var primitive in primitives) { writer.Write((byte)primitive.ObjectId); switch (primitive) { case PcbArc arc: WriteFootprintArc(writer, arc); break; case PcbPad pad: WriteFootprintPad(writer, pad); break; case PcbVia via: WriteFootprintVia(writer, via); break; case PcbTrack track: WriteFootprintTrack(writer, track); break; case PcbText text: WriteFootprintText(writer, text); break; case PcbFill fill: WriteFootprintFill(writer, fill); break; case PcbRegion region: WriteFootprintRegion(writer, region); break; case PcbComponentBody body: WriteFootprintComponentBody(writer, body); break; default: break; } } }); WriteUniqueIdPrimitiveInformation(footprintStorage, component); }
/// <summary> /// Writes the component parameter information. /// </summary> /// <param name="componentStorage">Component footprint storage key.</param> /// <param name="component">Component instance to have its parameters serialized.</param> private void WriteFootprintParameters(CFStorage componentStorage, PcbComponent component) { var parameters = component.ExportToParameters(); componentStorage.GetOrAddStream("Parameters").Write(writer => { WriteBlock(writer, w => WriteParameters(w, parameters)); }); }
/// <summary> /// Reads the component parameter information. /// </summary> /// <param name="componentStorage">Component footprint storage key.</param> /// <param name="component">Component instance where the parameters will be imported into.</param> private void ReadFootprintParameters(CFStorage componentStorage, PcbComponent component) { BeginContext("Parameters"); try { using (var reader = componentStorage.GetStream("Parameters").GetBinaryReader()) { var parameters = ReadBlock(reader, size => ReadParameters(reader, size)); component.ImportFromParameters(parameters); } } finally { EndContext(); } }
private void ReadUniqueIdPrimitiveInformation(CFStorage componentStorage, PcbComponent component) { if (!componentStorage.TryGetStorage("UniqueIdPrimitiveInformation", out var uniqueIdPrimitiveInformation)) { return; } BeginContext("UniqueIdPrimitiveInformation"); try { var recordCount = ReadHeader(uniqueIdPrimitiveInformation); using (var reader = uniqueIdPrimitiveInformation.GetStream("Data").GetBinaryReader()) { uint actualRecordCount = 0; while (reader.BaseStream.Position < reader.BaseStream.Length) { var parameters = ReadBlock(reader, size => ReadParameters(reader, size)); var primitiveIndex = parameters["PRIMITIVEINDEX"].AsIntOrDefault(); var primitiveObjectId = parameters["PRIMITIVEOBJECTID"].AsStringOrDefault(); var uniqueId = parameters["UNIQUEID"].AsStringOrDefault(); if (!CheckValue("PRIMITIVEINDEX < Primitives.Count", primitiveIndex < component.Primitives.Count, true)) { return; } var primitive = component.Primitives[primitiveIndex]; if (!CheckValue(nameof(primitiveObjectId), primitiveObjectId, primitive.ObjectId.ToString())) { return; } primitive.UniqueId = uniqueId; actualRecordCount++; } AssertValue(nameof(actualRecordCount), actualRecordCount, recordCount); } } finally { EndContext(); } }
/// <summary> /// Writes a list of strings from the <paramref name="component"/> to the "WideStrings" /// stream inside of the specified <paramref name="storage"/> key. /// <para> /// Each string entry is encoded inside a parameter string value with a comma separated /// list of integers that represent UTF-16 code-points. /// </para> /// <para> /// These strings are used as Unicode variants of the texts existing in text string /// binary records. /// </para> /// </summary> /// <param name="storage"> /// Storage key where to write to "WideStrings" stream. /// </param> /// <param name="component"> /// Component to have its list of strings serialized. /// </param> internal static void WriteWideStrings(CFStorage storage, PcbComponent component) { var texts = component.Primitives.OfType <PcbText>().ToList(); storage.GetOrAddStream("WideStrings").Write(writer => { var parameters = new ParameterCollection(); for (var i = 0; i < texts.Count; ++i) { var text = texts[i]; text.WideStringsIndex = i; var data = text.Text ?? ""; var codepoints = data.Select(c => Convert.ToInt32(c)); var intList = string.Join(",", codepoints); parameters.Add($"ENCODEDTEXT{i}", intList); } WriteBlock(writer, w => WriteParameters(w, parameters)); }); }
private static void WriteUniqueIdPrimitiveInformation(CFStorage componentStorage, PcbComponent component) { var uniqueIdPrimitiveInformation = componentStorage.GetOrAddStorage("UniqueIdPrimitiveInformation"); var primitives = component.Primitives.Where(p => !(p is PcbUnknown)).ToList(); WriteHeader(uniqueIdPrimitiveInformation, primitives.Count); uniqueIdPrimitiveInformation.GetOrAddStream("Data").Write(writer => { for (int i = 0; i < primitives.Count; ++i) { var primitive = primitives[i]; var parameters = new ParameterCollection { { "PRIMITIVEINDEX", i }, { "PRIMITIVEOBJECTID", primitive.ObjectId.ToString() }, { "UNIQUEID", primitive.UniqueId } }; WriteBlock(writer, w => WriteParameters(w, 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); }