예제 #1
0
        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);
        }
예제 #2
0
        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);
        }
예제 #3
0
        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());
        }
예제 #4
0
        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);
        }
예제 #5
0
        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);
            }
        }
예제 #6
0
        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]);
        }
예제 #7
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);
            }
        }
예제 #8
0
        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);
        }
예제 #9
0
 public static BitWriter Write_Bytes(this BitWriter writer, byte[] data)
 {
     writer.WriteBytes(data);
     return(writer);
 }
예제 #10
0
        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);
            }
        }