{************************************************************}
{                   Delphi VCL Extensions                    }
{                                                            }
{                  DXF files TGraphic class                  }
{                                                            }
{      Copyright (c) 2002-2013 SoftGold software company     }
{                                                            }
{************************************************************}

unit DXF;
{$INCLUDE SGDXF.INC}
{$IFDEF SG_BTI}
  {$DEFINE SG_BTI_HANDELS}
{$ENDIF}
interface

uses Windows, SysUtils, Classes, Graphics, SGConsts, CADImage, DXFConv, sgLines,
  sgLists, ExtData, sgFunction
  {$IFDEF SG_DECRYPT_FILES}
  , sgStmCrpt
  {$ENDIF}
  ;

type
  TsgCADdxfImage = class(TsgImageWithHandles)
  protected
    function CreateConverter: TsgDXFConverter; override;
    function IsAutocadLType: Boolean; override;
  public
    constructor Create; override;
    procedure LoadFromClipboardFormat(AFormat: Word;
      AClipboardObject: THandle; APalette: HPALETTE); {$IFNDEF SGFPC} override; {$ENDIF}
    procedure LoadFromStream(AStream: TStream); override;
    procedure SaveToClipboardFormat(var AFormat: Word;
      var AClipboardObject: THandle; var APalette: HPALETTE); {$IFNDEF SGFPC} override; {$ENDIF}
  end;

implementation

uses sgUnicode, MVFont, Math;

const
  cnstBlockRefHandleDefault = 0;
  cnstBadBlockRefHandle = 1;

  cnstNumberOfFitDataNeedRead = -1;
  cnstNumberOfFitDataUndefined = -2;

  cnstSection = 'SECTION';
  cnstTable = 'TABLE';
  cnstEndSec = 'ENDSEC';
  cnstSeqEnd = 'SEQEND';
  cnstATTRIBExtdata = 'ACDBATTR';

  cnstCodeValueUndefined = -1;

type
  TsgDXFEntityAccess = class(TsgDXFEntity);
  TsgDXFBlockAccess = class(TsgDXFBlock);
  TsgDXFBlockRecordAccess = class(TsgDXFBlockRecord);
  TsgDXFInsertAccess = class(TsgDXFInsert);
  TsgCADHatchAccess = class(TsgCADHatch);
  TsgDXFGroupAccess = class(TsgDXFGroup);
  TsgDXFTableAccess = class(TsgDXFTable);
  TsgDXFLeaderAccess = class(TsgDXFLeader);
  TsgDXFDimStyleAccess = class(TsgDXFDimensionStyle);
  TsgDXFDimensionAccess = class(TsgDXFDimension);
  TsgDXFDimensionPropertiesAccess = class(TsgDXFDimensionProperties);
  TsgDXFConverterAccess = class(TsgDXFConverter);
  TsgDXFAcadTableStyleAccess = class(TsgDXFAcadTableStyle);
{$IFDEF SG_BTI}
  TsgExtendedBlockDataAccess = class(TsgExtendedBlockData);
  TsgAreaFigureAccess = class(TsgAreaFigure);
{$ENDIF}
  TsgDXFPlotSettingsAccess = class(TsgDXFPlotSettings);
  TsgDXFTextAccess = class(TsgDXFText);
  TsgDXFSplineAccess = class(TsgDXFSpline);

  TDXFProxyReader = class(TCustomAlignedDataReader);

  TdxfObject = class;
  TdxfEntity = class;

  // Reader

  TdxfReader = class
  private
    FCode: Integer;
    FConverter: TsgDXFConverter;
    FFileInfo: TStringList;
    FLimit: PAnsiChar;
    FLine: Integer;
    FMain: TdxfEntity;
    FPos: PAnsiChar;
    FPrev: PAnsiChar;
    FValue: AnsiString;
    FInt: Integer;
    FDouble: Double;
    FHandle: UInt64;
    FValueStartPos: PAnsiChar;
    FValueSize: Integer;

    FLayerLinks: TStringList;
    FLTypeLinks: TStringList;
    FBlockLinks: TStringList;
    FStyleLinks: TStringList;
    FStyleHLinks: TsgCollection;
    FDimStyleLinks: TStringList;
    FBlockRecordHLinks: TsgCollection;
    FMStyleLinks: TStringList;
    FMStyleHLinks: TsgCollection;
    FTableStyleHLinks: TsgCollection;
    FFieldsHLinks: TsgCollection;
    FDictHLinks: TsgCollection;
    FImageDefsHLinks: TsgCollection;

    FPapers: TsgDXFGroup;

    FStylesByFont: TStringList;

    FActiveVPort: TsgDXFVport;
    FSortents: Integer;
    procedure DoEvent(Event: TNotifyEvent);
    function GetStrValue: string;
    function GetUValue: string;
    function GetFileInfo: string;
    function CreateStringList: TStringList;
    procedure ReadDouble(var AValue: Double);
    procedure ReadHandle(var AValue: UInt64);
    procedure ReadInt(var AValue: Integer);
    procedure ReadFileInfo;
    procedure SeekEOL;

    function GetConv: TsgDXFConverterAccess;

    function ForceLink(AList: TsgCollection; AHandle: UInt64): TObject; overload;
    function ForceLink(AList: TStrings; const AName: string): TObject; overload;
    function GetLayers(Name: string): TObject;
    function GetLTypes(Name: string): TObject;
    function GetBlockRecords(Name: string): TObject;
    function GetHStyles(Handle: UInt64): TObject;
    function GetStyles(Name: string): TObject;
    function GetHBlockRecords(Handle: UInt64): TObject;
    function GetDimStyles(Name: string): TObject;
    function GetMStyles(Name: string): TObject;
    function GetMHStyles(Handle: UInt64): TObject;
    function GetHTableStyles(Handle: UInt64): TObject;
    function GetHFields(Handle: UInt64): TObject;
    function GetHDictionary(Handle: UInt64): TObject;
    function GetHImageDefs(Handle: UInt64): TObject;
    function GetXDataProcs: TsgXDataProcs;
    function GetVersion: Byte;

  protected
    procedure DoCreate(AEntity: TsgDXFEntity);
    function GetValue: AnsiString; virtual;
    function ObjByHandle(const AHandle: UInt64): TsgDXFEntity;
    function EOF: Boolean;
    function IsInternalCADImage: Boolean;
    procedure ForceStandardObjects; virtual;
    procedure ForceNamedObjectsDictionary; virtual;
    procedure ForceLayouts; virtual;
    procedure ForceImageDefs; virtual;
    procedure InitPaper(const ABlock: TsgDXFEntity);
    property XDataProcs: TsgXDataProcs read GetXDataProcs;
  public
    constructor Create(Conv: TsgDXFConverter);
    destructor Destroy; override;
    function FloatValue: Double; virtual;
    function HandleValue: UInt64; virtual;
    function IntValue: Integer; virtual;
    procedure Read;
    procedure Next; virtual;
    property Code: Integer read FCode write FCode;
    property FileInfo: string read GetFileInfo;
    property StrValue: string read GetStrValue;
    property UValue: string read GetUValue;
    property Value: AnsiString read GetValue;
    property Version: Byte read GetVersion;

    property Conv: TsgDXFConverterAccess read GetConv;

    property Layers[Name: string]: TObject read GetLayers;
    property LTypes[Name: string]: TObject read GetLTypes;
    property BlockRecords[Name: string]: TObject read GetBlockRecords;
    property Styles[Name: string]: TObject read GetStyles;
    property HStyles[Handle: UInt64]: TObject read GetHStyles;
    property HBlockRecords[Handle: UInt64]: TObject read GetHBlockRecords;
    property DimStyles[Name: string]: TObject read GetDimStyles;
    property MStyles[Name: string]: TObject read GetMStyles;
    property MHStyles[Handle: UInt64]: TObject read GetMHStyles;
    property HTableStyles[Handle: UInt64]: TObject read GetHTableStyles;
    property HFields[Handle: UInt64]: TObject read GetHFields;
    property HDictionary[Handle: UInt64]: TObject read GetHDictionary;

    property HImageDefs[Handle: UInt64]: TObject read GetHImageDefs;
  end;

  TdxfBinReader = class(TdxfReader)
  private
    FGroupCodeSize: Integer;
    procedure Chunk;
    procedure Read(var ABuffer; ACount: Integer);
  public
    constructor Create(AConverter: TsgDXFConverter; const AGroupCodeSize: Integer);
    function FloatValue: Double; override;
    function HandleValue: UInt64; override;
    function IntValue: Integer; override;
    procedure Next; override;
  end;

  TdxfObjectClass = class of TdxfObject;

  PEntClass = ^TEntClass;
  TEntClass = record
    Ent: TsgDXFEntityClass;
    EntClass: TdxfObjectClass;
  end;

  TdxfObject = class
  private
    FAdded: Boolean;
    FComplex: Boolean;
    FEnt: TsgDXFEntity;
    FHandle: UInt64;
    FHardOwnerIDs: TsgInt64List;
    FLinkSoftIDs: TsgInt64List;
    FPaperSpace: Integer;
    FPointerIDs: TsgInt64List;
    FRctrsHardIDs: TsgInt64List;
    FRctrsSoftIDs: TsgInt64List;
    FReactorsRead: Boolean;
    FSoftOwnerIDs: TsgInt64List;
{$IFDEF SG_USEDXFSRC}
    FSrcEnd: PAnsiChar;
    FSrcStart: PAnsiChar;
{$ENDIF}
    FTexts: array[1..9] of string; // FTexts[5] - not fill, use AReader.FHandle
    FOwner: TdxfObject;
    FObj: TdxfObject;
    function GetName: string;
    procedure SetName(const Value: string);
  protected
    procedure SetLayerByName(AReader: TdxfReader; const AName: string); virtual;
  protected
    constructor Create; virtual;
    destructor Destroy; override;
    function AddEntity(const E: TdxfObject): Boolean; virtual;
    procedure ApplyHandle(const AConv: TsgDXFConverterAccess); virtual;
    procedure Commit(const AReader: TdxfReader); virtual;
    function CreateSubEntity(const AReader: TdxfReader; AName: string): TdxfObject; virtual;
    procedure DestroyObj; virtual;
    function EOFEnt(AObj: TdxfObject): Boolean; virtual;
    function GetConv: TsgDXFConverterAccess; virtual;
    function OwnerAdd: Integer; virtual;
    procedure ReadEntities(AReader: TdxfReader); virtual;
    function ReadEntity(AReader: TdxfReader; AEntName: string): Boolean; virtual;
    procedure ReadProps(AReader: TdxfReader); virtual;
    procedure ReadProperty(const AReader: TdxfReader); virtual;
    procedure ReadState(AReader: TdxfReader); virtual;
    function ReleaseEntity: TsgDXFEntity; virtual;
    property Conv: TsgDXFConverterAccess read GetConv;
    property Name: string read GetName write SetName;
  end;

  // Entity

  TdxfEntity = class(TdxfObject)
  private
    FElevation: Double;
    FExtrusion: TFPoint;
    FFloats: array[0..19] of Double;
    FInts: array[0..19] of Integer;
    FIntsRGBColor: TColor;
    FLineWeight: Double;
    FPoints: array[0..9] of TFPoint;
    FZThick: Double;
    procedure Coord(AReader: TdxfReader);
    function LoadColor(const AReader: TdxfReader): TsgColorCAD;
    procedure SetLWeight(const AValue: Double);
  protected
    constructor Create; override;
    procedure Commit(const AReader: TdxfReader); override;
    procedure ReadProperty(const AReader: TdxfReader); override;
    property Flags: Integer read FInts[10];
  end;

  TdxfMain = class(TdxfEntity)
  private
    FConv: TsgDXFConverterAccess;
    FSectionObjects: TdxfObject;
    procedure Initialize(AReader: TdxfReader; AObj: TdxfObject);
  protected
    destructor Destroy; override;
    function GetConv: TsgDXFConverterAccess; override;
    function CreateSubEntity(const AReader: TdxfReader;
      AName: string): TdxfObject; override;
    procedure DestroyObj; override;
    procedure ReadEntities(AReader: TdxfReader); override;
  end;

  TdxfCustomSection = class(TdxfObject)
  protected
    constructor Create; override;
    function EOFEnt(AObj: TdxfObject): Boolean; override;
  end;

  TdxfTables = class(TdxfCustomSection)
  protected
    function CreateSubEntity(const AReader: TdxfReader;
      AName: string): TdxfObject; override;
    procedure ReadEntities(AReader: TdxfReader); override;
  end;

  TdxfBlocks = class(TdxfCustomSection)
  end;

  TdxfEntities = class(TdxfCustomSection)
  private
    FPapers: TsgDXFGroup;
  protected
    function AddEntity(const E: TdxfObject): Boolean; override;
  end;

  TdxfObjects = class(TdxfCustomSection)
  protected
    function AddEntity(const E: TdxfObject): Boolean; override;
  end;

  TdxfClasses = class(TdxfCustomSection)
  end;

  TdxfHeader = class(TdxfEntity)
  private
    FHeadVarIndex: Integer;
    FHeadVars: TsgHeadVarStruct;
    procedure DoHeadVars(const AReader: TdxfReader);
  protected
    constructor Create; override;
    procedure Commit(const AReader: TdxfReader); override;
    function EOFEnt(AObj: TdxfObject): Boolean; override;
    procedure ReadProperty(const AReader: TdxfReader); override;
    property HeadVars: TsgHeadVarStruct read FHeadVars write FHeadVars;
  end;

  TdxfEndTab = class(TdxfObject)
  end;

  TdxfEndBlock = class(TdxfObject)
  end;

  TdxfEndSeq = class(TdxfObject)
  end;

  TdxfSeqend = class(TdxfObject)
  end;

  TdxfBasePolyLine = class(TdxfEntity)
  protected
    procedure Commit(const AReader: TdxfReader); override;
  end;

  TdxfBlock = class(TdxfEntity)
{$IFDEF SG_BTI}
  private
    FAttribsTypes: string;
    FAttributes: string;
    FCodeValue: Integer;
    FEntTypeNum: Integer;
    FInsUnits: Integer;
    FSegmentWidths: PF2DRect;
    FXData: TsgExtendedBlockData;
    FXDataAppName: string;
    function GetSegmentWidths: PF2DRect;
    procedure NextInteger(AReader: TdxfReader);
    procedure NextReal(AReader: TdxfReader);
    procedure NextString(AReader: TdxfReader);
{$ENDIF}
  protected
    constructor Create; override;
{$IFDEF SG_BTI}
    destructor Destroy; override;
{$ENDIF}
    function IsAcadTableBlock: Boolean;
    procedure Commit(const AReader: TdxfReader); override;
    function EOFEnt(AObj: TdxfObject): Boolean; override;
    procedure ReadProperty(const AReader: TdxfReader); override;
  end;

  TdxfDictionary = class(TdxfObject)
  private
    FNamesHardOwnerIDs: TStringList; //360
    FNamesLinkSoftIDs: TStringList; //350
  protected
    constructor Create; override;
    destructor Destroy; override;
    procedure Commit(const AReader: TdxfReader); override;
    procedure ReadProperty(const AReader: TdxfReader); override;
  end;

  TdxfDimAssoc = class(TdxfObject)
  protected
    procedure Commit(const AReader: TdxfReader); override;
  end;

  TdxfHatch = class(TdxfEntity)
  private
    FCurentIndexColorCAD: Byte;
    FCurentIndexColor: Byte;
    FBoundNum: Integer;
    FNumberOfFitData: Integer;
    FBoundType: Integer;
    FCurType: Pointer;
    FIsSolid: Boolean;
    FPointCount: Integer;
    function AddNewPattern(const AHatch: TsgCADHatch): PsgHatchPatternData;
    procedure DoSolidHatch(const AReader: TdxfReader);
    function GetLastHatchSegment(const AHatch: TsgCADHatch): Tsg2DCurve;
    function Pattern(const AHatch: TsgCADHatch): PsgHatchPatternData;
    procedure ReadGrad(const AReader: TdxfReader; const  AHatch: TsgCADHatch);
  protected
    constructor Create; override;
    procedure Commit(const AReader: TdxfReader); override;
    procedure ReadProperty(const AReader: TdxfReader); override;
  end;

  TdxfImageDef = class(TdxfObject)
  protected
    procedure Commit(const AReader: TdxfReader); override;
    function OwnerAdd: Integer; override;
    procedure ReadProperty(const AReader: TdxfReader); override;
  end;

  TdxfInsert = class(TdxfEntity)
  private
    FCodeValue: Integer;
    FEntGroup: string;
    FEntTypeNum: Integer;
    FExtData: TsgCADExtendedData;
    FXDataAppName: string;
    FConstructionStyle: string;
{$IFDEF SG_BTI}
//    FAttributes: string;
//    FAttribsTypes: string;
    FBlockPattern: TsgDXFBlock;
    FCount_1040: Integer;
    FCount_1042: Integer;
    FCurrentFigure: TsgAreaFigure;
    FFiguresList: TsgList;
    FLabelAlign: Byte;
    FLabelHeight: Double;
    FLabelShowSplitter: Boolean;
    FLabelStrings: array [0..4] of string;
    FLabelTextOffset: Double;
    FPXData: PsgExtendedData;
    FIndexStrings: Integer;
{$ENDIF}
    procedure ChangeEntEx(const AConverter: TsgDXFConverter);
    function GetExtData: TsgCADExtendedData;

    procedure NextHandleStr(const AReader: TdxfReader);
    procedure NextInt(const AReader: TdxfReader);
    procedure NextInteger(const AReader: TdxfReader);
    procedure NextPoint(const AReader: TdxfReader; const AIndexPoint: Byte);
    procedure NextReal(const AReader: TdxfReader);
    procedure NextReal1(const AReader: TdxfReader);
    procedure NextReal2(const AReader: TdxfReader);
    procedure NextString(const AReader: TdxfReader);
{$IFDEF SG_BTI}
    procedure ChangeEntity(AReader: TdxfReader);
    procedure ClearXData;
    function CurrentFigure: TsgAreaFigureAccess;
    function XData: PsgExtendedData;
    procedure ReadXDataString(const ACode: Integer; const AValue: string);
{$ENDIF}
  protected
    constructor Create; override;
    destructor Destroy; override;
    procedure Commit(const AReader: TdxfReader); override;
    procedure ReadProperty(const AReader: TdxfReader); override;
  end;

  TdxfPlotSettings = class(TdxfEntity)
  protected
    procedure ReadProperty(const AReader: TdxfReader); override;
    procedure ReadProps(AReader: TdxfReader); override;
    procedure SetLayerByName(AReader: TdxfReader; const AName: string); override;
  end;

  TdxfDictionaryVar = class(TdxfObject)
  protected
    procedure ReadProperty(const AReader: TdxfReader); override;
  end;

  TdxfLayout = class(TdxfEntity)
  private
    FPlotSettings: TdxfPlotSettings;
  protected
    constructor Create; override;
    destructor Destroy; override;
    procedure Commit(const AReader: TdxfReader); override;
    function OwnerAdd: Integer; override;
    procedure ReadProperty(const AReader: TdxfReader); override;
    procedure SetLayerByName(AReader: TdxfReader; const AName: string); override;
  end;

  TdxfMLine = class(TdxfEntity)
  private
    FVertex: TsgMVertex;
    procedure NewVertex;
  protected
    procedure Commit(const AReader: TdxfReader); override;
    procedure ReadProperty(const AReader: TdxfReader); override;
  end;

  TdxfMLStyle = class(TdxfEntity)
  private
    FCount: Integer;
    procedure NewEntry(AReader: TdxfReader);
  protected
    procedure Commit(const AReader: TdxfReader); override;
    function OwnerAdd: Integer; override;
    procedure ReadProperty(const AReader: TdxfReader); override;
    procedure SetLayerByName(AReader: TdxfReader; const AName: string); override;
  end;

  TdxfMText = class(TdxfEntity)
  protected
    constructor Create; override;
    procedure Commit(const AReader: TdxfReader); override;
    procedure ReadProperty(const AReader: TdxfReader); override;
  end;

  TdxfOLE = class(TdxfEntity)
  private
    FData: AnsiString;
    FHeader: AnsiString;
    FReadData: Boolean;
  protected
    procedure Commit(const AReader: TdxfReader); override;
    procedure ReadProperty(const AReader: TdxfReader); override;
  end;

  TdxfPenLine = class(TdxfEntity)
  protected
    procedure Commit(const AReader: TdxfReader); override;
  end;

  TdxfPenTableItem = class(TdxfEntity)
  private
    FPenTableItemWithSameNameAlreadyExistsInOwnerTable: TsgDXFPenTableItem;
  protected
    procedure Commit(const AReader: TdxfReader); override;
    procedure ReadProperty(const AReader: TdxfReader); override;
    procedure SetLayerByName(AReader: TdxfReader; const AName: string); override;
  public
    destructor Destroy; override;
  end;

  TdxfPoint = class(TdxfEntity)
  protected
    procedure Commit(const AReader: TdxfReader); override;
  end;

  TdxfProxy = class(TdxfEntity)
  private
    FData: PByte;
    FSize: Integer;
    FList: TList;
    FProps: TList;
    procedure AddData(const S: AnsiString);
    procedure InitProxyEntities(const AReader: TdxfReader);
  protected
    constructor Create; override;
    destructor Destroy; override;
    procedure Commit(const AReader: TdxfReader); override;
    procedure ReadProperty(const AReader: TdxfReader); override;
  end;

  TdxfMesh = class(TdxfProxy)
  private
    FIndexVertex: Integer;
    FIndexFace: Integer;
    FVertexArray: TFPointList;
    FFaceArray: TsgIntegerList;
    FEdgeArray: TsgIntegerList;
    FMode: Integer;  // 1 - Face; 2 - Edge
  protected
    constructor Create; override;
    destructor Destroy; override;
    procedure Commit(const AReader: TdxfReader); override;
    procedure ReadProperty(const AReader: TdxfReader); override;
  end;

  TdxfShape = class(TdxfEntity)
  protected
    constructor Create; override;
    procedure Commit(const AReader: TdxfReader); override;
  end;

  TdxfSortEntsTable = class(TdxfObject)
  private
    FStartTable: Boolean;
  protected
    procedure Commit(const AReader: TdxfReader); override;
    function OwnerAdd: Integer; override;
    procedure ReadProperty(const AReader: TdxfReader); override;
    procedure ReadState(AReader: TdxfReader); override;
  end;

  TdxfTable = class(TdxfObject)
  protected
    constructor Create; override;
    procedure Commit(const AReader: TdxfReader); override;
    function EOFEnt(AObj: TdxfObject): Boolean; override;
  end;

  TdxfText = class(TdxfEntity)
  protected
    constructor Create; override;
    procedure Commit(const AReader: TdxfReader); override;
    procedure ReadProperty(const AReader: TdxfReader); override;
  end;

  TdxfTolerance = class(TdxfEntity)
  private
    FCodeValue: Integer;
  protected
    constructor Create; override;
    procedure Commit(const AReader: TdxfReader); override;
    procedure ReadProperty(const AReader: TdxfReader); override;
  end;

  TdxfVertex = class(TdxfEntity)
  protected
    procedure Commit(const AReader: TdxfReader); override;
    procedure ReadProperty(const AReader: TdxfReader); override;
  end;

  TdxfViewport = class(TdxfEntity)
  private
    FIsAcad: Boolean;
    FCount_1010: Integer;
    FCount_1040: Integer;
    procedure Next3Reals(const AReader: TdxfReader);
    procedure NextReal(const AReader: TdxfReader);
  protected
    constructor Create; override;
    procedure Commit(const AReader: TdxfReader); override;
    procedure ReadProperty(const AReader: TdxfReader); override;
  end;

  TdxfVport = class(TdxfEntity)
  private
    FOrigin: TFPoint;
    FUCSVP: Integer;
    FXDir: TFPoint;
    FYDir: TFPoint;
  protected
    constructor Create; override;
    procedure Commit(const AReader: TdxfReader); override;
    procedure ReadProperty(const AReader: TdxfReader); override;
    procedure SetLayerByName(AReader: TdxfReader; const AName: string); override;
  end;

  TdxfWipeout = class(TdxfEntity)
  protected
    procedure Commit(const AReader: TdxfReader); override;
    procedure ReadProperty(const AReader: TdxfReader); override;
  end;

  TdxfWipeoutVars = class(TdxfEntity)
  protected
    procedure Commit(const AReader: TdxfReader); override;
    procedure ReadProperty(const AReader: TdxfReader); override;
    procedure SetLayerByName(AReader: TdxfReader; const AName: string); override;
  end;

  TdxfCircle = class(TdxfBasePolyLine)
  protected
    constructor Create; override;
    procedure Commit(const AReader: TdxfReader); override;
  end;

  TdxfLine = class(TdxfPenLine)
  protected
    procedure Commit(const AReader: TdxfReader); override;
  end;

  TdxfSolid = class(TdxfLine)
  protected
    procedure Commit(const AReader: TdxfReader); override;
  end;

  TdxfSpline = class(TdxfBasePolyLine)
  private
    FNewCtl: Boolean;
    FNewFit: Boolean;
    FCodeValue: Integer;
    FFlagsExtented: Integer;
    FXDataAppName: string;
    procedure AddControl;
    procedure AddFit;
    procedure AddKnot(Value: Single);
    procedure AddWeight(Value: Single);
    procedure NextInteger(const AReader: TdxfReader);
  protected
    procedure Commit(const AReader: TdxfReader); override;
    procedure ReadProperty(const AReader: TdxfReader); override;
    procedure SetDegreeSplineCurve; virtual;
  public
     constructor Create; override;
  end;

  TdxfPolyLine = class(TdxfBasePolyLine)
  protected
    procedure Commit(const AReader: TdxfReader); override;
    procedure SetElevation; virtual;
  end;

  TdxfAcadTable = class(TdxfInsert)
  private
    FBlockRecordHandle: UInt64;
    FColIndex: Integer;
    FEofCommon: Boolean;
    FIsTableSubClass: Boolean;
    FRowIndex: Integer;
    FTableStyleHandle: UInt64;
    function CurCell: TsgAcadTableCell;
  protected
    procedure Commit(const AReader: TdxfReader); override;
    procedure ReadProperty(const AReader: TdxfReader); override;
  end;

  TdxfAcadTableStyle = class(TdxfEntity)
  private
    FCellTypeIndex: TsgAcadTableCellType;
    function GetSell: TsgAcadTableCellStyle;
  protected
    procedure Commit(const AReader: TdxfReader); override;
    procedure ReadProperty(const AReader: TdxfReader); override;
    procedure SetLayerByName(AReader: TdxfReader; const AName: string); override;
    property Cell: TsgAcadTableCellStyle read GetSell;
  public
    constructor Create; override;
  end;

  TdxfACIS = class(TdxfPenLine)
  private
    FData: TStrings;
  protected
    procedure Commit(const AReader: TdxfReader); override;
    procedure ReadProperty(const AReader: TdxfReader); override;
    procedure ReadState(AReader: TdxfReader); override;
  end;

  TdxfArc = class(TdxfCircle)
  protected
    procedure Commit(const AReader: TdxfReader); override;
  end;

  TdxfAttdef = class(TdxfText)
  private
    FCodeValue: Integer;
    FXDataAppName: string;
    FLockPosition: Integer;
    procedure NextInteger(const AReader: TdxfReader); virtual;
  protected
    constructor Create; override;
    procedure Commit(const AReader: TdxfReader); override;
    procedure ReadProperty(const AReader: TdxfReader); override;
  end;

{$IFDEF SG_BTI}
  TdxfAttrib = class(TdxfAttdef)
  private
    FAttribType: Integer;
    procedure NextInteger(const AReader: TdxfReader); override;
  protected
    constructor Create; override;
    procedure Commit(const AReader: TdxfReader); override;
  end;
{$ENDIF}

  TdxfBlockRecord = class(TdxfObject)
  private
    FFlags: Integer;
    FLayout: UInt64;
  protected
    procedure Commit(const AReader: TdxfReader); override;
    procedure ReadProperty(const AReader: TdxfReader); override;
  end;

  TdxfDimension = class(TdxfInsert)
  private
    FExtHandled: Boolean;
    FExtCode: Integer;
    FProperties: TsgDXFDimensionProperties;
    procedure ExtHandleValue(const AReader: TdxfReader; var AHandled: Boolean);
    procedure ExtFloatValue(const AReader: TdxfReader; var AHandled: Boolean);
    procedure ExtIntValue(const AReader: TdxfReader; var AHandled: Boolean);
    procedure OverrideProperties;
    function GetProperties: TsgDXFDimensionProperties;
  protected
    destructor Destroy; override;
    procedure Commit(const AReader: TdxfReader); override;
    procedure ReadProperty(const AReader: TdxfReader); override;
    property Properties: TsgDXFDimensionProperties read GetProperties;
  end;

  TdxfDimStyle = class(TdxfPenTableItem)
  protected
    procedure Commit(const AReader: TdxfReader); override;
    procedure ReadProperty(const AReader: TdxfReader); override;
  end;

  TdxfEllipse = class(TdxfArc)
  protected
    constructor Create; override;
    procedure Commit(const AReader: TdxfReader); override;
  end;

  TdxfFace = class(TdxfSolid)
  protected
    procedure Commit(const AReader: TdxfReader); override;
  end;

  TdxfField = class(TdxfObject)
  private
    FBuffSize: Integer;
    FBytesRead: Integer;
    FData: PByte;
    FReadCache: Boolean;
    FReadDataSet: Boolean;
    FReadFieldObject: Boolean;
    FDictionary: UInt64;
  protected
    destructor Destroy; override;
    procedure Commit(const AReader: TdxfReader); override;
    procedure ReadProperty(const AReader: TdxfReader); override;
  end;

  TdxfFieldList = class(TdxfObject)
  private
    FOwnerDictionary: UInt64;
    FAcDbIdSet: Boolean;
  protected
    procedure Commit(const AReader: TdxfReader); override;
    procedure ReadProperty(const AReader: TdxfReader); override;
  end;

  TdxfHelix = class(TdxfSpline)
  private
    FLock: Boolean;
  protected
    procedure Commit(const AReader: TdxfReader); override;
    procedure ReadProperty(const AReader: TdxfReader); override;
  end;

  TdxfImageEnt = class(TdxfWipeout)
  private
    FImageDef: UInt64;
    FData: PByte;
    FSize: Integer;
    procedure AddData(const S: AnsiString);
  protected
    procedure Commit(const AReader: TdxfReader); override;
    procedure ReadProperty(const AReader: TdxfReader); override;
  public
    destructor Destroy; override;
  end;

  TdxfLayer = class(TdxfPenTableItem)
  protected
    constructor Create; override;
    procedure Commit(const AReader: TdxfReader); override;
    procedure ReadProperty(const AReader: TdxfReader); override;
  end;

  TdxfLeader = class(TdxfSpline)
  private
    FArrowScale: Double;
    FArrowSize: Double;
    FBlockRefHandle: UInt64;
    FCodeValue: Integer;
    FTextAnnotationHeight: Double;
    FTextAnnotationWidth: Double;
    FHookline: Integer;
    FHooklineDirectional: Integer;
    FHooklineVector: TFPoint;
    FAnnotationType: Integer;
    FTAD: Integer;
    FGAP: Double;
    FHRefAsAnnotation: UInt64;
  protected
    constructor Create; override;
    procedure Commit(const AReader: TdxfReader); override;
    procedure ReadProperty(const AReader: TdxfReader); override;
    procedure SetDegreeSplineCurve; override;
  end;

  TdxfLType = class(TdxfPenTableItem)
  private
    FElement: PsgLTypeElement;
    function GetElement: PsgLTypeElement;
    property Element: PsgLTypeElement read GetElement;
  protected
    procedure ReadProperty(const AReader: TdxfReader); override;
  end;

  TdxfLWPline = class(TdxfPolyLine)
  private
    FNewVertex: Boolean;
    procedure AddVertex;
  protected
    procedure Commit(const AReader: TdxfReader); override;
    procedure ReadProperty(const AReader: TdxfReader); override;
    procedure SetElevation; override;
  end;

  TdxfStyle = class(TdxfPenTableItem)
  protected
    constructor Create; override;
    procedure Commit(const AReader: TdxfReader); override;
    function GetPrimaryFont: string;
    procedure ReadProperty(const AReader: TdxfReader); override;
  end;

  TdxfTrace = class(TdxfSolid)
  end;

  TdxfRasterVariables = class(TdxfEntity)
  protected
    procedure Commit(const AReader: TdxfReader); override;
    procedure ReadProperty(const AReader: TdxfReader); override;
    procedure SetLayerByName(AReader: TdxfReader; const AName: string); override;
  end;

{$IFDEF DATA_LINK}
  TdxfDataLink = class(TdxfEntity)
  private
    FCustomData: Boolean;
  protected
    procedure Commit(const AReader: TdxfReader); override;
    procedure ReadProperty(const AReader: TdxfReader); override;
  end;
{$ENDIF}

  TdxfXRecord = class(TdxfObject)
  private
    FSoftOwner: TsgDXFEntity;
    FStartData: Boolean;
    FBinData: Pointer;
    procedure AddExData(const AReader: TdxfReader);
  protected
    destructor Destroy; override;
    procedure Commit(const AReader: TdxfReader); override;
    function OwnerAdd: Integer; override;
    procedure ReadProps(AReader: TdxfReader); override;
    procedure ReadProperty(const AReader: TdxfReader); override;
  end;

const
  cnstNamesToEntsAndClasses: array [0 ..{$IFDEF DATA_LINK} 75 {$ELSE} 74 {$ENDIF}] of record
    Name: string;
    Entity: TsgDXFEntityClass;
    EntityClass: TdxfObjectClass;
  end  =
 ((Name: cnstSeqEnd; Entity: nil; EntityClass: TdxfSeqend),
  (Name: 'VERTEX'; Entity: TsgDXFVertex; EntityClass: TdxfVertex),
  (Name: 'LINE'; Entity: TsgDXFLine; EntityClass: TdxfLine),
  (Name: 'SOLID'; Entity: TsgDXFSolid; EntityClass: TdxfSolid),
  (Name: 'CIRCLE'; Entity: TsgDXFCircle; EntityClass: TdxfCircle),
  (Name: 'ARC'; Entity: TsgDXFArc; EntityClass: TdxfArc),
  (Name: 'ELLIPSE'; Entity: TsgDXFEllipse; EntityClass: TdxfEllipse),
  (Name: 'DIMENSION'; Entity: TsgDXFDimension; EntityClass: TdxfDimension),
  (Name: 'LEADER'; Entity: TsgDXFLeader; EntityClass: TdxfLeader),
  (Name: 'LTYPE'; Entity: TsgDXFLineType; EntityClass: TdxfLType),
  (Name: 'LAYER'; Entity: TsgDXFLayer; EntityClass: TdxfLayer),
  (Name: 'BLOCK_RECORD'; Entity: TsgDXFBlockRecord;
    EntityClass: TdxfBlockRecord),
  (Name: 'POLYLINE'; Entity: TsgDXFPolyline; EntityClass: TdxfPolyline),
  (Name: 'LWPOLYLINE'; Entity: TsgDXFLWPolyline; EntityClass: TdxfLWPline),
  (Name: 'SPLINE'; Entity: TsgDXFSpline; EntityClass: TdxfSpline),
  (Name: 'HATCH'; Entity: TsgCADHatch; EntityClass: TDXFHatch),
  (Name: 'INSERT'; Entity: TsgDXFInsert; EntityClass: TdxfInsert),
  (Name: 'TEXT'; Entity: TsgDXFText; EntityClass: TdxfText),
  (Name: 'MTEXT'; Entity: TsgDXFMText; EntityClass: TdxfMText),
  (Name: 'ATTDEF'; Entity: TsgDXFAttdef; EntityClass: TdxfAttdef),
  (Name: 'VIEWPORT'; Entity: TsgDXFViewport; EntityClass: TdxfViewport),
  (Name: 'TABLE'; Entity: TsgDXFTable; EntityClass: TdxfTable),
  (Name: 'BLOCK'; Entity: TsgDXFBlock; EntityClass: TdxfBlock),
  (Name: 'VPORT'; Entity: TsgDXFVport; EntityClass: TdxfVport),
  (Name: '3DFACE'; Entity: TsgDXF3dFace; EntityClass: TdxfFace),
  (Name: 'POINT'; Entity: TsgDXFPoint; EntityClass: TdxfPoint),
  (Name: 'ATTRIB'; Entity: TsgDXFAttrib; EntityClass: {$IFDEF SG_BTI}
    TdxfAttrib {$ELSE} TdxfAttdef {$ENDIF}),
  (Name: 'SECTION'; Entity: TsgDXFSection; EntityClass: TdxfTable),
  (Name: 'LAYOUT'; Entity: TsgDXFLayout; EntityClass: TdxfLayout),
  (Name: cnstEndSec; Entity: nil; EntityClass: TdxfEndSeq),
  (Name: 'ENDTAB'; Entity: nil; EntityClass: TdxfEndTab),
  (Name: 'ENDBLK'; Entity: nil; EntityClass: TdxfEndBlock),
  (Name: 'EOF'; Entity: nil; EntityClass: TdxfSeqend),
  (Name: 'IMAGE'; Entity: TsgDXFImageEnt; EntityClass: TdxfImageEnt),
  (Name: 'IMAGEDEF'; Entity: TsgDXFImageDef; EntityClass: TdxfImageDef),
  (Name: 'STYLE'; Entity: TsgDXFStyle; EntityClass: TdxfStyle),
  (Name: 'DIMSTYLE'; Entity: TsgDXFDimensionStyle; EntityClass: TdxfDimStyle),
  (Name: 'REGION'; Entity: TsgDXFRegion; EntityClass: TdxfACIS),
  (Name: '3DSOLID'; Entity: TsgDXF3dSolid; EntityClass: TdxfACIS),
  (Name: 'BODY'; Entity: TsgDXFBody; EntityClass: TdxfACIS),
  (Name: 'SORTENTSTABLE'; Entity: TsgDXFSortEntsTable;
    EntityClass: TdxfSortEntsTable),
  (Name: 'ACAD_TABLE'; Entity: TsgDXFAcadTable; EntityClass: TdxfAcadTable),
  (Name: 'OLEFRAME'; Entity: TsgDXFOle2Frame; EntityClass: TdxfOLE),
  (Name: 'OLE2FRAME'; Entity: TsgDXFOle2Frame; EntityClass: TdxfOLE),
  (Name: 'DIMASSOC'; Entity: nil; EntityClass: TdxfDimAssoc),
  (Name: '3DLINE'; Entity: TsgDXFLine; EntityClass: TdxfLine),
  (Name: 'ACAD_PROXY_ENTITY'; Entity: TsgDXFProxy; EntityClass: TdxfProxy),
  (Name: 'TOLERANCE'; Entity: TsgDXFTolerance; EntityClass: TdxfTolerance),
  (Name: 'TRACE'; Entity: TsgDXFTrace; EntityClass: TdxfTrace),
  (Name: 'SHAPE'; Entity: TsgDXFShape; EntityClass: TdxfShape),
  (Name: 'WIPEOUT'; Entity: TsgCADWipeout; EntityClass: TdxfWipeout),
  (Name: 'WIPEOUTVARIABLES'; Entity: TsgCADWipeoutVariables; EntityClass: TdxfWipeoutVars),
  (Name: 'HELIX'; Entity: TsgCADHelix; EntityClass: TdxfHelix),
  (Name: 'MLINE'; Entity: TsgCADMLine; EntityClass: TdxfMLine),
  (Name: 'MLINESTYLE'; Entity: TsgMLineStyle; EntityClass: TdxfMLStyle),
  (Name: 'MPOLYGON'; Entity: TsgCADMPolygon; EntityClass: TdxfHatch),
  (Name: cntClassDXFTABLESTYLE; Entity: TsgDXFAcadTableStyle;
    EntityClass: TdxfAcadTableStyle),
  (Name: cnstDictionary; Entity: TsgDXFDictionary; EntityClass: TdxfDictionary),
  (Name: ''; Entity: nil; EntityClass: TdxfEntity),
  (Name: 'MESH'; Entity: TsgDXFProxy; EntityClass: TdxfMesh),
  (Name: 'PLANESURFACE'; Entity: TsgDXFRegion; EntityClass: TdxfACIS),
  (Name: 'FIELD'; Entity: TsgDXFField; EntityClass: TdxfField),
  (Name: cnstObjectsFIELDLIST; Entity: TsgDXFFieldList; EntityClass: TdxfFieldList),
  (Name: sRasterVariables; Entity: TsgCADRasterVariables; EntityClass: TdxfRasterVariables),
  (Name: cnstObjectsPLOTSETTINGS; Entity: TsgDXFPlotSettings; EntityClass: TdxfPlotSettings),
  (Name: cnstDictionaryVar; Entity: TsgDXFDictionaryVar; EntityClass: TdxfDictionaryVar),
  (Name: 'SURFACE'; Entity: TsgDXFRegion; EntityClass: TdxfACIS),

  (Name: cnstSectionTABLES; Entity: TsgDXFSectionTables; EntityClass: TdxfTables),
  (Name: cnstSectionBLOCKS; Entity: TsgDXFSectionBlocks; EntityClass: TdxfBlocks),
  (Name: cnstSectionENTITIES; Entity: TsgDXFSection; EntityClass: TdxfEntities),
  (Name: cnstSectionOBJECTS; Entity: TsgDXFSectionObjects; EntityClass: TdxfObjects),
  (Name: cnstSectionCLASSES; Entity: TsgDXFSection; EntityClass: TdxfClasses),
  (Name: cnstSectionHEADER; Entity: TsgDXFSection; EntityClass: TdxfHeader),
  (Name: 'THUMBNAILIMAGE'; Entity: TsgDXFSection; EntityClass: TdxfCustomSection),
  (Name: 'XRECORD'; Entity: TsgDXFXRecord; EntityClass: TdxfXRecord)
{$IFDEF DATA_LINK}
  ,(Name: 'DATALINK'; Entity: TsgCADDataLink; EntityClass: TdxfDataLink)
{$ENDIF}
  );

  sHexBin: array[Byte] of Byte = ($FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF,
    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF,
    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF,
    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
    $FF, $FF, $FF, $FF, $FF, $FF, $FF, 10, 11, 12, 13, 14, 15, $FF, $FF, $FF,
    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF,
    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, 10, 11, 12, 13, 14, 15, $FF, $FF,
    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF,
    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF,
    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF,
    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF,
    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF,
    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF,
    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF,
    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF,
    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF,
    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF,
    $FF);

var
  CF_DXF: Word;
  ListOfEntName: TsgStringList;
  HeadVars: TStringList = nil;
  DataBaseSections: TsgStringList = nil;

{Fuctions}

{$IFDEF SG_BTI}
procedure ApplyAttribsList(AXData: TsgExtendedBlockData;
  const AAttribs, ATypes: string);
var
  vValues, vEnumValues, vAttribsList, vAttribsTypes: TStringList;
  vAttribType: TsgAttribType;
  I, vAttrTypeInt: Integer;
  vName, vValue: string;
begin
  vAttribsList := TStringList.Create;
  vAttribsTypes := TStringList.Create;
  try
    try
      vAttribsList.LineBreak := sStringBreak;
      vAttribsList.Text := AAttribs;
      vAttribsTypes.LineBreak := sStringBreak;
      vAttribsTypes.Text := ATypes;
    finally
    end;
    if vAttribsTypes.Count = vAttribsList.Count then
    begin
      vValues := TStringList.Create;
      try
        vValues.LineBreak := cnstEnumValuesDelimiter;
        for I := 0 to vAttribsList.Count - 1 do
        begin
          vName := vAttribsList.Names[I];
          vValues.Text := vAttribsList.Values[vName];
          vValue := '';
          vEnumValues := nil;
          vAttrTypeInt := StrToIntDef(vAttribsTypes[I], 0);
          if (vAttrTypeInt < 0) or (vAttrTypeInt > 1) then
            vAttrTypeInt := 0;
          case vAttrTypeInt of
            1:
              begin
                vAttribType := atEnum;
                vEnumValues := vValues;
              end;
          else
          begin
            vAttribType := atString;
            if vValues.Count > 0 then
              vValue := vValues[0];
          end;
          end;
          AXData.AddAttribute(vName, vValue, vAttribType, vEnumValues);
        end;
      finally
        vValues.Free;
      end;
    end;
    if ATypes <> '' then
    begin
    end;
  finally
    vAttribsTypes.Free;
    vAttribsList.Free;
  end;
end;
{$ENDIF}

procedure AddBinData(const S: AnsiString; var AData: Pointer; var ASize: Integer);
var
  C: Integer;
  vData: PByte;
  vSrc: TsgNativeUInt;
begin
  C := Length(S) div 2;
  ReallocMem(AData, ASize + C);
  vData := AData;
  Inc(vData, ASize);
  Inc(ASize, C);
  vSrc := TsgNativeUInt(Pointer(S));
  while C > 0 do
  begin
    vData^ := sHexBin[PByte(vSrc)^] shl 4 or sHexBin[PByte(vSrc + 1)^];
    Inc(vData);
    Inc(vSrc, 2);
    Dec(C);
  end;
end;

procedure BinStr(var AString: AnsiString; var APPosition: PAnsiChar;
  APLimitParse: PAnsiChar);
var
  vPStartPosition: PAnsiChar;
  vLength: Integer;
begin
  vPStartPosition := APPosition;
  while (APPosition < APLimitParse)  and (APPosition^ <> #0) do
    Inc(APPosition);
  vLength := APPosition - vPStartPosition;
  if APPosition <> APLimitParse  then
    Inc(APPosition);
  SetLength(AString, vLength);
  if vLength > 0 then
    Move(vPStartPosition^, AString[1], vLength);
end;

procedure ClearStringList(AList: TStringList);
var
  I: Integer;
  vPointer: Pointer;
begin
  for I := AList.Count - 1 downto 0 do
  begin
    vPointer := AList.Objects[I];
    if vPointer <> nil then
      Dispose(vPointer);
  end;
  AList.Clear;
end;

procedure ClearCollectionObjects(AList: TsgCollection);
var
  I: Integer;
begin
  for I := 0 to AList.High do
    TObject(AList[I].Data).Free;
  AList.Clear;
end;

procedure FreeCollectionObjects(var AList: TsgCollection);
begin
  ClearCollectionObjects(AList);
  FreeAndNil(AList);
end;

procedure ClearStringsObjects(const AList: TStrings);
var
  vObj: TObject;
begin
  while AList.Count > 0 do
  begin
    vObj := AList.Objects[AList.Count - 1];
    AList.Delete(AList.Count - 1);
    vObj.Free;
  end;
end;

procedure FreeStringsObjects(var AList: TStrings);
begin
  ClearStringsObjects(AList);
  FreeAndNil(AList);
end;

function ExpandLWeight(const ALWeight: Double): Double;
begin
  if ALWeight <= 0 then
    Result := ALWeight
  else
    Result := 0.01 * ALWeight;
end;

function GetArrowTypeByHandle(const ABlockRefHandle: UInt64;
  const AConverter: TsgDXFConverter): Integer;
var
  vName: string;
begin
  vName := Trim(TsgDXFConverterAccess(AConverter).BlockRecordNameByHandle(
    ABlockRefHandle));
  Result := StrIndex(vName, sgDimensionArrowTypeNames);
end;

function GetOnefromZero(const AValue: Double): Double;
begin
  if AValue <> 0 then
    Result := AValue
  else
    Result := 1;
end;

procedure PreLinkObjects(const AObjects: TsgDXFEntity;
  const AConv: TsgDXFConverter);
var
  L: Integer;
  NamedObjects, SortEntsTables, ImageDefs: TsgDXFDictionary;
  vObj, Dict: TsgDXFEntity;
  vList: TList;

  function DictByName(const AConv: TsgDXFConverter; const AName, ADictItemName: string): TsgDXFDictionary;
  var
    E: TsgDXFEntity absolute Result;
    vState: TConvStatus;
  begin
    E := AConv.Sections[csObjects].FindEntByName(AName);
    if not Assigned(E) then
    begin
      vState := TsgDXFConverterAccess(AConv).Status;
      TsgDXFConverterAccess(AConv).Status := stDefault;
      Result := TsgDXFDictionary.Create;
      TsgDXFConverterAccess(AConv).SetHandle(Result);
      Result.Name := AName;
      AConv.Sections[csObjects].AddEntity(Result);
      TsgDXFConverterAccess(AConv).Status := vState;
    end;
  end;

  function DoSection(ADict: TsgDXFDictionary;
    const AName: string; const ASection: TsgDXFGroup;
    const AAliasName: string = ''): TsgDXFEntity;
  var
    K: Integer;
    Item, DictItem: TsgDXFEntity;
    OldE, Obj: TsgDXFEntity;
    E: TsgDXFEntity absolute Result;
  begin
    E := nil;
    DictItem := ADict.FindEntByName(AName);
    if Assigned(DictItem) then
    begin
      E := AObjects.FindEntByHandle(DictItem.Handle);
      if Assigned(E) then
      begin
        OldE := ASection;
        if Assigned(OldE) then
        begin
          AObjects.RemoveEntity(OldE);
          if OldE <> E then
            OldE.Free;
        end;
        K := 0;
        while K < E.Count do
        begin
          Item := E[K];
          Obj := AObjects.FindEntByHandle(Item.Handle);
          if Assigned(Obj) then
          begin
            Obj.Name := Item.Name;
            AObjects.RemoveEntity(Obj);
            TsgDXFEntityAccess(E).SetEntity(K, Obj);
            Inc(K);
          end
          else
            E.DeleteEntity(K);
          Item.Free;
        end;
        //if E.Count > 0 then
        begin
          if AObjects.IndexOfEntity(E) < 0 then
            AObjects.AddEntity(E);
          if AAliasName <> '' then
            E.Name := AAliasName
          else
            E.Name := AName;
        end
//          else
//          begin
//            AObjects.RemoveEntity(E);
//            FreeAndNil(E);
//          end;
      end;
    end;
  end;

begin
  if AObjects.Count > 0 then
  begin
    vList := TList.Create;

    NamedObjects := TsgDXFDictionary(AObjects[0]);
    ImageDefs := nil;
    vList.Add(NamedObjects);

    if Assigned(NamedObjects) then
    begin
      for L := 0 to NamedObjects.Count - 1 do
      begin
        Dict := AObjects.FindEntByHandle(NamedObjects[L].Handle);
        if Assigned(Dict) then
          Dict.Name := NamedObjects[L].Name;
      end;

      vObj := DoSection(NamedObjects, sAcadLayoutDictionary, AConv.Sections[csLayouts], cnstObjectsLAYOUTS);
      vList.Add(vObj);
      vObj := DoSection(NamedObjects, sAcadImageDict, AConv.Sections[csImageDefs], cnstObjectsIMAGEDEFS);
      ImageDefs := TsgDXFDictionary(vObj);
      vList.Add(vObj);
      vObj := DoSection(NamedObjects, sAcadMLineStyleDictionary, AConv.Sections[csMLineStyles], cnstObjectsMLINESTYLES);
      vList.Add(vObj);
      vObj := DoSection(NamedObjects, sAcadTableStyleDictionary, AConv.Sections[csTableStyles], cnstObjectsTABLESTYLES);
      vList.Add(vObj);
      vObj := DoSection(NamedObjects, sAcadFieldListDictionary, nil, cnstObjectsFIELDLIST);
      vList.Add(vObj);
      vObj := DoSection(NamedObjects, sAcadPlotSettingsDictionary, nil, cnstObjectsPLOTSETTINGS);
      vList.Add(vObj);
      vObj := DoSection(NamedObjects, sAcDbVariableDictionary, nil, sAcDbVariableDictionary);
      vList.Add(vObj);
{$IFDEF DATA_LINK}
      vObj := DoSection(NamedObjects, sDictionaryAcadDataLink, nil, sDictionaryAcadDataLink);
      vList.Add(vObj);
{$ENDIF}
    end;

    SortEntsTables := DictByName(AConv, sDictionaryVarSORTENTS, sAcadSortEnts);

    vList.Add(SortEntsTables);
    vList.Add(AConv.FieldList);
    for L := 0 to AObjects.Count - 1 do
      if AObjects[L].ClassType = TsgDXFSortEntsTable then
        SortEntsTables.AddEntity(AObjects[L])
      else
        if AObjects[L].ClassType = TsgDXFField then
          AConv.FieldList.AddEntity(AObjects[L])
        else
          if AObjects[L].ClassType = TsgDXFImageDef then
            if Assigned(ImageDefs) then
              ImageDefs.AddEntity(AObjects[L]);

    for L := 0 to SortEntsTables.Count - 1 do
      AObjects.RemoveEntity(SortEntsTables[L]);
    for L := 0 to AConv.FieldList.Count - 1 do
      AObjects.RemoveEntity(AConv.FieldList[L]);

    if Assigned(ImageDefs) then
      for L := 0 to ImageDefs.Count - 1 do
        AObjects.RemoveEntity(ImageDefs[L]);

    for L := 0 to vList.Count - 1 do
      if vList[L] <> nil then
        AObjects.RemoveEntity(TsgDXFEntity(vList[L]));

    vObj := AObjects.FindEntByName(sAcadImageVars);
    if Assigned(vObj) then
    begin
      AObjects.RemoveEntity(vObj);
      vObj.Name := sRasterVariables;
      vList.Add(vObj);
    end;
    vObj := AObjects.FindEntByName(sAcadWipeOutVarsDictionary);
    if Assigned(vObj) then
    begin
      AObjects.RemoveEntity(vObj);
      vObj.Name := cntClassDXFWIPEOUTVARIABLES;
      vList.Add(vObj);
    end;

    AObjects.Clear;
    for L := 0 to vList.Count - 1 do
      if vList[L] <> nil then
      begin
        if AObjects.IndexOfEntity(vList[L]) < 0 then
          AObjects.AddEntity(TsgDXFEntity(vList[L]));
      end;

    if SortEntsTables.Count <= 0 then
    begin
      AObjects.RemoveEntity(SortEntsTables);
      SortEntsTables.Free;
    end;

    if AConv.FieldList.Count <= 0 then
    begin
      vObj := AConv.FieldList;
      AObjects.RemoveEntity(AConv.FieldList);
      vObj.Free;
    end;

    vList.Free;
  end;
end;

procedure InitDataBaseSections;
begin
  DataBaseSections := TsgStringList.Create;
  DataBaseSections.CaseSensitive := False;

  DataBaseSections.AddObject(cnstTableBLOCK_RECORD, TObject(csBlockRecords));
  DataBaseSections.AddObject(cnstTableDIMSTYLE, TObject(csDimStyles));
  DataBaseSections.AddObject(cnstTableLTYPE, TObject(csLTypes));
  DataBaseSections.AddObject(cnstTableLAYER, TObject(csLayers));
  DataBaseSections.AddObject(cnstTableSTYLE, TObject(csStyles));
  DataBaseSections.AddObject(cnstTableVPORT, TObject(csVPorts));

  DataBaseSections.Sort;
end;

procedure InitListOfEntName;
var
  I, vLow, vHigh: Integer;
  vEntClass: PEntClass;
begin
  vLow := Low(cnstNamesToEntsAndClasses);
  vHigh := High(cnstNamesToEntsAndClasses);
  ListOfEntName.Capacity := vHigh - vLow + 1;
  ListOfEntName.CaseSensitive := False;
  ListOfEntName.Sorted := False;
  for I := vLow to vHigh do
  begin
    New(vEntClass);
    ListOfEntName.AddObject(cnstNamesToEntsAndClasses[I].Name,
      TObject(vEntClass));
    vEntClass.Ent := cnstNamesToEntsAndClasses[I].Entity;
    vEntClass.EntClass := cnstNamesToEntsAndClasses[I].EntityClass;
  end;
  ListOfEntName.Sorted := True;
end;

function IndexHeadVar(const AName: string): Integer;
const
  cnstHVars: array[0..55] of string = ('$HANDSEED', '$DIMALT', '$DIMALTF',
    '$DIMAPOST', '$DIMCLRD', '$DIMCLRE', '$DIMCLRT', '$DIMEXE', '$DIMEXO',
    '$DIMGAP', '$DIMLFAC', '$DIMPOST', '$MEASUREMENT', '$UCSORG', '$UCSXDIR',
    '$UCSYDIR', '$DWGCODEPAGE', '$PDMODE', '$TILEMODE', '$LTSCALE', '$DIMASZ',
    '$DIMSCALE', '$DIMSTYLE', '$PDSIZE', '$ACADVER', '$CECOLOR', '$CLAYER',
    '$CELTYPE', '$CELTSCALE', '$CELWEIGHT', '$DIMDEC', '$DIMTAD', '$DIMTIH',
    '$DIMTIX', '$DIMTOH', '$DIMBLK', '$DIMBLK1', '$DIMBLK2', '$DIMLDRBLK',
    '$DIMTXT', '$TEXTSIZE', '$FILLETRAD', '$INSUNITS', '$DIMTXSTY',
    '$TEXTSTYLE', '$EXTMIN', '$EXTMAX', '$INSBASE', cnstAttMode,
    '$DIMSE1', '$DIMSE2', '$DIMSD1', '$DIMSD2', '$DIMLWD', '$DIMLWE', '$DIMSAH');
var
  I: Integer;
begin
  Result := -1;
  if HeadVars = nil then
  begin
    HeadVars := TStringList.Create;
{$IFDEF SG_DEL6}
    HeadVars.CaseSensitive := True;
{$ENDIF}
    HeadVars.Duplicates := dupIgnore;
    for I := Low(cnstHVars) to High(cnstHVars) do
       HeadVars.AddObject(cnstHVars[I], TObject(I));
    HeadVars.Sorted := True;
  end;
  I := HeadVars.IndexOf(AnsiUpperCase(AName));
  if I > -1 then
    Result := Integer(HeadVars.Objects[I]);
end;

function IsBinaryDXF(AStream: TStream; var AGroupCodeSize: Integer): Boolean;
const
  cnstBin: array[0..21] of AnsiChar = 'AutoCAD Binary DXF'#13#10#26#0;
var
  vSize: Integer;
  Buf: array[0..21] of AnsiChar;
begin
  vSize := AStream.Read(Buf,22);
  Result := (vSize=22) and CompareMem(@cnstBin,@Buf,22);
  if Result then
  begin
    // Binary DXF-format version detection
    AGroupCodeSize := 0;
    vSize := AStream.Read(AGroupCodeSize, 2);
    if AGroupCodeSize <> 0 then
      AGroupCodeSize := 1
    else
      AGroupCodeSize := 2;
  end;
  AStream.Position := AStream.Position - vSize;
end;

procedure SeekEoln(var APos: PAnsiChar);{$IFDEF SG_INLINE} inline;{$ENDIF}
begin
  while not (APos^ in [#10, #13]) do
    Inc(APos);
end;

procedure SeekEoStr(var APos: PAnsiChar);{$IFDEF SG_INLINE} inline;{$ENDIF}
begin
  while APos^ <> #0 do
    Inc(APos);
end;

procedure SkeepBlanks(var APos: PAnsiChar);{$IFDEF SG_INLINE} inline;{$ENDIF}
begin
  while APos^ = ' ' do
    Inc(APos);
end;

procedure SkeepLimits(var APos: PAnsiChar);{$IFDEF SG_INLINE} inline;{$ENDIF}
begin
  //if APos < ALimit then // not need because additional eoln (see procedure TsgDXFConverter.SetSourceStream)
  begin
    if APos^ = #13 then
      Inc(APos);
    if APos^ = #10 then
      Inc(APos);
  end;
end;

function IsNeg(var APos: PAnsiChar): Boolean;{$IFDEF SG_INLINE} inline;{$ENDIF}
begin
  Result := APos^ = '-';
  if Result then
    Inc(APos)
  else
    if APos^ = '+' then
      Inc(APos);
end;

function DoIntValue(var APos: PAnsiChar;
  var AValue: Integer): Boolean;{$IFDEF SG_INLINE} inline;{$ENDIF}
begin
  while APos^ in ['0' .. '9'] do
  begin
    AValue := AValue * 10 + Ord(APos^) - Ord('0');
    Inc(APos);
  end;
  Result := APos^ in [#10, #13];
end;

procedure DoDoubleValue(var APos: PAnsiChar;
  var AValue: Double);{$IFDEF SG_INLINE} inline;{$ENDIF}
begin
  while APos^ in ['0' .. '9'] do
  begin
    AValue := AValue * 10 + Ord(APos^) - Ord('0');
    Inc(APos);
  end;
end;

function DoHandleValue(var APos: PAnsiChar;
  var AValue: UInt64): Boolean;{$IFDEF SG_INLINE} inline;{$ENDIF}
var
  vHexBin: Byte;
begin
  AValue := 0;
  repeat
    vHexBin := sHexBin[Ord(APos^)];
    Result := vHexBin <> $FF;
    if Result then
    begin
      AValue := AValue shl 4 or vHexBin;
      Inc(APos);
    end;
  until not Result;
  Result := APos^ in [#10, #13];
end;

{ TsgCADdxfImage }

{public}

constructor TsgCADdxfImage.Create;
begin
  inherited Create;
  CBFormat := CF_DXF;
end;

function TsgCADdxfImage.CreateConverter: TsgDXFConverter;
begin
  Result := TsgDXFConverter.CreateEx(GetConverterParams);
end;

function TsgCADdxfImage.IsAutocadLType: Boolean;
begin
  Result := True;
end;

procedure TsgCADdxfImage.LoadFromClipboardFormat(AFormat: Word;
  AClipboardObject: THandle; APalette: HPALETTE);
var
  vClipboardStream: TClipboardStream;
begin
  if AFormat = CF_DXF then
    AClipboardObject := GetClipboardData(CF_TEXT);
  if (AFormat <> CBFormat) or (AClipboardObject = 0)
  then
    raise EInvalidGraphic.Create('Invalid DXF data');
  vClipboardStream := TClipboardStream.Create(AClipboardObject);
  try
    LoadFromStream(vClipboardStream)
  finally
    vClipboardStream.Free
  end;
end;

procedure TsgCADdxfImage.LoadFromStream(AStream: TStream);
var
  vReader: TdxfReader;
  vGroupCodeSize: Integer;
{$IFDEF SG_DECRYPT_FILES}
  vStm, vOrigStream: TStream;
  vPos, vSrcPos: {$IFDEF SGDEL_4}Int64{$ELSE}Integer{$ENDIF};
  vIsDecoded: Boolean;
{$ENDIF}
begin
  inherited LoadFromStream(AStream);
{$IFDEF SG_DECRYPT_FILES}
  vOrigStream := nil;
  vPos := 0;
  vSrcPos := sgStmCrpt.DecryptStm(AStream, vStm);
  vIsDecoded := Assigned(vStm);
  try
    if vIsDecoded then
    begin
      vPos := vStm.Position;
      vOrigStream := AStream;
      AStream := vStm;
    end;
{$ENDIF}
    if IsBinaryDXF(AStream, vGroupCodeSize) then
      vReader := TdxfBinReader.Create(Converter, vGroupCodeSize)
    else
      vReader := TdxfReader.Create(Converter);
    Loading := Self;
    TsgDXFConverterAccess(Converter).CreateXDataProcs;
    try
      FMsg := sLoadFile;     // for OnProgress
      Converter.SetSourceStream(AStream);
  //    FConverter.Load;
      vReader.Read;
  {$IFNDEF SG_USEDXFSRC}
      Converter.Source := nil;//evg
  {$ENDIF}
      SetDefaultViewPort(Converter);
      GetExtents;
      if vReader.IsInternalCADImage then
        CheckActiveVPort;
    finally
      TsgDXFConverterAccess(Converter).DestroyXDataProcs;
      FileInfo := vReader.FileInfo;
      Loading := nil;
      vReader.Free;
    end;
{$IFDEF SG_DECRYPT_FILES}
  finally
    if vIsDecoded then
    begin
      vOrigStream.Position := vSrcPos + (vStm.Position - vPos);
      vStm.Free;
    end;
  end;
{$ENDIF}
end;

procedure TsgCADdxfImage.SaveToClipboardFormat(var AFormat: Word;
  var AClipboardObject: THandle; var APalette: HPALETTE);
var
  vClipboardStream: TClipboardStream;
begin
  AFormat := 0; AClipboardObject := 0; APalette := 0;
  if Converter.Source = nil then
    Exit;
  AFormat := CBFormat;
  vClipboardStream := TClipboardStream.Create(0);
  try
    SaveToStream(vClipboardStream);
    AClipboardObject := vClipboardStream.Handle;
  finally
    vClipboardStream.Free;
  end;
  if AFormat = CF_DXF then
  begin
    AFormat := CF_TEXT;
    SetClipboardData(CF_DXF, GlobalAlloc(GMEM_MOVEABLE, 4));
  end;
end;

{ TdxfReader }

{private}

function TdxfReader.CreateStringList: TStringList;
begin
  Result := TsgStringList.Create;
  TsgStringList(Result).CaseSensitive := False;
  TsgStringList(Result).Duplicates := dupIgnore;
  TsgStringList(Result).Sort;
end;

procedure TdxfReader.DoCreate(AEntity: TsgDXFEntity);
begin
  FConverter.DoCreate(AEntity);
end;

procedure TdxfReader.DoEvent(Event: TNotifyEvent);
begin
  if Assigned(Event) then
    Event(FConverter);
end;

function TdxfReader.EOF: Boolean;
const
  cnstEOF = $00464F45; // 'EOF'#0
begin
  Result := ((FValueSize = 3) and
    ((PInteger(FValueStartPos)^ and $00FFFFFF) xor cnstEOF = 0)) or
    (FPos >= FLimit);
end;

function TdxfReader.GetConv: TsgDXFConverterAccess;
begin
  Result := TsgDXFConverterAccess(FConverter);
end;

function TdxfReader.GetFileInfo: string;
begin
  if FFileInfo.Count > 0 then
    Result := FFileInfo[FFileInfo.Count - 1]
  else
    Result := '';
end;

function TdxfReader.GetDimStyles(Name: string): TObject;
begin
  if Conv.Counts[csDimStyles] > 0 then
    Result := Conv.Sections[csDimStyles].FindEntByName(Name)
  else
    Result := nil;
  if not Assigned(Result) then
    Result := ForceLink(FDimStyleLinks, Name);
end;

function TdxfReader.GetStyles(Name: string): TObject;
begin
  if Name = '' then
    Name := sStandardName;
  if Conv.Counts[csStyles] > 0 then
    Result := Conv.Sections[csStyles].FindEntByName(Name)
  else
    Result := nil;
  if not Assigned(Result) then
    Result := ForceLink(FStyleLinks, Name);
end;

function TdxfReader.GetHDictionary(Handle: UInt64): TObject;
begin
  Result := nil;
  if Handle <> cnstBadHandle then
  begin
    Result := Conv.Sections[csObjects].FindEntByHandle(Handle);
    if not Assigned(Result) then
      Result := ForceLink(FDictHLinks, Handle);
  end;
end;

function TdxfReader.GetHFields(Handle: UInt64): TObject;
begin
  Result := nil;
  if Handle <> cnstBadHandle then
  begin
    Result := Conv.FieldList.FindEntByHandle(Handle);
    if not Assigned(Result) then
      Result := ForceLink(FFieldsHLinks, Handle);
  end;
end;

function TdxfReader.GetHImageDefs(Handle: UInt64): TObject;
begin
  Result := nil;
  if Handle <> cnstBadHandle then
  begin
    if Conv.Counts[csImageDefs] > 0 then
      Result := Conv.Sections[csImageDefs].FindEntByHandle(Handle);
    if not Assigned(Result) then
      Result := ForceLink(FImageDefsHLinks, Handle);
  end;
end;

function TdxfReader.GetHStyles(Handle: UInt64): TObject;
begin
  Result := nil;
  if Handle <> cnstBadHandle then
  begin
    if Conv.Counts[csStyles] > 0 then
      Result := Conv.Sections[csStyles].FindEntByHandle(Handle);
    if not Assigned(Result) then
      Result := ForceLink(FStyleHLinks, Handle);
  end;
end;

function TdxfReader.GetHTableStyles(Handle: UInt64): TObject;
begin
  Result := nil;
  if Handle <> cnstBadHandle then
  begin
    if Conv.Counts[csTableStyles] > 0 then
      Result := Conv.Sections[csTableStyles].FindEntByHandle(Handle);
    if not Assigned(Result) then
      Result := ForceLink(FTableStyleHLinks, Handle);
  end;
end;

function TdxfReader.GetLayers(Name: string): TObject;
begin
  if Name = '' then
    Name := '0';
  if Conv.Counts[csLayers] > 0 then
    Result := Conv.Sections[csLayers].FindEntByName(Name)
  else
    Result := nil;
  if not Assigned(Result) then
    Result := ForceLink(FLayerLinks, Name);
end;

function TdxfReader.GetLTypes(Name: string): TObject;
begin
  if Name = '' then
    Name := sByLayer;
  if Conv.Counts[csLTypes] > 0 then
    Result := Conv.Sections[csLTypes].FindEntByName(Name)
  else
    Result := nil;
  if not Assigned(Result) then
    Result := ForceLink(FLTypeLinks, Name);
end;

function TdxfReader.GetMHStyles(Handle: UInt64): TObject;
begin
  Result := nil;
  if Handle <> cnstBadHandle then
  begin
    if Conv.Counts[csMLineStyles] > 0 then
      Result := Conv.Sections[csMLineStyles].FindEntByHandle(Handle)
    else
      Result := nil;
    if not Assigned(Result) then
      Result := ForceLink(FMStyleHLinks, Handle);
  end;
end;

function TdxfReader.GetMStyles(Name: string): TObject;
begin
  if Name = '' then
    Name := sStandardName;
  if Conv.Counts[csMLineStyles] > 0 then
    Result := Conv.Sections[csMLineStyles].FindEntByName(Name)
  else
    Result := nil;
  if not Assigned(Result) then
    Result := ForceLink(FMStyleLinks, Name);
end;

function TdxfReader.GetHBlockRecords(Handle: UInt64): TObject;
var
  I: Integer;
begin
  Result := nil;
  if Handle <> cnstBadHandle then
  begin
    if Conv.Counts[csBlockRecords] > 0 then
      Result := Conv.Sections[csBlockRecords].FindEntByHandle(Handle)
    else
      Result := nil;
    if not Assigned(Result) then
    begin
      I := FBlockRecordHLinks.IndexOf(Handle);
      if I < 0 then
        I := FBlockRecordHLinks.Add(Handle, TsgLinkObject.Create(Handle));
      Result := FBlockRecordHLinks[I].Data;
    end;
  end;
end;

function TdxfReader.GetBlockRecords(Name: string): TObject;
begin
  Result := Conv.Sections[csBlockRecords].FindEntByName(Name);
  if not Assigned(Result) then
    Result := ForceLink(FBlockLinks, Name);
end;

function TdxfReader.GetStrValue: string;
{$IFDEF SGDEL_2009}
var
  vUtfLen: Integer;
  vAnsi: sgRawByteString;
{$ENDIF}
begin
{$IFDEF SGDEL_2009}
  vAnsi := Value;
  if Version >= Byte(acR2007) then
  begin
    vUtfLen := Utf8ToUnicode(nil, MaxInt, PAnsiChar(vAnsi), Cardinal(-1));
    SetLength(Result, vUtfLen - 1);
    Utf8ToUnicode(PChar(Result), vUtfLen - 1, PAnsiChar(vAnsi), Cardinal(-1));
  end
  else
  begin
    SetCodePage(vAnsi, FConverter.CodePage, False);
    Result := string(vAnsi);
  end;
{$ELSE}
  Result := string(Value);
{$ENDIF}
end;

function TdxfReader.GetUValue: string;
begin
{$IFDEF SGDEL_2009}
  Result := ParseUnicode(StrValue, [puU, puM]);
{$ELSE}
  Result := StrValue;
{$ENDIF}
end;

function TdxfReader.GetValue: AnsiString;
begin
  if FValueSize >= 0 then
  begin
    SetString(FValue, FValueStartPos, FValueSize);
    FValueSize := -1;
    Result := FValue;
  end
  else
    Result := FValue;
end;

function TdxfReader.GetVersion: Byte;
begin
  Result := FConverter.HeadVarStruct.Version;
end;

function TdxfReader.GetXDataProcs: TsgXDataProcs;
begin
  Result := TsgDXFConverterAccess(FConverter).XDataProcs;
end;

procedure TdxfReader.ReadDouble(var AValue: Double);
var
  vNeg, vNegExp: Boolean;
  vDigits, vExp: Integer;
  vTmp: Pointer;
  vResult: Boolean;
begin
  AValue := 0;
  vNeg := IsNeg(FPos);
  DoDoubleValue(FPos, AValue);
  vDigits := 0;
  if (FPos^ = '.') or (FPos^ = ',') then
  begin
    repeat
      Inc(FPos);
    until FPos^ in [#10, #13, '0' .. '9', 'E', 'e'];
    vTmp := FPos;
    DoDoubleValue(FPos, AValue);
    vDigits := vTmp - FPos;
  end;
  vExp := 0;
  if Ord(FPos^) or $20 = Ord('e') then
  begin
    Inc(FPos);
    vNegExp := IsNeg(FPos);
    vResult := DoIntValue(FPos, vExp);
    if vNegExp then
      vExp := -vExp;
  end
  else
    vResult := FPos^ in [#10, #13];
  if FPos^ = ' ' then
  begin
    SkeepBlanks(FPos);
    vResult := True;
  end;
  if vResult then
  begin
    vDigits := vDigits + vExp;
    if vDigits <> 0 then
      AValue := sgPower10(AValue, vDigits);
    if vNeg then
      AValue := -AValue;
  end
  else
  begin
    //AValue := 0;
    SeekEOL;
  end;
end;

procedure TdxfReader.ReadFileInfo;
var
  vValue: string;
  vCodePage: Integer;
begin
  vValue := AnsiUpperCase(UValue);
  FFileInfo.Add(vValue);
  if (AnsiPos('INVENTORY', vValue) > 0) then//for version inventory
  begin
    vCodePage := GetDWGCodePageByName('ANSI_1251');
    TsgDXFConverterAccess(FConverter).PHeadVarStruct^.CodePage := vCodePage;
  end;
end;

procedure TdxfReader.ReadInt(var AValue: Integer);
var
  vNeg: Boolean;
begin
  AValue := 0;
  vNeg := IsNeg(FPos);
  if not DoIntValue(FPos, AValue) then
  begin
    if FPos^ = ' ' then
    begin
      SkeepBlanks(FPos);
      if vNeg then
        AValue := -AValue;
    end
    else
    begin
      AValue := 0;
      SeekEOL;
    end;
  end
  else
    if vNeg then
      AValue := -AValue;
end;

procedure TdxfReader.ReadHandle(var AValue: UInt64);
begin
  AValue := 0;
  if not DoHandleValue(FPos, AValue) then
  begin
    if FPos^ = ' ' then
      SkeepBlanks(FPos)
    else
    begin
      AValue := 0;
      SeekEOL;
    end;
  end;
end;

procedure TdxfReader.SeekEOL;
begin
  SeekEoln(FPos);
end;

{public}

constructor TdxfReader.Create(Conv: TsgDXFConverter);
begin
  FSortents := 127;
  FConverter := Conv;
  FMain := TdxfMain.Create;
  TdxfMain(FMain).FConv := TsgDXFConverterAccess(Conv);
  FMain.FEnt := Conv.Main;
  FFileInfo := TStringList.Create;
  FValueSize := -1;

  FLayerLinks := CreateStringList;
  FLTypeLinks := CreateStringList;
  FBlockLinks := CreateStringList;
  FStyleLinks := CreateStringList;
  FStyleHLinks := TsgCollection.Create;
  FDimStyleLinks := CreateStringList;
  FBlockRecordHLinks := TsgCollection.Create;
  FMStyleLinks := CreateStringList;
  FMStyleHLinks := TsgCollection.Create;
  FTableStyleHLinks := TsgCollection.Create;
  FFieldsHLinks := TsgCollection.Create;
  FDictHLinks := TsgCollection.Create;
  FImageDefsHLinks := TsgCollection.Create;

  FStylesByFont := TsgStringList.Create;
  TsgStringList(FStylesByFont).CaseSensitive := False;
  TsgStringList(FStylesByFont).Duplicates := dupIgnore;
  TsgStringList(FStylesByFont).Sorted := True;

  FPapers := TsgDXFGroup.Create;
end;

destructor TdxfReader.Destroy;
begin
  FFileInfo.Free;
  FMain.Free;

  FreeStringsObjects(TStrings(FLayerLinks));
  FreeStringsObjects(TStrings(FLTypeLinks));
  FreeStringsObjects(TStrings(FBlockLinks));
  FreeStringsObjects(TStrings(FStyleLinks));
  FreeCollectionObjects(FStyleHLinks);
  FreeStringsObjects(TStrings(FDimStyleLinks));
  FreeCollectionObjects(FBlockRecordHLinks);
  FreeStringsObjects(TStrings(FMStyleLinks));
  FreeCollectionObjects(FMStyleHLinks);
  FreeCollectionObjects(FTableStyleHLinks);
  FreeCollectionObjects(FFieldsHLinks);
  FreeCollectionObjects(FDictHLinks);
  FreeCollectionObjects(FImageDefsHLinks);

  FStylesByFont.Free;

  FPapers.Clear(False);
  FPapers.Free;
end;

function TdxfReader.FloatValue: Double;
begin
  if CodeTypes^[FCode] <> ctDouble then
    FDouble := ConvToFloatDef(Trim(UValue), 0);
  Result := FDouble;
end;

procedure TdxfReader.ForceImageDefs;
var
  vNamed: TsgDXFDictionary;
  vItem: TsgDXFOwneredItem;
  vImageDefs: TsgDXFDictionary;
  vStat: TConvStatus;
begin
  ForceNamedObjectsDictionary;
  vNamed := TsgDXFDictionary(Conv.Sections[csObjects][0]);
  vItem := TsgDXFOwneredItem(vNamed.FindEntByName(sAcadImageDict));

  vStat := Conv.Status;
  Conv.Status := stDefault;

  if not Assigned(vItem) then
  begin
    vItem := TsgDXFOwneredItem.Create;
    vItem.Name := sAcadImageDict;
//    vItem.Dictionary := vNamed;
    Conv.SetHandle(vItem);
    vNamed.AddEntity(vItem);
  end;

  vImageDefs := TsgDXFDictionary(Conv.Sections[csObjects].FindEntByHandle(vItem.Handle));

  if not Assigned(vImageDefs) then
  begin
    vImageDefs := TsgDXFDictionary.Create;
    vImageDefs.Name := cnstDictionary;
    vImageDefs.Handle := vItem.Handle;
    Conv.Sections[csObjects].AddEntity(vImageDefs);
  end;

  Conv.Status := vStat;
end;

procedure TdxfReader.ForceLayouts;
var
  I, J: Integer;
  vFind: Boolean;
  vNamed: TsgDXFDictionary;
  vItem: TsgDXFOwneredItem;
  vModelItem{, vPaperItem}: TsgDXFOwneredItem;
  vLayoutsDict: TsgDXFDictionary;
  vLayout: TsgDXFLayout;
  vStat: TConvStatus;

  function FindLayout(AHandle: UInt64; var AIndex: Integer): Boolean; overload;
  begin
    Result := False;
    AIndex := FPapers.Count - 1;
    while (AIndex >= 0) and not Result do
      if AHandle = TsgDXFBlock(FPapers[AIndex]).Layout.Handle then
        Inc(Result)
      else
        Dec(AIndex);
  end;

  function FindLayout(AName: string; var AIndex: Integer): Boolean; overload;
  begin
    Result := False;
    AIndex := FPapers.Count - 1;
    while (AIndex >= 0) and not Result do
      if AName = TsgDXFBlock(FPapers[AIndex]).Layout.Name then
        Inc(Result)
      else
        Dec(AIndex);
  end;

begin
  vStat := Conv.Status;
  Conv.Status := stDefault;

  ForceNamedObjectsDictionary;

  vNamed := TsgDXFDictionary(Conv.Sections[csObjects][0]);

  vItem := TsgDXFOwneredItem(vNamed.FindEntByName(sAcadLayoutDictionary));
  if not Assigned(vItem) then
  begin
    vItem := TsgDXFOwneredItem.Create;
    vItem.Name := sAcadLayoutDictionary;
//    vItem.Dictionary := vNamed;
    Conv.SetHandle(vItem);
    vNamed.AddEntity(vItem);
  end;

  vLayoutsDict := TsgDXFDictionary(Conv.Sections[csObjects].FindEntByHandle(vItem.Handle));
  if not Assigned(vLayoutsDict) then
  begin
    vLayoutsDict := TsgDXFDictionary.Create;
    vLayoutsDict.Handle := vItem.Handle;
    vLayoutsDict.Name := cnstDictionary;
    Conv.Sections[csObjects].AddEntity(vLayoutsDict);
  end;

  if (vLayoutsDict.Count = 0) and (FPapers.Count = 0) then
  begin
    FPapers.AddEntity(TsgDXFBlock.Create);
    FPapers[0].Name := sModelSpace;
    Conv.Sections[csBlocks].AddEntity(FPapers[0]);
  end;

  for I := 0 to FPapers.Count - 1 do
  begin
    vLayout := TsgDXFLayout(TsgDXFBlock(FPapers[I]).Layout);
    if vLayout = nil then
    begin
      vLayout := TsgDXFLayout.Create;
      if I >= 1 then
        vLayout.Name := sLayout + IntToStr(I);
      Conv.SetHandle(vLayout);
      Conv.Sections[csObjects].AddEntity(vLayout);
      vLayout.PaperSpaceBlock := TsgDXFBlock(FPapers[I]);

      vItem := TsgDXFOwneredItem.Create;
      vItem.Name := vLayout.Name;
      vItem.Handle := vLayout.Handle;
//      vItem.Dictionary := vLayoutsDict;
      vLayoutsDict.AddEntity(vItem);
    end;
  end;

  TsgDXFTableAccess(vLayoutsDict).SortEntByHandle;

  {if FPapers.Count >= 2 then
  begin
    vPaperItem := TsgDXFOwneredItem(vLayoutsDict.FindEntByHandle(TsgDXFBlock(FPapers[1]).Layout.Handle));
    if not Assigned(vPaperItem) then
      vPaperItem := TsgDXFOwneredItem(vLayoutsDict.FindEntByName(TsgDXFBlock(FPapers[1]).Layout.Name));
    if Assigned(vPaperItem) then
    begin
      vLayoutsDict.RemoveEntity(vPaperItem);
      vLayoutsDict.InsertEntity(0, vPaperItem);
    end;
  end;}

  if FPapers.Count >= 1 then
  begin
    vModelItem := TsgDXFOwneredItem(vLayoutsDict.FindEntByHandle(TsgDXFBlock(FPapers[0]).Layout.Handle));
    if not Assigned(vModelItem) then
      vModelItem := TsgDXFOwneredItem(vLayoutsDict.FindEntByName(TsgDXFBlock(FPapers[0]).Layout.Name));
    if Assigned(vModelItem) then
    begin
      vLayoutsDict.RemoveEntity(vModelItem);
      vLayoutsDict.InsertEntity(0, vModelItem);
    end;
  end;

  for I := 0 to vLayoutsDict.Count - 1 do
  begin
    vFind := FindLayout(vLayoutsDict[I].Handle, J);
    if not vFind then
      vFind := FindLayout(vLayoutsDict[I].Name, J);
    if vFind and (MaxI(I, J) < FPapers.Count) then
      TsgDXFGroupAccess(FPapers).ExchangeEntity(I, J);
  end;

  if Conv.HeadVarStruct.TileMode = 0 then
  begin
    Conv.DefaultLayoutIndex := FPapers.IndexOfName(sPaperSpace);
    if Conv.DefaultLayoutIndex = -1 then
      Conv.DefaultLayoutIndex := FPapers.IndexOfName(sPaperSpace12);
  end;

  Conv.Status := vStat;
end;

function TdxfReader.ForceLink(AList: TStrings; const AName: string): TObject;
var
  I: Integer;
begin
  I := AList.IndexOf(AName);
  if I < 0 then
    I := AList.AddObject(AName, TsgLinkObject.Create(AName));
  Result := AList.Objects[I];
end;

function TdxfReader.ForceLink(AList: TsgCollection; AHandle: UInt64): TObject;
var
  I: Integer;
begin
  I := AList.IndexOf(AHandle);
  if I < 0 then
    I := AList.Add(AHandle, TsgLinkObject.Create(AHandle));
  Result := AList[I].Data;
end;

procedure TdxfReader.ForceNamedObjectsDictionary;
var
  vNamed: TsgDXFDictionary;
  vStat: TConvStatus;
begin
  vStat := Conv.Status;
  Conv.Status := stDefault;
  if Conv.Counts[csObjects] <= 0 then
  begin
    vNamed := TsgDXFDictionary.Create;
    vNamed.Name := cnstDictionary;
    Conv.SetHandle(vNamed);
    Conv.Sections[csObjects].InsertEntity(0, vNamed);
  end;
  Conv.Status := vStat;
end;

procedure TdxfReader.ForceStandardObjects;
var
  A: TsgDimArrowType;
  I: Integer;
  vDimStyle: TsgDXFDimStyleAccess;
  vLTypeByLayer, vLTypeByBlock, vLTypeContinious, vLayer0: TsgDXFEntity;
  vVPort: TsgDXFVport;
begin
  Conv.CustomEntByName(sStandardName, csStyles);

  vLTypeByLayer := Conv.CustomEntByName(sByLayer, csLTypes);
  vLTypeByBlock := Conv.CustomEntByName(sByBlock, csLTypes);
  vLTypeContinious := Conv.CustomEntByName(sContinuous, csLTypes);
  TsgDXFTableAccess(Conv.Sections[csLTypes]).SortEntByHandle;
  Conv.Sections[csLTypes].RemoveEntity(vLTypeByLayer);
  Conv.Sections[csLTypes].RemoveEntity(vLTypeByBlock);
  Conv.Sections[csLTypes].RemoveEntity(vLTypeContinious);
  Conv.Sections[csLTypes].InsertEntity(0, vLTypeContinious); // 0
  Conv.Sections[csLTypes].InsertEntity(0, vLTypeByLayer);    //-1
  Conv.Sections[csLTypes].InsertEntity(0, vLTypeByBlock);    //-2

  vLayer0 := Conv.LayerByName('0');
  TsgDXFTableAccess(Conv.Sections[csLayers]).SortEntByHandle;
  Conv.Sections[csLayers].RemoveEntity(vLayer0);
  Conv.Sections[csLayers].InsertEntity(0, vLayer0);

  vDimStyle := TsgDXFDimStyleAccess(TsgDXFDimensionStyle.Create);
  try
    Conv.DimensionStyleByName(sStandardName);
    Conv.Sections[csDimStyles].AddEntity(vDimStyle);
    try
      for A := Low(TsgDimArrowType) to High(TsgDimArrowType) do
      begin
        case A of
          datUserarrow, datNone, datUndefined:;
        else
          if FDimStyleLinks.IndexOf(sgDimensionArrowTypeNames[A]) >= 0 then
            vDimStyle.DIMBLKT := A;
        end;
      end;
    finally
      Conv.Sections[csDimStyles].RemoveEntity(vDimStyle);
    end;
  finally
    vDimStyle.Free;
  end;

  if not Assigned(FActiveVPort) then
  begin
    for I := 0 to Conv.Counts[csVPorts] - 1 do
    begin
      vVPort := TsgDXFVport(Conv.Sections[csVPorts].Entities[I]);
      if SameText(vVPort.Name, sActiveVPort) then
      begin
        FActiveVPort := vVPort;
        break;
      end;
    end;
  end;

  if Assigned(FActiveVPort) then
    Conv.ActiveVPort := FActiveVPort
end;

function TdxfReader.HandleValue: UInt64;
begin
  if CodeTypes^[FCode] <> ctHex then
    FHandle := StringHexToIntDef(Trim(UValue), cnstBadHandle);
  Result := FHandle;
end;

procedure TdxfReader.InitPaper(const ABlock: TsgDXFEntity);
var
  I: Integer;
begin
  I := GetPaperIndex(ABlock.Name);
  case I of
    -1:; // not space
    0:   // [*|$]model_space
      begin
        if FPapers.IndexOfEntity(ABlock) < 0 then
          FPapers.InsertEntity(0, ABlock);
      end;
    1:  // [*|$]paper_space
      begin
        if FPapers.IndexOfEntity(ABlock) < 0 then
          if FPapers.Count <= 0 then
            FPapers.AddEntity(ABlock)
          else
            FPapers.InsertEntity(1, ABlock);
      end
  else // [*|$]paper_space[number + 2]
    if FPapers.IndexOfEntity(ABlock) < 0 then
      FPapers.AddEntity(ABlock);
  end;
end;

function TdxfReader.IntValue: Integer;
begin
  if CodeTypes^[FCode] <> ctInteger then
    FInt := StrToIntDef(Trim(UValue), 0);
  Result := FInt;
end;

function TdxfReader.IsInternalCADImage: Boolean;
begin
  Result := (XDataProcs <> nil) and (FFileInfo.Count > 0) and
   (FFileInfo[0] = AnsiUpperCase(cnstCreatedFileInfo));
end;

procedure TdxfReader.Read;
var
  vDS: Char;
//  vObj: TsgDXFEntity;
//  vSortentsTable, vSortentsVar, vVarDict: TsgDXFEntity;
  vNamedObjects: TsgDXFDictionary;

  {procedure SortPapersByHandle;
  var
    I: Integer;
    vBlock: TsgDXFBlockAccess;
  begin
    for I := 0 to Conv.Counts[csLayouts] - 1 do
    begin
      vBlock := TsgDXFBlockAccess(TsgDXFLayout(Conv.Sections[csLayouts][I]).PaperSpaceBlock);
      vBlock.SortEntByHandle;
    end;
  end;

  procedure CustomSort;
  begin
    if not Conv.SortEntities then
      SortPapersByHandle
  end;}

begin
  Conv.Clear;

//  vObj := Conv.Sections[csLayouts];
//  Conv.Sections[csLayouts] := nil;
//  vObj.Free;

  Conv.SetLoading(True, Conv.Source.Memory);
  try
    FPos := Conv.Source.Memory;
    FPrev := FPos;
    FLimit := FPos + Conv.Source.Size;
    Conv.HeadEnd := FLimit;
    SetLength(FValue, 63);
    vDS := SetDecimalSeparator('.');
    try
      DoEvent(Conv.BeforeRead);
      try
        FMain.ReadState(Self);
      except
        on E: Exception do
        begin
          E.Message := Format('DXF read error on line %d: %s'#13#10'%s',
            [FLine, FValue, E.Message]);
          raise;
        end;
      end;
    finally
      SetDecimalSeparator(vDS);
    end;
    if TdxfMain(FMain).FSectionObjects = nil then
    begin
      // need named object dictionary for PreLinkObjects
      // Conv.Sections[csObjects][0]
      vNamedObjects := TsgDXFDictionary.Create;
      vNamedObjects.Name := cnstDictionary;
      Conv.Sections[csObjects].InsertEntity(0, vNamedObjects);
    end;
    Conv.FillMainSection;
    Conv.ApplyXRecodData;
    ForceStandardObjects;
    ForceLayouts;
    ForceImageDefs;
    PreLinkObjects(Conv.Sections[csObjects], Conv);
{$IFDEF SG_BTI}
    if Conv.XDataProcs <> nil then
      Conv.XDataProcs.Initialize(Conv); // sort ents
{$ENDIF}
    LinkDataBase(Conv);
    LoadDataBase(Conv);
    DoEvent(Conv.AfterRead);
  finally
    Conv.SetLoading(False,FLimit);
    // sort entities
    (*
    vVarDict := Conv.Sections[csObjects].FindEntByName(sAcDbVariableDictionary);
    vSortentsVar := nil;
    if Assigned(vVarDict) then // dictionaryvar
    begin
      vSortentsVar := vVarDict.FindEntByName(sDictionaryVarSORTENTS);
      if Assigned(vSortentsVar) then
        FSortents := StrToIntDef(TsgDXFDictionaryVar(vSortentsVar).Value, FSortents);
    end;
    vSortentsTable := Conv.Sections[csObjects].FindEntByName(sDictionaryVarSORTENTS);
    if Assigned(vSortentsTable) then // dictionary
      CustomSort
    else
    begin
      if Assigned(vVarDict) then
      begin
        if Assigned(vSortentsVar) then // dictionaryvar
          SortPapersByHandle
        else
          CustomSort;
      end
      else
        CustomSort;
    end;
    *)
    Conv.SortEntities;
  end;
end;

procedure TdxfReader.Next;
begin
  FPrev := FPos;
  // read code
  SkeepBlanks(FPos);
  ReadInt(FCode);
  SkeepLimits(FPos);
  Inc(FLine);
  // read data
  FValueStartPos := FPos;
  if FPos < FLimit then
  begin
    SkeepBlanks(FPos);
    case CodeTypes^[FCode] of
      ctInteger: ReadInt(FInt);
      ctDouble: ReadDouble(FDouble);
      ctHex: ReadHandle(FHandle);
    else
      SeekEOL;
    end;
    FValueSize := FPos - FValueStartPos;
    repeat
      SkeepLimits(FPos);
    until (FPos >= FLimit) or not (FPos^ in [#10, #13]);
    Inc(FLine);
    // check limits
    if FConverter.Pos = 0 then
      FPos := FLimit;
    if FPos >= FLimit then
    begin
      FValueSize := -1;
      FCode := 0;
      FValue := cnstSeqEnd;
    end;
  end;
end;

function TdxfReader.ObjByHandle(const AHandle: UInt64): TsgDXFEntity;
var
  I: Integer;
  vBlocks: TsgDXFEntity;
begin
  Result := nil;
  vBlocks := FConverter.Sections[csBlocks];
  I := 0;
  while (I < vBlocks.Count) and not Assigned(Result) do
  begin
    Result := vBlocks[I].FindEntByHandle(AHandle);
    Inc(I);
  end;
  if not Assigned(Result) then
    Result := FConverter.Sections[csObjects].FindEntByHandle(AHandle);
end;

{ TdxfBinReader }

{private}

procedure TdxfBinReader.Chunk;
var
  vCount: Integer;
  vValue: PWord;
begin
  Read(FInt, 1);
  SetLength(FValue, FInt + FInt);
  vValue := PWord(FValue);
  vCount := FInt;
  while vCount > 0 do
  begin
    vValue^ := sgFunction.ByteBinToHex^[Ord(FPos^)];
    Inc(FPos);
    Inc(vValue);
    Dec(vCount);
  end;
end;

procedure TdxfBinReader.Read(var ABuffer; ACount: Integer);
begin
  Move(FPos^, ABuffer, ACount);
  Inc(FPos,ACount);
end;

{public}

constructor TdxfBinReader.Create(AConverter: TsgDXFConverter;
  const AGroupCodeSize: Integer);
begin
  inherited Create(AConverter);
  FGroupCodeSize := AGroupCodeSize;
  sgFunction.InitByteBinToHex;
end;

function TdxfBinReader.FloatValue: Double;
begin
  Result := FDouble;
end;

function TdxfBinReader.HandleValue: UInt64;
begin
  Result := StringHexToIntDef(Trim(UValue), cnstBadHandle);
end;

function TdxfBinReader.IntValue: Integer;
begin
  Result := FInt;
end;

procedure TdxfBinReader.Next;
begin
  FCode := 0;
  FInt := 0;
  FDouble := 0;
  if FPos >= FLimit then
  begin
    FValue := 'SEQEND';
    Exit;
  end;
  // Group code is a 2-byte binary value (1 byte in DXF files prior
  // to AutoCAD Release 14)
  Read(FCode, FGroupCodeSize);
  // Value
  FValueSize := -1;
  FValueStartPos := FPos;
  case FCode of
    0..9, 100..109, 300..309, 320..369,
      390, 470, 1000..1003, 1005..1009:
        begin
          SeekEoStr(FPos);
          FValueSize := FPos - FValueStartPos;
          Inc(FPos);
          //BinStr(FValue, FPos, FLimit);
        end;
    10..59, 110..149, 210..249, 460..469, 1010..1059:  Read(FDouble, 8);
    290..299, {undocumented} 255..257, 512 {}:         Read(FInt, 1);
    90..99, 420..429, 440..449, 450..459, 1071:        Read(FInt, 4);
    310..319, 1004:                                    Chunk;
    60..79, 170..179, 270..289, 370..389, 1060..1070:
      begin
        Read(FInt, 2);
        FInt := Smallint(FInt);
      end;
  else
    raise EReadError.CreateFmt('Illegal group code %d at %.8x',
      [FCode, TsgNativeInt(FPos) - TsgNativeInt(FPrev) + 20]);
  end;
end;

{ TdxfEntity }

{private}

procedure TdxfEntity.Coord(AReader: TdxfReader);
var
  A,B: Integer;
begin
  A := AReader.Code div 10 - 1;
  B := AReader.Code mod 10;
  FPoints[B].V[A] := AReader.FloatValue;
end;

procedure TdxfEntity.SetLWeight(const AValue: Double);
begin
  FEnt.LineWeight := ExpandLWeight(AValue);
end;

{protected}

constructor TdxfEntity.Create;
begin
  inherited Create;
  FFloats[8] := 1.0;
  FExtrusion.Z := 1.0;
  FInts[2] := 256;
  FIntsRGBColor := clNone;
  FLineWeight := fLineWeightByLayer;
end;

procedure TdxfEntity.Commit(const AReader: TdxfReader);
begin
  inherited Commit(AReader);
  FComplex := FComplex and (FEnt <> nil);
  if FEnt=nil then
    Exit;
  SetLayerByName(AReader, FTexts[8]);
  FEnt.LineType := TsgDXFLineType(AReader.LTypes[FTexts[6]]);
  FEnt.LineTypeScale := FFloats[8];
  FEnt.Visibility := FInts[0] = 0;
  FEnt.ColorCAD := LoadColor(AReader);
  FComplex := FComplex or FEnt.Complex;
  SetLWeight(FLineWeight);
{$IFDEF SG_USEDXFSRC}
  if FEnt <> nil then
  begin
    FEnt.SrcStart := FSrcStart;
    FEnt.SrcEnd := FSrcEnd;
  end;
{$ENDIF}
end;

function TdxfEntity.LoadColor(const AReader: TdxfReader): TsgColorCAD;
begin
  Result :=  MakeColorCAD(acIndexColor, FInts[2]);
  if FIntsRGBColor <> clNone then
    Result := MakeColorCAD(acRGBColor, FIntsRGBColor);
end;

procedure TdxfEntity.ReadProperty(const AReader: TdxfReader);
var
  vCode: Integer;
begin
  vCode := AReader.Code;
  case vCode of
    10..37:     Coord(AReader);
    38:         FElevation      := AReader.FloatValue;
    39:         FZThick         := AReader.FloatValue;
    40..59:     FFloats[vCode-40]   := AReader.FloatValue;
    60..79:     FInts[vCode-60]     := AReader.IntValue;
    210:        FExtrusion.X    := AReader.FloatValue;
    220:        FExtrusion.Y    := AReader.FloatValue;
    230:        FExtrusion.Z    := AReader.FloatValue;
    370:        FLineWeight     := AReader.IntValue;
    420:        FIntsRGBColor := BGRToRGB(AReader.IntValue);
    999:        AReader.ReadFileInfo;
  else
    inherited ReadProperty(AReader);
  end;
end;

{ TdxfBasePolyLine }

procedure TdxfBasePolyLine.Commit(const AReader: TdxfReader);
var
  vBasePolyLine: TsgCADBasePolyLine;
begin
  inherited Commit(AReader);
  vBasePolyLine := TsgCADBasePolyLine(FEnt);
  vBasePolyLine.Extrusion       := FExtrusion;
  vBasePolyLine.ZThick          := FZThick;
  vBasePolyLine.LineTypeScale   := vBasePolyLine.LineTypeScale;
  vBasePolyLine.Flags           := Flags;
  vBasePolyLine.Closed          := vBasePolyLine.Flags and 1 <> 0;
end;

{ TdxfBlock }

{$IFDEF SG_BTI}

{private}

function TdxfBlock.GetSegmentWidths: PF2DRect;
begin
  if FSegmentWidths = nil then
    New(FSegmentWidths);
  Result := FSegmentWidths;
end;

procedure TdxfBlock.NextInteger(AReader: TdxfReader);
begin
  case FCodeValue of
    Integer_70:
      begin
        FEntTypeNum := AReader.IntValue;
        FCodeValue := 0;
      end;
    Integer_71:
      begin
        FXData.Flags := AReader.IntValue;
        FCodeValue := 0;
      end;
    Integer_72:
      begin
        FInsUnits := AReader.IntValue;
        FCodeValue := 0;
      end;
    Integer_90:
      begin
        FXData.FillColor := AReader.IntValue;
        FCodeValue := 0;
      end;
    Word_280:
       begin
        FXData.CarvingMode := Byte(AReader.IntValue);
        FCodeValue := 0;
      end;
    Word_281:
       begin
        FXData.IsCircular := AReader.IntValue <> 0;
        FCodeValue := 0;
      end;
    Word_282:
       begin
        FXData.TypeSnapEntities := AReader.IntValue;
        FCodeValue := 0;
      end;
    Word_283:
       begin
        FXData.SegmentsCount := AReader.IntValue;
        FCodeValue := 0;
      end;
    Word_284:
       begin
        FXData.Alignment := AReader.IntValue <> 0;
        FCodeValue := 0;
      end;
  else
    FCodeValue := AReader.IntValue;
  end;
end;

procedure TdxfBlock.NextReal(AReader: TdxfReader);
begin
  case FCodeValue of
    Float_40:
      FXData.Length := AReader.FloatValue;
    Float_41:
      FXData.Width := AReader.FloatValue;
    Float_45:
      GetSegmentWidths^.Left := AReader.FloatValue;
    Float_46:
      GetSegmentWidths^.Top := AReader.FloatValue;
    Float_47:
      GetSegmentWidths^.Right := AReader.FloatValue;
    Float_48:
      GetSegmentWidths^.Bottom := AReader.FloatValue;
  end;
end;

procedure TdxfBlock.NextString(AReader: TdxfReader);
begin
  case FCodeValue of
    String_331:// XRefPath (i.e. FTexts[1]) contains Parent Block name
      FTexts[1] := AReader.UValue;
    String_410:
      FAttributes := FAttributes + AReader.UValue;
    String_411:
      FXData.LineType := AReader.FConverter.LTypeByName(AReader.UValue);
    String_412:
      FAttribsTypes := FAttribsTypes + AReader.UValue;
    String_430:
      FXData.ValueMask := TsgExtendedBlockDataAccess(FXData).FValueMask +
        AReader.UValue;
  end;
end;

{$ENDIF}

{protected}

constructor TdxfBlock.Create;
begin
  inherited Create;
  FComplex := True;
{$IFDEF SG_BTI}
  FXData := TsgExtendedBlockData.Create;
  FInsUnits := MaxInt;
{$ENDIF}
end;

function TdxfBlock.EOFEnt(AObj: TdxfObject): Boolean;
begin
  Result := AObj.ClassType = TdxfEndBlock;
end;

function TdxfBlock.IsAcadTableBlock: Boolean;
begin
  Result := Assigned(FEnt) and TsgDXFBlockAccess(FEnt).IsAcadTableBlock;
end;

{$IFDEF SG_BTI}
destructor TdxfBlock.Destroy;
begin
  if FSegmentWidths <> nil then
    Dispose(FSegmentWidths);
  FXData.Free;
  inherited Destroy;
end;
{$ENDIF}

procedure TdxfBlock.Commit(const AReader: TdxfReader);
var
  vBlock: TsgDXFBlock;
{$IFDEF SG_BTI}
  vEntity: TsgDXFEntity;
{$ENDIF}
begin
  inherited Commit(AReader);
  vBlock := TsgDXFBlock(FEnt);
  vBlock.XrefPath    := Trim(FTexts[1]);
  vBlock.Name        := Name;
  vBlock.Offset      := FPoints[0];
  TsgDXFBlockAccess(vBlock).SetFlags(Flags);
{$IFDEF SG_BTI}
  if (AReader.XDataProcs <> nil) and
     (AnsiPos(FXDataAppName, AReader.FileInfo) > 0) then
  begin
    if FSegmentWidths <> nil then
      FXData.SegmentWidths := FSegmentWidths^;
    if (FAttributes <> '') then
      ApplyAttribsList(FXData, FAttributes, FAttribsTypes);
    if not IsInsUnits(FInsUnits) then
      FInsUnits := AReader.FConverter.HeadVarStruct.InsUnits;
    if IsInsUnits(FInsUnits) then
      FXData.InsUnits := TsgInsUnits(FInsUnits);
    vEntity := AReader.XDataProcs.Import(FEntTypeNum, FXData);
    if vEntity <> nil then
    begin
      AReader.FConverter.Sections[csBlocks].RemoveEntity(vBlock);
      FAdded := False;
      vEntity.AssignEntity(vBlock);
      vEntity.Handle := vBlock.Handle;
      TsgDXFBlock(vEntity).BlockRecord.Handle := vBlock.BlockRecord.Handle;
      vBlock.Free;
      FEnt := vEntity;
    end;
  end;
{$ENDIF}
  AReader.InitPaper(FEnt);
end;

procedure TdxfBlock.ReadProperty(const AReader: TdxfReader);
var
  vObj: TObject;
begin
  case AReader.Code of
{$IFDEF SG_BTI}
    String_1001:
      FXDataAppName := AnsiUpperCase(AReader.UValue);
    Integer_1070:
      NextInteger(AReader);
    Float_1040:
      NextReal(AReader);
    String_1005:
      NextString(AReader);
{$ENDIF}
    Name_2:
      begin
        inherited ReadProperty(AReader);
        if not FAdded then
        begin
          vObj := AReader.BlockRecords[Name];
          if Assigned(vObj) then
          begin
            if vObj.ClassType <> TsgLinkObject then
            begin
              FAdded := True;
              FEnt.Free;
              FEnt := TsgDXFBlockRecordAccess(vObj).Block;
            end;
          end;
        end;
      end;
    330:
      begin
        inherited ReadProperty(AReader);
        if not FAdded and not FReactorsRead and (FSoftOwnerIDs.Last <> cnstBadHandle) then
        begin
          vObj := AReader.HBlockRecords[FSoftOwnerIDs.Last];
          if Assigned(vObj) and (vObj.ClassType = TsgDXFBlockRecord) then
          begin
            FAdded := True;
            Name := TsgDXFBlockRecord(vObj).Name;
            FEnt.Free;
            FEnt := TsgDXFBlockRecordAccess(vObj).Block;
          end;
        end;
      end
    else
      inherited ReadProperty(AReader);
  end;
end;


{ TdxfDictionary }

constructor TdxfDictionary.Create;
begin
  inherited Create;
  FNamesHardOwnerIDs := TStringList.Create; //360
  FNamesLinkSoftIDs := TStringList.Create;//350
end;

destructor TdxfDictionary.Destroy;
begin
  FreeAndNil(FNamesHardOwnerIDs);
  FreeAndNil(FNamesLinkSoftIDs);
  inherited Destroy;
end;

procedure TdxfDictionary.Commit(const AReader: TdxfReader);

  procedure CreateDictionaryItems(const AOwner: TsgDXFEntity;
    const AHandles: TsgInt64List; const ANames: TStrings);
  var
    I: Integer;
    vItem: TsgDXFOwneredItem;
  begin
    for I := 0 to ANames.Count - 1 do
    begin
      vItem := TsgDXFOwneredItem.Create;
      vItem.Name := ANames[I];
      ANames.Objects[I] := vItem;
      if I < AHandles.Count then
        vItem.Handle := AHandles[I];
//      vItem.Dictionary := FEnt;
      AOwner.AddEntity(vItem);
    end;
  end;

begin
  inherited Commit(AReader);
  FEnt.Name := cnstDictionary;
  CreateDictionaryItems(FEnt, FLinkSoftIDs, FNamesLinkSoftIDs);
  CreateDictionaryItems(FEnt, FHardOwnerIDs, FNamesHardOwnerIDs);
end;

procedure TdxfDictionary.ReadProperty(const AReader: TdxfReader);
begin
  inherited ReadProperty(AReader);
  case AReader.Code of
    350: FNamesLinkSoftIDs.AddObject(FTexts[3], nil);
    360: FNamesHardOwnerIDs.AddObject(FTexts[3], nil);
  end;
end;

{ TdxfDimAssoc }

procedure TdxfDimAssoc.Commit(const AReader: TdxfReader);
var
  vEntity, vAssocEntity: TsgDXFEntity;
  vHDim, vHAssoc: UInt64;
begin
  inherited Commit(AReader);
  if (FSoftOwnerIDs.Count > 0) and (FPointerIDs.Count > 0) then
  begin
    vHDim := FSoftOwnerIDs.Last;
    vHAssoc := FPointerIDs.Last;
    if (vHDim <> cnstBadHandle) and (vHAssoc <> cnstBadHandle) then
    begin
      vEntity := AReader.ObjByHandle(vHDim);
      vAssocEntity := AReader.ObjByHandle(vHAssoc);
      if vEntity is TsgDXFDimension then
        TsgDXFDimension(vEntity).Associated := vAssocEntity;
    end;
  end;
end;

{ TdxfHatch }

{private}

function TdxfHatch.AddNewPattern(const AHatch: TsgCADHatch):PsgHatchPatternData;
begin
  New(Result);
  AHatch.HatchPatternData.Add(Result);
  Result.Lines := nil;
end;

procedure TdxfHatch.DoSolidHatch(const AReader: TdxfReader);
var
  vSolidHatch: TsgCADCurvePolygon;
begin
  vSolidHatch := TsgCADCurvePolygon.Create;
  vSolidHatch.Clone(TsgCADCurvePolygon(FEnt));
  FEnt.Free;
  FEnt := vSolidHatch;
  AReader.DoCreate(FEnt);
end;

function TdxfHatch.GetLastHatchSegment(const AHatch: TsgCADHatch): Tsg2DCurve;
var
  vBoundary: Tsg2DBoundaryList;
begin
  Result := nil;
  if AHatch.BoundaryDataCount > 0 then
  begin
    vBoundary := AHatch.BoundaryDataLast;
    if vBoundary.Count > 0 then
      Result := vBoundary[vBoundary.Count - 1];
  end;
end;

function TdxfHatch.Pattern(const AHatch: TsgCADHatch): PsgHatchPatternData;
begin
  Result := PsgHatchPatternData(AHatch.HatchPatternData.Last);
end;

procedure TdxfHatch.ReadGrad(const AReader: TdxfReader; const  AHatch: TsgCADHatch);
begin
  case AReader.Code of
    421:
      begin
        AHatch.GradientColorCAD[FCurentIndexColorCAD] :=
          MakeColorCAD(acRGBColor, BGRToRGB(AReader.IntValue));
        Inc(FCurentIndexColorCAD);
      end;
    Integer_63:
      begin
        AHatch.GradientColorCAD[FCurentIndexColorCAD+FCurentIndexColor] :=
          MakeColorCAD(acIndexColor, AReader.IntValue);
        Inc(FCurentIndexColor);
      end;
  end;
end;

{protected}

procedure TdxfHatch.Commit(const AReader: TdxfReader);
var
  vHatch: TsgCADHatch;
  //vColor: TColor;
begin
  vHatch := TsgCADHatch(FEnt);
  //vColor := FEnt.Color;
  inherited Commit(AReader);
  //if vHatch.GradientName <> '' then
  // FEnt.Color := vColor;
  vHatch.Extrusion   := FExtrusion;
  vHatch.Offset := FPoints[1];
  vHatch.HatchName := FTexts[2];
  if vHatch.EntType = ceMPolygon then
    vHatch.SolidFill := FInts[11] and 1 <> 0
  else
    if Flags and 1 <> 0 then
      DoSolidHatch(AReader);
end;

constructor TdxfHatch.Create;
begin
  inherited Create;
  FCurentIndexColor := 0;
  FCurentIndexColorCAD := 0;
  FNumberOfFitData := cnstNumberOfFitDataUndefined;
end;

procedure TdxfHatch.ReadProperty(const AReader: TdxfReader);
var
  vHatch: TsgCADHatch;
  v2DCurve: Tsg2DCurve;

  function IsReadCurve: Boolean;
  begin
    Result := (v2DCurve <> nil) and (vHatch.EntType <> ceMPolygon);
  end;

begin
  vHatch := TsgCADHatch(FEnt);
  v2DCurve := GetLastHatchSegment(vHatch);
  inherited ReadProperty(AReader);
  case AReader.Code of
    421:  ReadGrad(AReader, vHatch);
    450:  FIsSolid := AReader.IntValue = 0;
    460:  vHatch.GradientAngle := RadToDeg(AReader.FloatValue);
    461:  vHatch.GradientUseCenter := Abs(AReader.FloatValue) < fAccuracy;
    470:
      if FIsSolid then
        vHatch.GradientName := ''
      else
        vHatch.GradientName := AReader.UValue;
    Integer_91:  FBoundNum := AReader.IntValue;
    Integer_92:
      begin
        FBoundType := AReader.IntValue;
        FCurType := nil;
      end;
    Integer_93:  FPointCount := AReader.IntValue;
    Integer_94, Integer_63:
      begin
        if (AReader.Code = Integer_94) and IsReadCurve and (v2DCurve is Tsg2DSpline) then
          Tsg2DSpline(v2DCurve).Degree := AReader.IntValue
        else
        begin
          case vHatch.EntType of
            ceHatch, ceGradientPolygon: ReadGrad(AReader, vHatch);
            ceMPolygon: vHatch.FillColor := MakeColorCAD(acIndexColor,AReader.IntValue);
          end;
        end;
      end;
    Integer_97:
      begin
        if FNumberOfFitData = cnstNumberOfFitDataNeedRead then
          FNumberOfFitData := AReader.IntValue
        else
          FCurType := nil;
      end;
    Integer_72:
      begin
        //if boundary is polyline read has bulge flag
        //else read edge type
        if FCurType = nil then
          FCurType := vHatch.AddBoundaryList(FBoundType);
        if vHatch.EntType <> ceMPolygon then
        begin
          FNumberOfFitData := cnstNumberOfFitDataUndefined;
          case AReader.IntValue of
            cnst2DCurvePoly:  v2DCurve := Tsg2DCurve(Tsg2DPolyline.Create);
            cnst2DCurveLine:
              begin
                if FBoundType and 2 = 0 then
                  v2DCurve := Tsg2DCurve(Tsg2DLine.Create)
                else
                  v2DCurve := Tsg2DCurve(Tsg2DPolyline.Create);
              end;
            cnst2DCurveArc:  v2DCurve  := Tsg2DCurve(Tsg2DArc.Create);
            cnst2DCurveEllipse: v2DCurve := Tsg2DCurve(Tsg2DEllipse.Create);
            cnst2DCurveSpline:
              begin
                v2DCurve := Tsg2DCurve(Tsg2DSpline.Create);
                if AReader.Version >= Byte(acR2010) then
                  FNumberOfFitData := cnstNumberOfFitDataNeedRead;
              end;
          else
            v2DCurve := nil;
          end;
        end
        else
        begin
          v2DCurve := Tsg2DCurve(Tsg2DPolyline.Create);
          Tsg2DPolyline(v2DCurve).Closed := True;
        end;
        if v2DCurve <> nil then
          vHatch.BoundaryDataLast.Add(v2DCurve);
      end;
    Integer_73:
      begin
        if IsReadCurve then
        begin
          case v2DCurve.EdgeType of
            cnst2DCurvePoly:
              Tsg2DPolyline(v2DCurve).Closed := FInts[13] = 1;
            cnst2DCurveArc, cnst2DCurveEllipse:
              Tsg2DArc(v2DCurve).CounterClockWise := FInts[13] = 1;
            cnst2DCurveSpline:
              Tsg2DSpline(v2DCurve).Rational := FInts[13] = 1;
          end;
        end;
      end;
    Integer_74:
      begin
        if IsReadCurve then
        begin
          case v2DCurve.EdgeType of
            cnst2DCurveSpline:
              Tsg2DSpline(v2DCurve).Periodic := FInts[14] = 1;
          end;
        end;
      end;
    XOther_11:
      begin
        if vHatch.EntType <> ceMPolygon then
          case v2DCurve.EdgeType of
            cnst2DCurveLine:
               Tsg2DLine(v2DCurve).SetEndPoint(MakeF2DPoint(FPoints[1].X,
                  Tsg2DLine(v2DCurve).EndPoint.Y));
            cnst2DCurveEllipse:
              Tsg2DEllipse(v2DCurve).MajorPoint := MakeF2DPoint(FPoints[1].X,
                  Tsg2DEllipse(v2DCurve).MajorPoint.Y);
          end;
      end;
    YOther_21:
      begin
        if vHatch.EntType <> ceMPolygon then
          case v2DCurve.EdgeType of
            cnst2DCurveLine:
              Tsg2DLine(v2DCurve).SetEndPoint(MakeF2DPoint(
                  Tsg2DLine(v2DCurve).EndPoint.X, FPoints[1].Y));
            cnst2DCurveEllipse:
              Tsg2DEllipse(v2DCurve).MajorPoint := MakeF2DPoint(
                  Tsg2DEllipse(v2DCurve).MajorPoint.X, FPoints[1].Y);
          end;
      end;
    Float_40:
      case v2DCurve.EdgeType of
        cnst2DCurveArc, cnst2DCurveEllipse:
          Tsg2DArc(v2DCurve).Radius := FFloats[0];
        cnst2DCurveSpline:
          Tsg2DSpline(v2DCurve).AddKnot(FFloats[0]);
      end;
    Float_41:  TsgCADHatchAccess(vHatch).PatternData.Scale := FFloats[1];
    Float_42:
      case v2DCurve.EdgeType of
        cnst2DCurvePoly:
          Tsg2DPolyline(v2DCurve).AddBulge(FFloats[2]);
        cnst2DCurveSpline:
          Tsg2DSpline(v2DCurve).AddWeight(FFloats[2]);
      end;
    Angle_50:           Tsg2DArc(v2DCurve).StartParam := FFloats[10];
    Angle_51:           Tsg2DArc(v2DCurve).EndParam := FFloats[11];
    Angle_52:           TsgCADHatchAccess(vHatch).PatternData.Angle := FFloats[12];
    Angle_53:           AddNewPattern(vHatch).LineAngle := FFloats[13];
    Float_43:           Pattern(vHatch).BaseP.X := FFloats[3];
    Float_44:           Pattern(vHatch).BaseP.Y := FFloats[4];
    Float_45:           Pattern(vHatch).Offset.X := FFloats[5];
    Float_46:           Pattern(vHatch).Offset.Y := FFloats[6];
    FloatRepeated_49:   Pattern(vHatch).Lines.Add(FFloats[9]);
    Integer_79:
      begin
        Pattern(vHatch).DashNum := FInts[19];
        Pattern(vHatch).IsDash := FInts[19] > 0;
        if FInts[19] > 0 then
          Pattern(vHatch).Lines := TsgDoubleList.Create(0, FInts[19]);
      end;
    XFirst_10, YFirst_20, ZFirst_30:
      begin
        if FBoundNum = 0 then
          vHatch.Elevation := FPoints[0]
        else
          if FCurType = nil then
            Exit
          else
            case AReader.Code of
              XFirst_10:
                  case v2DCurve.EdgeType of
                    cnst2DCurvePoly:
                      Tsg2DPolyline(v2DCurve).AddVertex(MakeF2DPoint(FPoints[0].X, 0));
                    cnst2DCurveLine:
                      Tsg2DLine(v2DCurve).SetStartPoint(MakeF2DPoint(FPoints[0].X, 0));
                    cnst2DCurveArc, cnst2DCurveEllipse:
                      Tsg2DArc(v2DCurve).CenterPoint := MakeF2DPoint(FPoints[0].X, 0);
                    cnst2DCurveSpline:
                      Tsg2DSpline(v2DCurve).AddControl(MakeF2DPoint(FPoints[0].X, 0));
                  end;
              YFirst_20:
                  case v2DCurve.EdgeType of
                    cnst2DCurvePoly:
                      Tsg2DPolyline(v2DCurve).GetLastVertex^.Y := FPoints[0].Y;
                    cnst2DCurveLine:
                      Tsg2DLine(v2DCurve).SetStartPoint(MakeF2DPoint(Tsg2DLine(v2DCurve).StartPoint.X,
                             FPoints[0].Y));
                    cnst2DCurveArc, cnst2DCurveEllipse:
                       Tsg2DArc(v2DCurve).CenterPoint :=
                         MakeF2DPoint(Tsg2DArc(v2DCurve).CenterPoint.X,
                             FPoints[0].Y);
                    cnst2DCurveSpline:
                      Tsg2DSpline(v2DCurve).GetLastVertex^.Y := FPoints[0].Y;
                  end;
            end;
      end;
  end;
end;

{ TdxfImageDef }

procedure TdxfImageDef.Commit(const AReader: TdxfReader);
begin
  inherited Commit(AReader);
end;

function TdxfImageDef.OwnerAdd: Integer;
begin
  Result := FOwner.FEnt.AddEntity(FEnt);
end;

procedure TdxfImageDef.ReadProperty(const AReader: TdxfReader);
begin
  inherited ReadProperty(AReader);
  case AReader.Code of
    Text_1: TsgDXFImageDef(FEnt).FileName := AReader.UValue;
  end;
end;

{ TdxfInsert }

{private}

procedure TdxfInsert.ChangeEntEx(const AConverter: TsgDXFConverter);
var
  vEntity: TsgDXFEntity;
begin
  vEntity := DXFConv.CreateRegEntity(FEntGroup, FEntTypeNum, AConverter,
    FExtData);
  if vEntity <> nil then
  begin
    AConverter.DeleteBlock(TsgDXFInsert(vEntity).Block, False);
    TsgDXFInsert(vEntity).Block.Free;
    TsgDXFInsert(vEntity).Clone(FEnt);
    TsgDXFInsert(vEntity).Block := TsgDXFInsert(FEnt).Block;
    FEnt.Free;
    FEnt := vEntity;
  end;
end;

function TdxfInsert.GetExtData: TsgCADExtendedData;
begin
  if FExtData = nil then
    FExtData := TsgCADExtendedData.Create;
  Result := FExtData;
end;

procedure TdxfInsert.NextHandleStr(const AReader: TdxfReader);
begin
{$IFDEF SG_BTI}
  case FCodeValue of
    String_100:
      begin
        FBlockPattern := TsgDXFBlock.Create;
        FBlockPattern.Name := AReader.UValue;
        XData^.Data.BlockPattern := FBlockPattern;
      end;
    String_331:
      begin
        XData^.Handle := Pointer(AReader.HandleValue);
      end;
    String_340:
      begin
        if XData^.Refs0 = nil then
          XData^.Refs0 := CreateTsgList;
        TsgList(XData^.Refs0).Add(Pointer(AReader.HandleValue));
      end;
    String_341:
      begin
        if XData^.Refs1 = nil then
          XData^.Refs1 := CreateTsgList;
        TsgList(XData^.Refs1).Add(Pointer(AReader.HandleValue));
      end;
    String_342:
      begin
        if XData^.Refs2 = nil then
          XData^.Refs2 := CreateTsgList;
        TsgList(XData^.Refs2).Add(Pointer(AReader.HandleValue));
      end;
//      String_410:
//        FAttributes := FAttributes + AReader.Value;
//      String_412:
//        FAttribsTypes := FAttribsTypes + AReader.Value;
    // begin only for TsgLabel
    String_430..String_434:
      FLabelStrings[FCodeValue-String_430] := AReader.UValue;
    // end
    // begin only for TsgAreaFigure
    String_439:
      CurrentFigure.FName := AReader.UValue;
    // end
    String_436, String_437:
      ReadXDataString(FCodeValue, AReader.UValue);
  end;
{$ENDIF}
end;

procedure TdxfInsert.NextInt(const AReader: TdxfReader);
begin
  case FCodeValue of
    440..448:  GetExtData.AddInt(FCodeValue, AReader.IntValue);
  end;
end;

procedure TdxfInsert.NextInteger(const AReader: TdxfReader);
begin
  case FCodeValue of
    Integer_70:
      begin
        FEntTypeNum := AReader.IntValue;
        FCodeValue := 0;
      end;
{$IFDEF SG_BTI}
    Integer_90:
      begin
        XData^.Data.xIntArray[0] := AReader.IntValue;
        FCodeValue := 0;
      end;
    Integer_91:
      begin
        XData^.Data.xIntArray[1] := AReader.IntValue;
        FCodeValue := 0;
      end;
    Word_280, Word_281:
       begin
        XData^.Data.xByteArray[FCodeValue-Word_280] := AReader.IntValue;
        FCodeValue := 0;
      end;
    Word_284..Word_288:
       begin
        XData^.Data.xByteArray[FCodeValue-Word_284+2] := AReader.IntValue;
        FCodeValue := 0;
      end;
    // begin only for TsgLabel
    Integer_290:
      begin
        FLabelShowSplitter := AReader.IntValue <> 0;
        FCodeValue := 0;
      end;
    Integer_400:
      begin
        FLabelAlign := AReader.IntValue;
        FCodeValue := 0;
      end;
    // end
    // begin only for TsgAreaFigure
    Integer_170:
      begin
        FCurrentFigure := nil;
        CurrentFigure.FType := TsgFigureType(AReader.IntValue);
        FCount_1042 := 0;
        FCodeValue := 0;
      end;
    Word_289:
      begin
        CurrentFigure.FFlags := AReader.IntValue;
        FCodeValue := 0;
      end;
    // end
{$ENDIF}
    60..69, 71..74:
      begin
        GetExtData.AddByte(FCodeValue, AReader.IntValue);
        FCodeValue := 0;
      end;
  else
    FCodeValue := AReader.IntValue;
  end;
end;

procedure TdxfInsert.NextPoint(const AReader: TdxfReader;
  const AIndexPoint: Byte);
var
  vIndex: Integer;
  vP2DPoint: TF2DPoint;
  vP3DPoint: TFPoint;

  procedure SetPoint3DValue;
  begin
    vP3DPoint := GetExtData.DataPoint[vIndex];
    vP3DPoint.V[AIndexPoint] := AReader.FloatValue;
    GetExtData.DataPoint[vIndex] := vP3DPoint;
  end;

begin
  case FCodeValue of
    10..15://3D points
      begin
        if (AIndexPoint = 0) or (GetExtData.DataCount = 0) then
          GetExtData.AddPoint(FCodeValue, cnstFPointZero);
        vIndex := GetExtData.DataCount - 1;
        SetPoint3DValue;
      end;
    16..19://2D points
      begin
        if (AIndexPoint = 0) or (GetExtData.DataCount = 0) then
          GetExtData.AddPoint2D(FCodeValue, cnstF2DPointZero);
        vIndex := GetExtData.DataCount - 1;
        if GetExtData.DataType[vIndex] = edtF2DPoint then
        begin
          vP2DPoint := GetExtData.DataPoint2D[vIndex];
          if AIndexPoint < 2 then
          begin
            vP2DPoint.V[AIndexPoint] := AReader.FloatValue;
            GetExtData.DataPoint2D[vIndex] := vP2DPoint;
          end
          else
          begin
            vP3DPoint.X := vP2DPoint.X;
            vP3DPoint.Y := vP2DPoint.Y;
            vP3DPoint.Z := AReader.FloatValue;
            GetExtData.ChangeType(vIndex, edtF3DPoint);
            GetExtData.DataPoint[vIndex] := vP3DPoint;
          end
        end
        else
          SetPoint3DValue;
      end;
  end;
end;

procedure TdxfInsert.NextReal(const AReader: TdxfReader);
begin
  case FCodeValue of
{$IFDEF SG_BTI}
    Float_40:
      begin
        XData^.Data.xDoubleArray[FCount_1040] := AReader.FloatValue;
        Inc(FCount_1040);
      end;
{$ENDIF}
    120..127:  GetExtData.AddSingle(FCodeValue, AReader.FloatValue);
    130..131:  GetExtData.AddDouble(FCodeValue, AReader.FloatValue);
  end;
end;

procedure TdxfInsert.NextReal1(const AReader: TdxfReader);
begin
{$IFDEF SG_BTI}
  case FCodeValue of
    Float_140:  FLabelHeight := AReader.FloatValue;
    Float_141:  FLabelTextOffset := AReader.FloatValue;
    Float_239:  CurrentFigure.FKoef := AReader.FloatValue;
  end;
{$ENDIF}
end;

procedure TdxfInsert.NextReal2(const AReader: TdxfReader);
begin
{$IFDEF SG_BTI}
  case FCodeValue of
    FloatRepeated_49:
      begin
        CurrentFigure.FParams[FCount_1042] := AReader.FloatValue;
        Inc(FCount_1042);
      end;
  end;
{$ENDIF}
end;

procedure TdxfInsert.NextString(const AReader: TdxfReader);
begin
  case FCodeValue of
    0:
      FEntGroup := AnsiUpperCase(AReader.UValue);
    Text_3:
      FConstructionStyle := AReader.StrValue;
   470..474:
      GetExtData.AddString(FCodeValue, AReader.StrValue);
  end;
end;

{$IFDEF SG_BTI}
procedure TdxfInsert.ChangeEntity(AReader: TdxfReader);
var
  vEntity: TsgDXFEntity;
begin
  if FEntTypeNum in [cnstArea, cnstComplexArea] then
  begin
    if (FFiguresList <> nil) and (FFiguresList.Count > 0) then
    begin
      XData^.Refs3 := FFiguresList;
      FFiguresList := nil;
    end;
  end;
  if Length(FConstructionStyle) > 0 then
    FPXData.Data.DimStyle := AReader.Conv.DimensionStyleByName(FConstructionStyle);
  vEntity := AReader.XDataProcs.Import(FEntTypeNum, FPXData);
  if vEntity <> nil then
  begin
    if FEntTypeNum = cnstLabel then
    begin
      TsgLabel(vEntity).Align := FLabelAlign;
      TsgLabel(vEntity).Height := FLabelHeight;
      TsgLabel(vEntity).TextOffset := FLabelTextOffset;
      TsgLabel(vEntity).ShowSplitter := FLabelShowSplitter;
      TsgLabel(vEntity).Style := TsgDXFStyle(AReader.Styles[Trim(FLabelStrings[0])]);
      TsgLabel(vEntity).TextLeft := FLabelStrings[1];
      TsgLabel(vEntity).TextRight := FLabelStrings[2];
      TsgLabel(vEntity).TextTop := FLabelStrings[3];
      TsgLabel(vEntity).TextBottom := FLabelStrings[4];
      ClearXData;
    end
    else
    begin
      FBlockPattern := nil;
      ClearXDataStrings(FPXData^);
      DisposeAndNil(FPXData);
    end;
    TsgDXFInsert(vEntity).Block.Free;
    TsgDXFInsert(vEntity).Clone(FEnt);
    TsgDXFInsert(vEntity).Block := TsgDXFInsert(FEnt).Block;
    FEnt.Free;
    FEnt := vEntity;
  end;
end;

procedure TdxfInsert.ClearXData;
begin
  FreePointerList(FFiguresList, ptvObject);
  FreeAndNil(FBlockPattern);
  if FPXData <> nil then
  begin
    ClearXDataStrings(FPXData^);
    TObject(FPXData^.Refs0).Free;
    TObject(FPXData^.Refs1).Free;
    TObject(FPXData^.Refs2).Free;
    DisposeAndNil(FPXData);
  end;
end;

function TdxfInsert.CurrentFigure: TsgAreaFigureAccess;
begin
  if FCurrentFigure = nil then
  begin
    FCurrentFigure := TsgAreaFigure.Create;
    if FFiguresList = nil then
    begin
      FFiguresList := TsgList.Create;
      FFiguresList.Sorted := False;
    end;
    FFiguresList.Add(Pointer(FCurrentFigure));
  end;
  Result := TsgAreaFigureAccess(FCurrentFigure);
end;

function TdxfInsert.XData: PsgExtendedData;
begin
  if FPXData = nil then
  begin
    New(FPXData);
    ClearXDataStrings(FPXData^);
    FillChar(FPXData^, SizeOf(FPXData^), 0);
    FPXData^.Data.xStringArray[0] := cnstDefaultValueMask;
  end;
  Result := FPXData;
end;

procedure TdxfInsert.ReadXDataString(const ACode: Integer; const AValue: string);
begin
  case ACode of
    String_436:
      begin
        Inc(FIndexStrings);
        if FIndexStrings <= High(XData.Data.xStringArray) then
          XData.Data.xStringArray[FIndexStrings] := AValue;
      end;
    String_437:
      begin
        if FIndexStrings < 0 then
          FIndexStrings := 0;
        if FIndexStrings <= High(XData.Data.xStringArray) then
          XData.Data.xStringArray[FIndexStrings] :=
            XData.Data.xStringArray[FIndexStrings] + AValue;
      end;
  end;
end;
{$ENDIF}

{protected}

constructor TdxfInsert.Create;
begin
  inherited Create;
  FFloats[1] := 1.0;
  FFloats[2] := 1.0;
  FFloats[3] := 1.0;
{$IFDEF SG_BTI}
  FFiguresList := TsgList.Create;
  FFiguresList.Sorted := False;
  FIndexStrings := -1;
{$ENDIF}
end;

destructor TdxfInsert.Destroy;
begin
{$IFDEF SG_BTI}
  ClearXData;
{$ENDIF}
  if FExtData <> nil then
    FExtData.Free;
  inherited Destroy;
end;

procedure TdxfInsert.Commit(const AReader: TdxfReader);
var
  vInsertAccess: TsgDXFInsertAccess;
  vMInsert: TsgCADMInsert;
begin
  vMInsert := nil;
  if (ClassType = TdxfInsert) and (((FInts[10] >= 1) and (FInts[11] > 1))
    or ((FInts[10] > 1) and (FInts[11] >= 1))) then
  begin
    vMInsert := TsgCADMInsert.Create;
    vMInsert.Clone(FEnt);
    FEnt.Free;
    FEnt := vMInsert;
    AReader.DoCreate(FEnt);
  end;
  inherited Commit(AReader);
  vInsertAccess := TsgDXFInsertAccess(FEnt);
  vInsertAccess.Point       := FPoints[0];
  vInsertAccess.Extrusion   := FExtrusion;
  vInsertAccess.Scale       := MakeFPoint(FFloats[1], FFloats[2], FFloats[3]);
  vInsertAccess.Angle       := FFloats[10];
  vInsertAccess.BlockRecord := TsgDXFBlockRecord(AReader.BlockRecords[Name]);
  if AnsiPos(FXDataAppName, AReader.FileInfo) > 0 then
  begin
    if (FExtData <> nil) and (FEntGroup = cnstGroupTypeName[gtSVG]) then
      ChangeEntEx(AReader.FConverter);
{$IFDEF SG_BTI}
    if (AReader.XDataProcs <> nil) and (FEntGroup <> cnstGroupTypeName[gtSVG]) then
    begin
//      if (FPXData <> nil) and (FAttributes <> '') then
//      begin
//        if FPXData^.Attribs = nil then
//          FPXData^.Attribs := TsgStringListNV.Create;
//        ApplyAttribsList(FPXData^.Attribs, FAttributes, FAttribsTypes);
//      end;
      ChangeEntity(AReader);
    end;
{$ENDIF}
  end;
{$IFDEF SG_BTI}
  case FEnt.EntClass.EG of
    gtBTI:
      begin
        if TsgDXFEntityAccess(FEnt).GetEntTypeEx <> cnstLabel then
          if AReader.XDataProcs <> nil then
            AReader.XDataProcs.AddEntity(FEnt);
      end;
  end;
{$ENDIF}
  if Assigned(vMInsert) then
  begin
    vMInsert.NumCols := FInts[10];
    vMInsert.NumRows := FInts[11];
    vMInsert.ColSpacing := FFloats[4];
    vMInsert.RowSpacing := FFloats[5];
  end;
end;

procedure TdxfInsert.ReadProperty(const AReader: TdxfReader);

begin
  case AReader.Code of
    String_1001:
      FXDataAppName := AnsiUpperCase(AReader.UValue);
    String_1000:
      NextString(AReader);
    String_1003://style name
      NextString(AReader);
    String_1005:
      NextHandleStr(AReader);
    Integer_1070:
      NextInteger(AReader);//a 16-bit integer
    Integer_1071:
      NextInt(AReader);//a 32-bit integer
    Float_1040:
      NextReal(AReader);
    Float_1041:
      NextReal1(AReader);
    Float_1042:
      NextReal2(AReader);
    Float_1010:
      NextPoint(AReader,0);
    Float_1020:
      NextPoint(AReader,1);
    Float_1030:
      NextPoint(AReader,2);
    else
      inherited ReadProperty(AReader);
  end;
end;

{ TdxfLayout }

constructor TdxfLayout.Create;
begin
  inherited Create;
  FInts[7] := -1;
  FPlotSettings := nil;
end;

destructor TdxfLayout.Destroy;
begin
  FPlotSettings.FEnt.Free;
  FPlotSettings.Free;
  inherited Destroy;
end;

function TdxfLayout.OwnerAdd: Integer;
begin
  Result := FOwner.FEnt.AddEntity(FEnt);
end;

procedure TdxfLayout.Commit(const AReader: TdxfReader);
var
  vLayout: TsgDXFLayout;
  vBlockRecord: TsgDXFBlockRecordAccess;
  vHandleVPort: UInt64;
  vVPort: TsgDXFVport;
begin
  vLayout := TsgDXFLayout(FEnt);
  vLayout.PlotSettings.AssignEntity(FPlotSettings.FEnt);
  inherited Commit(AReader);
  vBlockRecord := TsgDXFBlockRecordAccess(AReader.Conv.BlockRecordByHandle(FSoftOwnerIDs.Last));
  if Assigned(vBlockRecord) then
    vLayout.PaperSpaceBlock := vBlockRecord.Block;

  if AReader.FPapers.Entities[0] = vBlockRecord.Block then
  begin
    if Assigned(FPointerIDs) and (FPointerIDs.Count > 0) then
    begin
      vHandleVPort := FPointerIDs.Last;
      vVPort := TsgDXFVport(AReader.Conv.Sections[csVPorts].FindEntByHandle(vHandleVPort));
      if Assigned(vVPort) then
        AReader.FActiveVPort := vVPort;
    end;
  end;
end;

procedure TdxfLayout.ReadProperty(const AReader: TdxfReader);
var
  vLayout: TsgDXFLayout;
  vPoint: TFPoint;
begin
  vLayout := TsgDXFLayout(FEnt);
  inherited ReadProperty(AReader);
  case AReader.Code of
    Text_1:     vLayout.Name := FTexts[1];
    XOther_13:
      begin
        vPoint := vLayout.UCSOrigin;
        vPoint.X := AReader.FloatValue;
        vLayout.UCSOrigin := vPoint;
      end;
    YOther_23:
      begin
        vPoint := vLayout.UCSOrigin;
        vPoint.Y := AReader.FloatValue;
        vLayout.UCSOrigin := vPoint;
      end;
    ZOther_33:
      begin
        vPoint := vLayout.UCSOrigin;
        vPoint.Z := AReader.FloatValue;
        vLayout.UCSOrigin := vPoint;
      end;
    XOther_16:
      begin
        vPoint := vLayout.UCSXDir;
        vPoint.X := AReader.FloatValue;
        vLayout.UCSXDir := vPoint;
      end;
    YOther_26:
      begin
        vPoint := vLayout.UCSXDir;
        vPoint.Y := AReader.FloatValue;
        vLayout.UCSXDir := vPoint;
      end;
    ZOther_36:
      begin
        vPoint := vLayout.UCSXDir;
        vPoint.Z := AReader.FloatValue;
        vLayout.UCSXDir := vPoint;
      end;
    XOther_17:
      begin
        vPoint := vLayout.UCSYDir;
        vPoint.X := AReader.FloatValue;
        vLayout.UCSYDir := vPoint;
      end;
    YOther_27:
      begin
        vPoint := vLayout.UCSYDir;
        vPoint.Y := AReader.FloatValue;
        vLayout.UCSYDir := vPoint;
      end;
    ZOther_37:
      begin
        vPoint := vLayout.UCSYDir;
        vPoint.Z := AReader.FloatValue;
        vLayout.UCSYDir := vPoint;
      end;
    String_100:
      begin
        if (AReader.UValue = sAcDbPlotSettings) and (FPlotSettings = nil) then
        begin
          FPlotSettings := TdxfPlotSettings(CreateSubEntity(AReader, cnstObjectsPLOTSETTINGS));
          FPlotSettings.ReadState(AReader);
        end;
      end;
  end;
end;

procedure TdxfLayout.SetLayerByName(AReader: TdxfReader; const AName: string);
begin
  // do nothing
end;

{ TdxfMLine }

{private}

procedure TdxfMLine.NewVertex;
begin
  if FVertex <> nil then
  begin
    FVertex.Complete;
    FVertex.Point := FPoints[1];
    FVertex.Direction := FPoints[2];
    FVertex.Miter := FPoints[3];
    TsgCADMLine(FEnt).AddEntity(FVertex);
  end;
  FVertex := TsgMVertex.Create;
end;

{protected}

procedure TdxfMLine.Commit(const AReader: TdxfReader);
var
  vMLine: TsgCADMLine;
begin
  inherited Commit(AReader);
  NewVertex;
  FVertex.Free;
  vMLine := TsgCADMLine(FEnt);
  vMLine.StartPoint := FPoints[0];
  vMLine.Extrusion := FExtrusion;
  vMLine.ScaleFactor := FFloats[0];
  vMLine.Justify := FInts[10];
  vMLine.Flags := FInts[11];
  vMLine.Style := TsgMLineStyle(AReader.MStyles[Name]);
end;

procedure TdxfMLine.ReadProperty(const AReader: TdxfReader);
begin
  case AReader.Code of
    XOther_11:  NewVertex;
  end;
  inherited ReadProperty(AReader);
  case AReader.Code of
    Float_41:   FVertex.Add(FFloats[1]);
    Integer_74: FVertex.NewList;
    340: TsgCADMLine(FEnt).Style := TsgMLineStyle(AReader.MHStyles[AReader.HandleValue]);
  end;
end;

{ TdxfMLStyle }

{private}

procedure TdxfMLStyle.NewEntry(AReader: TdxfReader);
begin
  if FCount = 0 then
    Exit;
  TsgMLineStyle(FEnt).NewEntry(FFloats[9], LoadColor(AReader),
    TsgDXFLineType(AReader.LTypes[FTexts[6]]));
  FTexts[6] := '';
  FInts[2] := 0;
  FIntsRGBColor := clNone;
end;

function TdxfMLStyle.OwnerAdd: Integer;
begin
  Result := FOwner.FEnt.AddEntity(FEnt);
end;

{protected}

procedure TdxfMLStyle.Commit(const AReader: TdxfReader);
var
  vMLineStyle: TsgMLineStyle;
begin
  ApplyHandle(AReader.Conv);
  NewEntry(AReader);
  vMLineStyle := TsgMLineStyle(FEnt);
  vMLineStyle.Name := Name;
  vMLineStyle.Flags := Flags;
end;

procedure TdxfMLStyle.ReadProperty(const AReader: TdxfReader);
begin
  if AReader.Code = FloatRepeated_49 then
    NewEntry(AReader);
  inherited ReadProperty(AReader);
  case AReader.Code of
    FloatRepeated_49:   Inc(FCount);
    Integer_71:         TsgMLineStyle(FEnt).ColorCAD := LoadColor(AReader);
  end;
end;

procedure TdxfMLStyle.SetLayerByName(AReader: TdxfReader; const AName: string);
begin
  // do nothing
end;

{ TdxfMText }

constructor TdxfMText.Create;
begin
  inherited Create;
  FPoints[1] := cnstFPointIllegal;
  FFloats[4] := 1;
  FInts[13] := 1;
end;

procedure TdxfMText.Commit(const AReader: TdxfReader);
var
  vMText: TsgDXFMText;
begin
  inherited Commit(AReader);
  vMText := TsgDXFMText(FEnt);
  vMText.Angle       := FFloats[10];//take into account the order Angle & Point1
  vMText.Text        := FTexts[3] + FTexts[1];
  vMText.Style       := TsgDXFStyle(AReader.Styles[Trim(FTexts[7])]);
  vMText.Point       := FPoints[0];
  vMText.Point1      := FPoints[1];
  vMText.Extrusion   := FExtrusion;
  vMText.Height      := FFloats[0];
  vMText.RectWidth   := FFloats[1];
  vMText.Align       := FInts[11];
  vMText.LineSpacingFactor := FFloats[4];
  vMText.LineSpacingStyle  := FInts[13];
  if (FOwner.ClassType = TdxfBlock) and TdxfBlock(FOwner).IsAcadTableBlock then
    TsgDXFMText(FEnt).Hyphenation := True;
end;

procedure TdxfMText.ReadProperty(const AReader: TdxfReader);
begin
  case AReader.Code of
    Text_1:     FTexts[1] := AReader.StrValue;
    Text_3:     FTexts[3] := FTexts[3] + AReader.StrValue;
    else        inherited ReadProperty(AReader);
  end;
end;

{ TdxfObject }

constructor TdxfObject.Create;
begin
  FHardOwnerIDs := TsgInt64List.Create;
  FLinkSoftIDs := TsgInt64List.Create;
  FPointerIDs := TsgInt64List.Create;
  FRctrsHardIDs := TsgInt64List.Create;
  FRctrsSoftIDs := TsgInt64List.Create;
  FSoftOwnerIDs := TsgInt64List.Create;
end;

function TdxfObject.CreateSubEntity(const AReader: TdxfReader;
  AName: string): TdxfObject;
var
  vPEntClass: PEntClass;
  I: Integer;
  vBlock: TsgDXFBlock;
begin
  I := ListOfEntName.IndexOf(AName);
  if I >= 0 then
  begin
    vPEntClass := PEntClass(ListOfEntName.Objects[I]);
    Result := vPEntClass^.EntClass.Create;
    if Assigned(vPEntClass^.Ent) then
    begin
      if vPEntClass^.Ent = TsgDXFBlockRecord then
      begin
        vBlock := TsgDXFBlock.Create;
        Result.FEnt := vBlock.BlockRecord;
      end
      else
        Result.FEnt := vPEntClass^.Ent.Create;
      AReader.DoCreate(Result.FEnt);
    end;
  end
  else
  begin
    Result := TdxfEntity.Create;
    Result.ReleaseEntity;
  end;
  Result.FOwner := Self;
end;

destructor TdxfObject.Destroy;
begin
  FreeAndNil(FHardOwnerIDs);
  FreeAndNil(FLinkSoftIDs);
  FreeAndNil(FPointerIDs);
  FreeAndNil(FRctrsHardIDs);
  FreeAndNil(FRctrsSoftIDs);
  FreeAndNil(FSoftOwnerIDs);
  inherited Destroy;
end;

procedure TdxfObject.DestroyObj;
begin
  FreeAndNil(FObj);
end;

function TdxfObject.EOFEnt(AObj: TdxfObject): Boolean;
begin
  Result := AObj.ClassType = TdxfSeqend;
end;

function TdxfObject.GetConv: TsgDXFConverterAccess;
begin
  if Assigned(FOwner) then
    Result := TsgDXFConverterAccess(FOwner.Conv)
  else
    Result := nil;
end;

function TdxfObject.GetName: string;
begin
  Result := Trim(FTexts[2]);
end;

function TdxfObject.OwnerAdd: Integer;
begin
  Result := FOwner.FEnt.AddEntity(FEnt);
end;

function TdxfObject.AddEntity(const E: TdxfObject): Boolean;
begin
  Result := False;
  if Assigned(FEnt) then
  begin
    if E.FAdded then
      Result := True
    else
      Result := FEnt.AddEntity(E.FEnt) >= 0;
  end;
end;

procedure TdxfObject.ApplyHandle(const AConv: TsgDXFConverterAccess);
begin
  if AConv.MaxHandle < FHandle then
    AConv.MaxHandle := FHandle;
  if Assigned(FEnt) then
    FEnt.Handle := FHandle;
end;

procedure TdxfObject.Commit(const AReader: TdxfReader);
begin
  ApplyHandle(AReader.Conv);
end;

procedure TdxfObject.ReadProperty(const AReader: TdxfReader);
begin
  case AReader.Code of
    1..4, 6..9:
      begin
        FTexts[AReader.Code] := AReader.UValue;
      end;
    5:
      begin
        FHandle := AReader.HandleValue;
      end;
    102:
      begin
        FReactorsRead := not FReactorsRead;
      end;
    330:
      begin
        if FReactorsRead then
          FRctrsSoftIDs.Add(AReader.HandleValue)
        else
          FSoftOwnerIDs.Add(AReader.HandleValue);
      end;
    331:
      begin
        if FReactorsRead then
          FRctrsSoftIDs.Add(AReader.HandleValue)
        else
          FPointerIDs.Add(AReader.HandleValue);
      end;
    350:
      begin
        FLinkSoftIDs.Add(AReader.HandleValue);
      end;
    360:
      begin
        if FReactorsRead then
          FRctrsHardIDs.Add(AReader.HandleValue)
        else
          FHardOwnerIDs.Add(AReader.HandleValue);
      end;
  end;
end;

procedure TdxfObject.ReadState(AReader: TdxfReader);
begin
{$IFDEF SG_USEDXFSRC}
  FSrcStart := AReader.FPrev;
{$ENDIF}
  ReadProps(AReader);
{$IFDEF SG_USEDXFSRC}
  FSrcEnd := AReader.FPrev;
{$ENDIF}
  Commit(AReader);
  AReader.Conv.SetLoading(True, AReader.FPos);
  AReader.DoEvent(AReader.Conv.OnRead);
  if FComplex then
    ReadEntities(AReader);
end;

function TdxfObject.ReleaseEntity: TsgDXFEntity;
begin
  Result := FEnt;
  FEnt := nil;
end;

procedure TdxfObject.SetLayerByName(AReader: TdxfReader; const AName: string);
begin
  FEnt.Layer := TsgDXFLayer(AReader.Layers[AName]);
end;

procedure TdxfObject.SetName(const Value: string);
begin
  FTexts[2] := Value;
end;

procedure TdxfObject.ReadProps(AReader: TdxfReader);
begin
  repeat
    AReader.Next;
    case AReader.Code of
      EntitysBegin_66:  FComplex := AReader.IntValue <> 0;
      PaperSpace_67:    FPaperSpace := Ord(AReader.IntValue <> 0);
      else              ReadProperty(AReader);
    end;
  until AReader.Code = Info_0;
end;

procedure TdxfObject.ReadEntities(AReader: TdxfReader);
begin
  while not AReader.EOF and not ReadEntity(AReader, AReader.UValue) do;
end;

function TdxfObject.ReadEntity(AReader: TdxfReader; AEntName: string): Boolean;
begin
  FObj := CreateSubEntity(AReader, AEntName);
  try
    FObj.ReadState(AReader);
    Result := EOFEnt(FObj);
    if Assigned(FObj.FEnt) then
      if not AddEntity(FObj) then
        FObj.ReleaseEntity.Free;
  finally
    DestroyObj;
  end;
end;

{ TdxfOLE }

procedure TdxfOLE.Commit(const AReader: TdxfReader);
var
  vBinData: AnsiString;
  vOLE2Frame: TsgDXFOle2Frame;
  vOleHeader: PsgOle2FrameHeaderData;

  procedure SetBinData(const AHexDec: AnsiString; var ABinData: AnsiString);
  var
    I, L: Integer;
    vS: AnsiString;
    vPStr, vPBinData: Pointer;
  begin
    vS := AHexDec; // need work with local variable (patch for Delph 6)
    L := Length(vS) shr 1;
    SetLength(ABinData, L);
    vPStr := PPointer(@vS)^;
    vPBinData := PPointer(@ABinData)^;
    I := 0;
    while I < L do
    begin
      PByte(vPBinData)^ := sHexBin[PByte(vPStr)^] shl 4;
      Inc(PByte(vPStr));
      PByte(vPBinData)^ := PByte(vPBinData)^ or sHexBin[PByte(vPStr)^];
      Inc(PByte(vPStr));
      Inc(PByte(vPBinData));
      Inc(I);
    end;
  end;

begin
  inherited Commit(AReader);
  vOLE2Frame := TsgDXFOle2Frame(FEnt);
  SetBinData(FHeader, vBinData);
  vOleHeader := PsgOle2FrameHeaderData(PPointer(@vBinData)^);
  if FInts[10] >= 2 then
  begin
    vOLE2Frame.Point              := FPoints[0];
    vOLE2Frame.Point1             := FPoints[1];
    vOLE2Frame.OLEObjectType      := FInts[11];
    vOLE2Frame.TileModeDescriptor := FInts[12];
    if Assigned(vOleHeader) then
      vOLE2Frame.Aspect := vOleHeader^.DrawAspect;
  end
  else
    if Assigned(vOleHeader) then
    begin
      vOLE2Frame.Point := vOleHeader^.Point1;
      vOLE2Frame.Point1 := vOleHeader^.Point3;
      vOLE2Frame.TileModeDescriptor := vOleHeader^.TileModeDescriptor xor 1;
      vOLE2Frame.Aspect := vOleHeader^.DrawAspect;
    end;
  SetBinData(FData, vBinData);
  vOLE2Frame.BinaryData := vBinData;
end;

procedure TdxfOLE.ReadProperty(const AReader: TdxfReader);
const
  cnstOleDataSignature = $46433044; //'D0CF'
var
  S: AnsiString;
begin
  case AReader.Code of
    String_310:
      begin
        S := AnsiString(AReader.Value);
        FReadData := FReadData or
          (PInteger(PPointer(@S)^)^ = cnstOleDataSignature); //(Copy(S, 1, 4) = 'D0CF');
        if FReadData then
          FData := FData + S
        else
          FHeader := FHeader + S;
      end;
    else
      inherited ReadProperty(AReader);
  end;
end;

{ TdxfPenLine }

procedure TdxfPenLine.Commit(const AReader: TdxfReader);
var P: TsgDXFPenLine;
begin
  inherited Commit(AReader);
  P := TsgDXFPenLine(FEnt);
  P.Point       := FPoints[0];
  P.Extrusion   := FExtrusion;
  P.ZThick      := FZThick;
end;

{ TdxfPenTableItem }

procedure TdxfPenTableItem.Commit(const AReader: TdxfReader);
begin
  inherited Commit(AReader);
  if FEnt is TsgDXFLayer then
    TsgDXFConverterAccess.SetLayerNameOfPassingInspection(TsgDXFLayer(FEnt), Name)
  else
    TsgDXFPenTableItem(FEnt).Name := Name;
  TsgDXFPenTableItem(FEnt).Flags := Flags;
end;

destructor TdxfPenTableItem.Destroy;
begin
  if Assigned(FPenTableItemWithSameNameAlreadyExistsInOwnerTable) then
    ReleaseEntity.Free;
  inherited Destroy;
end;

procedure TdxfPenTableItem.ReadProperty(const AReader: TdxfReader);
begin
  inherited ReadProperty(AReader);
  case AReader.Code of
    Name_2:
      begin
        FPenTableItemWithSameNameAlreadyExistsInOwnerTable :=
          TsgDXFPenTableItem(FOwner.FEnt.FindEntByName(Name));
        FAdded := Assigned(FPenTableItemWithSameNameAlreadyExistsInOwnerTable);
      end;
  end;
end;

procedure TdxfPenTableItem.SetLayerByName(AReader: TdxfReader;
  const AName: string);
begin
  // do nothing
end;

{ TdxfPoint }

procedure TdxfPoint.Commit(const AReader: TdxfReader);
var
  P: TsgDXFPoint;
begin
  inherited Commit(AReader);
  P := TsgDXFPoint(FEnt);
  P.Point     := FPoints[0];
  P.Extrusion := FExtrusion;
  P.ZThick    := FZThick;
end;

{ TdxfProxy }

{private}

procedure TdxfProxy.AddData(const S: AnsiString);
begin
  AddBinData(S, Pointer(FData), FSize);
end;

{protected}

destructor TdxfProxy.Destroy;
begin
  FList.Free;
  FreeRecordList(FProps);
  if FData <> nil then
    FreeMem(FData);
  inherited Destroy;
end;

procedure TdxfProxy.Commit(const AReader: TdxfReader);
var
  ProxyReader: IProxyReader;
begin
  inherited Commit(AReader);
  if FData=nil then
    Exit;
  AReader.ForceStandardObjects;
  ProxyReader := TDXFProxyReader.Create(FData, TsgDWGVersion(AReader.Version));
  DXFConv.ReadProxyData(FList, FProps, AReader.Conv, ProxyReader);
  InitProxyEntities(AReader);
end;

procedure TdxfProxy.InitProxyEntities(const AReader: TdxfReader);
var
  I, K: Integer;
  vE: TsgDXFEntity;
  vT: TsgDXFTextAccess absolute vE;
  vP: PsgSubProxyProps;
  vFontName: string;
  vStyle: TsgDXFStyle;
begin
  for I := 0 to FList.Count - 1 do
  begin
    vE := FList[I];
    vP := FProps[I];
    vE.Visibility := FEnt.Visibility;
    vE.LineTypeScale := FEnt.LineTypeScale;
    if vP^.ColorID <= 0 then
      vE.ColorCAD := FEnt.ColorCAD
    else
      vE.ColorCAD := MakeColorCAD(acIndexColor, vP^.ColorID);
    if vP^.LayerIndex < 0 then
      vE.Layer := FEnt.Layer
    else
      vE.Layer := AReader.Conv.Layers[vP^.LayerIndex];
    vE.LineType := AReader.Conv.LTypes[vP^.LTypeIndex + 2];
    case vE.EntType of
      ceText, ceAttrib, ceAttdef:
        begin
          vFontName := vT.SHXFont;
          if vT.WinFont then
            vFontName := vT.FontName;
          K := AReader.FStylesByFont.IndexOf(vFontName);
          if K >= 0 then
            vStyle := TsgDXFStyle(AReader.FStylesByFont.Objects[K])
          else
          begin
            vFontName := ChangeFileExt(vFontName, '');
            K := AReader.FStylesByFont.IndexOf(vFontName);
            if K >= 0 then
              vStyle := TsgDXFStyle(AReader.FStylesByFont.Objects[K])
            else
              vStyle := AReader.Conv.StyleByName(cnstStandard);
          end;
          vT.StyleRef := vStyle;
        end;
    end;
    FEnt.AddEntity(vE);
  end;
end;

constructor TdxfProxy.Create;
begin
  inherited Create;
  FList := TList.Create;
  FProps := TList.Create;
end;

procedure TdxfProxy.ReadProperty(const AReader: TdxfReader);
begin
  case AReader.Code of
    String_310: AddData(AReader.Value);
    else        inherited ReadProperty(AReader);
  end;
end;

{ TdxfShape }

constructor TdxfShape.Create;
begin
  inherited Create;
  FPoints[1] := cnstFPointIllegal;
  FFloats[1] := 1.0;
end;

procedure TdxfShape.Commit(const AReader: TdxfReader);
var
  vShape: TsgDXFShape;
begin
  inherited Commit(AReader);
  vShape := TsgDXFShape(FEnt);
  vShape.ShapeName    := Name;
  vShape.Point        := FPoints[0];
  vShape.Extrusion    := FExtrusion;
  vShape.Height       := FFloats[0];// Size
  vShape.Scale        := FFloats[1];// Width factor
  vShape.Rotation     := FFloats[10];
  vShape.ObliqueAngle := FFloats[11];
end;

{ TdxfSortEntsTable }

procedure TdxfSortEntsTable.Commit(const AReader: TdxfReader);
begin
  inherited Commit(AReader);
  FPointerIDs := nil; // release list
  TsgDXFSortEntsTable(FEnt).SortObject := TsgDXFEntity(AReader.HBlockRecords[FSoftOwnerIDs.Last]);
  TsgDXFSortEntsTable(FEnt).Name := sAcadSortEnts;
end;

function TdxfSortEntsTable.OwnerAdd: Integer;
begin
  Result := FOwner.FEnt.AddEntity(FEnt);
end;

procedure TdxfSortEntsTable.ReadProperty(const AReader: TdxfReader);
const
  cnstAcDbSortentsTable = 'AcDbSortentsTable';
begin
  case AReader.Code of
    String_100: FStartTable := AReader.UValue = cnstAcDbSortentsTable;
    Text_5:
      if FStartTable then
        TsgDXFSortEntsTable(FEnt).HandlesNew.Add(AReader.HandleValue)
      else
        inherited ReadProperty(AReader);
  else
    inherited ReadProperty(AReader);
  end;
end;

procedure TdxfSortEntsTable.ReadState(AReader: TdxfReader);
begin
  FPointerIDs.Free;
  FPointerIDs := TsgDXFSortEntsTable(FEnt).HandlesOld;
  inherited ReadState(AReader);
end;

{ TdxfTable }

constructor TdxfTable.Create;
begin
  inherited Create;
  FComplex := True;
end;

function TdxfTable.EOFEnt(AObj: TdxfObject): Boolean;
begin
  Result := AObj.ClassType = TdxfEndTab;
end;

procedure TdxfTable.Commit(const AReader: TdxfReader);
var
  I: Integer;
  S: string;
  C: TConvSection;
begin
  inherited Commit(AReader);
  FEnt.Name := Name;

  I := DataBaseSections.IndexOf(Name);
  if I >= 0 then
  begin
    C := TConvSection(DataBaseSections.Objects[I]);
    AReader.Conv.Sections[C] := TsgDXFGroup(FEnt);
    case C of
      csBlockRecords:
        begin
          ReleaseEntity.Free;
          FEnt := TsgDXFBlockRecords.Create;
          FEnt.Handle := FHandle;
          FEnt.Name := Name;
          TsgDXFEntityAccess(FEnt).SetConverter(AReader.Conv);
        end;
      csStyles:
        begin
          for I := 0 to FEnt.Count - 1 do
          begin
            S := TsgDXFStyle(FEnt[I]).GetPrimaryFontName;
            if S <> '' then
              AReader.FStylesByFont.AddObject(S, FEnt[I]);
            S := TsgDXFStyle(FEnt[I]).FontName;
            if S <> '' then
              AReader.FStylesByFont.AddObject(S, FEnt[I]);
          end;
        end;
    end;
  end;

end;

{ TdxfText }

constructor TdxfText.Create;
begin
  inherited Create;
  FPoints[1] := cnstFPointIllegal;
  FFloats[1] := 1.0;
end;

procedure TdxfText.Commit(const AReader: TdxfReader);
var
  vText: TsgDXFText;
begin
  inherited Commit(AReader);
  vText := TsgDXFText(FEnt);
  vText.Text         := FTexts[1];
  vText.Style        := TsgDXFStyle(AReader.Styles[Trim(FTexts[7])]);
  vText.Point        := FPoints[0];
  vText.Point1       := FPoints[1];
  vText.Extrusion    := FExtrusion;
  vText.Height       := FFloats[0];
  vText.Scale        := FFloats[1];
  vText.Rotation     := FFloats[10];
  vText.ObliqueAngle := FFloats[11];
  vText.Generation   := FInts[11];
  vText.HAlign       := FInts[12];
  vText.VAlign       := FInts[13];
end;

procedure TdxfText.ReadProperty(const AReader: TdxfReader);
begin
  case AReader.Code of
    Text_1: begin
      FTexts[1] := AReader.StrValue;
      ReplaceAnsi(FTexts[1], cnstCaretAndSpace, cnstCaret);
    end
  else
    inherited ReadProperty(AReader);
  end;
end;

{ TdxfTolerance }

constructor TdxfTolerance.Create;
begin
  inherited Create;
  FPoints[1] := cnstFPointIllegal;
end;

procedure TdxfTolerance.Commit(const AReader: TdxfReader);
var
  vTolerance: TsgDXFTolerance;
begin
  inherited Commit(AReader);
  vTolerance := TsgDXFTolerance(FEnt);
  vTolerance.Text        := FTexts[1];
  vTolerance.Point       := FPoints[0];
  vTolerance.Point1      := FPoints[1];
  vTolerance.Extrusion   := FExtrusion;
  vTolerance.DimStyle := AReader.FConverter.DimensionStyleByName(FTexts[3]);
end;

procedure TdxfTolerance.ReadProperty(const AReader: TdxfReader);
var
  vTolerance: TsgDXFTolerance;
begin
  vTolerance := TsgDXFTolerance(FEnt);
  case AReader.Code of
    Integer_1070:
      case FCodeValue of
        Integer_176:
          begin
            vTolerance.DimlineColor := MakeColorCAD(acIndexColor,AReader.IntValue);
            FCodeValue := 0;
          end;
      else
        FCodeValue := AReader.IntValue;
      end;
    Float_1040:
      case FCodeValue of
        Float_40:  vTolerance.DimScaleOverall := Abs(AReader.FloatValue);
        Float_140: vTolerance.Height  := Abs(AReader.FloatValue);
      end;
    String_1005:
      case FCodeValue of
        String_340: vTolerance.Style := TsgDXFStyle(AReader.HStyles[AReader.HandleValue]);
      end;
    else
      inherited ReadProperty(AReader);
  end;
end;

{ TdxfVertex }

procedure TdxfVertex.Commit(const AReader: TdxfReader);
var
  vVertex: TsgDXFVertex;
begin
  inherited Commit(AReader);
  FComplex := False;
  vVertex := TsgDXFVertex(FEnt);
  vVertex.Point                       := FPoints[0];
  vVertex.StartWidth                  := FFloats[0];
  vVertex.EndWidth                    := FFloats[1];
  vVertex.Bulge                       := FFloats[2];
  vVertex.Flags                       := Flags;
end;


procedure TdxfVertex.ReadProperty(const AReader: TdxfReader);
begin
  inherited ReadProperty(AReader);
  case AReader.Code of
    71:  TsgDXFVertex(FEnt).PolyFaceVertexIndex1 := FInts[11];
    72:  TsgDXFVertex(FEnt).PolyFaceVertexIndex2 := FInts[12];
    73:  TsgDXFVertex(FEnt).PolyFaceVertexIndex3 := FInts[13];
    74:  TsgDXFVertex(FEnt).PolyFaceVertexIndex4 := FInts[14];
  end;
end;

{ TdxfViewport }

{private}

procedure TdxfViewport.Next3Reals(const AReader: TdxfReader);
begin
  Inc(FCount_1010);
  case FCount_1010 of
    1..3: FPoints[7].V[FCount_1010-1] := AReader.FloatValue;
    4..6: FPoints[6].V[FCount_1010-4] := AReader.FloatValue;
  end;
end;

procedure TdxfViewport.NextReal(const AReader: TdxfReader);
begin
  Inc(FCount_1040);
  case FCount_1040 of
    1: FFloats[11]    := AReader.FloatValue;
    2: FFloats[5]     := AReader.FloatValue;
    3: FPoints[2].X   := AReader.FloatValue;
    4: FPoints[2].Y   := AReader.FloatValue;
  end;
end;

{protected}

constructor TdxfViewport.Create;
begin
  inherited Create;
  FInts[8] := 1;
  FInts[9] := 1;
  FPoints[6].Z := 1.0;
end;

procedure TdxfViewport.Commit(const AReader: TdxfReader);
var
  vViewport: TsgDXFViewport;
begin
  inherited Commit(AReader);
  vViewport := TsgDXFViewport(FEnt);
  vViewport.PSpaceCenter        := FPoints[0];
  vViewport.MSpaceCenter        := FPoints[2];
  vViewport.ViewDirection       := FPoints[6];
  vViewport.ViewTarget          := FPoints[7];
  vViewport.PSpaceWidth         := FFloats[0];
  vViewport.PSpaceHeight        := FFloats[1];
  vViewport.FrontClipPlane      := FFloats[3];
  vViewport.BackClipPlane       := FFloats[4];
  vViewport.MSpaceHeight        := FFloats[5];
  vViewport.ViewTwistAngle      := FFloats[11];
  vViewport.StatusField         := FInts[8];
  vViewport.ThisID              := FInts[9];
  vViewport.Handle := FHandle;
  AReader.Conv.SetHandle(vViewport);
end;

procedure TdxfViewport.ReadProperty(const AReader: TdxfReader);
var
  vViewport: TsgDXFViewport;
begin
  vViewport := TsgDXFViewport(FEnt);
  inherited ReadProperty(AReader);
  case AReader.Code of
    Integer_90:  vViewport.Flags := AReader.IntValue;
    String_340:  vViewport.ClippingBoundaryHandle := AReader.HandleValue;
    String_341, String_331: vViewport.FrozenLayers.Add(AReader.HandleValue);
      // acR2000 - String_341; acR2004+ - String_331; acR12 - 1003 (see below)
    String_1001:
      begin
        vViewport.XDataAppName := AReader.UValue;
        FIsAcad := vViewport.XDataAppName = sACADXDataAppName;
      end;
  end;
  case AReader.Code of
    1003: if FIsAcad then vViewport.FrozenLayers.Add(AReader.Conv.LayerByName(AReader.UValue).Handle);
    1040: if FIsAcad then NextReal(AReader);
    1010,1020,1030: if FIsAcad then Next3Reals(AReader);
  end;
end;

{ TdxfVport }

constructor TdxfVport.Create;
begin
  inherited Create;
  FPoints[6] := MakeFPoint(0,0,1);
end;

procedure TdxfVport.Commit(const AReader: TdxfReader);
var
  vVPort: TsgDXFVport;
begin
  inherited Commit(AReader);
  vVPort := TsgDXFVport(FEnt);
  vVPort.CircleZoomPercent   := FInts[12];
  vVPort.UCSOrigin           := FOrigin;
  vVPort.UCSXDir             := FXDir;
  vVPort.UCSYDir             := FYDir;
  vVPort.UCSVP               := FUCSVP = 1;
  vVPort.ViewAspectRatio     := FFloats[1];
  vVPort.ViewCenterPoint     := FPoints[2];
  vVPort.ViewDirection       := FPoints[6];
  vVPort.ViewTarget          := FPoints[7];
  vVPort.ViewHeight          := FFloats[0];
  vVPort.ViewTwistAngle      := FFloats[11];
  vVPort.Name := Name;
end;

procedure TdxfVport.ReadProperty(const AReader: TdxfReader);
begin
  inherited ReadProperty(AReader);
  case AReader.Code of
    UCSVP_65:   FUCSVP := AReader.IntValue;
    XOther_110: FOrigin.X := AReader.FloatValue;
    YOther_120: FOrigin.Y := AReader.FloatValue;
    ZOther_130: FOrigin.Z := AReader.FloatValue;
    XOther_111: FXDir.X := AReader.FloatValue;
    YOther_121: FXDir.Y := AReader.FloatValue;
    ZOther_131: FXDir.Z := AReader.FloatValue;
    XOther_112: FYDir.X := AReader.FloatValue;
    YOther_122: FYDir.Y := AReader.FloatValue;
    ZOther_132: FYDir.Z := AReader.FloatValue;
  end;
end;

procedure TdxfVport.SetLayerByName(AReader: TdxfReader; const AName: string);
begin
  // do nothing
end;

{ TdxfWipeout }

procedure TdxfWipeout.Commit(const AReader: TdxfReader);
var
  vWipeout: TsgCADWipeout;
begin
  inherited Commit(AReader);
  vWipeout := TsgCADWipeout(FEnt);
  vWipeout.Flags := Flags;
  vWipeout.ClippingBoundaryType := FInts[11];
  vWipeout.Point := FPoints[0];
  vWipeout.UVector := FPoints[1];
  vWipeout.VVector := FPoints[2];
  vWipeout.Size := FPoints[3];
end;

procedure TdxfWipeout.ReadProperty(const AReader: TdxfReader);
begin
  inherited ReadProperty(AReader);
  case AReader.Code of
    YOther_24:
      TsgCADWipeout(FEnt).AddPoint(FPoints[4].X, FPoints[4].Y);
    Word_280:
      TsgCADWipeout(FEnt).UseClipping := AReader.IntValue <> 0;
  end;
end;

{ TdxfWipeoutVars }

procedure TdxfWipeoutVars.Commit(const AReader: TdxfReader);
begin
  inherited Commit(AReader);
  FComplex := False;
end;

procedure TdxfWipeoutVars.ReadProperty(const AReader: TdxfReader);
begin
  inherited ReadProperty(AReader);
  if AReader.Code = Integer_70 then
    TsgCADWipeoutVariables(FEnt).DisplayImageFrame := FInts[10] = 1;
end;

procedure TdxfWipeoutVars.SetLayerByName(AReader: TdxfReader;
  const AName: string);
begin
  // do nothing
end;

{ TdxfCircle }

constructor TdxfCircle.Create;
begin
  inherited Create;
  FFloats[11] := 360;
end;

procedure TdxfCircle.Commit(const AReader: TdxfReader);
begin
  inherited Commit(AReader);
  TsgDXFCircle(FEnt).Point  := FPoints[0];
  TsgDXFCircle(FEnt).Radius := IfThen(FFloats[0] > fDoubleResolution,
    FFloats[0], 1.0);
end;

{ TdxfLine }

procedure TdxfLine.Commit(const AReader: TdxfReader);
begin
  inherited Commit(AReader);
  TsgDXFLine(FEnt).Point1 := FPoints[1];
end;

{ TdxfSolid }

procedure TdxfSolid.Commit(const AReader: TdxfReader);
begin
  inherited Commit(AReader);
  TsgDXFSolid(FEnt).Point2 := FPoints[2];
  TsgDXFSolid(FEnt).Point3 := FPoints[3];
end;

{ TdxfSpline }

{private}

procedure TdxfSpline.AddControl;
begin
  if FNewCtl then
  begin
    TsgDXFSpline(FEnt).Controls.Add(FPoints[0]);
  end;
  FNewCtl := True;
end;

procedure TdxfSpline.AddFit;
begin
  if FNewFit then
  begin
    TsgDXFSpline(FEnt).Fit.Add(FPoints[1]);
  end;
  FNewFit := True;
end;

procedure TdxfSpline.AddKnot(Value: Single);
begin
  TsgDXFSpline(FEnt).Knots.Add(Value);
end;

procedure TdxfSpline.AddWeight(Value: Single);
begin
  TsgDXFSpline(FEnt).AddWeight(Value);
end;

{protected}

procedure TdxfSpline.Commit(const AReader: TdxfReader);
begin
  if FNewCtl then AddControl;
  if FNewFit then AddFit;
  inherited Commit(AReader);
  TsgDXFSpline(FEnt).BeginningTangent := FPoints[2];
  TsgDXFSpline(FEnt).EndingTangent := FPoints[3];
  SetDegreeSplineCurve;
  if FFlagsExtented > -1 then
    TsgDXFSplineAccess(FEnt).FlagsExtented := FFlagsExtented;
end;

constructor TdxfSpline.Create;
begin
  inherited Create;
  FCodeValue := cnstCodeValueUndefined;
  FFlagsExtented := -1;
end;

procedure TdxfSpline.ReadProperty(const AReader: TdxfReader);
begin
  case AReader.Code of
    XFirst_10:         AddControl;
    XOther_11:         AddFit;
    Float_40:          AddKnot(AReader.FloatValue);
    Float_41:          AddWeight(AReader.FloatValue);
    Integer_1070,
    Integer_1071:
      begin
        NextInteger(AReader);
        Exit;
      end;
    String_1001:
      begin
        FXDataAppName := AnsiUpperCase(AReader.UValue);
        Exit;
      end;
  end;
  inherited ReadProperty(AReader);
end;

procedure TdxfSpline.NextInteger(const AReader: TdxfReader);
begin
 case FCodeValue of
    Integer_70:
      begin
        if FXDataAppName = UpperCase(GetAppID) then
          FFlagsExtented := AReader.IntValue;
        FCodeValue := cnstCodeValueUndefined;
      end;
  else
    FCodeValue := AReader.IntValue;
  end;
end;

procedure TdxfSpline.SetDegreeSplineCurve;
begin
  TsgDXFSpline(FEnt).Degree := FInts[11];
end;

{ TdxfPolyLine }

procedure TdxfPolyLine.Commit(const AReader: TdxfReader);
var
  vPolyLine: TsgDXFPolyLine;
begin
  inherited Commit(AReader);
  vPolyLine := TsgDXFPolyLine(FEnt);
  vPolyLine.StartWidth      := ConvertDoubleToSingle(FFloats[0]);
  vPolyLine.EndWidth        := ConvertDoubleToSingle(FFloats[1]);
  vPolyLine.GlobalWidth     := ConvertDoubleToSingle(FFloats[3]);
  if FInts[13] <> 0 then
    FInts[11] := FInts[13];
  if FInts[14] <> 0 then
    FInts[12] := FInts[14];
  vPolyLine.MeshM := FInts[11];
  vPolyLine.MeshN := FInts[12];
  SetElevation;
end;

procedure TdxfPolyLine.SetElevation;
begin
  TsgDXFPolyLine(FEnt).Elevation := FPoints[0].Z;
end;

{ TdxfAcadTable }

procedure TdxfAcadTable.Commit(const AReader: TdxfReader);
begin
  inherited Commit(AReader);
  FComplex := False;
  TsgDXFAcadTable(FEnt).Style := TsgDXFAcadTableStyle(AReader.HTableStyles[FTableStyleHandle]);
  TsgDXFAcadTable(FEnt).Block := TsgDXFBlock(AReader.HBlockRecords[FBlockRecordHandle]);
end;

function TdxfAcadTable.CurCell: TsgAcadTableCell;
begin
  Result := TsgDXFAcadTable(FEnt).Cell[FColIndex, FRowIndex];
end;

procedure TdxfAcadTable.ReadProperty(const AReader: TdxfReader);
const
  cnstAcDbTable = 'AcDbTable';
var
  vFlags: Byte;
  vAcadTable: TsgDXFAcadTable;
begin
  vAcadTable := TsgDXFAcadTable(FEnt);
  case AReader.Code of
    1:  CurCell.Text := CurCell.Text + AReader.UValue;
    3:  CurCell.Text := CurCell.Text + AReader.UValue;
    7:  CurCell.TextStyle := TsgDXFStyle(AReader.Styles[AReader.UValue]);
    40: vAcadTable.Properties.HorzCellMargin := AReader.FloatValue;
    41: vAcadTable.Properties.VertCellMargin := AReader.FloatValue;
    63: CurCell.FillColor := MakeColorCAD(acIndexColor, AReader.IntValue);
    64: CurCell.TextColor := MakeColorCAD(acIndexColor, AReader.IntValue);
    65..69: CurCell.BorderColor[AReader.Code - 64] :=
      MakeColorCAD(acIndexColor, AReader.IntValue);
    70: vAcadTable.Properties.FlowDirection := AReader.IntValue;
    90: vAcadTable.Flags := AReader.IntValue;
    91:
      if not FEofCommon then
        vAcadTable.NumRows := AReader.IntValue;
    92:
      if FIsTableSubClass and not FEofCommon then
        vAcadTable.NumCols := AReader.IntValue;
    93..96:
      if not FEofCommon then
      begin
        vFlags := vAcadTable.OverrideFlags;
        vFlags := vFlags or AReader.IntValue shl (AReader.Code - 93);
        vAcadTable.OverrideFlags := vFlags;
      end;
    100: FIsTableSubClass := AReader.StrValue = cnstAcDbTable;
    140: CurCell.TextHeight := AReader.FloatValue;
    141:
      begin
        vAcadTable.RowHeight[FRowIndex] := AReader.FloatValue;
        Inc(FRowIndex);
        if FRowIndex = vAcadTable.NumRows then
          FRowIndex := 0;
      end;
    142:
      begin
        vAcadTable.ColWidth[FColIndex] := AReader.FloatValue;
        Inc(FColIndex);
        if FColIndex = vAcadTable.NumCols then
        begin
          FColIndex := -1;
          FEofCommon := True;
        end;
      end;
    144: CurCell.BlockScale := AReader.FloatValue;
    145: CurCell.Rotation := AReader.FloatValue;
    170: CurCell.CellAlignment := AReader.IntValue;
    171:
      begin
        Inc(FColIndex);
        if FColIndex = vAcadTable.NumCols then
        begin
          FColIndex := 0;
          Inc(FRowIndex);
        end;
        CurCell.IsTextType := AReader.IntValue = 1;
      end;
    172: CurCell.Flags := AReader.IntValue;
    173: CurCell.MergedValue := AReader.IntValue;
    174: CurCell.AutoFit := AReader.IntValue = 1;
    175: CurCell.MergedWidth := AReader.IntValue;
    176: CurCell.MergedHeight := AReader.IntValue;
    177: CurCell.OverrideFlag := AReader.IntValue;
    178: CurCell.VirtualEgdeFlag := AReader.IntValue = 1;
    179: CurCell.NumAttdefs := AReader.IntValue;
    274..279: CurCell.BorderLineWeight[AReader.Code - 274] :=
      ExpandLWeight(AReader.IntValue);
    280: vAcadTable.Properties.TitleSuppressed := AReader.IntValue = 1;
    281: vAcadTable.Properties.HeaderSuppressed := AReader.IntValue = 1;
    283: CurCell.BkColorOn := AReader.IntValue = 1;
    284..289: CurCell.BorderVisible[AReader.Code - 284] :=
      AReader.IntValue = 1;
    300: CurCell.AttdefValue := AReader.UValue;
    331: CurCell.AttdefHandle := AReader.HandleValue;
    340: CurCell.BlockRecordHandle := AReader.HandleValue;
    // Read TableStyle Handle for AcadTable
    342: FTableStyleHandle := AReader.HandleValue;
    343: FBlockRecordHandle := AReader.HandleValue;
    // Field handle
    344: CurCell.Field := TsgDXFField(AReader.HFields[AReader.HandleValue]);
  else
    inherited ReadProperty(AReader);
  end;
end;

{ TdxfAcadTableStyle }

procedure TdxfAcadTableStyle.Commit(const AReader: TdxfReader);
begin
  inherited Commit(AReader);
  FEnt.Name := Name;
  TsgDXFAcadTableStyle(FEnt).Description := FTexts[3];
end;

constructor TdxfAcadTableStyle.Create;
begin
  inherited Create;
  FCellTypeIndex := Pred(cttData);
end;

function TdxfAcadTableStyle.GetSell: TsgAcadTableCellStyle;
begin
  if FCellTypeIndex = Pred(cttData) then
    FCellTypeIndex := Succ(FCellTypeIndex);
  Result := TsgDXFAcadTableStyle(FEnt).CellStyle[FCellTypeIndex];
end;

procedure TdxfAcadTableStyle.ReadProperty(const AReader: TdxfReader);
begin
  case AReader.Code of
    7:
      begin
        inherited ReadProperty(AReader);
        FCellTypeIndex := Succ(FCellTypeIndex);
        Cell.TextStyle :=
          TsgDXFStyle(AReader.FConverter.StyleByName(Trim(FTexts[7])));
      end;
    40: TsgDXFAcadTableStyle(FEnt).HorzCellMargin := AReader.FloatValue;
    41: TsgDXFAcadTableStyle(FEnt).VertCellMargin := AReader.FloatValue;
    62: Cell.TextColor := MakeColorCAD(acIndexColor, AReader.IntValue);
    63: Cell.FillColor := MakeColorCAD(acIndexColor, AReader.IntValue);
    64..69: Cell.BorderColor[AReader.Code - 64] := MakeColorCAD(acIndexColor, AReader.IntValue);
    70: TsgDXFAcadTableStyle(FEnt).FlowDirection := AReader.IntValue;
    71: TsgDXFAcadTableStyleAccess(FEnt).Flags := AReader.IntValue;
    90: Cell.DataType := AReader.IntValue;
    91: Cell.UnitType := AReader.IntValue;
    140: Cell.TextHeight := AReader.FloatValue;
    170: Cell.CellAlignment := AReader.IntValue;
    274..279: Cell.BorderLineWeight[AReader.Code - 274] := ExpandLWeight(AReader.FloatValue);
    284..289: Cell.BorderVisible[AReader.Code - 284] := AReader.IntValue = 1;
    280: TsgDXFAcadTableStyle(FEnt).TitleSuppressed := AReader.IntValue = 1;
    281: TsgDXFAcadTableStyle(FEnt).HeaderSuppressed := AReader.IntValue = 1;
    283: Cell.BkColorOn := AReader.IntValue = 1;
    else
      inherited ReadProperty(AReader);
  end;
end;

procedure TdxfAcadTableStyle.SetLayerByName(AReader: TdxfReader;
  const AName: string);
begin
  // do nothing
end;

{ TdxfACIS }

procedure TdxfACIS.Commit(const AReader: TdxfReader);
var
  vACISEntity: TsgDXFACISEntity;
begin
  vACISEntity := TsgDXFACISEntity(FEnt);
  FEnt := vACISEntity.Pen;
  inherited Commit(AReader);
  FEnt := vACISEntity;
  vACISEntity.Handle := vACISEntity.Pen.Handle;
end;

procedure TdxfACIS.ReadProperty(const AReader: TdxfReader);
var
  S: string;
  I: Integer;
begin
  case AReader.Code of
    Text_1: FData.Add(string(AReader.Value));
    Text_3:
    begin
      I := FData.Count - 1;
      S := FData[I];
      if (S <> '') and (S[Length(S)] <> '|') then
        FData[I] := S + string(AReader.Value)
      else
        FData.Add(string(AReader.Value));
    end
  else
    inherited ReadProperty(AReader);
  end;
end;

procedure TdxfACIS.ReadState(AReader: TdxfReader);
begin
  FData := TsgDXFACISEntity(FEnt).ProprietaryData;
  inherited ReadState(AReader);
end;

{ TdxfArc }

procedure TdxfArc.Commit(const AReader: TdxfReader);
begin
  inherited Commit(AReader);
  TsgDXFArc(FEnt).StartAngle := FFloats[10];
  TsgDXFArc(FEnt).EndAngle   := FFloats[11];
end;

{ TdxfAttdef }

constructor TdxfAttdef.Create;
begin
  inherited Create;
  FCodeValue := cnstCodeValueUndefined;
  FLockPosition := -1;
end;

procedure TdxfAttdef.Commit(const AReader: TdxfReader);
var
  vAttdef: TsgDXFAttdef;
begin
  FInts[13] := FInts[14];
  inherited Commit(AReader);
  vAttdef := TsgDXFAttdef(FEnt);
  vAttdef.Value       := FTexts[1];
  vAttdef.Tag         := Name;
  vAttdef.Flags       := Flags;
  if (FLockPosition > -1) and (AReader.Version < Byte(acR2007)) then
    vAttdef.LockPosition := FLockPosition <> 0;
end;

procedure TdxfAttdef.ReadProperty(const AReader: TdxfReader);
begin
  case AReader.Code of
    Word_280:
      begin
        if AReader.Version >= Byte(acR2007) then
          TsgDXFAttdef(FEnt).LockPosition := AReader.IntValue <> 0;
      end;
    String_1001:
      begin
        FXDataAppName := AnsiUpperCase(AReader.UValue);
      end;
    Integer_1070:
       NextInteger(AReader);
    else
      inherited ReadProperty(AReader);
  end;
end;

procedure TdxfAttdef.NextInteger(const AReader: TdxfReader);
begin
 case FCodeValue of
    Info_0:
      begin
        if FXDataAppName = UpperCase(sACADXDataAttribAppName) then
          FLockPosition := AReader.IntValue;
        FCodeValue := cnstCodeValueUndefined;
      end;
  else
    FCodeValue := AReader.IntValue;
  end;
end;

{$IFDEF SG_BTI}
{ TdxfAttrib }

{private}

procedure TdxfAttrib.NextInteger(const AReader: TdxfReader);
begin
  case FCodeValue of
    Word_280:
      begin
        FAttribType := AReader.IntValue;
        FCodeValue := cnstCodeValueUndefined;
      end;
  else
    inherited NextInteger(AReader);
  end;
end;

{protected}

constructor TdxfAttrib.Create;
begin
  inherited Create;
  FAttribType := -1;
end;

procedure TdxfAttrib.Commit(const AReader: TdxfReader);
var
  vAttdef: TsgDXFAttdef;
begin
  inherited Commit(AReader);
  if FAttribType >= 0 then
  begin
    vAttdef := TsgDXFAttrib(FEnt);
    FEnt := TsgAttrib.Create;
    FEnt.AssignEntity(vAttdef);
    TsgAttrib(FEnt).TypeValue := TsgAttribType(FAttribType);
    vAttdef.Free;
  end;
end;
{$ENDIF}

{ TdxfDimension }

{private}

procedure TdxfDimension.ExtFloatValue(const AReader: TdxfReader; var AHandled: Boolean);
begin
  case FExtCode of
    Float_40:   Properties.Scale := AReader.FloatValue;
    Float_41:   Properties.ArrowSize := Abs(AReader.FloatValue);
    Float_42:   Properties.ExtLineOffset := AReader.FloatValue;
    Float_44:   Properties.ExtLineExt := AReader.FloatValue;
    Float_141:  Properties.SizeCenterMark := AReader.FloatValue;
    Float_140:  Properties.TextHeight := Abs(AReader.FloatValue);
    Float_144:  Properties.DIMLFAC := Abs(AReader.FloatValue);
    Float_147:  Properties.TextOffset := AReader.FloatValue;
  else
    AHandled := False;
  end;
end;

procedure TdxfDimension.ExtHandleValue(const AReader: TdxfReader; var AHandled: Boolean);
begin
  case FExtCode of
    340: Properties.TextStyle := TsgDXFStyle(AReader.HStyles[AReader.HandleValue]);
    341: Properties.DIMLDRBLK := TsgDXFBlock(AReader.HBlockRecords[AReader.HandleValue]);
    342: Properties.DIMBLK    := TsgDXFBlock(AReader.HBlockRecords[AReader.HandleValue]);
    343: Properties.DIMBLK1   := TsgDXFBlock(AReader.HBlockRecords[AReader.HandleValue]);
    344: Properties.DIMBLK2   := TsgDXFBlock(AReader.HBlockRecords[AReader.HandleValue]);
  else
    AHandled := False;
  end;
end;

procedure TdxfDimension.ExtIntValue(const AReader: TdxfReader; var AHandled: Boolean);
begin
  case FExtCode of
    Integer_73:   Properties.DIMTIX := AReader.IntValue;
    Integer_74:   Properties.DIMTOH := AReader.IntValue = 1;
    Integer_75:   Properties.DIMSE1 := AReader.IntValue = 1;
    Integer_76:   Properties.DIMSE2 := AReader.IntValue = 1;
    Integer_77:   Properties.TextPosVert := TsgDimTextPosVert(AReader.IntValue);
    Integer_173:  Properties.DIMSAH := AReader.IntValue = 1;
    Integer_174:  Properties.DIMTIX := AReader.IntValue;
    Integer_176:  Properties.DIMCLRD := MakeColorCAD(acIndexColor, AReader.IntValue);
    Integer_177:  Properties.DIMCLRE := MakeColorCAD(acIndexColor, AReader.IntValue);
    Integer_178:  Properties.DIMCLRT := MakeColorCAD(acIndexColor, AReader.IntValue);
    Integer_271:  Properties.DIMDEC := AReader.IntValue;
    Word_281:     Properties.DIMSD1 := AReader.IntValue = 1;
    Word_282:     Properties.DIMSD2 := AReader.IntValue = 1;
            371:  Properties.DIMLWD := ExpandLWeight(AReader.IntValue);
            372:  Properties.DIMLWE := ExpandLWeight(AReader.IntValue);
  else
    FExtCode := AReader.IntValue;
    AHandled := False;
  end;
end;

function TdxfDimension.GetProperties: TsgDXFDimensionProperties;
var
  vConv: TsgDXFConverterAccess;
  vProps: TsgDXFDimensionPropertiesAccess;
begin
  if not Assigned(FProperties) then
  begin
    FProperties := TsgDXFDimensionProperties.Create;
    vConv := Conv;
    if Assigned(vConv) then
    begin
      vProps := TsgDXFDimensionPropertiesAccess(FProperties);
      vProps.FDimProps := vConv.HeadVarStruct.DimProps;
      if Assigned(vConv.Sections[csStyles]) then
        vProps.TextStyle := TsgDXFStyle(vConv.Sections[csStyles].FindEntByName(vConv.HeadVarStruct.DimTextStyle));
    end;
  end;
  Result := FProperties;
end;

procedure TdxfDimension.OverrideProperties;
var
  vDim: TsgDXFDimensionAccess;
  vDimProps, vProps: TsgDXFDimensionPropertiesAccess;
begin
  if Assigned(FProperties) then
  begin
    vDim := TsgDXFDimensionAccess(FEnt);
    vDimProps := TsgDXFDimensionPropertiesAccess(vDim.ActualDimStyle);
    vProps := TsgDXFDimensionPropertiesAccess(FProperties);
    if Assigned(vDimProps) and Assigned(vProps) then
      vDimProps.AssignEntity(vProps);
  end;
end;

{protected}


destructor TdxfDimension.Destroy;
begin
  FProperties.Free;
  inherited Destroy;
end;

procedure TdxfDimension.Commit(const AReader: TdxfReader);
var
  vDimStyle: TsgDXFDimensionStyle;
  vDimension: TsgDXFDimension;
  vStyleName: string;
begin
  FFloats[10] := FFloats[14];
  inherited Commit(AReader);
  vDimension := TsgDXFDimension(FEnt);
  vStyleName := Trim(FTexts[3]);
  if vStyleName = '' then
    vStyleName := AReader.Conv.HeadVarStruct.DimStyle;
  vDimStyle := TsgDXFDimensionStyle(AReader.DimStyles[vStyleName]);
  vDimension.Style := vDimStyle;
  vDimension.Scale        := cnstFPointSingle;
  vDimension.DefPoint     := FPoints[0];
  vDimension.MiddlePoint  := FPoints[1];
  vDimension.Point        := FPoints[2];
  vDimension.LinDefPoint1 := FPoints[3];
  vDimension.LinDefPoint2 := FPoints[4];
  vDimension.RadDefPoint  := FPoints[5];
  vDimension.ArcDefPoint  := FPoints[6];
  vDimension.Flags        := Flags;
  vDimension.TextOverride := FTexts[1];
  vDimension.TextRotation := FFloats[13];
  OverrideProperties;
end;

procedure TdxfDimension.ReadProperty(const AReader: TdxfReader);
begin
  FExtHandled := True;
  case AReader.Code of
    Integer_1070: ExtIntValue(AReader, FExtHandled);
    Float_1040:   ExtFloatValue(AReader, FExtHandled);
    String_1005:  ExtHandleValue(AReader, FExtHandled);
  else
    FExtHandled := False;
  end;
  if FExtHandled then
    FExtCode := 0
  else
    inherited ReadProperty(AReader);
end;

{ TdxfDimStyle }

procedure TdxfDimStyle.Commit(const AReader: TdxfReader);
var
  I: TsgDimNameVal;
  vDimStyle: TsgDXFDimStyleAccess;
  vBlock: TsgDXFBlock;
begin
  inherited Commit(AReader);
  vDimStyle := TsgDXFDimStyleAccess(FEnt);
  vBlock := nil;
  for I := vnDIMBLK to vnDIMLRBLK do
    if vDimStyle.GetBlocks(I) = nil then
    begin
      if vBlock = nil then
        vBlock := TsgDXFBlock(AReader.DimStyles[sgDimensionArrowTypeNames[datClosedfilled]]);
      vDimStyle.SetBlocks(I, vBlock);
    end;
end;

procedure TdxfDimStyle.ReadProperty(const AReader: TdxfReader);
var
  vDimStyle: TsgDXFDimensionStyle;
begin
  vDimStyle := TsgDXFDimensionStyle(FEnt);
  inherited ReadProperty(AReader);
  case AReader.Code of
    2:
      begin
        if AnsiCompareText(AReader.Conv.HeadVarStruct.DimStyle, Name) = 0 then
        begin
          TsgDXFDimStyleAccess(vDimStyle).FDimProps := AReader.Conv.HeadVarStruct.DimProps;
          vDimStyle.TextStyle := TsgDXFStyle(AReader.Styles[AReader.Conv.HeadVarStruct.DimTextStyle]);
        end;
      end;
    5..7:         Exit;
    105:          FHandle                  := AReader.HandleValue;
    Float_40:     vDimStyle.Scale          := FFloats[0];
    Float_41:     vDimStyle.ArrowSize      := FFloats[1];
    Float_42:     vDimStyle.ExtLineOffset  := FFloats[2];
    Float_44:     vDimStyle.ExtLineExt     := FFloats[4];
    Integer_73:   vDimStyle.DIMTIH         := AReader.IntValue = 1;
    Integer_74:   vDimStyle.DIMTOH         := AReader.IntValue = 1;
    Integer_75:   vDimStyle.DIMSE1         := AReader.IntValue = 1;
    Integer_76:   vDimStyle.DIMSE2         := AReader.IntValue = 1;
    Integer_77:   vDimStyle.TextPosVert    := TsgDimTextPosVert(FInts[17]);
    Float_140:    vDimStyle.TextHeight     := AReader.FloatValue;
    Float_141:    vDimStyle.SizeCenterMark := AReader.FloatValue;
    Float_144:    vDimStyle.DIMLFAC        := AReader.FloatValue;
    Float_147:    vDimStyle.TextOffset     := AReader.FloatValue;
    Integer_173:  vDimStyle.DIMSAH         := AReader.IntValue = 1;
    Integer_174:  vDimStyle.DIMTIX         := AReader.IntValue;
    Integer_176:  vDimStyle.DIMCLRD        := MakeColorCAD(acIndexColor, AReader.IntValue);
    Integer_177:  vDimStyle.DIMCLRE        := MakeColorCAD(acIndexColor, AReader.IntValue);
    Integer_178:  vDimStyle.DIMCLRT        := MakeColorCAD(acIndexColor, AReader.IntValue);
    Integer_271:  vDimStyle.DIMDEC         := AReader.IntValue;
    Word_281:     vDimStyle.DIMSD1         := AReader.IntValue = 1;
    Word_282:     vDimStyle.DIMSD2         := AReader.IntValue = 1;
    String_340:   vDimStyle.TextStyle      := TsgDXFStyle(AReader.HStyles[AReader.HandleValue]);
    341:          vDimStyle.DIMLDRBLK      := TsgDXFBlock(AReader.HBlockRecords[AReader.HandleValue]);
    342:          vDimStyle.DIMBLK         := TsgDXFBlock(AReader.HBlockRecords[AReader.HandleValue]);
    343:          vDimStyle.DIMBLK1        := TsgDXFBlock(AReader.HBlockRecords[AReader.HandleValue]);
    344:          vDimStyle.DIMBLK2        := TsgDXFBlock(AReader.HBlockRecords[AReader.HandleValue]);
    371:          vDimStyle.DIMLWD         := ExpandLWeight(AReader.IntValue);
    372:          vDimStyle.DIMLWE         := ExpandLWeight(AReader.IntValue);
  end;
end;

{ TdxfEllipse }

constructor TdxfEllipse.Create;
begin
  inherited Create;
  FFloats[2] := 2*Pi;
end;

procedure TdxfEllipse.Commit(const AReader: TdxfReader);
var
  vEllipse: TsgDXFEllipse;
begin
  FFloats[10] := Degree(FFloats[1]);
  FFloats[11] := Degree(FFloats[2]);
  inherited Commit(AReader);
  vEllipse := TsgDXFEllipse(FEnt);
  vEllipse.EndPoint := FPoints[1];
  vEllipse.Ratio := FFloats[0];
end;

{ TdxfFace }

procedure TdxfFace.Commit(const AReader: TdxfReader);
begin
  inherited Commit(AReader);
  TsgDXF3DFace(FEnt).Flags := Flags;
end;

{ TdxfField }

procedure TdxfField.Commit(const AReader: TdxfReader);
var
  vField: TsgDXFField;
begin
  inherited Commit(AReader);
  vField := TsgDXFField(FEnt);
  vField.Name := 'FIELD';
//  vField.Dictionary := FOwner.FEnt;
  vField.ObjectIDs.Assign(FPointerIDs);
end;

destructor TdxfField.Destroy;
begin
  if FData <> nil then
    ReallocMem(FData, 0);
  inherited Destroy;
end;

procedure TdxfField.ReadProperty(const AReader: TdxfReader);
const
  cnstAcDbField = 'AcDbField';
var
  vField: TsgDXFField;
begin
  inherited ReadProperty(AReader);
  vField := TsgDXFField(FEnt);
  case AReader.Code of
    1:
      if FReadDataSet then
        vField.DataSet.AddString(AReader.Code, FTexts[1])
      else
        if FReadCache then
          vField.Cache.AddString(AReader.Code, FTexts[1])
        else
          vField.EvaluatorID := FTexts[1];
    2: vField.FieldCode := Name;
    3, 4: vField.OverflowFieldCode := FTexts[AReader.Code];
    100: FReadFieldObject := AReader.UValue = cnstAcDbField;
    330:
      if not FReactorsRead then
      begin
        if not FReadFieldObject then
        begin
          FSoftOwnerIDs.Free;
          FSoftOwnerIDs := TsgInt64List.Create;
        end
        else
          if FReadCache then
            vField.Cache.AddInt64(AReader.Code, FSoftOwnerIDs.Last)
          else
            if FReadDataSet then
              vField.DataSet.AddInt64(AReader.Code, FSoftOwnerIDs.Last);
      end
      else
        FDictionary := FRctrsSoftIDs.Last;
    93: FReadDataSet := AReader.IntValue > 0;
    90, 91:
      if FReadCache then
        vField.Cache.AddInt(AReader.Code, AReader.IntValue)
      else
        if FReadDataSet then
          vField.DataSet.AddInt(AReader.Code, AReader.IntValue);
    140:
      if FReadCache then
        vField.Cache.AddDouble(AReader.Code, AReader.FloatValue)
      else
        if FReadDataSet then
          vField.DataSet.AddDouble(AReader.Code, AReader.FloatValue);
    92:
      if FReadCache or FReadDataSet then
      begin
        FBuffSize := AReader.IntValue;
        ReallocMem(FData, FBuffSize);
        FBytesRead := 0;
      end;
    310:
      begin
        AddBinData(AReader.Value, Pointer(FData), FBytesRead);
        if FBytesRead = FBuffSize then
        begin
          if FReadCache then
            vField.Cache.AddBinary(AReader.Code, FBuffSize, FData)
          else
            if FReadDataSet then
              vField.DataSet.AddBinary(AReader.Code, FBuffSize, FData);
          ReallocMem(FData, 0);
          FBuffSize := 0;
          FBytesRead := 0;
        end;
      end;
    // Key string for the field data
    6: vField.DataSet.AddString(AReader.Code, AReader.UValue);
    7:
      begin
        FReadCache := True;
        FReadDataSet := False;
        // Key string for the evaluated cache, always ACFD_FIELD_VALUE
        vField.Cache.AddString(AReader.Code, AReader.UValue);
      end;
    9, 301:
      if FReadCache then
        vField.Cache.AddString(AReader.Code, AReader.UValue);
    98:
      if FReadCache then
        vField.Cache.AddInt(AReader.Code, AReader.IntValue);
  end;
end;

{ TdxfFieldList }

procedure TdxfFieldList.Commit(const AReader: TdxfReader);
var
  I: Integer;
  vItem: TsgDXFOwneredItem;
begin
  inherited Commit(AReader);
  FEnt.Name := cnstObjectsFIELDLIST;
  for I := 0 to FSoftOwnerIDs.Count - 1 do
  begin
    vItem := TsgDXFOwneredItem.Create;
    vItem.Handle := FSoftOwnerIDs[I];
    vItem.Name := 'FIELD';
//    vItem.Dictionary := FEnt;
    FEnt.AddEntity(vItem);
  end;
end;

procedure TdxfFieldList.ReadProperty(const AReader: TdxfReader);
const
  cnstAcDbIdSet = 'AcDbIdSet';
begin
  inherited ReadProperty(AReader);
  case AReader.Code of
    100:
      begin
        FAcDbIdSet := AReader.UValue = cnstAcDbIdSet;
        if FAcDbIdSet then
        begin
          FOwnerDictionary := FSoftOwnerIDs.Last;
          FSoftOwnerIDs.Clear;
        end;
      end;
  end;
end;

{ TdxfHelix }

procedure TdxfHelix.Commit(const AReader: TdxfReader);
var
  vHelix: TsgCADHelix;
begin
  vHelix := TsgCADHelix(FEnt);
  inherited Commit(AReader);
  vHelix.Point := FPoints[0];
  vHelix.Start := FPoints[1];
  vHelix.Turns := FFloats[1];
  vHelix.TurnHeight := FFloats[2];
end;

procedure TdxfHelix.ReadProperty(const AReader: TdxfReader);
var
  vHelix: TsgCADHelix;
begin
  vHelix := TsgCADHelix(FEnt);
  if AReader.Code = 100 then
  begin
    FLock := AReader.Value = 'AcDbHelix';
    if FLock then
    begin
      if FNewCtl then
        AddControl;
      if FNewFit then
        AddFit;
    end;
  end;
  if not FLock then
    inherited ReadProperty(AReader)
  else
  begin
    FNewCtl := False;
    FNewFit := False;
    case AReader.Code of
      Float_40:         vHelix.Radius := AReader.FloatValue;
      Integer_290:      vHelix.Clockwise := AReader.IntValue = 0;
      else              inherited ReadProperty(AReader);
    end;
  end;
end;

{ TdxfImageEnt }

procedure TdxfImageEnt.AddData(const S: AnsiString);
begin
  AddBinData(S, Pointer(FData), FSize);
end;

procedure TdxfImageEnt.Commit(const AReader: TdxfReader);
//var
//  vProxy: TsgDXFProxy;
//  vProxyReader: IProxyReader;
//  vEnts: TList;
//  vProps: TList;
begin
  inherited Commit(AReader);
  TsgDXFImageEnt(FEnt).ImageDef := TsgDXFImageDef(AReader.HImageDefs[FImageDef]);
// for future version
//  if (FData <> nil) then
//  begin
//    vProxy := TsgDXFProxy.Create;
//    try
//      vEnts := TList.Create;
//      vProps := TList.Create;
//      try
//        vProxyReader := TCustomAlignedDataReader.Create(FData, TsgDWGVersion(AReader.Version));
//        ReadProxyData(vEnts, vProps, AReader.Conv, vProxyReader);
//      finally
//        vEnts.Free;
//        FreeRecordList(vProps);
//      end;
//    finally
//      vProxy.Free;
//    end;
//  end;
end;

destructor TdxfImageEnt.Destroy;
begin
  if FData <> nil then
    FreeMem(FData);
  inherited Destroy;
end;

procedure TdxfImageEnt.ReadProperty(const AReader: TdxfReader);
begin
  case AReader.Code of
    String_310: AddData(AReader.Value);
    String_340: FImageDef := AReader.HandleValue;
    else        inherited ReadProperty(AReader);
  end;
end;

{ TdxfLayer }

procedure TdxfLayer.Commit(const AReader: TdxfReader);
var
  Dictionary: TsgDXFEntity;
begin
  inherited Commit(AReader);
  FEnt.Visible := FInts[2] >= 0;
  if FRctrsHardIDs.Count > 0 then
  begin
    Dictionary := TsgDXFDictionary.Create;
    Dictionary.Handle := FRctrsHardIDs.Last;
    TsgDXFLayer(FEnt).Dictionary := Dictionary;
  end;
end;

constructor TdxfLayer.Create;
begin
  inherited Create;
  FLineWeight := fLineWeightDefault;
end;

procedure TdxfLayer.ReadProperty(const AReader: TdxfReader);
begin
  inherited ReadProperty(AReader);
  case AReader.Code of
    Integer_290: TsgDXFLayer(FEnt).IsPlotting := AReader.IntValue <> 0;
  end;
end;

{ TdxfLeader }

constructor TdxfLeader.Create;
begin
  inherited Create;
  FHookline := 1;
  FHooklineDirectional := 1;
  FHooklineVector := cnstXOrtAxis;
  FInts[11] := 1;
  FTAD := -1;
  FGAP := 0;
  FAnnotationType := 3;
  FBlockRefHandle := cnstBadBlockRefHandle;
end;

procedure TdxfLeader.Commit(const AReader: TdxfReader);
var
  vLeader: TsgDXFLeaderAccess;
begin
  inherited Commit(AReader);
  vLeader := TsgDXFLeaderAccess(FEnt);
  vLeader.IsSpline  := FInts[12] = 1;
  vLeader.DimStyle := TsgDXFDimensionStyle(AReader.DimStyles[Trim(FTexts[3])]);
  case FBlockRefHandle of
    cnstBadBlockRefHandle:      begin end;
    cnstBlockRefHandleDefault:  vLeader.DIMLDRBLK := TsgDXFBlock(AReader.BlockRecords[sgDimensionArrowTypeNames[datClosedfilled]]);
  else
    vLeader.DIMLDRBLK := TsgDXFBlock(AReader.HBlockRecords[FBlockRefHandle]);
  end;
  if FArrowSize <> 0 then
    vLeader.ArrowSize := FArrowSize;
  if FArrowScale <> 0 then
    vLeader.ArrowScale := FArrowScale;
  if (FTAD < 0) and (vLeader.DimStyle <> nil) then
    FTAD := Byte(vLeader.DimStyle.TextPosVert);
  if FAnnotationType <> 3 then
  begin
    TsgDXFLeaderAccess(vLeader).DoAdditionalLine(
      1(*FHookline*), FHooklineDirectional, FHooklineVector,
      FTAD, FGAP, FTextAnnotationWidth);
  end;
end;

procedure TdxfLeader.ReadProperty(const AReader: TdxfReader);
begin
  case AReader.Code of
    //Float_40, Float_41: Exit;
    Float_40: FTextAnnotationHeight := AReader.FloatValue;
    Float_41: FTextAnnotationWidth := AReader.FloatValue;
    Integer_73: FAnnotationType := AReader.IntValue;
    Integer_75: FHookline := AReader.IntValue;
    Integer_74: FHooklineDirectional := AReader.IntValue;

    Float_211:  FHooklineVector.X := AReader.FloatValue;
    Float_221:  FHooklineVector.Y := AReader.FloatValue;
    Float_231:  FHooklineVector.Z := AReader.FloatValue;

    String_340: FHRefAsAnnotation := AReader.HandleValue;

    Integer_1070:
    begin
      case FCodeValue of
        Integer_77:
          begin
            FTAD := AReader.IntValue;
            FCodeValue := 0;
          end;
      else
        FCodeValue := AReader.IntValue;
      end;
    end;

    Float_1040:
      case FCodeValue of
        Float_40: FArrowScale := Abs(AReader.FloatValue);
        Float_41: FArrowSize  := Abs(AReader.FloatValue);
        Float_147: FGAP := AReader.FloatValue;
      end;
    String_1005:
      case FCodeValue of
        String_341:   FBlockRefHandle := AReader.HandleValue;
      end;
    else  inherited ReadProperty(AReader);
  end;
end;

procedure TdxfLeader.SetDegreeSplineCurve;
begin
  TsgDXFLeader(FEnt).Arrowhead := FInts[11] <> 0;
end;

{ TdxfLType }

{private}

function TdxfLType.GetElement: PsgLTypeElement;
begin
  if FElement = nil then
  begin
    New(FElement);
    FillChar(FElement^, SizeOf(FElement^), 0);
    FElement^.Text := '';
    TsgDXFLineType(FEnt).Lines.Add(FElement);
  end;
  Result := FElement;
end;

{protected}

procedure TdxfLType.ReadProperty(const AReader: TdxfReader);
begin
  inherited ReadProperty(AReader);
  case AReader.Code of
    Float_44:          Element^.XOffset := FFloats[4];
    Float_45:          Element^.YOffset := FFloats[5];
    Float_46:          Element^.Scale := FFloats[6];
    FloatRepeated_49:
    begin
      FElement := nil;
      Element^.Dash := FFloats[9];
    end;
    Angle_50:          Element^.Rotation := FFloats[10];
    Integer_74:        Element^.ComplexType := FInts[14];
    Integer_75:        Element^.ShapeNumber := FInts[15];
    String_340:        Element^.Style := AReader.HStyles[AReader.HandleValue];
    VarName_9:         Element^.Text := FTexts[9];
  end;
end;

{ TdxfLWPline }

{private}

procedure TdxfLWPline.AddVertex;
var
  vVertex: TsgDXFVertex;
begin
  vVertex := TsgDXFVertex.Create;
  vVertex.Point       := FPoints[0];
  vVertex.StartWidth  := FFloats[0];
  vVertex.EndWidth    := FFloats[1];
  vVertex.Bulge       := FFloats[2];
  TsgDXFLWPolyLine(FEnt).AddEntity(vVertex);
  FFloats[0] := 0;
  FFloats[1] := 0;
  FFloats[2] := 0;
end;

{protected}

procedure TdxfLWPline.Commit(const AReader: TdxfReader);
begin
  if FNewVertex then AddVertex;
  inherited Commit(AReader);
  FComplex := False;
end;

procedure TdxfLWPline.ReadProperty(const AReader: TdxfReader);
begin
  if AReader.Code = 10 then
  begin
    if FNewVertex then AddVertex;
    FNewVertex := True;
  end;
  inherited ReadProperty(AReader);
end;

procedure TdxfLWPline.SetElevation;
begin
  TsgDXFLWPolyline(FEnt).Elevation := FElevation;
end;

{ TdxfStyle }

constructor TdxfStyle.Create;
begin
  inherited Create;
  Name := sStandardName;
  FTexts[3] := 'txt';
  FFloats[1] := 1.0;
  FFloats[2] := 2.5;
end;

function TdxfStyle.GetPrimaryFont: string;
begin
  Result := Trim(FTexts[3]);
end;

procedure TdxfStyle.Commit(const AReader: TdxfReader);
var
  vStyle: TsgDXFStyle;
begin
  inherited Commit(AReader);
  vStyle := TsgDXFStyle(FEnt);
  vStyle.FixedHeight         := FFloats[0];
  vStyle.WidthFactor         := FFloats[1];
  vStyle.LastHeightUsed      := FFloats[2];
  vStyle.ObliqueAngle        := FFloats[10];
  vStyle.TextGenFlags        := FInts[11];
  vStyle.PrimaryFont         := GetPrimaryFont;
  vStyle.BigFont             := Trim(FTexts[4]);
  if vStyle.PrimaryFont = '' then
    vStyle.PrimaryFont := sDefaultSHXFont;
end;

procedure TdxfStyle.ReadProperty(const AReader: TdxfReader);
var
  vCardinal: Cardinal;
begin
  case AReader.Code of
    String_1000:        TsgDXFStyle(FEnt).FontName := Trim(AReader.UValue);
    Integer_1071:
      begin
        vCardinal := AReader.IntValue;
        if vCardinal and $1000000 <> 0 then
          TsgDXFStyle(FEnt).FontStyle := [fmItalic];
        if vCardinal and $2000000 <> 0 then
          TsgDXFStyle(FEnt).FontStyle := TsgDXFStyle(FEnt).FontStyle + [fmBold];
      end
    else                inherited ReadProperty(AReader);
  end;
end;

{ TdxfRasterVariables }

procedure TdxfRasterVariables.Commit(const AReader: TdxfReader);
begin
  inherited Commit(AReader);
  FComplex := False;
end;

procedure TdxfRasterVariables.ReadProperty(const AReader: TdxfReader);
begin
  inherited ReadProperty(AReader);
  case AReader.Code of
    Integer_70: TsgCADRasterVariables(FEnt).DisplayImageFrame := FInts[10] = 1;
    Integer_71: TsgCADRasterVariables(FEnt).ImageDisplayQuality := FInts[11] = 1;
    Integer_72: TsgCADRasterVariables(FEnt).UnitsForInsertingImages := FInts[12];
  end;
end;

procedure TdxfRasterVariables.SetLayerByName(AReader: TdxfReader;
  const AName: string);
begin
  // do nothing
end;

{$IFDEF DATA_LINK}

{ TdxfDataLink }

procedure TdxfDataLink.Commit(const AReader: TdxfReader);
begin
  inherited Commit(AReader);
  FComplex := False;
end;

procedure TdxfDataLink.ReadProperty(const AReader: TdxfReader);
begin
  inherited ReadProperty(AReader);
  if FCustomData then
  begin
    case AReader.Code of
      String_309:
       begin
         if SameText(AReader.StrValue, 'DATAMAP_END') then
           FCustomData := False;
       end;
    end;
  end
  else
  begin
    case AReader.Code of
      String_302: TsgCADDataLink(FEnt).FileName := AReader.StrValue;
      Text_1:
       begin
         if SameText(AReader.StrValue,'DATAMAP_BEGIN') then
           FCustomData := True;
       end;
    end;
  end;
end;
{$ENDIF}

{ TdxfPlotSettings }

procedure TdxfPlotSettings.ReadProperty(const AReader: TdxfReader);
var
  vPlotSettings : TsgDXFPlotSettings;
  vPlotSettingsData : PsgPlotSettingsData;
begin
  vPlotSettings := TsgDXFPlotSettings(FEnt);
  vPlotSettingsData := TsgDXFPlotSettingsAccess(vPlotSettings).PlotData;
  inherited ReadProperty(AReader);
  case AReader.Code of
    Text_1: vPlotSettingsData^.PageSetupName := AReader.StrValue;
    Name_2: vPlotSettingsData^.PrintOrConfigName := AReader.StrValue;
    Text_4: vPlotSettingsData^.PaperSize := AReader.StrValue;
    LineTypeName_6: vPlotSettingsData^.PlotViewName := AReader.StrValue;
    TextFont_7: vPlotSettingsData^.CurrentStyleSheet := AReader.StrValue;
    Float_40: vPlotSettingsData^.UnprintableMargin.Left := FFloats[0];
    Float_41: vPlotSettingsData^.UnprintableMargin.Bottom := FFloats[1];
    Float_42: vPlotSettingsData^.UnprintableMargin.Right := FFloats[2];
    Float_43: vPlotSettingsData^.UnprintableMargin.Top := FFloats[3];
    Float_44: vPlotSettingsData^.PlotPaperSize.X := FFloats[4];
    Float_45: vPlotSettingsData^.PlotPaperSize.Y := FFloats[5];
    Float_46: vPlotSettingsData^.PlotOrigin.X := FFloats[6];
    Float_47: vPlotSettingsData^.PlotOrigin.Y := FFloats[7];
    Float_48: vPlotSettingsData^.PlotWindowAreaMin.X := FFloats[8];
    FloatRepeated_49: vPlotSettingsData^.PlotWindowAreaMin.Y := FFloats[9];
    Integer_70: vPlotSettingsData^.PlotLayoutFlags :=
      ConvertIntegerToPlotLayoutFlags(Flags);
    Integer_72: vPlotSettingsData^.PlotPaperUnits := TsgPlotPaperUnits(FInts[12]);
    Integer_73: vPlotSettingsData^.PlotRotation := GetPlotRotation(FInts[13]);
    Integer_74: vPlotSettingsData^.PlotType := TsgPlotType(FInts[14]);
    Integer_75: vPlotSettingsData^.StandardScaleType := FInts[15];
    Integer_76: vPlotSettingsData^.ShadePlotMode := FInts[16];
    Integer_77: vPlotSettingsData^.ShadePlotResolutionLevel := FInts[17];
    Integer_78: vPlotSettingsData^.ShadePlotCustomDPI := FInts[18];
    Float_140: vPlotSettingsData^.PlotWindowAreaMax.X := AReader.FloatValue;
    Float_141: vPlotSettingsData^.PlotWindowAreaMax.Y := AReader.FloatValue;
    Float_142: vPlotSettingsData^.NumeratorOfCustomPrintScale := AReader.FloatValue;
    Float_143: vPlotSettingsData^.DenominatorOfCustomPrintScale := AReader.FloatValue;
    Float_147: vPlotSettingsData^.FloatingPointScaleFactor := AReader.FloatValue;
    Float_148: vPlotSettingsData^.PaperImageOrigin.X := AReader.FloatValue;
    Float_149: vPlotSettingsData^.PaperImageOrigin.Y := AReader.FloatValue;
  end;
end;

procedure TdxfPlotSettings.ReadProps(AReader: TdxfReader);
var
  vDoBreak: Boolean;
begin
  vDoBreak := False;
  repeat
    AReader.Next;
    case AReader.Code of
      Info_0:           vDoBreak := True;
      String_100:
        begin
          if FOwner.ClassType = TdxfLayout then
            vDoBreak := AReader.UValue <> sAcDbPlotSettings;
        end;
    else
      ReadProperty(AReader);
    end;
  until vDoBreak;
end;

procedure TdxfPlotSettings.SetLayerByName(AReader: TdxfReader;
  const AName: string);
begin
  // do nothing
end;

{ TdxfDictionaryVar }

procedure TdxfDictionaryVar.ReadProperty(const AReader: TdxfReader);
begin
  inherited ReadProperty(AReader);
  case AReader.Code of
    Text_1: TsgDXFDictionaryVar(FEnt).Value := AReader.UValue;
  end;
end;

{ TdxfBlockRecord }

procedure TdxfBlockRecord.Commit(const AReader: TdxfReader);
var
  vName: string;
  vBlkRec: TsgDXFBlockRecordAccess;
begin
  inherited Commit(AReader);
  vName := Name;
  if vName = '' then
    vName := '*U$' + IntToHex(FHandle, 0);
  if (Length(vName) = 2) and (vName[1] = '*') then
    vName := vName + IntToStr(AReader.Conv.Sections[csBlocks].Count);

  vBlkRec := TsgDXFBlockRecordAccess(FEnt);
  vBlkRec.Name := vName;
  vBlkRec.SetFlags(FFlags);
  AReader.InitPaper(vBlkRec.Block);
end;

procedure TdxfBlockRecord.ReadProperty(const AReader: TdxfReader);
begin
  inherited ReadProperty(AReader);
  case AReader.Code of
    340: FLayout := AReader.HandleValue;
     70: FFlags := AReader.IntValue;
  end;
end;

{ TdxfHeader }

procedure TdxfHeader.Commit(const AReader: TdxfReader);
begin
  inherited Commit(AReader);
  AReader.Conv.HeadVarStruct := FHeadVars;
end;

constructor TdxfHeader.Create;
begin
  inherited Create;
  FComplex := True;
end;

procedure TdxfHeader.DoHeadVars(const AReader: TdxfReader);
begin
  case FHeadVarIndex of
    0: AReader.Conv.MaxHandle := FHandle;
    1: FHeadVars.DimProps.Alt := FInts[10] <> 0;
    2: FHeadVars.DimProps.AltF := FFloats[0];
    3: FHeadVars.DimProps.APost := FTexts[1];
    4: FHeadVars.DimProps.Clrd := MakeColorCAD(acIndexColor,FInts[10]);
    5: FHeadVars.DimProps.Clre := MakeColorCAD(acIndexColor,FInts[10]);
    6: FHeadVars.DimProps.Clrt := MakeColorCAD(acIndexColor,FInts[10]);
    7: FHeadVars.DimProps.Exe := FFloats[0];
    8: FHeadVars.DimProps.Exo := FFloats[0];
    9: FHeadVars.DimProps.Gap := FFloats[0];
    10: FHeadVars.DimProps.LFac := FFloats[0];
    11: FHeadVars.DimProps.POST := FTexts[1];
    20: FHeadVars.DimProps.Asz := FFloats[0];
    21: FHeadVars.DimProps.Scale := FFloats[0];
    22: FHeadVars.DimStyle := Name;
    30: FHeadVars.DimProps.Dec := FInts[10];
    31: FHeadVars.DimProps.Tad := FInts[10];
    32: FHeadVars.DimProps.Tih := FInts[10] = 1;
    33: FHeadVars.DimProps.Tix := FInts[10];
    34: FHeadVars.DimProps.Toh := FInts[10] = 1;
    35: FHeadVars.DimProps.Arrows.Blk := GetArrowTypeByName(FTexts[1], datClosedfilled);
    36: FHeadVars.DimProps.Arrows.Blk1 := GetArrowTypeByName(FTexts[1], datClosedfilled);
    37: FHeadVars.DimProps.Arrows.Blk2 := GetArrowTypeByName(FTexts[1], datClosedfilled);
    38: FHeadVars.DimProps.Arrows.LrBlk := GetArrowTypeByName(FTexts[1], datClosedfilled);
    39: FHeadVars.DimProps.Txt := FFloats[0];
    43: FHeadVars.DimTextStyle := FTexts[7];
    49: FHeadVars.DimProps.SE1 := FInts[10] = 1;
    50: FHeadVars.DimProps.SE2 := FInts[10] = 1;
    51: FHeadVars.DimProps.SD1 := FInts[10] = 1;
    52: FHeadVars.DimProps.SD2 := FInts[10] = 1;
    53: FHeadVars.DimProps.LwD := ExpandLWeight(FInts[10]);
    54: FHeadVars.DimProps.LwE := ExpandLWeight(FInts[10]);
    55: FHeadVars.DimProps.Sah := FInts[10] = 1;

    12: FHeadVars.Measurement := FInts[10] <> 0;
    13: FHeadVars.UCSORG := FPoints[0];
    14: FHeadVars.UCSXDir := FPoints[0];
    15: FHeadVars.UCSYDir := FPoints[0];
    16: if FTexts[3] <> '' then
          FHeadVars.CodePage := GetDWGCodePageByName(FTexts[3]);
    17: FHeadVars.PointDisplayMode := FInts[10];
    18: FHeadVars.TileMode := FInts[10];
    19: FHeadVars.LTScale := GetOnefromZero(FFloats[0]);
    23: FHeadVars.PointDisplaySize := FFloats[0];
    24: AReader.Conv.GetDWGVersion(AnsiString(FTexts[1]), TsgDWGVersion(FHeadVars.Version));
    25: FHeadVars.CEColor := MakeColorCAD(acIndexColor, FInts[2]);
    26: FHeadVars.CLayer := FTexts[8];
    27: FHeadVars.CELType := FTexts[6];
    28: FHeadVars.CELTScale := FFloats[0];
    29: FHeadVars.CELWeight := ExpandLWeight(FLineWeight);
    40: FHeadVars.TextSize := FFloats[0];
    41: FHeadVars.FilletRadius := FFloats[0];
    42: FHeadVars.InsUnits := FInts[10];
    44: FHeadVars.TextStyle := FTexts[7];
    45: FHeadVars.ExtMim := FPoints[0];
    46: FHeadVars.ExtMax := FPoints[0];
    47: FHeadVars.InsBase := FPoints[0];
    48: FHeadVars.AttMode := GetAttributeMode(FInts[10]);
  end;
end;

function TdxfHeader.EOFEnt(AObj: TdxfObject): Boolean;
begin
  Result := AObj.ClassType = TdxfEndSeq;
end;

procedure TdxfHeader.ReadProperty(const AReader: TdxfReader);
begin
  inherited ReadProperty(AReader);
  case AReader.Code of
    9: FHeadVarIndex := IndexHeadVar(FTexts[9]);
  else
    DoHeadVars(AReader);
  end;
end;

{ TdxfMain }

function TdxfMain.CreateSubEntity(const AReader: TdxfReader;
  AName: string): TdxfObject;
begin
  Result := inherited CreateSubEntity(AReader, AName);
  if Assigned(Result.FEnt) then
    Result.FEnt.Name := AName;
  Initialize(AReader, Result);
end;

destructor TdxfMain.Destroy;
begin
  FSectionObjects.Free;
  inherited Destroy;
end;

procedure TdxfMain.DestroyObj;
begin
  if FSectionObjects <> FObj then
    inherited DestroyObj;
end;

function TdxfMain.GetConv: TsgDXFConverterAccess;
begin
  Result := FConv;
end;

procedure TdxfMain.Initialize(AReader: TdxfReader; AObj: TdxfObject);
var
  vBlock: TsgDXFBlock;

  procedure ForceBlockRecords(const AConv: TsgDXFConverterAccess);
  begin
    if AConv.Sections[csBlockRecords] = nil then
    begin
      AConv.Sections[csBlockRecords] := TsgDXFBlockRecords.Create;
      TsgDXFEntityAccess(AConv.Sections[csBlockRecords]).SetConverter(AConv);
    end;
  end;

begin
  if AObj.ClassType = TdxfHeader then
  begin
    TdxfHeader(AObj).HeadVars := AReader.Conv.HeadVarStruct;
  end
  else
  if AObj.ClassType = TdxfEntities then
  begin
    TdxfEntities(AObj).ReleaseEntity.Free;
    TdxfEntities(AObj).FPapers := AReader.FPapers;
    ForceBlockRecords(AReader.Conv);
    if AReader.FPapers.Count <= 0 then
    begin
      vBlock := TsgDXFBlock.Create;
      vBlock.Name := sModelSpace;
      AReader.Conv.Sections[csBlocks].AddEntity(vBlock);
      AReader.InitPaper(vBlock);
    end;
    if AReader.FPapers.Count <= 1 then
    begin
      vBlock := TsgDXFBlock.Create;
      vBlock.Name := sPaperSpace;
      AReader.Conv.Sections[csBlocks].AddEntity(vBlock);
      AReader.InitPaper(vBlock);
    end;
  end
  else
  if AObj.ClassType = TdxfBlocks then
  begin
    AObj.ReleaseEntity.Free;
    AObj.FEnt := AReader.Conv.Sections[csBlocks];
    ForceBlockRecords(AReader.Conv);
  end
  else
  if AObj.ClassType = TdxfTables then
  begin
    AObj.ReleaseEntity.Free;
    AObj.FEnt := AReader.Conv.Sections[csTables];
  end
  else
  if AObj.ClassType = TdxfObjects then
  begin
    AObj.ReleaseEntity.Free;
    AObj.FEnt := AReader.Conv.Sections[csObjects];
    FSectionObjects := AObj;
  end;
end;

procedure TdxfMain.ReadEntities(AReader: TdxfReader);
begin
  while not AReader.EOF do
  begin
    if Trim(AReader.UValue) = cnstSection then
    begin
      AReader.Next;
      if (AReader.Code = Name_2) and not AReader.EOF then
        ReadEntity(AReader, AReader.UValue);
    end
    else
      if AReader.UValue = cnstTable then
      begin
        FObj := CreateSubEntity(AReader, cnstSectionTABLES);
        try
          FObj.ReadEntities(AReader);
          if Assigned(FObj.FEnt) then
            if not AddEntity(FObj) then
              FObj.ReleaseEntity.Free;
        finally
          DestroyObj;
        end;
      end
      else
        inherited ReadEntities(AReader);
  end;
end;

{ TdxfCustomSection }

constructor TdxfCustomSection.Create;
begin
  inherited Create;
  FComplex := True;
end;

function TdxfCustomSection.EOFEnt(AObj: TdxfObject): Boolean;
begin
  Result := AObj.ClassType = TdxfEndSeq;
end;

{ TdxfTables }

function TdxfTables.CreateSubEntity(const AReader: TdxfReader; AName: string): TdxfObject;
begin
  Result := inherited CreateSubEntity(AReader, AName);
  Result.Name := AReader.UValue;
end;

procedure TdxfTables.ReadEntities(AReader: TdxfReader);
var
  vDoBreak: Boolean;
begin
  vDoBreak := False;
  while not AReader.EOF and not vDoBreak do
  begin
    if AReader.UValue = cnstTable then
    begin
      AReader.Next;
      if (AReader.Code = Name_2) and not AReader.EOF then
        vDoBreak := ReadEntity(AReader, cnstTable);
    end
    else
      if AReader.UValue = cnstEndSec then
        vDoBreak := ReadEntity(AReader, AReader.UValue)
      else
      begin
        inherited ReadEntities(AReader);
        vDoBreak := True;
      end;
  end;
end;

{ TdxfEntities }

function TdxfEntities.AddEntity(const E: TdxfObject): Boolean;
begin
  Result := TsgDXFBlock(FPapers[E.FPaperSpace]).AddEntity(E.FEnt) >= 0;
end;

{ TdxfObjects }

function TdxfObjects.AddEntity(const E: TdxfObject): Boolean;
begin
  if E.FAdded then
    Result := True
  else
    Result := E.OwnerAdd >= 0;
end;

{ TdxfXRecord }

procedure TdxfXRecord.Commit(const AReader: TdxfReader);
var
  E: TsgDXFEntityAccess;//TsgDXFOwneredItem
begin
  inherited Commit(AReader);
  if (FSoftOwnerIDs.Count > 0) and (FSoftOwnerIDs.First <> cnstBadHandle) then
    if Assigned(AReader.Conv.Sections[csObjects]) then
    begin
      FSoftOwner := AReader.Conv.Sections[csObjects].FindEntByHandle(FSoftOwnerIDs.First);
      if Assigned(FSoftOwner) then
      begin
        E := TsgDXFEntityAccess(FSoftOwner.FindEntByHandle(FHandle));
        if Assigned(E) then
        begin
          FEnt.Name := E.Name;
          FSoftOwner.RemoveEntity(E);
          if (E.GetNamedItem <> nil) and (TsgOwneredItem(E.GetNamedItem).RefCount = 0) then
            E.Free;
        end;
      end;
    end;
end;

destructor TdxfXRecord.Destroy;
begin
  if FBinData <> nil then
    ReallocMem(FBinData, 0);
  inherited Destroy;
end;

function TdxfXRecord.OwnerAdd: Integer;
begin
  if FSoftOwner <> nil then
    Result := FSoftOwner.AddEntity(FEnt)
  else
    Result := inherited OwnerAdd;
end;

procedure TdxfXRecord.AddExData(const AReader: TdxfReader);
var
  vCode: SmallInt;
  vBinDataSize: Integer;
begin
  vCode := AReader.Code;
  case CodeTypes^[vCode] of
    ctInteger:
      case vCode of
        280, 281, 290..299: TsgDXFXRecord(FEnt).Data.AddByte(vCode, AReader.IntValue);
        60..79, 170..179, 270..279, 282..289, 370..389, 400..409, 1060..1070:
          TsgDXFXRecord(FEnt).Data.AddInt16(vCode, AReader.IntValue);
      else
        TsgDXFXRecord(FEnt).Data.AddInt(vCode, AReader.IntValue);
      end;
    ctDouble:   TsgDXFXRecord(FEnt).Data.AddDouble(vCode, AReader.FloatValue);
    ctString:   TsgDXFXRecord(FEnt).Data.AddString(vCode, AReader.UValue);
    ctHex:      TsgDXFXRecord(FEnt).Data.AddInt64(vCode, AReader.HandleValue);
  else
    case vCode of
      310:
        begin
          vBinDataSize := 0;
          AddBinData(AReader.Value, FBinData, vBinDataSize);
          TsgDXFXRecord(FEnt).Data.AddBinary(vCode, vBinDataSize, FBinData);
        end
    else
      //raise EError.CreateFmt('Unknown XRecord(%x) code "%d"', [FHandle, vCode]);
    end;
  end;
end;

procedure TdxfXRecord.ReadProperty(const AReader: TdxfReader);
begin
  inherited ReadProperty(AReader);
  case AReader.Code of
    100:
      begin
        FStartData := AReader.Value = sAcDbXrecord;
        AReader.Next;
        if AReader.Code <> 280 then
          ReadProperty(AReader);
      end;
    0:   FStartData := False;
  else
    if FStartData then
      AddExData(AReader);
  end;
end;

procedure TdxfXRecord.ReadProps(AReader: TdxfReader);
begin
  repeat
    AReader.Next;
    ReadProperty(AReader);
  until AReader.Code = Info_0;
end;

{ TdxfMesh }

procedure TdxfMesh.Commit(const AReader: TdxfReader);
begin
  inherited Commit(AReader);
  FillSubDMesh(FEnt, FVertexArray, FFaceArray);
end;

constructor TdxfMesh.Create;
begin
  inherited Create;
  FVertexArray := TFPointList.Create;
  FFaceArray := TsgIntegerList.Create;
  FEdgeArray := TsgIntegerList.Create;
  FIndexFace := 0;
  FIndexVertex := 0;
  FMode := 0;
end;

destructor TdxfMesh.Destroy;
begin
  FEdgeArray.Free;
  FFaceArray.Free;
  FVertexArray.Free;
  inherited Destroy;
end;

procedure TdxfMesh.ReadProperty(const AReader: TdxfReader);
begin
  case AReader.Code of
    Integer_92: FVertexArray.Count := AReader.IntValue;
    Integer_93:
      begin
        FFaceArray.Count := AReader.IntValue;
        FMode := 1;
      end;
    Integer_94:
      begin
        FEdgeArray.Count := AReader.IntValue;
        FMode := 2;
      end;
    (*95: //Edge crease count of level 0
      inherited ReadProperty(AReader); *)
    Integer_90:
      begin
        case FMode of
          1:
            begin
              FFaceArray[FIndexFace] :=  AReader.IntValue;
              Inc(FIndexFace);
            end;
          2:
            begin
              AReader.IntValue;
            end;
          else
            inherited ReadProperty(AReader);
        end;
      end;
    XFirst_10: FVertexArray.List[FIndexVertex].X :=  AReader.FloatValue;
    YFirst_20: FVertexArray.List[FIndexVertex].Y :=  AReader.FloatValue;
    ZFirst_30:
      begin
        FVertexArray.List[FIndexVertex].Z :=  AReader.FloatValue;
        Inc(FIndexVertex);
      end
    else
      inherited ReadProperty(AReader);
  end;
end;

initialization
  CF_DXF := RegisterClipboardFormat('SoftGold DXF Image');
  TPicture.RegisterFileFormat('dxf', 'AutoCAD DXF', TsgCADdxfImage);
{$IFDEF SG_DXT}
  TPicture.RegisterFileFormat('dxt', 'CADSoftTools drawing template',
    TsgCADdxfImage);
{$ENDIF}
  TPicture.RegisterClipboardFormat(CF_DXF, TsgCADdxfImage);
  TsgDXFConverterAccess.RegisterXRefGraphicClass('dxf', TsgCADdxfImage);
  ListOfEntName := TsgStringList.Create;
  InitListOfEntName;
  InitDataBaseSections;

finalization
  TPicture.UnRegisterGraphicClass(TsgCADdxfImage);
  TsgDXFConverterAccess.UnRegisterXRefGraphicClass(TsgCADdxfImage);
  ClearStringList(ListOfEntName);
  ListOfEntName.Free;
  HeadVars.Free;
  DataBaseSections.Free;

end.
