internal DictionaryObject(DxfObject owner) : base(DxfObjectCode.Dictionary) { this.isHardOwner = false; this.cloning = DictionaryCloningFlags.KeepExisting; this.entries = new Dictionary<string, string>(); this.Owner = owner; }
/// <summary> /// Initializes a new instance of the <c>ImageDef</c> class. /// </summary> /// <param name="fileName">Image file name with full or relative path.</param> /// <param name="name">Image definition name, if null or empty the file name without the extension will be used.</param> /// <remarks> /// <para> /// The name assigned to the image definition must be unique. /// </para> /// <para> /// Supported image formats: BMP, JPG, PNG, TIFF.<br /> /// Even thought AutoCAD supports more image formats, this constructor is restricted to the ones the .net library supports in common with AutoCAD. /// Use the generic constructor instead. /// </para> /// <para> /// Note (this is from the ACAD docs): AutoCAD 2000, AutoCAD LT 2000, and later releases do not support LZW-compressed TIFF files, /// with the exception of English language versions sold in the US and Canada.<br /> /// If you have TIFF files that were created using LZW compression and want to insert them into a drawing /// you must save the TIFF files with LZW compression disabled. /// </para> /// </remarks> public ImageDef(string fileName, string name) : base(name, DxfObjectCode.ImageDef, true) { if (string.IsNullOrEmpty(fileName)) throw new ArgumentNullException("fileName", "The image file name cannot be null or empty."); FileInfo info = new FileInfo(fileName); if (!info.Exists) throw new FileNotFoundException("Image file not found", fileName); this.fileName = fileName; try { using (Image bitmap = Image.FromFile(fileName)) { this.width = bitmap.Width; this.height = bitmap.Height; this.horizontalResolution = bitmap.HorizontalResolution; this.verticalResolution = bitmap.VerticalResolution; // the System.Drawing.Image stores the image resolution in inches this.resolutionUnits = ImageResolutionUnits.Inches; } } catch (Exception) { throw new ArgumentException("Image file not supported.", fileName); } this.reactors = new Dictionary<string, ImageDefReactor>(); }
/// <summary> /// Initializes a new instance of the <c>ImageDef</c> class. /// </summary> /// <param name="fileName">Image file name with full or relative path.</param> /// <param name="name">Image definition name, if null or empty the file name without the extension will be used.</param> /// <param name="width">Image width in pixels.</param> /// <param name="horizontalResolution">Image horizontal resolution in pixels.</param> /// <param name="height">Image height in pixels.</param> /// <param name="verticalResolution">Image vertical resolution in pixels.</param> /// <param name="units">Image resolution units.</param> /// <remarks> /// <para> /// The name assigned to the image definition must be unique. /// </para> /// <para> /// This is a generic constructor for all image formats supported by AutoCAD, note that not all AutoCAD versions support the same image formats. /// </para> /// <para> /// Note (this is from the ACAD docs): AutoCAD 2000, AutoCAD LT 2000, and later releases do not support LZW-compressed TIFF files, /// with the exception of English language versions sold in the US and Canada.<br /> /// If you have TIFF files that were created using LZW compression and want to insert them into a drawing /// you must save the TIFF files with LZW compression disabled. /// </para> /// </remarks> public ImageDef(string fileName, string name, int width, double horizontalResolution, int height, double verticalResolution, ImageResolutionUnits units) : base(name, DxfObjectCode.ImageDef, true) { if (string.IsNullOrEmpty(fileName)) throw new ArgumentNullException("fileName", "The image file name cannot be null or empty."); this.fileName = fileName; this.width = width; this.height = height; this.horizontalResolution = horizontalResolution; this.verticalResolution = verticalResolution; this.resolutionUnits = units; this.reactors = new Dictionary<string, ImageDefReactor>(); }
public void Write(Stream stream, DxfDocument document, bool binary) { this.doc = document; this.isBinary = binary; if (this.doc.DrawingVariables.AcadVer < DxfVersion.AutoCad2000) throw new NotSupportedException("Only AutoCad2000 and newer dxf versions are supported."); this.encodedStrings = new Dictionary<string, string>(); // create the default PaperSpace layout in case it does not exist. The ModelSpace layout always exists if (this.doc.Layouts.Count == 1) this.doc.Layouts.Add(new Layout("Layout1")); // create the application registry AcCmTransparency in case it doesn't exists, it is required by the layer and entity transparency this.doc.ApplicationRegistries.Add(new ApplicationRegistry("AcCmTransparency")); // create the application registry GradientColor1ACI and GradientColor2ACI in case they don't exists , they are required by the hatch gradient pattern this.doc.ApplicationRegistries.Add(new ApplicationRegistry("GradientColor1ACI")); this.doc.ApplicationRegistries.Add(new ApplicationRegistry("GradientColor2ACI")); // dictionaries List<DictionaryObject> dictionaries = new List<DictionaryObject>(); // Named dictionary it is always the first to appear in the object section DictionaryObject namedObjectDictionary = new DictionaryObject(this.doc); this.doc.NumHandles = namedObjectDictionary.AsignHandle(this.doc.NumHandles); dictionaries.Add(namedObjectDictionary); // create the Group dictionary, this dictionary always appear even if there are no groups in the drawing DictionaryObject groupDictionary = new DictionaryObject(namedObjectDictionary); this.doc.NumHandles = groupDictionary.AsignHandle(this.doc.NumHandles); foreach (Group group in this.doc.Groups.Items) { groupDictionary.Entries.Add(group.Handle, group.Name); } dictionaries.Add(groupDictionary); namedObjectDictionary.Entries.Add(groupDictionary.Handle, DxfObjectCode.GroupDictionary); // Layout dictionary DictionaryObject layoutDictionary = new DictionaryObject(namedObjectDictionary); this.doc.NumHandles = layoutDictionary.AsignHandle(this.doc.NumHandles); if (this.doc.Layouts.Count > 0) { foreach (Layout layout in this.doc.Layouts.Items) { layoutDictionary.Entries.Add(layout.Handle, layout.Name); } dictionaries.Add(layoutDictionary); namedObjectDictionary.Entries.Add(layoutDictionary.Handle, DxfObjectCode.LayoutDictionary); } // create the Underlay definitions dictionary DictionaryObject dgnDefinitionDictionary = new DictionaryObject(namedObjectDictionary); this.doc.NumHandles = dgnDefinitionDictionary.AsignHandle(this.doc.NumHandles); if (this.doc.UnderlayDgnDefinitions.Count > 0) { foreach (UnderlayDgnDefinition underlayDef in this.doc.UnderlayDgnDefinitions.Items) { dgnDefinitionDictionary.Entries.Add(underlayDef.Handle, underlayDef.Name); dictionaries.Add(dgnDefinitionDictionary); namedObjectDictionary.Entries.Add(dgnDefinitionDictionary.Handle, DxfObjectCode.UnderlayDgnDefinitionDictionary); } } DictionaryObject dwfDefinitionDictionary = new DictionaryObject(namedObjectDictionary); this.doc.NumHandles = dwfDefinitionDictionary.AsignHandle(this.doc.NumHandles); if (this.doc.UnderlayDwfDefinitions.Count > 0) { foreach (UnderlayDwfDefinition underlayDef in this.doc.UnderlayDwfDefinitions.Items) { dwfDefinitionDictionary.Entries.Add(underlayDef.Handle, underlayDef.Name); dictionaries.Add(dwfDefinitionDictionary); namedObjectDictionary.Entries.Add(dwfDefinitionDictionary.Handle, DxfObjectCode.UnderlayDwfDefinitionDictionary); } } DictionaryObject pdfDefinitionDictionary = new DictionaryObject(namedObjectDictionary); this.doc.NumHandles = pdfDefinitionDictionary.AsignHandle(this.doc.NumHandles); if (this.doc.UnderlayPdfDefinitions.Count > 0) { foreach (UnderlayPdfDefinition underlayDef in this.doc.UnderlayPdfDefinitions.Items) { pdfDefinitionDictionary.Entries.Add(underlayDef.Handle, underlayDef.Name); dictionaries.Add(pdfDefinitionDictionary); namedObjectDictionary.Entries.Add(pdfDefinitionDictionary.Handle, DxfObjectCode.UnderlayPdfDefinitionDictionary); } } // create the MLine style dictionary DictionaryObject mLineStyleDictionary = new DictionaryObject(namedObjectDictionary); this.doc.NumHandles = mLineStyleDictionary.AsignHandle(this.doc.NumHandles); if (this.doc.MlineStyles.Count > 0) { foreach (MLineStyle mLineStyle in this.doc.MlineStyles.Items) { mLineStyleDictionary.Entries.Add(mLineStyle.Handle, mLineStyle.Name); } dictionaries.Add(mLineStyleDictionary); namedObjectDictionary.Entries.Add(mLineStyleDictionary.Handle, DxfObjectCode.MLineStyleDictionary); } // create the image dictionary DictionaryObject imageDefDictionary = new DictionaryObject(namedObjectDictionary); this.doc.NumHandles = imageDefDictionary.AsignHandle(this.doc.NumHandles); if (this.doc.ImageDefinitions.Count > 0) { foreach (ImageDefinition imageDef in this.doc.ImageDefinitions.Items) { imageDefDictionary.Entries.Add(imageDef.Handle, imageDef.Name); } dictionaries.Add(imageDefDictionary); namedObjectDictionary.Entries.Add(imageDefDictionary.Handle, DxfObjectCode.ImageDefDictionary); namedObjectDictionary.Entries.Add(this.doc.RasterVariables.Handle, DxfObjectCode.ImageVarsDictionary); } this.doc.DrawingVariables.HandleSeed = this.doc.NumHandles.ToString("X"); this.Open(stream, this.doc.DrawingVariables.AcadVer < DxfVersion.AutoCad2007 ? Encoding.Default : null); // The comment group, 999, is not used in binary DXF files. if (!this.isBinary) { foreach (string comment in this.doc.Comments) this.WriteComment(comment); } //HEADER SECTION this.BeginSection(DxfObjectCode.HeaderSection); foreach (HeaderVariable variable in this.doc.DrawingVariables.Values) { this.WriteSystemVariable(variable); } // writing a copy of the active dimension style variables in the header section will avoid to be displayed as <style overrides> in AutoCad DimensionStyle activeDimStyle; if(this.doc.DimensionStyles.TryGetValue(this.doc.DrawingVariables.DimStyle, out activeDimStyle)) this.WriteActiveDimensionStyleSystemVaribles(activeDimStyle); this.EndSection(); //CLASSES SECTION this.BeginSection(DxfObjectCode.ClassesSection); this.WriteRasterVariablesClass(1); if (this.doc.ImageDefinitions.Items.Count > 0) { this.WriteImageDefClass(this.doc.ImageDefinitions.Count); this.WriteImageDefRectorClass(this.doc.Images.Count); this.WriteImageClass(this.doc.Images.Count); } this.EndSection(); //TABLES SECTION this.BeginSection(DxfObjectCode.TablesSection); //registered application tables this.BeginTable(this.doc.ApplicationRegistries.CodeName, (short) this.doc.ApplicationRegistries.Count, this.doc.ApplicationRegistries.Handle); foreach (ApplicationRegistry id in this.doc.ApplicationRegistries.Items) { this.WriteApplicationRegistry(id); } this.EndTable(); //viewport tables this.BeginTable(this.doc.VPorts.CodeName, (short) this.doc.VPorts.Count, this.doc.VPorts.Handle); foreach (VPort vport in this.doc.VPorts) { this.WriteVPort(vport); } this.EndTable(); //line type tables //The LTYPE table always precedes the LAYER table. I guess because the layers reference the line types, //why this same rule is not applied to DIMSTYLE tables is a mystery, since they also reference text styles and block records this.BeginTable(this.doc.LineTypes.CodeName, (short) this.doc.LineTypes.Count, this.doc.LineTypes.Handle); foreach (LineType lineType in this.doc.LineTypes.Items) { this.WriteLineType(lineType); } this.EndTable(); //layer tables this.BeginTable(this.doc.Layers.CodeName, (short) this.doc.Layers.Count, this.doc.Layers.Handle); foreach (Layer layer in this.doc.Layers.Items) { this.WriteLayer(layer); } this.EndTable(); //text style tables this.BeginTable(this.doc.TextStyles.CodeName, (short) this.doc.TextStyles.Count, this.doc.TextStyles.Handle); foreach (TextStyle style in this.doc.TextStyles.Items) { this.WriteTextStyle(style); } this.EndTable(); //dimension style tables this.BeginTable(this.doc.DimensionStyles.CodeName, (short) this.doc.DimensionStyles.Count, this.doc.DimensionStyles.Handle); foreach (DimensionStyle style in this.doc.DimensionStyles.Items) { this.WriteDimensionStyle(style); } this.EndTable(); //view this.BeginTable(this.doc.Views.CodeName, (short)this.doc.Views.Count, this.doc.Views.Handle); this.EndTable(); //UCS this.BeginTable(this.doc.UCSs.CodeName, (short) this.doc.UCSs.Count, this.doc.UCSs.Handle); foreach (UCS ucs in this.doc.UCSs.Items) { this.WriteUCS(ucs); } this.EndTable(); //block record table this.BeginTable(this.doc.Blocks.CodeName, (short) this.doc.Blocks.Count, this.doc.Blocks.Handle); foreach (Block block in this.doc.Blocks.Items) { this.WriteBlockRecord(block.Record); } this.EndTable(); this.EndSection(); //End section tables //BLOCKS SECTION this.BeginSection(DxfObjectCode.BlocksSection); foreach (Block block in this.doc.Blocks.Items) { Layout layout = null; if (block.Name.StartsWith(Block.DefaultPaperSpaceName)) { // the entities of the layouts associated with the blocks "*Paper_Space0", "*Paper_Space1",... are included in the Blocks Section string index = block.Name.Remove(0, 12); if (!string.IsNullOrEmpty(index)) { layout = block.Record.Layout; } } this.WriteBlock(block, layout); } this.EndSection(); //End section blocks //ENTITIES SECTION this.BeginSection(DxfObjectCode.EntitiesSection); foreach (Layout layout in this.doc.Layouts) { if (!layout.IsPaperSpace) { // ModelSpace List<DxfObject> entities = this.doc.Layouts.GetReferences(layout); foreach (DxfObject o in entities) { this.WriteEntity(o as EntityObject, layout); } } else if (layout.AssociatedBlock.Name.StartsWith(Block.DefaultPaperSpaceName)) { // only the entities of the layout associated with the block "*Paper_Space" are included in the Entities Section string index = layout.AssociatedBlock.Name.Remove(0, 12); if (string.IsNullOrEmpty(index)) { this.WriteEntity(layout.Viewport, layout); List<DxfObject> entities = this.doc.Layouts.GetReferences(layout); foreach (DxfObject o in entities) { this.WriteEntity(o as EntityObject, layout); } } } } this.EndSection(); //End section entities //OBJECTS SECTION this.BeginSection(DxfObjectCode.ObjectsSection); foreach (DictionaryObject dictionary in dictionaries) { this.WriteDictionary(dictionary); } foreach (Group group in this.doc.Groups.Items) { this.WriteGroup(group, groupDictionary.Handle); } foreach (Layout layout in this.doc.Layouts) { this.WriteLayout(layout, layoutDictionary.Handle); } foreach (MLineStyle style in this.doc.MlineStyles.Items) { this.WriteMLineStyle(style, mLineStyleDictionary.Handle); } foreach (UnderlayDgnDefinition underlayDef in this.doc.UnderlayDgnDefinitions.Items) { this.WriteUnderlayDefinition(underlayDef, dgnDefinitionDictionary.Handle); } foreach (UnderlayDwfDefinition underlayDef in this.doc.UnderlayDwfDefinitions.Items) { this.WriteUnderlayDefinition(underlayDef, dwfDefinitionDictionary.Handle); } foreach (UnderlayPdfDefinition underlayDef in this.doc.UnderlayPdfDefinitions.Items) { this.WriteUnderlayDefinition(underlayDef, pdfDefinitionDictionary.Handle); } // the raster variables dictionary is only needed when the drawing has image entities if (this.doc.ImageDefinitions.Count > 0) { this.WriteRasterVariables(this.doc.RasterVariables, imageDefDictionary.Handle); foreach (ImageDefinition imageDef in this.doc.ImageDefinitions.Items) { foreach (ImageDefinitionReactor reactor in imageDef.Reactors.Values) { this.WriteImageDefReactor(reactor); } this.WriteImageDef(imageDef, imageDefDictionary.Handle); } } this.EndSection(); //End section objects this.Close(); stream.Position = 0; }
public void WriteDictionary(Dictionary dictionary) { //if (this.activeTable != StringCode.ObjectsSection) //{ // throw new InvalidDxfTableException(this.activeTable, this.file); //} this.WriteCodePair(0, StringCode.Dictionary); this.WriteCodePair(5, Convert.ToString(10, 16)); this.WriteCodePair(100, SubclassMarker.Dictionary); this.WriteCodePair(281, 1); this.WriteCodePair(3, dictionary); this.WriteCodePair(350, Convert.ToString(11, 16)); this.WriteCodePair(0, StringCode.Dictionary); this.WriteCodePair(5, Convert.ToString(11, 16)); this.WriteCodePair(100, SubclassMarker.Dictionary); this.WriteCodePair(281, 1); }
private void WriteXData(Dictionary<ApplicationRegistry, XData> xData) { if (xData == null) return; foreach (ApplicationRegistry appReg in xData.Keys) { this.WriteCodePair(XDataCode.AppReg, appReg); foreach (XDataRecord x in xData[appReg].XDataRecord) { this.WriteCodePair(x.Code, x.Value.ToString()); } } }
/// <summary> /// Initializes a new instance of the <c>DxfDocument</c> class. /// </summary> /// <param name="drawingVariables"><see cref="HeaderVariables">Drawing variables</see> of the document.</param> /// <param name="createDefaultObjects">Check if the default objects need to be created.</param> internal DxfDocument(HeaderVariables drawingVariables, bool createDefaultObjects) : base("DOCUMENT") { this.comments = new List<string> {"Dxf file generated by netDxf https://netdxf.codeplex.com, Copyright(C) 2009-2016 Daniel Carvajal, Licensed under LGPL"}; this.Owner = null; this.drawingVariables = drawingVariables; this.NumHandles = this.AsignHandle(0); this.DimensionBlocksGenerated = 0; this.GroupNamesGenerated = 0; this.AddedObjects = new Dictionary<string, DxfObject> { {this.Handle, this} }; // keeps track of the added objects this.activeLayout = Layout.ModelSpaceName; // entities lists this.arcs = new List<Arc>(); this.ellipses = new List<Ellipse>(); this.dimensions = new List<Dimension>(); this.faces3d = new List<Face3d>(); this.solids = new List<Solid>(); this.traces = new List<Trace>(); this.inserts = new List<Insert>(); this.lwPolylines = new List<LwPolyline>(); this.polylines = new List<Polyline>(); this.polyfaceMeshes = new List<PolyfaceMesh>(); this.lines = new List<Line>(); this.circles = new List<Circle>(); this.points = new List<Point>(); this.texts = new List<Text>(); this.mTexts = new List<MText>(); this.hatches = new List<Hatch>(); this.splines = new List<Spline>(); this.images = new List<Image>(); this.mLines = new List<MLine>(); this.rays = new List<Ray>(); this.xlines = new List<XLine>(); this.viewports = new List<Viewport>(); this.meshes = new List<Mesh>(); this.leaders = new List<Leader>(); this.tolerances = new List<Tolerance>(); this.underlays = new List<Underlay>(); this.wipeouts = new List<Wipeout>(); this.attributeDefinitions = new List<AttributeDefinition>(); if (createDefaultObjects) this.AddDefaultObjects(); }
private void ReadBlocks() { Debug.Assert(this.chunk.ReadString() == DxfObjectCode.BlocksSection); // the blocks list will be added to the document after reading the blocks section to handle possible nested insert cases. Dictionary<string, Block> blocks = new Dictionary<string, Block>(StringComparer.OrdinalIgnoreCase); this.chunk.Next(); while (this.chunk.ReadString() != DxfObjectCode.EndSection) { switch (this.chunk.ReadString()) { case DxfObjectCode.BeginBlock: Block block = this.ReadBlock(); blocks.Add(block.Name, block); break; default: this.chunk.Next(); break; } } // post process the possible nested blocks, // in nested blocks (blocks that contains Insert entities) the block definition might be defined AFTER the insert that references them foreach (KeyValuePair<Insert, string> pair in this.nestedInserts) { Insert insert = pair.Key; insert.Block = blocks[pair.Value]; foreach (Attribute att in insert.Attributes) { // attribute definitions might be null if an INSERT entity attribute has not been defined in the block AttributeDefinition attDef; if (insert.Block.AttributeDefinitions.TryGetValue(att.Tag, out attDef)) att.Definition = attDef; att.Owner = insert; } // in the case the insert belongs to a *PaperSpace# the insert owner has not been assigned yet, // in this case the owner units are the document units and will be assigned at the end with the rest of the entities if (insert.Owner != null) { // apply the units scale to the insertion scale (this is for nested blocks) double scale = UnitHelper.ConversionFactor(insert.Owner.Record.Units, insert.Block.Record.Units); insert.Scale *= scale; } } foreach (KeyValuePair<Dimension, string> pair in this.nestedDimensions) { Dimension dim = pair.Key; dim.Block = blocks[pair.Value]; } // add the blocks to the document // the block entities will not be added to the document at this point // entities like MLine and Image require information that is defined AFTER the block section, // this is the case of the MLineStyle and ImageDefinition that are described in the objects section foreach (Block block in blocks.Values) this.doc.Blocks.Add(block, false); }
/// <summary> /// Reads the whole stream. /// </summary> /// <param name="stream">Stream.</param> public DxfDocument Read(Stream stream) { if (stream == null) throw new ArgumentNullException(nameof(stream)); string dwgcodepage = CheckHeaderVariable(stream, HeaderVariableCode.DwgCodePage, out this.isBinary); try { if (this.isBinary) { Encoding encoding; DxfVersion version = DxfDocument.CheckDxfFileVersion(stream, out this.isBinary); if (version >= DxfVersion.AutoCad2007) encoding = Encoding.UTF8; // the strings in a dxf binary file seems to be stored as UTF8 even if the file looks like ANSI else { if (string.IsNullOrEmpty(dwgcodepage)) encoding = Encoding.GetEncoding(Encoding.Default.WindowsCodePage); // use the default windows code page, if unable to read the code page header variable. else { int codepage; encoding = Encoding.GetEncoding(int.TryParse(dwgcodepage.Split('_')[1], out codepage) ? codepage : Encoding.Default.WindowsCodePage); } } this.chunk = new BinaryCodeValueReader(new BinaryReader(stream), encoding); } else { Encoding encoding; Encoding encodingType = EncodingType.GetType(stream); bool isUnicode = (encodingType.EncodingName == Encoding.UTF8.EncodingName) || (encodingType.EncodingName == Encoding.BigEndianUnicode.EncodingName) || (encodingType.EncodingName == Encoding.Unicode.EncodingName); if (isUnicode) encoding = Encoding.UTF8; else { // if the file is not UTF-8 use the code page provided by the dxf file if (string.IsNullOrEmpty(dwgcodepage)) encoding = Encoding.GetEncoding(Encoding.Default.WindowsCodePage); // use the default windows code page, if unable to read the code page header variable. else { int codepage; encoding = Encoding.GetEncoding(!int.TryParse(dwgcodepage.Split('_')[1], out codepage) ? Encoding.Default.WindowsCodePage : codepage); } } this.chunk = new TextCodeValueReader(new StreamReader(stream, encoding, true)); } } catch (Exception ex) { throw new IOException("Unknown error opening the reader.", ex); } this.doc = new DxfDocument(new HeaderVariables(), false); this.entityList = new Dictionary<EntityObject, string>(); this.viewports = new Dictionary<Viewport, string>(); this.hatchToPaths = new Dictionary<Hatch, List<HatchBoundaryPath>>(); this.hatchContourns = new Dictionary<HatchBoundaryPath, List<string>>(); this.decodedStrings = new Dictionary<string, string>(); this.leaderAnnotation = new Dictionary<Leader, string>(); // blocks this.nestedInserts = new Dictionary<Insert, string>(); this.nestedDimensions = new Dictionary<Dimension, string>(); this.blockRecords = new Dictionary<string, BlockRecord>(StringComparer.OrdinalIgnoreCase); this.blockEntities = new Dictionary<Block, List<EntityObject>>(); // objects this.dictionaries = new Dictionary<string, DictionaryObject>(StringComparer.OrdinalIgnoreCase); this.groupEntities = new Dictionary<Group, List<string>>(); this.dimStyleToHandles = new Dictionary<DimensionStyle, string[]>(); this.imageDefReactors = new Dictionary<string, ImageDefinitionReactor>(StringComparer.OrdinalIgnoreCase); this.imgDefHandles = new Dictionary<string, ImageDefinition>(StringComparer.OrdinalIgnoreCase); this.imgToImgDefHandles = new Dictionary<Image, string>(); this.mLineToStyleNames = new Dictionary<MLine, string>(); this.underlayToDefinitionHandles = new Dictionary<Underlay, string>(); this.underlayDefHandles = new Dictionary<string, UnderlayDefinition>(); // for layouts errors workarounds this.blockRecordPointerToLayout = new Dictionary<string, BlockRecord>(StringComparer.OrdinalIgnoreCase); this.orphanLayouts = new List<Layout>(); this.chunk.Next(); // read the comments at the head of the file, any other comments will be ignored // they sometimes hold information about the program that has generated the dxf // binary files do not contain any comments this.doc.Comments.Clear(); while (this.chunk.Code == 999) { this.doc.Comments.Add(this.chunk.ReadString()); this.chunk.Next(); } while (this.chunk.ReadString() != DxfObjectCode.EndOfFile) { if (this.chunk.ReadString() == DxfObjectCode.BeginSection) { this.chunk.Next(); switch (this.chunk.ReadString()) { case DxfObjectCode.HeaderSection: this.ReadHeader(); break; case DxfObjectCode.ClassesSection: this.ReadClasses(); break; case DxfObjectCode.TablesSection: this.ReadTables(); break; case DxfObjectCode.BlocksSection: this.ReadBlocks(); break; case DxfObjectCode.EntitiesSection: this.ReadEntities(); break; case DxfObjectCode.ObjectsSection: this.ReadObjects(); break; case DxfObjectCode.ThumbnailImageSection: this.ReadThumbnailImage(); break; case DxfObjectCode.AcdsDataSection: this.ReadAcdsData(); break; default: throw new Exception(string.Format("Unknown section {0}.", this.chunk.ReadString())); } } this.chunk.Next(); } stream.Position = 0; // perform all necessary post processes this.PostProcesses(); // to play safe we will add the default table objects to the document in case they do not exist, // if they already present nothing is overridden // add default layer this.doc.Layers.Add(Layer.Default); // add default line types this.doc.Linetypes.Add(Linetype.ByLayer); this.doc.Linetypes.Add(Linetype.ByBlock); this.doc.Linetypes.Add(Linetype.Continuous); // add default text style this.doc.TextStyles.Add(TextStyle.Default); // add default application registry this.doc.ApplicationRegistries.Add(ApplicationRegistry.Default); // add default dimension style this.doc.DimensionStyles.Add(DimensionStyle.Default); // add default MLine style this.doc.MlineStyles.Add(MLineStyle.Default); this.doc.ActiveLayout = Layout.ModelSpaceName; return this.doc; }
/// <summary> /// Initializes a new instance of the <c>ImageDefinition</c> class. /// </summary> /// <param name="fileName">Image file name with full or relative path.</param> /// <param name="name">Image definition name.</param> /// <param name="width">Image width in pixels.</param> /// <param name="horizontalResolution">Image horizontal resolution in pixels.</param> /// <param name="height">Image height in pixels.</param> /// <param name="verticalResolution">Image vertical resolution in pixels.</param> /// <param name="units">Image resolution units.</param> /// <remarks> /// <para> /// The name assigned to the image definition must be unique. /// </para> /// <para> /// This is a generic constructor for all image formats supported by AutoCAD, note that not all AutoCAD versions support the same image formats. /// </para> /// <para> /// Note (this is from the ACAD docs): AutoCAD 2000, AutoCAD LT 2000, and later releases do not support LZW-compressed TIFF files, /// with the exception of English language versions sold in the US and Canada.<br /> /// If you have TIFF files that were created using LZW compression and want to insert them into a drawing /// you must save the TIFF files with LZW compression disabled. /// </para> /// </remarks> public ImageDefinition(string fileName, string name, int width, double horizontalResolution, int height, double verticalResolution, ImageResolutionUnits units) : base(name, DxfObjectCode.ImageDef, false) { if (string.IsNullOrEmpty(fileName)) throw new ArgumentNullException(nameof(fileName), "The image file name should be at least one character long."); this.fileName = fileName; this.width = width; this.height = height; this.horizontalResolution = horizontalResolution; this.verticalResolution = verticalResolution; this.resolutionUnits = units; this.reactors = new Dictionary<string, ImageDefinitionReactor>(); }
/// <summary> /// Reads the whole stream. /// </summary> /// <param name="stream">Stream.</param> public DxfDocument Read(Stream stream) { if (stream == null) throw new ArgumentNullException("stream", "The stream cannot be null"); string dwgcodepage = CheckHeaderVariable(stream, HeaderVariableCode.DwgCodePage, out this.isBinary); try { if (this.isBinary) { Encoding encoding; DxfVersion version = DxfDocument.CheckDxfFileVersion(stream, out this.isBinary); if (version >= DxfVersion.AutoCad2007) encoding = Encoding.UTF8; // the strings in a dxf binary file seems to be stored as UTF8 even if the file looks like ANSI else { if (string.IsNullOrEmpty(dwgcodepage)) encoding = Encoding.GetEncoding(Encoding.Default.WindowsCodePage); // use the default windows code page, if unable to read the code page header variable. else { int codepage; if (!int.TryParse(dwgcodepage.Split('_')[1], out codepage)) encoding = Encoding.GetEncoding(Encoding.Default.WindowsCodePage); // use the default windows code page, if unable to read the code page header variable. else encoding = Encoding.GetEncoding(codepage); } } this.chunk = new BinaryCodeValueReader(new BinaryReader(stream), encoding); } else { Encoding encoding; Encoding encodingType = EncodingType.GetType(stream); bool isUnicode = (encodingType.EncodingName == Encoding.UTF8.EncodingName) || (encodingType.EncodingName == Encoding.BigEndianUnicode.EncodingName) || (encodingType.EncodingName == Encoding.Unicode.EncodingName); if (isUnicode) encoding = Encoding.UTF8; else { // if the file is not UTF-8 use the code page provided by the dxf file if (string.IsNullOrEmpty(dwgcodepage)) encoding = Encoding.GetEncoding(Encoding.Default.WindowsCodePage); // use the default windows code page, if unable to read the code page header variable. else { int codepage; if (!int.TryParse(dwgcodepage.Split('_')[1], out codepage)) encoding = Encoding.GetEncoding(Encoding.Default.WindowsCodePage); // use the default windows code page, if unable to read the code page header variable. else encoding = Encoding.GetEncoding(codepage); // use the default windows code page, if unable to read the code page header variable. } } this.chunk = new TextCodeValueReader(new StreamReader(stream, encoding, true)); } } catch (Exception ex) { throw (new DxfException("Unknown error opening the reader.", ex)); } this.doc = new DxfDocument(new HeaderVariables(), false); this.entityList = new Dictionary<EntityObject, string>(); this.viewports = new Dictionary<Viewport, string>(); this.hatchToPaths = new Dictionary<Hatch, List<HatchBoundaryPath>>(); this.hatchContourns = new Dictionary<HatchBoundaryPath, List<string>>(); this.decodedStrings = new Dictionary<string, string>(); // blocks this.nestedInserts = new Dictionary<Insert, string>(); this.nestedDimensions = new Dictionary<Dimension, string>(); this.blockRecords = new Dictionary<string, BlockRecord>(StringComparer.OrdinalIgnoreCase); this.blockEntities = new Dictionary<Block, List<EntityObject>>(); // objects this.dictionaries = new Dictionary<string, DictionaryObject>(StringComparer.OrdinalIgnoreCase); this.groupEntities = new Dictionary<Group, List<string>>(); this.dimStyleToHandles = new Dictionary<DimensionStyle, string[]>(); this.imageDefReactors = new Dictionary<string, ImageDefReactor>(StringComparer.OrdinalIgnoreCase); this.imgDefHandles = new Dictionary<string, ImageDef>(StringComparer.OrdinalIgnoreCase); this.imgToImgDefHandles = new Dictionary<Image, string>(); this.mLineToStyleNames = new Dictionary<MLine, string>(); // for layouts errors workarounds this.blockRecordPointerToLayout = new Dictionary<string, BlockRecord>(StringComparer.OrdinalIgnoreCase); this.orphanLayouts = new List<Layout>(); this.chunk.Next(); // read the comments at the head of the file, any other comments will be ignored // they sometimes hold information about the program that has generated the dxf // binary files do not contain any comments this.doc.Comments.Clear(); while (this.chunk.Code == 999) { this.doc.Comments.Add(this.chunk.ReadString()); this.chunk.Next(); } while (this.chunk.ReadString() != DxfObjectCode.EndOfFile) { if (this.chunk.ReadString() == DxfObjectCode.BeginSection) { this.chunk.Next(); switch (this.chunk.ReadString()) { case DxfObjectCode.HeaderSection: this.ReadHeader(); break; case DxfObjectCode.ClassesSection: this.ReadClasses(); break; case DxfObjectCode.TablesSection: this.ReadTables(); break; case DxfObjectCode.BlocksSection: this.ReadBlocks(); break; case DxfObjectCode.EntitiesSection: this.ReadEntities(); break; case DxfObjectCode.ObjectsSection: this.ReadObjects(); break; case DxfObjectCode.ThumbnailImageSection: this.ReadThumbnailImage(); break; case DxfObjectCode.AcdsDataSection: this.ReadAcdsData(); break; default: throw new InvalidDxfSectionException(this.chunk.ReadString(), string.Format("Unknown section {0}.", this.chunk.ReadString())); } } this.chunk.Next(); } stream.Position = 0; // post process the dimension style list to assign the variables DIMTXSTY, DIMBLK, DIMBLK1, DIMBLK2, DIMLTYPE, DILTEX1, and DIMLTEX2 foreach (KeyValuePair<DimensionStyle, string[]> pair in this.dimStyleToHandles) { DimensionStyle defaultDim = DimensionStyle.Default; BlockRecord record; record = this.doc.GetObjectByHandle(pair.Value[0]) as BlockRecord; pair.Key.DIMBLK = record == null ? null : this.doc.Blocks[record.Name]; record = this.doc.GetObjectByHandle(pair.Value[1]) as BlockRecord; pair.Key.DIMBLK1 = record == null ? null : this.doc.Blocks[record.Name]; record = this.doc.GetObjectByHandle(pair.Value[2]) as BlockRecord; pair.Key.DIMBLK2 = record == null ? null : this.doc.Blocks[record.Name]; TextStyle txtStyle; txtStyle = this.doc.GetObjectByHandle(pair.Value[3]) as TextStyle; pair.Key.DIMTXSTY = txtStyle == null ? this.doc.TextStyles[defaultDim.DIMTXSTY.Name] : this.doc.TextStyles[txtStyle.Name]; LineType ltype; ltype = this.doc.GetObjectByHandle(pair.Value[4]) as LineType; pair.Key.DIMLTYPE = ltype == null ? this.doc.LineTypes[defaultDim.DIMLTYPE.Name] : this.doc.LineTypes[ltype.Name]; ltype = this.doc.GetObjectByHandle(pair.Value[5]) as LineType; pair.Key.DIMLTEX1 = ltype == null ? this.doc.LineTypes[defaultDim.DIMLTEX1.Name] : this.doc.LineTypes[ltype.Name]; ltype = this.doc.GetObjectByHandle(pair.Value[6]) as LineType; pair.Key.DIMLTEX2 = ltype == null ? this.doc.LineTypes[defaultDim.DIMLTEX2.Name] : this.doc.LineTypes[ltype.Name]; } // post process the image list to assign their image definitions. foreach (KeyValuePair<Image, string> pair in this.imgToImgDefHandles) { Image image = pair.Key; image.Definition = this.imgDefHandles[pair.Value]; image.Definition.Reactors.Add(image.Handle, this.imageDefReactors[image.Handle]); // we still need to set the definitive image size, now that we know all units involved double factor = UnitHelper.ConversionFactor(this.doc.DrawingVariables.InsUnits, this.doc.RasterVariables.Units); image.Width *= factor; image.Height *= factor; } // post process the MLines to assign their MLineStyle foreach (KeyValuePair<MLine, string> pair in this.mLineToStyleNames) { MLine mline = pair.Key; mline.Style = this.GetMLineStyle(pair.Value); } // post process the entities of the blocks foreach (KeyValuePair<Block, List<EntityObject>> pair in this.blockEntities) { Block block = pair.Key; foreach (EntityObject entity in pair.Value) { // now that we have all information required by the block entities we can add them to the document // entities like MLine and Image require information that is defined AFTER the block section, // this is the case of the MLineStyle and ImageDef that are described in the objects section block.Entities.Add(entity); } } // add the dxf entities to the document foreach (KeyValuePair<EntityObject, string> pair in this.entityList) { Layout layout; Block block; if (pair.Value == null) { // the Model layout is the default in case the entity has not one defined layout = this.doc.Layouts[Layout.ModelSpaceName]; block = layout.AssociatedBlock; } else { block = this.GetBlock(((BlockRecord) this.doc.GetObjectByHandle(pair.Value)).Name); layout = block.Record.Layout; } // the viewport with id 1 is stored directly in the layout since it has no graphical representation Viewport viewport = pair.Key as Viewport; if (viewport != null) { if (viewport.Id == 1) { // the base layout viewport has always id = 1 and we will not add it to the entities list of the document. // this viewport has no graphical representation, it is the view of the paper space layout itself and it does not show the model. layout.Viewport = viewport; layout.Viewport.Owner = block; } else { this.doc.ActiveLayout = layout.Name; this.doc.AddEntity(pair.Key, false, false); } } else { // apply the units scale to the insertion scale (this is for not nested blocks) Insert insert = pair.Key as Insert; if (insert != null) { double scale = UnitHelper.ConversionFactor(this.doc.DrawingVariables.InsUnits, insert.Block.Record.Units); insert.Scale *= scale; } this.doc.ActiveLayout = layout.Name; this.doc.AddEntity(pair.Key, false, false); } } // assign a handle to the default layout viewports foreach (Layout layout in this.doc.Layouts) { if (layout.Viewport == null) continue; if (string.IsNullOrEmpty(layout.Viewport.Handle)) this.doc.NumHandles = layout.Viewport.AsignHandle(this.doc.NumHandles); } // post process viewports clipping boundaries foreach (KeyValuePair<Viewport, string> pair in this.viewports) { EntityObject entity = this.doc.GetObjectByHandle(pair.Value) as EntityObject; if (entity != null ) pair.Key.ClippingBoundary = entity; } // post process the hatch boundary paths foreach (KeyValuePair<Hatch, List<HatchBoundaryPath>> pair in this.hatchToPaths) { Hatch hatch = pair.Key; foreach (HatchBoundaryPath path in pair.Value) { List<string> entities = this.hatchContourns[path]; foreach (string handle in entities) { EntityObject entity = this.doc.GetObjectByHandle(handle) as EntityObject; if (entity != null) path.AddContour(entity); } hatch.BoundaryPaths.Add(path); } } // post process group entities foreach (KeyValuePair<Group, List<string>> pair in this.groupEntities) { foreach (string handle in pair.Value) { EntityObject entity = this.doc.GetObjectByHandle(handle) as EntityObject; if (entity != null) pair.Key.Entities.Add(entity); } } // to play safe we will add the default table objects to the document in case they do not exist, // if they already present nothing is overridden // add default layer this.doc.Layers.Add(Layer.Default); // add default line types this.doc.LineTypes.Add(LineType.ByLayer); this.doc.LineTypes.Add(LineType.ByBlock); this.doc.LineTypes.Add(LineType.Continuous); // add default text style this.doc.TextStyles.Add(TextStyle.Default); // add default application registry this.doc.ApplicationRegistries.Add(ApplicationRegistry.Default); // add default dimension style this.doc.DimensionStyles.Add(DimensionStyle.Default); // add default MLine style this.doc.MlineStyles.Add(MLineStyle.Default); this.doc.ActiveLayout = Layout.ModelSpaceName; return this.doc; }