internal void Write(BitWriter writer) { writer.StartCrcCalculation(); writer.WriteStringAscii(Version.VersionString(), nullTerminated: false); writer.WriteBytes(0, 0, 0, 0, 0); if (Version == DwgVersionId.R14) { writer.WriteByte((byte)MaintenenceVersion); } else { writer.WriteByte(0); } writer.WriteByte(1); writer.WriteInt(ImagePointer); writer.WriteBytes(0, 0); writer.WriteShort(CodePage); writer.WriteInt(5); // 5 records HeaderVariablesLocator.Write(writer); ClassSectionLocator.Write(writer); ObjectMapLocator.Write(writer); UnknownSection_R13C3AndLaterLocator.Write(writer); UnknownSection_PaddingLocator.Write(writer); writer.WriteCrc(xorValue: 0x3CC4); // value for 5 records writer.WriteBytes(HeaderSentinel); }
internal void Write(BitWriter writer, int offsetAdjustment) { var startOffset = writer.Position; writer.WriteBytes(StartSentinel); var imageCount = 0; if (HeaderData?.Length > 0) { imageCount++; } if (BmpData?.Length > 0) { imageCount++; } if (WmfData?.Length > 0) { imageCount++; } var imageControlByteCount = imageCount * (1 + 4 + 4) + // each set of data writes a byte and two ints 1; // `imageCount` below var overallSize = imageControlByteCount + (HeaderData?.Length ?? 0) + (BmpData?.Length ?? 0) + (WmfData?.Length ?? 0); writer.Write_RL(overallSize); writer.Write_RC((byte)imageCount); if (HeaderData?.Length > 0) { writer.Write_RC(1); writer.Write_RL(writer.Position - startOffset + offsetAdjustment); // start writer.Write_RL(HeaderData.Length); } if (BmpData?.Length > 0) { writer.Write_RC(2); writer.Write_RL(writer.Position - startOffset + offsetAdjustment); // start writer.Write_RL(BmpData.Length); } if (WmfData?.Length > 0) { writer.Write_RC(3); writer.Write_RL(writer.Position - startOffset + offsetAdjustment); // start writer.Write_RL(WmfData.Length); } writer.WriteBytes(EndSentinel); }
internal void WriteSecondHeader(BitWriter writer, int id) { // compute the minimum number of bytes necessary to encode the handle var handleBytes = BitConverter.GetBytes(HandleOrOffset); if (BitConverter.IsLittleEndian) { Array.Reverse(handleBytes); } var bytesList = new List <byte>(handleBytes); while (bytesList.Count > 0 && bytesList[0] == 0) { bytesList.RemoveAt(0); } if (bytesList.Count == 0) { // ensure there's a least one byte bytesList.Add(0); } writer.Write_RC((byte)bytesList.Count); writer.Write_RC((byte)id); writer.WriteBytes(bytesList.ToArray()); }
public void Save(Stream stream) { var objectMap = new DwgObjectMap(); AssignHandles(objectMap); // write the file header; this will be re-written again once the pointers have been calculated var writer = new BitWriter(stream); var fileHeaderLocation = writer.Position; FileHeader.Write(writer); var variablesStart = writer.Position; Variables.Write(writer, FileHeader.Version); FileHeader.HeaderVariablesLocator = DwgFileHeader.DwgSectionLocator.HeaderVariablesLocator(variablesStart - fileHeaderLocation, writer.Position - variablesStart); var classesStart = writer.Position; DwgClasses.Write(Classes, writer); FileHeader.ClassSectionLocator = DwgFileHeader.DwgSectionLocator.ClassSectionLocator(classesStart - fileHeaderLocation, writer.Position - classesStart); var paddingStart = writer.Position; writer.WriteBytes(new byte[0x200]); // may contain the MEASUREMENT variable as the first 4 bytes, but not required FileHeader.UnknownSection_PaddingLocator = DwgFileHeader.DwgSectionLocator.UnknownSection_PaddingLocator(paddingStart - fileHeaderLocation, writer.Position - paddingStart); var objectDataStart = writer.Position; SaveObjects(writer, objectMap, objectDataStart); var objectMapStart = writer.Position; objectMap.Write(writer); FileHeader.ObjectMapLocator = DwgFileHeader.DwgSectionLocator.ObjectMapLocator(objectMapStart - fileHeaderLocation, writer.Position - objectMapStart); var unknownR13C3Start = writer.Position; DwgUnknownSectionR13C3.Write(writer); FileHeader.UnknownSection_R13C3AndLaterLocator = DwgFileHeader.DwgSectionLocator.UnknownSection_R13C3AndLaterLocator(unknownR13C3Start - fileHeaderLocation, writer.Position - unknownR13C3Start); var secondHeaderStart = writer.Position; FileHeader.WriteSecondHeader(writer, Variables, secondHeaderStart - fileHeaderLocation); var imageDataStart = writer.Position; ImageData.Write(writer, imageDataStart - fileHeaderLocation); FileHeader.ImagePointer = imageDataStart - fileHeaderLocation; // re-write the file header now that the pointer values have been set var endPos = writer.Position; writer.BaseStream.Seek(fileHeaderLocation, SeekOrigin.Begin); FileHeader.Write(writer); writer.BaseStream.Seek(endPos, SeekOrigin.Begin); }
internal void Write(BitWriter writer, DwgVersionId version) { writer.AlignByte(); using (var ms = new MemoryStream()) { // write the variables to memory var variableWriter = new BitWriter(ms); WriteVariables(variableWriter, version); var variableBytes = variableWriter.AsBytes(); // now write it all out writer.WriteBytes(StartSentinel); writer.StartCrcCalculation(initialValue: InitialCrcValue); writer.Write_RL(variableBytes.Length); writer.WriteBytes(variableBytes); writer.WriteCrc(); writer.WriteBytes(EndSentinel); } }
private const int MaxSectionSizeBuffer = 10; // the maximum size of 2 MC values public void Write(BitWriter writer) { void WriteSection(byte[] data) { writer.StartCrcCalculation(initialValue: DwgHeaderVariables.InitialCrcValue); writer.WriteShortBigEndian((short)(data.Length + 2)); // account for crc writer.WriteBytes(data); writer.WriteCrc(writeCrcAsMsb: true); } // write in sections, each section is at most 2032 bytes, stop writing if remaining space is less than 10 var sectionStart = writer.Position; var lastHandle = 0; var lastLocation = 0; var ms = new MemoryStream(); var sectionWriter = new BitWriter(ms); foreach (var kvp in _handleOffsets.OrderBy(k => k.Key)) { var sectionSize = writer.Position - sectionStart; if (sectionSize >= MaxSectionSize - MaxSectionSizeBuffer) { // flush section var sectionBytes = sectionWriter.AsBytes(); WriteSection(sectionBytes); ms.Dispose(); ms = new MemoryStream(); sectionWriter = new BitWriter(ms); sectionStart = writer.Position; } // now write the values var handleDiff = kvp.Key - lastHandle; var locationDiff = kvp.Value - lastLocation; sectionWriter.Write_MC(handleDiff); sectionWriter.Write_MC(locationDiff); lastHandle = kvp.Key; lastLocation = kvp.Value; } // flush the final section var finalBytes = sectionWriter.AsBytes(); if (finalBytes.Length > 0) { WriteSection(finalBytes); } ms.Dispose(); // always finish with an empty section WriteSection(new byte[0]); }
internal static void Write(IList <DwgClassDefinition> classes, BitWriter writer) { writer.AlignByte(); using (var ms = new MemoryStream()) { // write the classes to memory var classWriter = new BitWriter(ms); foreach (var c in classes) { c.Write(classWriter); } var classBytes = classWriter.AsBytes(); // now write it all out writer.WriteBytes(StartSentinel); writer.StartCrcCalculation(initialValue: DwgHeaderVariables.InitialCrcValue); writer.Write_RL(classBytes.Length); writer.WriteBytes(classBytes); writer.WriteCrc(); writer.WriteBytes(EndSentinel); } }
public static BitWriter Write_H(this BitWriter writer, DwgHandleReference handle) { var bytes = new Stack <byte>(); var offset = handle.HandleOrOffset; while (offset != 0) { bytes.Push((byte)(offset & 0xFF)); offset >>= 8; } var header = (((int)handle.Code) << 4) | (bytes.Count & 0x0F); writer.WriteByte((byte)header); writer.WriteBytes(bytes); return(writer); }
public static BitWriter Write_Bytes(this BitWriter writer, byte[] data) { writer.WriteBytes(data); return(writer); }
internal void WriteSecondHeader(BitWriter writer, DwgHeaderVariables headerVariables, int pointer) { // write to memory the backtrack to fill in size and crc using (var ms = new MemoryStream()) { var tempWriter = new BitWriter(ms); tempWriter.WriteBytes(SecondHeaderStartSentinel); var sizeOffset = tempWriter.Position; tempWriter.Write_RL(0); // size, filled in later tempWriter.Write_BL(pointer); tempWriter.WriteStringAscii(Version.VersionString(), nullTerminated: false); tempWriter.WriteBytes(new byte[] { 0, 0, 0, 0, 0, 0 }); // 6 zero bytes tempWriter.WriteBits(0x00000000, 4); // 4 zero bits tempWriter.WriteBytes(new byte[] { 0, 0 }); // 2 unknown bytes tempWriter.WriteBytes(SecondHeaderMidSentinel); tempWriter.WriteByte(5); // record locator count HeaderVariablesLocator.Write(tempWriter, writingSecondHeader: true); ClassSectionLocator.Write(tempWriter, writingSecondHeader: true); ObjectMapLocator.Write(tempWriter, writingSecondHeader: true); UnknownSection_R13C3AndLaterLocator.Write(tempWriter, writingSecondHeader: true); UnknownSection_PaddingLocator.Write(tempWriter, writingSecondHeader: true); tempWriter.Write_BS(14); headerVariables.NextAvailableHandle.WriteSecondHeader(tempWriter, 0); headerVariables.BlockControlObjectHandle.WriteSecondHeader(tempWriter, 1); headerVariables.LayerControlObjectHandle.WriteSecondHeader(tempWriter, 2); headerVariables.StyleObjectControlHandle.WriteSecondHeader(tempWriter, 3); headerVariables.LineTypeObjectControlHandle.WriteSecondHeader(tempWriter, 4); headerVariables.ViewControlObjectHandle.WriteSecondHeader(tempWriter, 5); headerVariables.UcsControlObjectHandle.WriteSecondHeader(tempWriter, 6); headerVariables.ViewPortControlObjectHandle.WriteSecondHeader(tempWriter, 7); headerVariables.AppIdControlObjectHandle.WriteSecondHeader(tempWriter, 8); headerVariables.DimStyleControlObjectHandle.WriteSecondHeader(tempWriter, 9); headerVariables.ViewPortEntityHeaderControlObjectHandle.WriteSecondHeader(tempWriter, 10); headerVariables.NamedObjectsDictionaryHandle.WriteSecondHeader(tempWriter, 11); headerVariables.MLineStyleDictionaryHandle.WriteSecondHeader(tempWriter, 12); headerVariables.GroupDictionaryHandle.WriteSecondHeader(tempWriter, 13); tempWriter.WriteByte(0); // unknown tempWriter.AlignByte(); var crcOffset = tempWriter.Position; tempWriter.WriteShort(0); // CRC, filled in later if (Version == DwgVersionId.R14) { // unknown garbage bytes tempWriter.WriteBytes(new byte[] { 0, 0, 0, 0, 0, 0, 0, 0 }); } tempWriter.WriteBytes(SecondHeaderEndSentinel); // get bytes of header var secondHeaderBytes = tempWriter.AsBytes(); // fill in size var sizeBytes = BitConverter.GetBytes(secondHeaderBytes.Length - SecondHeaderStartSentinel.Length - SecondHeaderEndSentinel.Length); if (!BitConverter.IsLittleEndian) { Array.Reverse(sizeBytes); } Array.Copy(sizeBytes, 0, secondHeaderBytes, sizeOffset, sizeBytes.Length); // fill in crc var crc = BitReaderExtensions.ComputeCRC(secondHeaderBytes, sizeOffset, crcOffset - sizeOffset, DwgHeaderVariables.InitialCrcValue); var crcBytes = BitConverter.GetBytes(crc); if (!BitConverter.IsLittleEndian) { Array.Reverse(crcBytes); } Array.Copy(crcBytes, 0, secondHeaderBytes, crcOffset, crcBytes.Length); // write to the real writer writer.WriteBytes(secondHeaderBytes); } }