public static DwgDrawing Load(byte[] data) { var reader = new BitReader(data); var drawing = new DwgDrawing(); drawing.FileHeader = DwgFileHeader.Parse(reader); drawing.Variables = DwgHeaderVariables.Parse(reader.FromOffset(drawing.FileHeader.HeaderVariablesLocator.Pointer), drawing.FileHeader.Version); drawing.Classes = DwgClasses.Parse(reader.FromOffset(drawing.FileHeader.ClassSectionLocator.Pointer), drawing.FileHeader.Version); // don't read the R13C3 and later unknown section drawing.FileHeader.ValidateSecondHeader(reader, drawing.Variables); drawing.ImageData = DwgImageData.Parse(reader.FromOffset(drawing.FileHeader.ImagePointer)); var objectCache = DwgObjectCache.Parse(reader.FromOffset(drawing.FileHeader.ObjectMapLocator.Pointer), drawing.FileHeader.Version); drawing.LoadObjects(reader, objectCache); return(drawing); }
internal static DwgHeaderVariables Parse(BitReader reader, DwgVersionId version) { var header = new DwgHeaderVariables(); reader.ValidateSentinel(StartSentinel); reader.StartCrcCheck(); var size = reader.Read_RL(); var startOffset = reader.Offset; header.ReadVariables(reader, version); reader.AlignToByte(); var unreadByteCount = Math.Max(startOffset + size - reader.Offset, 0); var unreadBytes = reader.ReadBytes(unreadByteCount); reader.ValidateCrc(initialValue: InitialCrcValue); reader.ValidateSentinel(EndSentinel); return(header); }
public DwgDrawing() { FileHeader = new DwgFileHeader(DwgVersionId.Default, 0, 0, 0); Variables = new DwgHeaderVariables(); Classes = new List <DwgClassDefinition>(); var continuous = new DwgLineType("CONTINUOUS") { Description = "Solid line" }; var defaultLayer = new DwgLayer("0") { LineType = continuous }; var standardStyle = new DwgStyle("STANDARD"); var standardMLineStyle = DwgMLineStyle.GetDefaultMLineStyle(); BlockHeaders = new DwgBlockControlObject() { DwgBlockHeader.GetPaperSpaceBlockRecord(defaultLayer), DwgBlockHeader.GetModelSpaceBlockRecord(defaultLayer) }; Layers = new DwgLayerControlObject { defaultLayer }; Styles = new DwgStyleControlObject() { standardStyle }; LineTypes = new DwgLineTypeControlObject() { new DwgLineType("BYLAYER"), new DwgLineType("BYBLOCK"), continuous }; Views = new DwgViewControlObject(); UCSs = new DwgUCSControlObject(); ViewPorts = new DwgViewPortControlObject() { DwgViewPort.GetActiveViewPort() }; AppIds = new DwgAppIdControlObject() { DwgAppId.GetAcadAppId(), DwgAppId.GetAcadMLeaderVersionAppId() }; DimStyles = new DwgDimStyleControlObject() { DwgDimStyle.GetStandardDimStyle(standardStyle) }; ViewPortEntityHeaders = new DwgViewPortEntityHeaderControlObject(); GroupDictionary = new DwgDictionary(); MLineStyleDictionary = new DwgDictionary() { { standardMLineStyle.Name, standardMLineStyle } }; NamedObjectDictionary = new DwgDictionary(); PaperSpaceBlockRecord = BlockHeaders["*PAPER_SPACE"]; ModelSpaceBlockRecord = BlockHeaders["*MODEL_SPACE"]; ByLayerLineType = LineTypes["BYLAYER"]; ByBlockLineType = LineTypes["BYBLOCK"]; ContinuousLineType = LineTypes["CONTINUOUS"]; CurrentLayer = Layers["0"]; TextStyle = Styles["STANDARD"]; CurrentEntityLineType = LineTypes["BYBLOCK"]; DimensionStyle = DimStyles["STANDARD"]; CurrentMultiLineStyle = (DwgMLineStyle)MLineStyleDictionary["Standard"]; DimensionTextStyle = Styles["STANDARD"]; }
public void SetNextAvailableHandle(DwgHeaderVariables variables) { var next = _nextHandle++; variables.NextAvailableHandle = new DwgHandleReference(DwgHandleReferenceCode.Declaration, next); }
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); } }
internal void ValidateSecondHeader(BitReader parentReader, DwgHeaderVariables headerVariables) { var reader = parentReader.FromOffset(SecondHeaderPointer); reader.ValidateSentinel(SecondHeaderStartSentinel); var sectionStart = reader.Offset; reader.StartCrcCheck(); var reportedSectionSize = reader.Read_RL(); var expectedLocation = reader.Read_BL(); if (expectedLocation != sectionStart - SecondHeaderStartSentinel.Length) { throw new DwgReadException("Reported second header location incorrect."); } var version = DwgVersionIdExtensions.VersionIdFromString(reader.ReadStringAscii(6)); if (version != Version) { throw new DwgReadException("Inconsistent reported version."); } reader.ReadBytes(6); reader.Read_B(); reader.Read_B(); reader.Read_B(); reader.Read_B(); reader.ReadBytes(2); reader.ValidateBytes(SecondHeaderMidSentinel); var recordLocatorCount = reader.ReadByte(); for (int i = 0; i < recordLocatorCount; i++) { var id = reader.ReadByte(); var pointer = reader.Read_BL(); var length = reader.Read_BL(); if (pointer != 0) { switch (i) { case 0: HeaderVariablesLocator.ValidateLocator(id, pointer, length); break; case 1: ClassSectionLocator.ValidateLocator(id, pointer, length); break; case 2: ObjectMapLocator.ValidateLocator(id, pointer, length); break; case 3: UnknownSection_R13C3AndLaterLocator.ValidateLocator(id, pointer, length); break; case 4: UnknownSection_PaddingLocator.ValidateLocator(id, pointer, length); break; } } } var handleRecordCount = reader.Read_BS(); for (int i = 0; i < handleRecordCount; i++) { var byteCount = reader.Read_RC(); var id = reader.Read_RC(); var handle = DwgHandleReference.ReadSecondHeader(reader, byteCount); if (byteCount > 0) { if (id != i) { throw new DwgReadException("Invalid record handle ID."); } var actualHandle = -1; switch (i) { case 0: actualHandle = headerVariables.NextAvailableHandle.HandleOrOffset; break; case 1: actualHandle = headerVariables.BlockControlObjectHandle.HandleOrOffset; break; case 2: actualHandle = headerVariables.LayerControlObjectHandle.HandleOrOffset; break; case 3: actualHandle = headerVariables.StyleObjectControlHandle.HandleOrOffset; break; case 4: actualHandle = headerVariables.LineTypeObjectControlHandle.HandleOrOffset; break; case 5: actualHandle = headerVariables.ViewControlObjectHandle.HandleOrOffset; break; case 6: actualHandle = headerVariables.UcsControlObjectHandle.HandleOrOffset; break; case 7: actualHandle = headerVariables.ViewPortControlObjectHandle.HandleOrOffset; break; case 8: actualHandle = headerVariables.AppIdControlObjectHandle.HandleOrOffset; break; case 9: actualHandle = headerVariables.DimStyleControlObjectHandle.HandleOrOffset; break; case 10: actualHandle = headerVariables.ViewPortEntityHeaderControlObjectHandle.HandleOrOffset; break; case 11: actualHandle = headerVariables.NamedObjectsDictionaryHandle.HandleOrOffset; break; case 12: actualHandle = headerVariables.MLineStyleDictionaryHandle.HandleOrOffset; break; case 13: actualHandle = headerVariables.GroupDictionaryHandle.HandleOrOffset; break; } if (actualHandle > 0) { if (handle != actualHandle) { throw new DwgReadException($"Invalid record handle ID at location {i}. Expected: {handle}, Actual: {actualHandle}"); } } } } reader.ReadByte(); reader.ValidateCrc(initialValue: DwgHeaderVariables.InitialCrcValue); var junkByteCount = Math.Max(0, reportedSectionSize - (reader.Offset - sectionStart)); reader.SkipBytes(junkByteCount); reader.ValidateSentinel(SecondHeaderEndSentinel); var computedSectionSize = reader.Offset - sectionStart - SecondHeaderEndSentinel.Length; if (computedSectionSize != reportedSectionSize) { throw new DwgReadException($"Reported and actual second header sizes differ. Expected: {reportedSectionSize}, Actual: {computedSectionSize}"); } }