{************************************************************}
{                   Delphi VCL Extensions                    }
{                                                            }
{                    Export CAD to DWG                       }
{                                                            }
{      Copyright (c) 2012-2013 SoftGold software company     }
{                                                            }
{************************************************************}
unit CADtoDWG;
{$I SGDXF.INC}

interface

uses
  Windows, SysUtils, Graphics, Classes, CADExport, CADImage, DXFConv, sgConsts,
  ExtData, MVFont, ActiveX, sgOle, sgBitmap, sgFunction, Math, sgDefinitions
  {$IFDEF SGDEL_6}, DateUtils{$ENDIF}
  ,sgLists, sgComparer, sgLines, sgDWGBits, CADDirectExport, TTF
{$IFDEF SGDEL_XE2}
  , System.Types
{$ENDIF}
  ;
const
  cntDWGR15SectionsCount = 6;

  sInvalidSectNumber: string = 'The section number is invalid';
  sCannotFindTable: string = 'Table (%s) (%d) cannot be found';
  sCannotFindTableCode: string = 'Table (%d) cannot be found';
  sDWGCodeInvalid: string = 'DWG code (%d) id is invalid';
  sHandleInvalid: string = 'Handle is invalid';
  sPlotStyleIsAbsent: string = 'Plot style is absent';
  sBlockIsNil: string = 'Block is nil';
  sLayerIsNil: string = 'Layer is nil';
  sLTypeIsNil: string = 'LType is nil';
  sCannotFindBlock: string = 'Cannot find block %h';
  sListsNotEqual: string = 'Lists are not equal';
  sPaperSpaceLayoutIsNil: string = '*Paper_Space layout is nil';
  sDublicatedHandle: string = 'Duplicated handle';
  sFlathHatchCreationError: string = 'FlathHatch creation error';
  sGradientIsNotSupported: string = 'Gradient is not supported';

type
  PsgDWGR15Locators = ^TsgDWGR15Locators;
  TsgDWGR15Locators = packed array[0..cntDWGR15SectionsCount - 1] of TdwgLocator;

  EDWGExportError = class(Exception);
  EDWGUnsupportedExportVersion = class(EDWGExportError);

type
  PsgDWGCreatedElement = ^TsgDWGCreatedElement;
  TsgDWGCreatedElement = record
    Handle: UInt64;
    OwnerHandle: UInt64;
    Location: Integer;
    DWGObjCode: Word;
    Obj: TObject;
    Size: Integer;
    Name: string;
    Handles: TsgDWGHandleArray;
  end;
  TsgSortElemBy = (seHandle, seLocation, seDWGObjCode, seObject, seOwnerHandle,
    seName);

  TsgDWGCreatedElements = class
  private
    FElements: TsgList;
    FFindBeforeAdd: Boolean;
    FSortBy: TsgSortElemBy;
    procedure ClearElem(var Elem: TsgDWGCreatedElement);
    procedure GotoFirstLastElem(const AElem: TsgDWGCreatedElement; var AIndex: Integer;
      AFirst: Boolean);
    function CountElem(AIndex: Integer; Elem: TsgDWGCreatedElement): Integer;
    function Find(const Elem: TsgDWGCreatedElement; ASortBy: TsgSortElemBy;
      AGotoFirstElem: Boolean = False): Integer;
    function GetFindBeforeAdd: Boolean;
    procedure SetSortBy(const Value: TsgSortElemBy);
    procedure SetFindBeforeAdd(const Value: Boolean);
  protected
    function CompareElements(const Element1, Element2: Pointer): Integer;
    function GetCount: Integer;
    function GetElement(AIndex: Integer): TsgDWGCreatedElement;
    function GetPtrElement(AIndex: Integer): PsgDWGCreatedElement;
    procedure GotoFirstElem(const AElem: TsgDWGCreatedElement; var AIndex: Integer);
    procedure GotoLastElem(const AElem: TsgDWGCreatedElement; var AIndex: Integer);
  public
    constructor Create;
    destructor Destroy; override;
    function AddElement(const AValue: TsgDWGCreatedElement): Integer; overload;
    function AddElement(const AHandle: UInt64; ALocation: Integer; ADWGObjCode: Word;
      AName: string = ''; AOwnerHandle: UInt64 = cnstBadHandle; AObject: TObject = nil;
      ASize: Integer = 0): Integer; overload;
    procedure Clear;
    function CountOf(const OwnerHandle: UInt64; var AIndex: Integer): Integer; overload;
    function CountOf(const ALocation: Integer; var AIndex: Integer): Integer; overload;
    function CountOf(const ADWGObjCode: Word; var AIndex: Integer): Integer; overload;
    function CountOf(const AObject: TObject; var AIndex: Integer): Integer; overload;
    function CountOf(const AName: string; var AIndex: Integer): Integer; overload;
    function IndexOf(const AHandle: UInt64; OwnerHandle: Boolean = False;
      PElem: PsgDWGCreatedElement = nil): Integer; overload;
    function IndexOf(const ALocation: Integer; PElem: PsgDWGCreatedElement = nil): Integer; overload;
    function IndexOf(const ADWGObjCode: Word; PElem: PsgDWGCreatedElement = nil): Integer; overload;
    function IndexOf(const AObject: TObject; PElem: PsgDWGCreatedElement = nil): Integer; overload;
    function IndexOf(const AName: string; PElem: PsgDWGCreatedElement = nil): Integer; overload;
    procedure Sort;
    property Count: Integer read GetCount;
    property Element[AIndex: Integer]: TsgDWGCreatedElement read GetElement; default;
    property FindBeforeAdd: Boolean read GetFindBeforeAdd write SetFindBeforeAdd;
    property SortBy: TsgSortElemBy read FSortBy write SetSortBy;
  end;

  TsgDWGReadEvent = procedure(ABits: TsgDWGBits) of object;

  TsgCADtoDWG = class(TsgCADDirectExport)
  private
    FSections: TList;
    FMaintenanceVersion: Byte;
    FClasses: TStringList;
    FObjectsMap: TsgDWGCreatedElements;
    FCreatedElements: TsgDWGCreatedElements;
    FCreatedEndBlk: TsgUInt64Pairs;
    FCreatedSeqEnd: TsgUInt64Pairs;
    FDWGCodePage: Word;
    FCodePage: Integer;
    FModelSpaceHandle: UInt64;
    FPaperSpaceHandle: UInt64;
    FScalesDictionary: TStringList;
    FVariableDictionary: TStringList;
    FEntitiesWithAddedHandles: TList;
    FACADXDataAppID: UInt64;
    FXDataAppID: UInt64;
    FAddedViewPort: TsgDXFViewport;
    FSGInserts: TList;
    function AddCreatedElem(const AName: string; const AClass: TsgDXFEntityClass;
      const AElements: TsgDWGCreatedElements; ADWGCode: Word;
      AHandle: UInt64 = cnstBadHandle; AOwnerHandle: UInt64 = cnstBadHandle): Integer;
    function AddCommonEntityData(const AHandle: UInt64; const AObjType: Word;
      const ABits: TsgDWGBits; const AReactorsCount: Cardinal = 0;
      Entity: TsgDXFEntity = nil; EntMode: Byte = 3; PLineTypeFlags: PByte = nil;
      PPlotstyleFlags: PByte = nil): Cardinal;
    procedure AddEED(const ABits: TsgDWGBits; const E: TsgDXFEntity;
      const AEEData: TsgCADExtendedData);
    procedure AddHandlesUpdateAndFinish(const ABits: TsgDWGBits;
      const AHandles: array of TsgDWGHandle; const ObjHandle: UInt64;
      const ADWGCode: Word; AWriteCRC: Boolean = True);
    procedure AddHandlesData(const ABits: TsgDWGBits; const AHandles: array of TsgDWGHandle);
    procedure AddOwnerAndXDiObjHandle(var AHandles: TsgDWGHandleArray; const OwnerHandle: Uint64 = cnstBadHandle;
      const XDiObjHandle: Uint64 = cnstBadHandle);
    procedure AddHandleToArray(const AHandle: TsgDWGHandle;
      var AHandles: TsgDWGHandleArray; AIndex: Integer = -1);
    procedure AddCommonEntityHandleData(const ObjHandle: UInt64; ABits: TsgDWGBits;
      AEntity: TsgDXFEntity; const AOwnerHandle: UInt64; DWGCode: Word; EntMode,
      LTypeFlags, PlotStyleFlags: Byte; ANeedLayer: Boolean; const APrevEntHandle,
      ANextEntHandle: UInt64; AOwner: TsgDXFEntity);
    procedure AddXRecords(const ABits: TsgDWGBits; XRecordConv: Boolean;
      const XRecords: TsgCADExtendedData);

    procedure CreateTablesRecord;
    procedure CreateDictionaryListByStrList(const DictionaryName: string;
      DWGCode: Word; AList: TStringList);
    function CheckEntHandle(AEntity: TsgDXFEntity; ADoRaise: Boolean = True): Boolean;
    function ConvertEEDToDWG(E: TsgDXFEntity; Source, Dest: TsgCADExtendedData;
      var EEDHandle: UInt64): Boolean;
    procedure DoBeforeAddCommonEntData(ABits: TsgDWGBits; var Handle: UInt64;
      var E: TsgDXFEntity; var DWGCode: Word; OwnerDWGCode: Word; AOwner: TsgDXFEntity);
    procedure DoAfterAddEntHandlesData(const ObjHandle: UInt64; ABits: TsgDWGBits;
      AEntity: TsgDXFEntity; const AOwnerHandle: UInt64; DWGCode: Word;
      EntMode, LTypeFlags, PlotStyleFlags: Byte; const APrevEntHandle,
      ANextEntHandle: UInt64; AOwner: TsgDXFEntity;
      var Handles: TsgDWGHandleArray);

    procedure ExportCreatedTableRecords;
    procedure ExportViewPortEntityHeaders;
    procedure ExportSectionTables;
    function ExportTableAppID(const AppInfo: string): UInt64;
    procedure ExportTableBLOCK_RECORD;
    procedure ExportTableSTYLE;
    procedure ExportTableLTYPE;
    procedure ExportTableLAYER;
    procedure ExportTableVPORT;
    procedure ExportTableDIMSTYLE;
    procedure ExportTableOBJECTS;
    procedure ExportSectionENTITIES;

    function ExportCADFill(CADFill: TsgCADFill; const Data: TsgDirectExportData): Boolean;
    function ExportLine(L: TsgDXFLine; ABits: TsgDWGBits): Boolean;
    function ExportSolid(S: TsgDXFSolid; ABits: TsgDWGBits): Boolean;
    function ExportText(T: TsgDXFText; ABits: TsgDWGBits): Boolean;
    function ExportOle2Frame(OLE2: TsgDXFOle2Frame; ExportData: TObject): Boolean;
    function ExportOle2FrameCreateOleGroup(OLE2: TsgDXFOle2Frame; ExportData: TObject): Boolean;
    function ExportPoint(P: TsgDXFPoint; ABits: TsgDWGBits): Boolean;
    function ExportCircle(C: TsgDXFCircle; ABits: TsgDWGBits): Boolean;
    function ExportPolyline(PLine: TsgDXFPolyline; DWGCode: Word; ABits: TsgDWGBits;
      const AIsTempObject: Boolean = False): Boolean;
    function ExportLWPolyline(LWPolyline: TsgDXFLWPolyline; ABits: TsgDWGBits): Boolean;
    function ExportSeqEnd(E: TsgDXFEntity; ABits: TsgDWGBits): Boolean;
    function ExportVertex(Owner: TsgDXFEntity; V: TsgDXFVertex; DWGCode: Word;
      ABits: TsgDWGBits): Boolean;
    function ExportSpline(Spline: TsgDXFSpline; ABits: TsgDWGBits): Boolean;
    function ExportFlatPoly(FlatPoly: TsgFlatPoly; const Data: TsgDirectExportData): Boolean;
    function ExportShape(S: TsgDXFShape; ABits: TsgDWGBits): Boolean;
    function ExportInsert(Insert: TsgDXFInsert; ABits: TsgDWGBits; EEData: TsgCADExtendedData): Boolean;
    function ExportMText(M: TsgDXFMText; ABits: TsgDWGBits): Boolean;
    function ExportTolerance(T: TsgDXFTolerance; ABits: TsgDWGBits): Boolean;
    function Export3DFace(F: TsgDXF3dFace; ABits: TsgDWGBits): Boolean;
    function ExportEllipse(E: TsgDXFEllipse; ABits: TsgDWGBits): Boolean;
    function ExportLeader(L: TsgDXFLeader; ABits: TsgDWGBits): Boolean;
    function ExportDimension(D: TsgDXFDimension; ABits: TsgDWGBits;
      DWGCode: Word): Boolean;
    function ExportHatch(H: TsgCADPolyPolygon; ABits: TsgDWGBits;
      DWGCode: Word): Boolean;
    function ExportViewPort(V: TsgDXFViewPort; ABits: TsgDWGBits): Boolean;
    function ExportWipeOut(W: TsgCADWipeout; ABits: TObject): Boolean;
    function ExportWipeOutAsExternalFile(W: TsgCADWipeout; AData: TObject): Boolean;
//    function ExportACISEntity(A: TsgDXFACISEntity; const AExportData: TsgDWGExportData): Boolean;
//    function ExportChildEntities(E: TsgDXFEntity; const AExportData: TsgDWGExportData): Boolean;
//    function ExportFlatHatch(FlatHatch: TsgFlatHatch; Data: TsgDWGExportData): Boolean;

    {$IFDEF SG_BTI}
    function ExportPolyPolyline2D(Poly: TsgCADPolyPolyline2D; const AExportData: TsgDirectExportData): Boolean;
    {$ENDIF}
    function ExportMLine(M: TsgCADMLine; const ABits: TsgDWGBits;
      const AExportData: TsgDirectExportData): Boolean;
    function ExportUnknownObject(E: TsgDXFEntity; const AExportData: TsgDirectExportData): Boolean;

    procedure FinishObject(const ObjHandle: UInt64; const ABits: TsgDWGBits;
      const AObjSize: Cardinal; ADWGCode: Word; AWriteCRC: Boolean = True);

    function GetSection(Index: Integer): TMemoryStream;
    function GetDWGCodePage: Word;
    function GetHandleByEntity(AEntity: TsgDXFEntity): UInt64;

    function GetEntityHandle(const AEntity: TsgDXFEntity; ADoNewHandle: Boolean = False;
      ADWGCode: Word = cntDWGObjCodeUNSUSED; const AName: string = ''; ADoRaise: Boolean = False;
      AFirst: Boolean = True): UInt64;
    function GetDictionaryHandle(AName: string): UInt64;
    function GetDWGCodeByClass(const AClassName: string): Word;
    function GetRealDWGCode(const DWGCode: Word): Word;
    function GetEntHandleByIndex(Group: TsgDXFEntity; Index: Integer; AList: TList;
      EntIndex: Integer; AFirst: Boolean): UInt64;
    function GetStyleHandle(Style: TsgDXFEntity; ADimStyle: Boolean): UInt64;
    function GetLineTypeHandle(LineType: TsgDXFLineType): UInt64;
    function GetAuxHeaderSectionIndex: Integer;
    function GetClassesSectionIndex: Integer;
    function GetHeaderVarsSectionIndex: Integer;
    function GetMeasurementSectionIndex: Integer;
    function GetObjFreeSpaceSectionIndex: Integer;
    function GetObjectMapSectionIndex: Integer;
    function GetFileHeaderSectionIndex: Integer;
    function GetPreviewSectionIndex: Integer;
    function GetObjectsSectionIndex: Integer;
    function GetSecondHeaderSectionIndex: Integer;
    function GetDefVal(const Value, DefValue: Double): Double;
    function GetPaperSpaceBlockHandle: UInt64;
    function GetModelSpaceBlockHandle: UInt64;

    function IsEntityHasNotEED(const Entity: TsgDXFEntity): Boolean;

    procedure OnWriteDimStyleControlObject(ABits: TsgDWGBits);//DimStyleCtrlObject needs additional WriteRC(0)

    procedure ProcBlockControl(BlockHandles: TsgInt64List);
    procedure ProcBlock(ABlock: TsgDXFBlock; const AName: string;
      Data: Pointer; APaperSpaceIndex: Integer = -1);
    procedure ProcBlockRecord(ABlock: TsgDXFBlock; const AName: string;
      Data: Pointer; ACurrPaperSpaceIndex: Integer = -1);
    procedure ProcStyle(const AOwner: UInt64; const AStyle: TsgDXFStyle;
      AHandles: TsgInt64List);
    procedure ProcStyleControl(const AHandle: UInt64; StylesHandles: TsgInt64List);
    procedure ProcControlObject(const AHandle: UInt64; ACode: Word; ANumentries: Cardinal;
      const AHandles: array of TsgDWGHandle; ReadEvent: TsgDWGReadEvent = nil);
    procedure ProcLType(AOwnerHandle: UInt64; ALType: TsgDXFLineType);
    procedure ProcLTypeControlObject(const AHandle: UInt64; const ALTypesHandles: array of TsgDWGHandle);
    procedure ProcLayer(const AOwnerHandle: UInt64; ALayer: TsgDXFLayer;
      var ProcHandles: TsgDWGHandleArray; var ZeroLayerIndex: Integer);
    procedure ProcLayerControlObject(const AHandle: UInt64;
      const ProcLayerHandles: TsgDWGHandleArray);
    procedure ProcVPort(const AOwnerHandle: UInt64; AVPort: TsgDXFVPort;
      var ProcVPortHandles: TsgDWGHandleArray);
    procedure ProcViewPortControlObject(const AHandle: UInt64;
      const ProcViewPortHandles: TsgDWGHandleArray);
    procedure ProcDimStyle(const AOwnerHandle: UInt64;
      ADimStyle: TsgDXFDimensionStyle; var AProcHandles: TsgDWGHandleArray);
    procedure ProcDimStylesControlObject(const AHandle: UInt64;
      const ADimStyleHandles: TsgDWGHandleArray);
    procedure ProcDictionary(const Handle, OwnerHandle: UInt64; Items: TStringList);
    procedure ProcRasterVariables(const ARasterVariables: TsgCADRasterVariables;
      const OwnerHandle: UInt64);
    procedure ProcScale(const Handle, OwnerHandle: UInt64; const Index: Integer;
      const Name: string);
    procedure ProcMLineStyle(const AStyle: TsgMLineStyle; const OwnerHandle: UInt64);
    procedure ProcWipeoutVar(const Handle, OwnerHandle: UInt64);
    procedure ProcVariableDictionary(const Handle, OwnerHandle: UInt64; const Index: Integer;
      const Name: string);
    procedure ProcDWGProps(const Handle, OwnerHandle: UInt64);
    procedure ProcLayout(ALayout: TsgDXFLayout; const Handle, OwnerHandle: UInt64;
      AIndex: Integer; AName: string);
    procedure ProcViewPortEntHeader(const AIndex: Integer);
    procedure ProcImageDef(AImageDef: TsgDXFImageDef);

    procedure SaveObjectToStream(const AHandle: UInt64; const ABits: TsgDWGBits;
      DWGCode: Word);

    procedure WriteByteToStream(const Stream: TStream; const Byte: Byte;
      const Count: Integer);
  protected
    procedure Clear; override;
    function CorrectLineWeight(const ALineWeight: Double;
      ANeedToConvert: Boolean): Integer; override;
    procedure DoExport(const E: TsgDXFEntity; const Data: PsgDirectExportData = nil;
      const AIsTempObject: Boolean = False); override;
    procedure ExportSectionAuxHeader(const HandsSeed: UInt64;
      const ADateCreate, ADateUpdate: TDateTime);
    procedure ExportSectionClasses(const APaddingSize: Integer); virtual;
    procedure ExportSectionHeaderVars(const AHandSeed: UInt64;
      const ADateCreate, ADateUpdate: TDateTime);
    procedure ExportSectionMeasurement(const Measurement: Word = 1);//0 = English, 1 = Metric
    procedure ExportSectionObjects;
    procedure ExportSectionObjMap;
    procedure ExportSectionObjFreeSpace(const ADateUpdate: TDateTime;
      const ObjCount, ObjOffset: Cardinal);
    procedure ExportSectionPreview(const ImageOffset: Cardinal);
    procedure ExportSectionSecondHeader(const AHandSeed: UInt64;
      Offset: Cardinal; const Locators: TsgDWGR15Locators);

    function GetArrowBlockHandle(const Value: TsgDimArrowType): UInt64;
    procedure GetCreateAndUpdateDateTime(var ADateCreate, ADateUpdate: TDateTime);
    function GetModelAndPaperSpaceBlockHandle(const AIndex: Integer): UInt64;

    function GetPreviewImageHeigth: Integer;
    function GetPreviewImageWidth: Integer;
    function GetPreviewImageRect: TRect;
    function GetLocatorsCount: Integer; virtual;
    function GetSectionsCount: Integer; virtual;

    function GetMLineStyle: TsgMLineStyle; //!!!
    function GetBlockControlObjectHandle: UInt64;
    function GetLayerControlObjectHandle: UInt64;
    function GetStyleControlObjectHandle: UInt64;
    function GetLineTypeControlObjectHandle: UInt64;
    function GetViewControlObjectHandle: UInt64;
    function GetVPortControlObjectHandle: UInt64;
    function GetUCSontrolObjectHandle: UInt64;
    function GetAppIDControlObjectHandle: UInt64;
    function GetDimStyleControlObjectHandle: UInt64;
    function GetViewPortEntityHeaderControlObjectHandle: UInt64;
    function GetCurrentViewportEntityHeaderHandle: UInt64;
    function GetLastActiveViewportHandle(ALayout: TsgDXFLayout): UInt64;

    function GetDictionaryAcadGroupHandle: UInt64;
    function GetDictionaryAcadImageDict: UInt64;
    function GetDictionaryAcadMLineStyleHandle: UInt64;
    function GetDictionaryNamedObjectHandle: UInt64;
    function GetDictionaryLayoutsHandle: UInt64;
    function GetDictionaryPlotSettingHandle: UInt64;
    function GetDictionaryPlotStyleHandle: UInt64;
    function GetPaperSpaceLayoutHandle(PIndex: PInteger = nil): UInt64;

    function GetFingerPrintGUID: string;
    function GetVersionGUID: string;

    function Get64bitof70Group(Flags: Word): Byte; //see DWG documentation
    function GetXdep(const AName: string): Byte; //see DWG documentation
    function GetBitSizePos(DWGCode: Word): Cardinal; virtual;
    function GetActiveLayerHandle(AGetZeroLayer: Boolean = False): UInt64;
    function GetObjectsFileOffset: Cardinal;
    function GetSecondHeaderOffset: Cardinal;
    function GetPreViewImageOffset: Cardinal;
    function GetHeaderVarsOffset: Cardinal;
    function GetClassesOffset: Cardinal;
    function GetObjMapOffset: Cardinal;
    function GetObjFreeSpaceOffset: Cardinal;
    function GetTemplateOffset: Cardinal;
    function GetAuxHeaderOffset: Cardinal;
    function GetExportExceptionClass: ExceptClass; override;
    function GetNextEntHandle(Group: TsgDXFEntity; Index: Integer;
      AList: TList = nil): UInt64; override;
    function GetPrevEntHandle(Group: TsgDXFEntity; Index: Integer;
      AList: TList = nil): UInt64; override;

    function IsPaperLayout(const AName: string): Boolean;
    function IsPaperSpace(const AName: string; ABlock: TsgDXFBlock): Boolean; overload;
    function IsPaperSpace(ABlock: TsgDXFBlock): Boolean; overload;

    procedure PrepareDrawingDatabase; override;
    function PrepareTextForDWG(const Text: string): string;
    procedure ProcessExport(Stream: TStream); override;

    procedure SaveSectionToStream(const ASectNum: Integer;
      const ABits: TsgDWGBits; const ABeginSentinel, AEndSentinel: array of Byte;
      ANeedToClear: Boolean = True);
    procedure SetVersion(const Value: TsgDWGVersion); override;
    function WriteDateTimeAsJulian(const ADate: TDateTime; const ABits: TsgDWGBits;
      AUseRL: Boolean; PJDate: PCardinal = nil; PMilSec: PCardinal = nil;
      AWriteMilSec: Boolean = True): Integer;
    function WriteEntityHandle(const ABits: TsgDWGBits; const Entity: TsgDXFEntity;
      const ACode: Byte; AHandle: Boolean = True): Integer;
    procedure WriteSectionSize(const ABits: TsgDWGBits; const ASizePos: Cardinal = 0;
      const ASizeDelta: Integer = 0);
    property ModelSpaceBlockHandle: UInt64 read GetModelSpaceBlockHandle;
    property PaperSpaceBlockHandle: UInt64 read GetPaperSpaceBlockHandle;
    property Sections[Index: Integer]: TMemoryStream read GetSection;
  public
    constructor Create(ACADImage: TsgCADImage); override;
    destructor Destroy; override;

    property DWGCodePage: Word read GetDWGCodePage;
    property MaintenanceVersion: Byte read FMaintenanceVersion;
  end;


implementation

const
  cntDWGR15FileHeaderSize = SizeOf(TdwgFileHeader) + //File header variables
    cntDWGR15SectionsCount * SizeOf(TdwgLocator)   + //Locator records count is 6
    SizeOf(Word)                                   + //CRC
    SizeOf(TsgDWGSentinel);                          //End Sentinel
  cntSizeTempValue = $FFFFFFFF;
  cntOffsetTempValue = cntSizeTempValue;
  cntPaddingSize = $80 * SizeOf(Cardinal);
  cntDWGObjCodeTEXT = 1;
  cntDWGObjCodeATTRIB = 2;
  cntDWGObjCodeATTDEF = 3;
  cntDWGObjCodeBLOCK = 4;
  cntDWGObjCodeENDBLK = 5;
  cntDWGObjCodeSEQEND = 6;
  cntDWGObjCodeINSERT = 7;
  cntDWGObjCodeMINSERT1 = 8;
  cntDWGObjCodeMINSERT2 = 9;
  cntDWGObjCodeVERTEX2D = $0A;
  cntDWGObjCodeVERTEX3D = $0B;
  cntDWGObjCodeVERTEXMESH = $0C;
  cntDWGObjCodeVERTEXPFACE = $0D;
  cntDWGObjCodeVERTEXPFACEFACE = $0E;
  cntDWGObjCodePOLYLINE2D = $0F;
  cntDWGObjCodePOLYLINE3D = $10;
  cntDWGObjCodeARC = $11;
  cntDWGObjCodeCIRCLE = $12;
  cntDWGObjCodeLINE = $13;
  cntDWGObjCodeDIMENSIONORDINATE = $14;
  cntDWGObjCodeDIMENSIONLINEAR = $15;
  cntDWGObjCodeDIMENSIONALIGNED = $16;
  cntDWGObjCodeDIMENSIONANG3Pt = $17;
  cntDWGObjCodeDIMENSIONANG2Ln = $18;
  cntDWGObjCodeDIMENSIONRADIUS = $19;
  cntDWGObjCodeDIMENSIONDIAMETER = $1A;
  cntDWGObjCodePOINT = $1B;
  cntDWGObjCode3DFACE = $1C;
  cntDWGObjCodePOLYLINEPFACE = $1D;
  cntDWGObjCodePOLYLINEMESH = $1E;
  cntDWGObjCodeSOLID = $1F;
  cntDWGObjCodeTRACE = $20;
  cntDWGObjCodeSHAPE = $21;
  cntDWGObjCodeVIEWPORT = $22;
  cntDWGObjCodeELLIPSE = $23;
  cntDWGObjCodeSPLINE = $24;
  cntDWGObjCodeREGION = $25;
  cntDWGObjCode3DSOLID = $26;
  cntDWGObjCodeBODY = $27;
  cntDWGObjCodeRAY = $28;
  cntDWGObjCodeXLINE = $29;
  cntDWGObjCodeDICTIONARY1 = $2A;
  cntDWGObjCodeDICTIONARY2 = $2B;
  cntDWGObjCodeMTEXT = $2C;
  cntDWGObjCodeLEADER = $2D;
  cntDWGObjCodeTOLERANCE = $2E;
  cntDWGObjCodeMLINE = $2F;
  cntDWGObjCodeBLOCKCONTROLOBJ = $30;
  cntDWGObjCodeBLOCKHEADER = $31;
  cntDWGObjCodeLAYERCONTROLOBJ = $32;
  cntDWGObjCodeLAYER = $33;
  cntDWGObjCodeSTYLECONTROLOBJ = $34;
  cntDWGObjCodeSTYLE1 = $35;
  cntDWGObjCodeSTYLE2 = $36;
  cntDWGObjCodeSTYLE3 = $37;
  cntDWGObjCodeLTYPECONTROLOBJ = $38;
  cntDWGObjCodeLTYPE1 = $39;
  cntDWGObjCodeLTYPE2 = $3A;
  cntDWGObjCodeLTYPE3 = $3B;
  cntDWGObjCodeVIEWCONTROLOBJ = $3C;
  cntDWGObjCodeVIEW = $3D;
  cntDWGObjCodeUCSCONTROLOBJ = $3E;
  cntDWGObjCodeUCS = $3F;
  cntDWGObjCodeVPORTCONTROLOBJ = $40;
  cntDWGObjCodeVPORT = $41;
  cntDWGObjCodeAPPIDCONTROLOBJ = $42;
  cntDWGObjCodeAPPID = $43;
  cntDWGObjCodeDIMSTYLECONTROLOBJ = $44;
  cntDWGObjCodeDIMSTYLE = $45;
  cntDWGObjCodeVPENTHDRCTRLOBJ = $46;
  cntDWGObjCodeVPENTHDR = $47;
  cntDWGObjCodeGROUP = $48;
  cntDWGObjCodeMLINESTYLE = $49;
  cntDWGObjCodeOLE2FRAME = $4A;
  cntDWGObjCodeDUMMY = $4B;
  cntDWGObjCodeLONGTRANSACTION = $4C;
  cntDWGObjCodeLWPOLYLINE = $4D;
  cntDWGObjCodeHATCH = $4E;
  cntDWGObjCodeXRECORD = $4F;
  cntDWGObjCodeACDBPLACEHOLDER = $50;
  cntDWGObjCodeVBA_PROJECT = $51;
  cntDWGObjCodeLAYOUT = $52;

  cntDWGObjCodeUSER = 3000; //only for internal use, codes will not be saved into DWG file
  cntDWGObjCodeMPOLYGON = cntDWGObjCodeUSER + 1;
  cntDWGObjCodeWIPEOUT = cntDWGObjCodeUSER + 2;
  cntDWGObjCodeIMAGE = cntDWGObjCodeUSER + 3;
  cntDWGObjCodeIMAGEBYFILE = cntDWGObjCodeUSER + 4;
  cntDWGObjCodeIMAGEDEF = cntDWGObjCodeUSER + 5;
  cntDWGObjCodeFLATHATCH = cntDWGObjCodeUSER + 6;
  cntDWGObjCodePROXY = cntDWGObjCodeUSER + 7;
  cntDWGObjCodePOLYPOLYLINE2D = cntDWGObjCodeUSER + 8;
  cntDWGObjCodeRASTERVARIABLES = cntDWGObjCodeUSER + 9;
  cntDWGObjCodeUNKNOWNOBJ = cntDWGObjCodeUSER + 10;

  cntEmptyDictionary = ' ';
type
  PsgDWGScale = ^TsgDWGScale;
  TsgDWGScale = record
    ScaleParam1: Double;
    ScaleParam2: Double;
    ScaleParam3: Byte;
  end;

  TsgCADImageEx = class(TsgCADImage);
  TsgDXFEntityEx = class(TsgDXFEntity);
  Tsg2DPolylineEx = class(Tsg2DPolyline);
  Tsg2DSplineEx = class(Tsg2DSpline);
  TsgDXFBlockEx = class(TsgDXFBlock);
  TsgDXFInsertEx = class(TsgDXFInsert);
  TsgDXFDimensionEx = class(TsgDXFDimension);
  TsgDXFTextEx = class(TsgDXFText);
  TsgDXFMTextEx = class(TsgDXFMText);
  TsgDXFToleranceEx = class(TsgDXFTolerance);
  TsgDXFVertexEx = class(TsgDXFVertex);
{$IFDEF SG_BTI}
  TsgAreaFigureAccess = class(TsgAreaFigure);
  TsgExtendedBlockDataEx = class(TsgExtendedBlockData);
{$ENDIF}
  TsgDXFTableAccess = class(TsgDXFTable);
  TsgDXFImageEntAccess = class(TsgDXFImageEnt);
  TsgBitmapAccess = class(TsgBitmap);
  TsgAcadTableCellAccess = class(TsgAcadTableCell);
  TsgMLineStyleAccess = class(TsgMLineStyle);
  TsgDXFPolylineAccess = class(TsgDXFPolyline);
  TsgDXF3dFaceAccess = class(TsgDXF3dFace);

{ TsgCADtoDWG }

function TsgCADtoDWG.AddCommonEntityData(const AHandle: UInt64; const AObjType: Word;
  const ABits: TsgDWGBits; const AReactorsCount: Cardinal = 0; Entity: TsgDXFEntity = nil;
  EntMode: Byte = 3; PLineTypeFlags: PByte = nil; PPlotstyleFlags: PByte = nil): Cardinal;
var
  vEntName: string;
  vFlags: Byte;
  vEEData: TsgCADExtendedData;
begin
  Result := 0;
  if AObjType = 0 then Exit;
  ABits.WriteOT(GetRealDWGCode(AObjType));
  Result := ABits.Position;
  ABits.WriteRL(cntSizeTempValue);
  ABits.WriteHandle(AHandle, cntDWGObjHandleType0);
  vEEData := TsgCADExtendedData.Create; //EED
  try
    if Assigned(Entity) and (not IsEntityHasNotEED(Entity)) and Entity.GetExtData(vEEData) then
      AddEED(ABits, Entity, vEEData)
    else
      ABits.WriteBS(0);
  finally
    vEEData.Free;
  end;

  if EntMode <> 3 then //is entity
  begin
    ABits.WriteBit(0); //proxy graphic
    ABits.WriteBB(EntMode); //entmode
  end;

  ABits.WriteBL(AReactorsCount); //Reactors count

  if EntMode <> 3 then //is entity
  begin
    ABits.WriteBit(0);//Nolinks
    if Entity <> nil then
    begin
      ABits.WriteCMC(Entity.ColorCAD); //color
      ABits.WriteBD(Entity.LineTypeScale); // Ltype scale
    end
    else
    begin
      ABits.WriteCMC(cnstColorCADByLayer);
      ABits.WriteBD(1);
    end;
    vFlags := 0;
    if (Entity is TsgDXFPenLine) or (Entity is TsgDXFInsert) then
    begin
      if TsgDXFPenLine(Entity).LineType <> nil then
        vEntName := TsgDXFPenLine(Entity).LineType.EntName;
      if vEntName <> '' then
      begin
        if SameText(vEntName, sByBlock) then
          vFlags := 1
        else
          if SameText(vEntName, sContinuous) then
            vFlags := 2
          else
            if not SameText(vEntName, sByLayer) then
              vFlags := 3;
      end;
    end;
    ABits.WriteBB(vFlags);//Ltype flags
    if PLineTypeFlags <> nil then
      PLineTypeFlags^ := vFlags;
    ABits.WriteBB(0);//Plotstyle flags
    if PPlotstyleFlags <> nil then
      PPlotstyleFlags^ := 0;
    if Entity <> nil then
    begin
      ABits.WriteBS(BoolToBit(not Entity.Visibility));//Invisibility
      ABits.WriteRC(CorrectLineWeight(Entity.LineWeight, True)); //Lineweight
    end
    else
    begin
      ABits.WriteBS(0);
      ABits.WriteRC(29);
    end;
  end;
end;

procedure TsgCADtoDWG.AddCommonEntityHandleData(const ObjHandle: UInt64;
  ABits: TsgDWGBits; AEntity: TsgDXFEntity; const AOwnerHandle: UInt64; DWGCode: Word;
  EntMode, LTypeFlags, PlotStyleFlags: Byte; ANeedLayer: Boolean; const APrevEntHandle,
  ANextEntHandle: UInt64; AOwner: TsgDXFEntity);
var
  vHandles: TsgDWGHandleArray;
  vEnt: TsgDXFEntity;

  procedure CheckNeedLayer;
  begin
    if ANeedLayer then
    begin
      if AOwner = nil then
        AddHandleToArray(CreateDWGHandle(GetActiveLayerHandle(True), cntDWGObjHandleHardPointer), vHandles)
      else
        AddHandleToArray(CreateDWGHandle(GetEntityHandle(AOwner.Layer), cntDWGObjHandleHardPointer), vHandles)
    end
    else
      AddHandleToArray(CreateDWGHandle(cnstBadHandle, cntDWGObjHandleHardPointer), vHandles);
  end;

begin
  if EntMode = 0 then
    AddOwnerAndXDiObjHandle(vHandles, AOwnerHandle)
  else
    AddHandleToArray(CreateDWGHandle(cnstBadHandle, cntDWGObjHandleHardOwner), vHandles);

  AddHandleToArray(CreateDWGHandle(APrevEntHandle, cntDWGObjHandleSoftPointer),
    vHandles);
  AddHandleToArray(CreateDWGHandle(ANextEntHandle, cntDWGObjHandleSoftPointer),
    vHandles);

  if AEntity <> nil then  //Layer
  begin
    if AEntity.Layer = nil then
      CheckNeedLayer
    else
      AddHandleToArray(CreateDWGHandle(GetEntityHandle(AEntity.Layer),
        cntDWGObjHandleHardPointer), vHandles);
  end
  else
    CheckNeedLayer;

  if LTypeFlags = 3 then //LType
  begin
    if AOwner <> nil then
      vEnt := AOwner
    else
      vEnt := AEntity;
    if vEnt <> nil then
      AddHandleToArray(CreateDWGHandle(GetEntityHandle(vEnt.LineType, False, 0, '',
        True), cntDWGObjHandleHardPointer), vHandles)
    else
      DoError(True, sLTypeIsNil);
  end;

  DoError(PlotStyleFlags = 3, sPlotStyleIsAbsent);

  DoAfterAddEntHandlesData(ObjHandle, ABits, AEntity, AOwnerHandle, DWGCode, EntMode,
    LTypeFlags, PlotStyleFlags, APrevEntHandle, ANextEntHandle, AOwner, vHandles);

  AddHandlesUpdateAndFinish(ABits, vHandles, ObjHandle, GetRealDWGCode(DWGCode));
end;

function TsgCADtoDWG.AddCreatedElem(const AName: string; const AClass: TsgDXFEntityClass;
  const AElements: TsgDWGCreatedElements; ADWGCode: Word; AHandle: UInt64 = cnstBadHandle;
  AOwnerHandle: UInt64 = cnstBadHandle): Integer;
var
  vHandle: UInt64;
  vEntity: TsgDXFEntity;
begin
  vEntity := nil;
  if AClass <> nil then
  begin
    vEntity := AClass.Create;
    vEntity.Name := AName;
  end;
  vHandle := AHandle;
  if vHandle = cnstBadHandle then
    vHandle := DoHandle;
  Result := AElements.AddElement(vHandle, -1, ADWGCode, AName, AOwnerHandle, vEntity);
end;

procedure TsgCADtoDWG.AddEED(const ABits: TsgDWGBits; const E: TsgDXFEntity;
  const AEEData: TsgCADExtendedData);
var
  vBits: TsgDWGBits;
  vEEData: TsgCADExtendedData;
  vEEDHandle: UInt64;
begin
  vBits := TsgDWGBits.Create;
  try
    vEEData := TsgCADExtendedData.Create;
    try
      if not ConvertEEDToDWG(E, AEEData, vEEData, vEEDHandle) then
      begin
        ABits.WriteBS(0);
        Exit;
      end;
      AddXRecords(vBits, True, vEEData);
      ABits.WriteBS(vBits.Size);
      ABits.WriteHandle(vEEDHandle, cntDWGObjHandleHardPointer);
      ABits.WriteBytes(vBits.Data, vBits.Size);
      ABits.WriteBS(0);
    finally
      vEEData.Free;
    end;
  finally
    vBits.Free;
  end;
end;

procedure TsgCADtoDWG.AddHandlesData(const ABits: TsgDWGBits; const AHandles: array of TsgDWGHandle);
var
  I: Integer;
begin
  for I := Low(AHandles) to High(AHandles) do
    ABits.WriteHandle(AHandles[I].Handle, AHandles[I].Code);
end;

procedure TsgCADtoDWG.AddHandlesUpdateAndFinish(const ABits: TsgDWGBits;
  const AHandles: array of TsgDWGHandle; const ObjHandle: UInt64;
  const ADWGCode: Word; AWriteCRC: Boolean = True);
begin
  ABits.UpdateRL(GetBitSizePos(ADWGCode), ABits.Position);
  AddHandlesData(ABits, AHandles);
  FinishObject(ObjHandle, ABits, ABits.Size, ADWGCode, AWriteCRC);
end;

procedure TsgCADtoDWG.AddHandleToArray(const AHandle: TsgDWGHandle;
  var AHandles: TsgDWGHandleArray; AIndex: Integer = -1);
begin
  if AIndex < 0 then AIndex := High(AHandles) + 1;
  if AIndex > High(AHandles) then
    SetLength(AHandles, AIndex + 1);
  AHandles[AIndex] := AHandle;
end;

procedure TsgCADtoDWG.AddOwnerAndXDiObjHandle(var AHandles: TsgDWGHandleArray;
  const OwnerHandle: Uint64 = cnstBadHandle; const XDiObjHandle: Uint64 = cnstBadHandle);
var
  I, vLength: Integer;
begin
  vLength := Length(AHandles);
  if vLength < 2 then
  begin
    SetLength(AHandles, vLength + 2);
    I := 0;
    while vLength > 0 do
    begin
      AHandles[2 + I] := AHandles[I];
      Inc(I);
      Dec(vLength);
    end;
  end;
  AHandles[0] := CreateDWGHandle(OwnerHandle, cntDWGObjHandleSoftPointer);
  AHandles[1] := CreateDWGHandle(XDiObjHandle, cntDWGObjHandleHardOwner);
end;

procedure TsgCADtoDWG.AddXRecords(const ABits: TsgDWGBits;
  XRecordConv: Boolean; const XRecords: TsgCADExtendedData);
var
  I: Integer;
  vInt64: Int64;
begin
  for I := 0 to XRecords.DataCount - 1 do
  begin
    if XRecordConv then
      ABits.WriteRC(Byte(XRecords.DataCode[I]))
    else
      ABits.WriteRS(Word(XRecords.DataCode[I]));
    case XRecords.DataType[I] of
      edtByte: ABits.WriteRC(XRecords.DataByte[I]);
      edtInt16: ABits.WriteRS(XRecords.DataInt16[I]);
      edtInt: ABits.WriteRL(XRecords.DataInt[I]);
      edtInt64:
        begin
          vInt64 := XRecords.DataInt64[I];
          ABits.WriteBytes(@vInt64, 8, True);
        end;
      edtSingle: ABits.WriteRD(XRecords.DataSingle[I]);
      edtDouble: ABits.WriteRD(XRecords.DataDouble[I]);
      edtString: ABits.WriteXRecordText(XRecords.DataString[I], FCodePage,
        XRecordConv);
      edtF2DPoint: ABits.Write2RD(XRecords.DataPoint2D[I]);
      edtF3DPoint:  ABits.Write3RD(XRecords.DataPoint[I]);
    end;
  end;
end;

function TsgCADtoDWG.GetBitSizePos(DWGCode: Word): Cardinal;
var
  vBits: TsgDWGBits;
begin
  vBits := TsgDWGBits.Create;
  try
    Result := vBits.WriteOT(DWGCode);
  finally
    vBits.Free;
  end;
end;

function TsgCADtoDWG.CheckEntHandle(AEntity: TsgDXFEntity; ADoRaise: Boolean = True): Boolean;
begin
  Result := False;
  if AEntity = nil then Exit;
  Result := AEntity.Handle <> cnstBadHandle;
  if (not Result) and ADoRaise then
    raise EDWGExportError.Create(sHandleInvalid);
end;

procedure TsgCADtoDWG.Clear;
  procedure ClearCreatedElements(const Elements: TsgDWGCreatedElements);
  var
    I: Integer;
    vItem: TsgDWGCreatedElement;
  begin
    for I := 0 to Elements.Count - 1 do
    begin
      vItem := Elements.Element[I];
      vItem.Obj.Free;
      vItem.Name := '';
      Finalize(vItem.Handles);
    end;
    Elements.Clear;
  end;
var
  I: Integer;
  vLayout: TsgDXFLayout;
begin
  inherited Clear;
  for I := 0 to FSections.Count - 1 do
    TMemoryStream(FSections[I]).Clear;
  FClasses.Clear;
  ClearCreatedElements(FCreatedElements);
  ClearCreatedElements(FObjectsMap);
  FModelSpaceHandle := cnstBadHandle;
  FPaperSpaceHandle := cnstBadHandle;
  FACADXDataAppID := cnstBadHandle;
  FXDataAppID := cnstBadHandle;
  FCreatedEndBlk.Clear;
  FCreatedSeqEnd.Clear;
  for I := 0 to FEntitiesWithAddedHandles.Count - 1 do
    TsgDXFEntity(FEntitiesWithAddedHandles[I]).Handle := cnstBadHandle;
  FEntitiesWithAddedHandles.Clear;
  if FAddedViewPort <> nil then
  begin
    vLayout := GetPaperLayout;
    if vLayout <> nil then
      vLayout.PaperSpaceBlock.RemoveEntity(FAddedViewPort);
    FAddedViewPort.Free;
  end;
  FAddedViewPort := nil;
end;

function TsgCADtoDWG.ConvertEEDToDWG(E: TsgDXFEntity; Source, Dest: TsgCADExtendedData;
  var EEDHandle: UInt64): Boolean;
var
  I: Integer;
  vAppID, S, vBlockName: string;
  vBlockRecord: TsgDXFBlockRecord;
  vBlock: TsgDXFBlock;
  vBlockRecordHandle: UInt64;
begin
  Result := False;
//  if IsEntityHasNotEED(E) then Exit; //IsEntityHasNotEED calls AddCommonEntityData calling here is duplicated code
  EEDHandle := cnstBadHandle;
  if (Source = nil) or (Dest = nil) then Exit;
  Dest.AssignData(Source);
  if Dest.DataCount = 0 then Exit;
  if Dest.DataCode[0] <> String_1001 then
    Exit
  else
  begin
    vAppID := Source.DataString[0];
    if SameText(vAppID, sACADXDataAppName) then
      EEDHandle := FACADXDataAppID
    else
      EEDHandle := FXDataAppID;
    Dest.Delete(0);
  end;
  for I := Dest.DataCount - 1 downto 0 do
  begin
    case Dest.DataType[I] of
      edtObject:
        begin
          Dest.Delete(I);
          Continue;
        end;
    end;
    Dest.DataCode[I] := Dest.DataCode[I] - 1000;
    case Dest.DataCode[I] of
      2:
        begin
          if Dest.DataType[I] = edtString then
          begin
            S := Dest.DataString[I];
            Dest.ChangeType(I, edtByte);
            if S = '{' then
              Dest.DataByte[I] := 0
            else
             Dest.DataByte[I] := 1;
          end;
        end;
      5:
        begin
          if Dest.DataType[I] = edtInt64 then
          begin
            vBlockRecordHandle := Dest.DataInt64[I]; //change BlockRecord.Handle to Block.Handle
            vBlockRecord := TsgDXFBlockRecord(Converter.Sections[csBlockRecords].FindEntByHandle(vBlockRecordHandle));
            if vBlockRecord <> nil then
            begin
              vBlockName := vBlockRecord.Name;
              vBlock := TsgDXFBlock(Converter.Sections[csBlocks].FindEntByName(vBlockName));
              if vBlock <> nil then
                Dest.DataInt64[I] := vBlock.Handle;
            end;
          end;
        end;
    end;
  end;
  Result := Dest.DataCount > 0;
end;

function TsgCADtoDWG.CorrectLineWeight(const ALineWeight: Double;
  ANeedToConvert: Boolean): Integer;
begin
  if ANeedToConvert then
  begin
    Result := ConvertLineWeightToDWG(ALineWeight);
//    if ALineWeight < 0 then
//      Result := 29;
  end
  else
  begin
    if ALineWeight < 0 then
      Result := Trunc(ALineWeight)
    else
      Result := Trunc(ALineWeight) * 100;
  end;
end;

constructor TsgCADtoDWG.Create(ACADImage: TsgCADImage);
var
  I: Integer;
begin
  FScalesDictionary := TStringList.Create;
  FVariableDictionary := TStringList.Create;
  inherited Create(ACADImage);
  FClasses := TStringList.Create;
  FClasses.Sorted := True;
  FClasses.Duplicates := dupError;
  FMaintenanceVersion := 6;
  FSections := TList.Create;
  for I := 0 to GetSectionsCount - 1 do
    FSections.Add(TMemoryStream.Create);
  FObjectsMap := TsgDWGCreatedElements.Create;
  FObjectsMap.FindBeforeAdd := False;
  FCreatedElements := TsgDWGCreatedElements.Create;
  FCreatedEndBlk := TsgUInt64Pairs.Create;
  FCreatedSeqEnd := TsgUInt64Pairs.Create;
  FDWGCodePage := sgDWGCodePageFromCP({CP_ACP}Converter.HeadVarStruct.CodePage, True);
  FCodePage := sgCodePageFromDWG(FDWGCodePage);
  FEntitiesWithAddedHandles := TList.Create;
  FSGInserts := TList.Create;
end;

procedure TsgCADtoDWG.CreateDictionaryListByStrList(const DictionaryName: string;
  DWGCode: Word; AList: TStringList);
var
  I, vIndex: Integer;
  vElem: TsgDWGCreatedElement;
begin
  vIndex := FCreatedElements.IndexOf(DictionaryName);
  vElem := FCreatedElements[vIndex];
  for I := 0 to AList.Count - 1 do
    AddCreatedElem(AList.Values[AList.Names[I]], nil, FCreatedElements,
      DWGCode, cnstBadHandle, cnstBadHandle);
end;

procedure TsgCADtoDWG.CreateTablesRecord;
var
  vOwnerDictHandle: UInt64;
  I, J, vIndex: Integer;
  vPaperSpace: TsgDXFLayout;
  vHasViewPort: Boolean;
  vViewPortsCount: Integer;
  vViewport: TsgDXFViewport;
  vRasterVariables: TsgCADRasterVariables;

  procedure AddPenTable(const AName: string; DWGCode: Word);
  begin
    AddCreatedElem(AName, TsgDXFPenTableItem, FCreatedElements, DWGCode);
  end;

  function AddDictionary(const AName: string; const Handle: Uint64 = cnstBadHandle): Integer;
  begin
    Result := AddCreatedElem(AName, TsgDXFDictionary, FCreatedElements,
      cntDWGObjCodeDICTIONARY1, Handle, vOwnerDictHandle);
    if AName = sNamedObjectsDictionary then
      vOwnerDictHandle := FCreatedElements[Result].Handle;
  end;

  procedure CreateVieportEntHeaderHandles(const CreatedIndex, ViewPortEntIndex: Integer);
  var
    vElem: PsgDWGCreatedElement;
  begin
    if CreatedIndex >= 0 then
    begin
      vElem := FCreatedElements.GetPtrElement(CreatedIndex);
      SetLength(vElem.Handles, 5);
      vElem.Handles[0] := CreateDWGHandle(GetViewPortEntityHeaderControlObjectHandle,
        cntDWGObjHandleSoftPointer);// viewport entity control (soft pointer)
      vElem^.Handles[1] := CreateDWGHandle(cnstBadHandle, cntDWGObjHandleHardOwner);// xdicobjhandle (hard owner)
      vElem^.Handles[2] := CreateDWGHandle(cnstBadHandle, cntDWGObjHandleHardPointer);// External reference block handle (hard pointer)
      vElem^.Handles[3] := CreateDWGHandle(cnstBadHandle, cntDWGObjHandleSoftPointer);// Corresponding viewport entity (soft owner)
      vElem^.Handles[4] := CreateDWGHandle(cnstBadHandle, cntDWGObjHandleHardPointer);// next ViewPortEnt handle hard pointer
    end
    else
      vElem := nil;
    case ViewPortEntIndex of
      0..MaxInt:
        vElem^.Handles[3].Handle := vElem.OwnerHandle;
//      -1:
//        begin
//          vCount := FCreatedElements.CountOf(Word(cntDWGObjCodeVPENTHDR), vIndex);
//          if vCount > 1 then
//          begin
//            vIndex := FCreatedElements.IndexOf(vFirstViewPortEntHnd);
//            for I := vIndex + 1 to vIndex + vCount - 1 do
//            begin
//              vElem := FCreatedElements.GetPtrElement(I);
//              vElem^.Handles[4].Handle := FCreatedElements[I - 1].Handle;
//            end;
//          end;
//        end;
    end;
  end;

  function AddViewPortEntHnd(const Handle, OwnerHandle: UInt64; ThisID: Integer = -1): Integer;
  var
    vElem: PsgDWGCreatedElement;
  begin
    Result := AddCreatedElem('', nil, FCreatedElements, cntDWGObjCodeVPENTHDR,
      Handle, OwnerHandle);
    if ThisID = 1 then //location is ThisID
    begin
      vElem := FCreatedElements.GetPtrElement(Result);
      vElem^.Location := ThisID;
    end;
  end;

begin
  vOwnerDictHandle := cnstBadHandle;

  //Tables AppId, UCS, View, ViewPortEntityControl
  AddPenTable(sAppIDTableRecord, cntDWGObjCodeAPPIDCONTROLOBJ);
  AddPenTable(sUCSTableRecord, cntDWGObjCodeUCSCONTROLOBJ);
  AddPenTable(sViewTableRecord, cntDWGObjCodeVIEWCONTROLOBJ);
  AddPenTable(sViewPortEntityControl, cntDWGObjCodeVPENTHDRCTRLOBJ);

  vRasterVariables := TsgCADRasterVariables(ExportCADImage.Converter.Sections[csObjects].FindEntByName(sRasterVariables));
  //Dictionaries
  for I := Low(cnstDWGDictionaries) to High(cnstDWGDictionaries) do
  begin
    if SameText(cnstDWGDictionaries[I], sAcadImageVars) then
    begin
      if Assigned(vRasterVariables) then
        AddDictionary(cnstDWGDictionaries[I], vRasterVariables.Handle);
    end
    else
      AddDictionary(cnstDWGDictionaries[I]);
  end;


  vPaperSpace := GetPaperLayout;
  //Paper space Layout, only if GetPaperLayout = nil
  if vPaperSpace = nil then
    AddCreatedElem(sLayout + '1', nil, FCreatedElements, cntDWGObjCodeLAYOUT,
      cnstBadHandle);

  //View entity headers
  for I := 1 to Converter.LayoutsCount - 1 do
  begin
    vPaperSpace := Converter.Layouts[I];
    if vPaperSpace <> nil then
    begin
      vHasViewPort := False;
      vViewPortsCount := 0;
      //vFirstViewPortEntHnd := cnstBadHandle;
      for J := 0 to vPaperSpace.PaperSpaceBlock.Count - 1 do
      begin
        if vPaperSpace.PaperSpaceBlock.Entities[J] is TsgDXFViewport then
        begin
          Inc(vViewPortsCount);
          vViewport := TsgDXFViewport(vPaperSpace.PaperSpaceBlock.Entities[J]);
          if vViewport.ThisID = 1 then
          begin
            vIndex := AddViewPortEntHnd(DoHandle, vViewport.Handle, vViewport.ThisID);
            CreateVieportEntHeaderHandles(vIndex, 0);
            vHasViewPort := True;
          end;
          Break;
        end;
      end;
      if (vViewPortsCount > 0) and (not vHasViewPort) and (GetPaperLayout = vPaperSpace) then //only for *PAPER_SPACE
      begin
        FAddedViewPort := CreateViewPortAsACADWindow(vPaperSpace, DoHandle);
        vPaperSpace.PaperSpaceBlock.AddEntity(FAddedViewPort);
        vIndex := AddViewPortEntHnd(DoHandle, FAddedViewPort.Handle, FAddedViewPort.ThisID);
        CreateVieportEntHeaderHandles(vIndex, 0);
      end;
    end;
  end;
end;

destructor TsgCADtoDWG.Destroy;
var
  I: Integer;
begin
  Clear;
  ClearList(FSections, True);
  FSections.Free;
  FClasses.Free;
  FObjectsMap.Free;
  FCreatedElements.Free;
  FCreatedEndBlk.Free;
  FCreatedSeqEnd.Free;
  for I := 0 to FScalesDictionary.Count - 1 do
    Dispose(PsgDWGScale(FScalesDictionary.Objects[I]));
  FScalesDictionary.Free;
  FVariableDictionary.Free;
  FEntitiesWithAddedHandles.Free;
  FreeListOfList(FSGInserts);
  inherited Destroy;
end;

const
  sDWGEntityCodes: array[TsgCADEntities] of Word = (cntDWGObjCodeUNSUSED, cntDWGObjCodePOINT,
    cntDWGObjCodeLINE, cntDWGObjCodeSOLID, cntDWGObjCodeTRACE, cntDWGObjCodeCIRCLE,
    cntDWGObjCodeARC, cntDWGObjCodeELLIPSE, cntDWGObjCodeUNSUSED, cntDWGObjCodeLWPOLYLINE,
    cntDWGObjCodeSPLINE, cntDWGObjCodeSPLINE, cntDWGObjCodeLEADER, cntDWGObjCodeINSERT,
    cntDWGObjCodeUNSUSED, cntDWGObjCodeTOLERANCE, cntDWGObjCodeMTEXT, cntDWGObjCodeSHAPE,
    cntDWGObjCodeTEXT, cntDWGObjCodeATTDEF, cntDWGObjCodeATTRIB, cntDWGObjCode3DFACE,
    cntDWGObjCodeIMAGE, cntDWGObjCodeVIEWPORT, cntDWGObjCodeREGION, cntDWGObjCodeBODY,
    cntDWGObjCode3DSOLID, cntDWGObjCodeUNSUSED, cntDWGObjCodeHATCH, cntDWGObjCodeOLE2FRAME,
    cntDWGObjCodeHATCH, cntDWGObjCodeHATCH, cntDWGObjCodeHATCH, cntDWGObjCodeHATCH,
    cntDWGObjCodeINSERT, cntDWGObjCodeLWPOLYLINE, cntDWGObjCodeFLATHATCH, cntDWGObjCodeUNSUSED,
    cntDWGObjCodePROXY, cntDWGObjCodeUNSUSED, cntDWGObjCodeWIPEOUT, cntDWGObjCodeMLINE,
    cntDWGObjCodeUNSUSED{$IFDEF SG_BTI}, cntDWGObjCodePOLYPOLYLINE2D{$ENDIF}, cntDWGObjCodeUNSUSED,
    cntDWGObjCodeUNSUSED, cntDWGObjCodeUNSUSED, cntDWGObjCode3DSOLID, cntDWGObjCode3DSOLID,
    cntDWGObjCode3DSOLID, cntDWGObjCodeLWPOLYLINE);


procedure TsgCADtoDWG.DoAfterAddEntHandlesData(const ObjHandle: UInt64;
  ABits: TsgDWGBits; AEntity: TsgDXFEntity; const AOwnerHandle: UInt64;
  DWGCode: Word; EntMode, LTypeFlags, PlotStyleFlags: Byte;
  const APrevEntHandle, ANextEntHandle: UInt64; AOwner: TsgDXFEntity;
  var Handles: TsgDWGHandleArray);

  procedure AddSeqEnd;
  begin
    FCreatedSeqEnd.ActivePairValue := apFirst;
    AddHandleToArray(CreateDWGHandle(FCreatedSeqEnd[FCreatedSeqEnd.IndexOf(AEntity.Handle)].Second, cntDWGObjHandleHardOwner), Handles);
  end;

var
  I, vIndex: Integer;
  vEnt: TsgDXFEntity;
  vHandle: UInt64;

begin
  if AEntity <> nil then
  begin
    case DWGCode of
      cntDWGObjCodeSHAPE:
        begin
          if Assigned(TsgDXFText(AEntity).Style) then
            vHandle := TsgDXFText(AEntity).Style.Handle
          else
            vHandle := GetEntityHandle(Converter.StyleByName(sStandardName));
          AddHandleToArray(CreateDWGHandle(vHandle, cntDWGObjHandleHardPointer), Handles);
        end;
      cntDWGObjCodeATTRIB, cntDWGObjCodeATTDEF, cntDWGObjCodeTEXT:
        AddHandleToArray(CreateDWGHandle(GetStyleHandle(TsgDXFText(AEntity).Style, False),
          cntDWGObjHandleHardPointer), Handles);
      cntDWGObjCodeMTEXT:
        AddHandleToArray(CreateDWGHandle(GetStyleHandle(TsgDXFMText(AEntity).Style, False),
          cntDWGObjHandleHardPointer), Handles);
      cntDWGObjCodePOLYLINE2D, cntDWGObjCodePOLYLINEMESH,
      cntDWGObjCodePOLYLINEPFACE, cntDWGObjCodePOLYLINE3D:
        begin
          if Version < acR2004 then
          begin
            AddHandleToArray(CreateDWGHandle(AEntity.Entities[0].Handle, cntDWGObjHandleSoftPointer), Handles);
            AddHandleToArray(CreateDWGHandle(AEntity.Entities[AEntity.Count - 1].Handle, cntDWGObjHandleSoftPointer), Handles);
          end
          else
            for I := 0 to AEntity.Count - 1 do
              AddHandleToArray(CreateDWGHandle(AEntity.Entities[I].Handle, cntDWGObjHandleHardOwner), Handles);
          AddSeqEnd;
        end;
      cntDWGObjCodeINSERT, cntDWGObjCodeMINSERT1:
        begin
          if TsgDXFInsert(AEntity).Block <> nil then
            vEnt := TsgDXFInsert(AEntity).Block
          else
            vEnt := nil;
          AddHandleToArray(CreateDWGHandle(GetEntityHandle(vEnt), cntDWGObjHandleHardPointer), Handles);
          if Version < acR2004 then
          begin
            if TsgDXFInsert(AEntity).HasAttribs then
            begin
              AddHandleToArray(CreateDWGHandle(TsgDXFAttrib(TsgDXFInsert(AEntity).Attribs[0]).Handle, cntDWGObjHandleSoftPointer), Handles);
              AddHandleToArray(CreateDWGHandle(TsgDXFAttrib(TsgDXFInsert(AEntity).Attribs[TsgDXFInsert(AEntity).Attribs.Count - 1]).Handle, cntDWGObjHandleSoftPointer), Handles);
            end
          end
          else
          begin
            for I := 0 to TsgDXFInsert(AEntity).Attribs.Count - 1 do
              AddHandleToArray(CreateDWGHandle(TsgDXFAttrib(TsgDXFInsert(AEntity).Attribs[I]).Handle, cntDWGObjHandleSoftPointer), Handles);
          end;
          if TsgDXFInsert(AEntity).HasAttribs then
            AddSeqEnd;
        end;
      cntDWGObjCodeTOLERANCE:
        AddHandleToArray(CreateDWGHandle(GetStyleHandle(TsgDXFTolerance(AEntity).DimStyle, True),
          cntDWGObjHandleHardPointer), Handles);
      cntDWGObjCodeLEADER:
        begin
          AddHandleToArray(CreateDWGHandle(cnstBadHandle, cntDWGObjHandleHardPointer), Handles);
          AddHandleToArray(CreateDWGHandle(GetStyleHandle(TsgDXFLeader(AEntity).DimStyle, True),
            cntDWGObjHandleHardPointer), Handles);
        end;
      cntDWGObjCodeDIMENSIONALIGNED, cntDWGObjCodeDIMENSIONLINEAR,
      cntDWGObjCodeDIMENSIONANG2Ln, cntDWGObjCodeDIMENSIONRADIUS,
      cntDWGObjCodeDIMENSIONDIAMETER:
        begin
          AddHandleToArray(CreateDWGHandle(GetStyleHandle(TsgDXFDimension(AEntity).Style, True),
            cntDWGObjHandleHardPointer), Handles);
          AddHandleToArray(CreateDWGHandle(TsgDXFDimension(AEntity).Block.Handle,
            cntDWGObjHandleHardPointer), Handles);
        end;
      cntDWGObjCodeVIEWPORT:
        begin
          if Assigned(TsgDXFViewport(AEntity).FrozenLayers) then
            for I := 0 to TsgDXFViewport(AEntity).FrozenLayers.Count - 1 do // FrozenLayers
              if Version = acR2000 then
                AddHandleToArray(CreateDWGHandle(TsgDXFViewport(AEntity).FrozenLayers[I],
                  cntDWGObjHandleHardPointer), Handles)
              else
                AddHandleToArray(CreateDWGHandle(TsgDXFViewport(AEntity).FrozenLayers[I],
                  cntDWGObjHandleSoftPointer), Handles);
          AddHandleToArray(CreateDWGHandle(GetEntityHandle(TsgDXFViewport(AEntity).GetBoundary(Converter)), cntDWGObjHandleHardPointer), Handles); //Clip boundary handle (soft pointer) checked files shows (hard pointer)
          if Version = acR2000 then
          begin
            vHandle := cnstBadHandle;
            vIndex := FCreatedElements.IndexOf(AEntity.Handle, True);
            if vIndex >= 0 then
              vHandle := FCreatedElements[vIndex].Handle;
           AddHandleToArray(CreateDWGHandle(vHandle, cntDWGObjHandleHardPointer), Handles); // VIEWPORT ENT HEADER ((hard pointer))
          end;
          AddHandleToArray(CreateDWGHandle(cnstBadHandle, cntDWGObjHandleHardPointer), Handles); // H 345 Named UCS Handle (hard pointer)
          AddHandleToArray(CreateDWGHandle(cnstBadHandle, cntDWGObjHandleHardPointer), Handles); // H 346 Base UCS Handle (hard pointer)
          if Version >= acR2007 then
          begin
            AddHandleToArray(CreateDWGHandle(cnstBadHandle, cntDWGObjHandleSoftPointer), Handles); // H 332 Background (soft pointer)
            AddHandleToArray(CreateDWGHandle(cnstBadHandle, cntDWGObjHandleHardPointer), Handles); // H 348 Visual Style (hard pointer)
            AddHandleToArray(CreateDWGHandle(cnstBadHandle, cntDWGObjHandleSoftPointer), Handles); // H 333 Shadeplot ID (soft pointer)
            AddHandleToArray(CreateDWGHandle(cnstBadHandle, cntDWGObjHandleHardOwner), Handles); // H 361 Sun (hard owner)
          end;
        end;
      cntDWGObjCodeWIPEOUT, cntDWGObjCodeIMAGE:
        begin
          AddHandleToArray(CreateDWGHandle(GetImageDefHandle(TsgCADWipeout(AEntity)), cntDWGObjHandleHardPointer), Handles); // H imagedef (hard pointer)
          AddHandleToArray(CreateDWGHandle(cnstBadHandle, cntDWGObjHandleHardOwner), Handles); // H imagedefreactor (hard owner)
        end;
      cntDWGObjCodeMLINE:
        AddHandleToArray(CreateDWGHandle(GetEntityHandle(TsgCADMLine(AEntity).Style), cntDWGObjHandleHardPointer), Handles); // mline style oject handle (hard pointer)
    end;
  end;
end;

procedure TsgCADtoDWG.DoBeforeAddCommonEntData(ABits: TsgDWGBits; var Handle: UInt64;
  var E: TsgDXFEntity; var DWGCode: Word; OwnerDWGCode: Word; AOwner: TsgDXFEntity);
var
  vIndex: Integer;
  vPLine: TsgDXFPolyline;

  function Check2DPolyline: Boolean;
  var
    I: Integer;
    vVertex: TsgDXFVertex;
  begin
    Result := (vPLine.Flags and 8 = 0) or (not IsZero(vPLine.GlobalWidth)) or
      (not IsZero(vPLine.StartWidth)) or (not IsZero(vPLine.EndWidth)); //!!! maybe ZThick
    if not Result then
    begin
      for I := 0 to vPLine.Count do
      begin
        vVertex := TsgDXFVertex(vPLine.Entities[I]);
        if (not IsZero(vVertex.StartWidth)) or (not IsZero(vVertex.EndWidth)) or (not IsZero(vVertex.Bulge)) then //!!! maybe check Point.Z
        begin
          Result := True;
          Break;
        end;
      end;
    end;
  end;

  procedure ChangeToSeqEnd;
  begin
    DWGCode := cntDWGObjCodeSEQEND;
    Handle := FCreatedSeqEnd.Second[vIndex];
    E := AOwner;
  end;

  function CheckSeqEndAndChange: Boolean;
  begin
    FCreatedSeqEnd.ActivePairValue := apFirst;
    vIndex := FCreatedSeqEnd.IndexOf(E.Handle);
    if vIndex >= 0 then //SeqEnd
    begin
      ChangeToSeqEnd;
      Result := True;
    end
    else
    begin
      FCreatedSeqEnd.AddPair(E.Handle, DoHandle);
      Result := False;
    end;
  end;

begin
  if E is TsgDXFBlock then //ENDBLK
  begin
    FCreatedEndBlk.ActivePairValue := apFirst;
    vIndex := FCreatedEndBlk.IndexOf(E.Handle);
    DoError(vIndex < 0, sCannotFindBlock, [E.Handle]);
    Handle := FCreatedEndBlk[vIndex].Second;
    DWGCode := cntDWGObjCodeENDBLK;
    E := nil;
    Exit;
  end;
  if E is TsgDXFPolyline then
  begin
    vPLine := TsgDXFPolyline(E);
    case E.EntType of
      cePolyline:
        begin
          if vPLine.IsPolygonMesh then
            DWGCode := cntDWGObjCodePOLYLINEMESH
          else
            if vPLine.IsPolyFaceMesh then
              DWGCode := cntDWGObjCodePOLYLINEPFACE
            else
              if TsgDXFPolylineAccess(vPLine).Is3dPolyline then
                DWGCode := cntDWGObjCodePOLYLINE3D
              else
                DWGCode := cntDWGObjCodePOLYLINE2D;
        end;
      ceLWPolyline:
        DWGCode := cntDWGObjCodeLWPOLYLINE;
    else
      DWGCode := cntDWGObjCodePOLYLINE3D;
    end;
    if DWGCode <> cntDWGObjCodeLWPOLYLINE then
      CheckSeqEndAndChange;
    Exit;
  end;
  if E is TsgDXFVertex then
  begin
    case OwnerDWGCode of
      cntDWGObjCodePOLYLINE2D:
        DWGCode := cntDWGObjCodeVERTEX2D;//2D Vertex
      cntDWGObjCodePOLYLINE3D:
        DWGCode := cntDWGObjCodeVERTEX3D;//3D Vertex
      cntDWGObjCodePOLYLINEMESH:
        DWGCode := cntDWGObjCodeVERTEXMESH;
      else
        DWGCode := cntDWGObjCodeVERTEXPFACE;
    end;
    if TsgDXFVertexEx(E).FPolyFaceIndexes <> nil then
      DWGCode := cntDWGObjCodeVERTEXPFACEFACE;
    E := AOwner;
    Exit;
  end;
  if E.EntType = ceInsert then
  begin
    if TsgDXFInsert(E).HasAttribs then
      if CheckSeqEndAndChange then Exit;
    if E.ClassType = TsgCADMInsert then
      DWGCode := cntDWGObjCodeMINSERT1;
  end;
  if E is TsgDXFDimension then
  begin
    DWGCode := cntDWGObjCodeDIMENSIONLINEAR;
//    case DimSubclassNum(TsgDXFDimension(E).Flags) of //for future versions
//      1: DWGCode := cntDWGObjCodeDIMENSIONALIGNED;
//      2: DWGCode := cntDWGObjCodeDIMENSIONANG2Ln;
//      3: DWGCode := cntDWGObjCodeDIMENSIONDIAMETER;
//      4: DWGCode := cntDWGObjCodeDIMENSIONRADIUS;
//      5: DWGCode := cntDWGObjCodeDIMENSIONANG3Pt;
//      6: DWGCode := cntDWGObjCodeDIMENSIONORDINATE;
//    else
//      DWGCode := cntDWGObjCodeDIMENSIONLINEAR;
//    end;
    Exit;
  end;
  if E is TsgCADPolyPolygon then
  begin
    case E.EntType of
      ceMPolygon: DWGCode := cntDWGObjCodeMPOLYGON;
    else
      DWGCode := cntDWGObjCodeHATCH;
    end;
    Exit;
  end;
  if E.EntType = ceImageEnt then
  begin
    case GetExportImageIndex(TsgDXFImageEnt(E), ExportImageFileIndex) of
      cntImageExportAsImage:
        DWGCode := cntDWGObjCodeIMAGE;
      cntImageExportAsOLE2Frame:
        DWGCode := cntDWGObjCodeOLE2FRAME;
      cntImageExportAsFile:
        DWGCode := cntDWGObjCodeIMAGEBYFILE;
    end;
    Exit;
  end;
end;

procedure TsgCADtoDWG.DoExport(const E: TsgDXFEntity; const Data: PsgDirectExportData = nil;
  const AIsTempObject: Boolean = False);
var
  vBits: TsgDWGBits;
  vCode: Word;
  vLTypeFlags, vPlotStyeFlags: Byte;
  vHandle: UInt64;
  vEnt: TsgDXFEntity;
  vExportData: TsgDWGExportDataClass;
  vColorCadOld: TsgColorCAD;

  function GetImageDef(I: TsgDXFImageEntAccess): TsgDXFImageDef;
  begin
    if I.ImageDefExport <> nil then
      Result := I.ImageDefExport
    else
      Result := I.ImageDef;
  end;

begin

  vBits := TsgDWGBits.Create;
  vExportData := nil;
  try
    vCode := sDWGEntityCodes[E.EntType];
    if ((vCode = cntDWGObjCodeUNSUSED) and (Data.EntDWGCode <> cntDWGObjCodeUNSUSED)) or Data.UseEntCode then
      vCode := Data.EntDWGCode;
    vHandle := E.Handle;
    vEnt := E;
    DoBeforeAddCommonEntData(vBits, vHandle, vEnt, vCode, Data.OwnerDWGCode, Data.Owner);
    if Data.UseEntCode then
      vCode := Data.EntDWGCode;
    if vCode = cntDWGObjCodeUNSUSED then
      vCode := cntDWGObjCodeUNKNOWNOBJ;//all unknown objects will be exported as cntDWGObjCodePOINT see GetRealDWGCode
    try
      case vCode of
        cntDWGObjCodeWIPEOUT, cntDWGObjCodeIMAGE, cntDWGObjCodeIMAGEBYFILE:
        begin
          if IsNeedImageDefHandle(TsgCADWipeOut(vEnt)) and Assigned(TsgDXFImageEntAccess(vEnt).ImageDefExport) then
          begin
            vColorCadOld := vEnt.ColorCAD;
            vEnt.ColorCAD := cnstColorCADByBlackWhite;
          end;
        end;
      end;
      AddCommonEntityData(vHandle, vCode, vBits, 0, vEnt, Data.EntMode, @vLTypeFlags, @vPlotStyeFlags);
    finally
      case vCode of
        cntDWGObjCodeWIPEOUT, cntDWGObjCodeIMAGE, cntDWGObjCodeIMAGEBYFILE:
        begin
          if IsNeedImageDefHandle(TsgCADWipeOut(vEnt)) and Assigned(TsgDXFImageEntAccess(vEnt).ImageDefExport) then
            vEnt.ColorCAD := vColorCadOld;
        end;
      end;
    end;
    case vCode of
      cntDWGObjCodeSEQEND:
        ExportSeqEnd(nil, vBits);
      cntDWGObjCodeLINE:
        ExportLine(TsgDXFLine(E), vBits);
      cntDWGObjCodePOINT:
        ExportPoint(TsgDXFPoint(E), vBits);
      cntDWGObjCodeSOLID, cntDWGObjCodeTRACE:
        ExportSolid(TsgDXFSolid(E), vBits);
      cntDWGObjCodeCIRCLE, cntDWGObjCodeARC:
        ExportCircle(TsgDXFCircle(E), vBits);
      cntDWGObjCodePOLYLINEMESH, cntDWGObjCodePOLYLINEPFACE,
      cntDWGObjCodePOLYLINE2D, cntDWGObjCodePOLYLINE3D:
        ExportPolyline(TsgDXFPolyline(E), vCode, vBits, AIsTempObject);
      cntDWGObjCodeLWPOLYLINE:
        begin
          case E.EntType of
            ceFlatPoly, ceFlatPoly3D:
              begin
                ExportFlatPoly(TsgFlatPoly(E), Data^);
                Exit; //TsgFlatPoly is not exported, only members of the FlatPoly.Group property
              end;
          else
            ExportLWPolyline(TsgDXFLWPolyline(E), vBits);
          end;
        end;
      cntDWGObjCodeINSERT, cntDWGObjCodeMINSERT1:
        begin
          if (TsgDXFInsert(E).Block <> nil) and IsNameInternal(TsgDXFInsert(E).Block.Name) then
          begin
            ExportUnknownObject(E, Data^);
            Exit;
          end
          else
            ExportInsert(TsgDXFInsert(E), vBits, nil);
        end;
      cntDWGObjCodeSPLINE:
        ExportSpline(TsgDXFSpline(E), vBits);
      cntDWGObjCodeATTRIB, cntDWGObjCodeATTDEF, cntDWGObjCodeTEXT:
        ExportText(TsgDXFText(E), vBits);
      cntDWGObjCodeSHAPE:
        ExportShape(TsgDXFShape(E), vBits);
      cntDWGObjCodeOLE2FRAME:
      begin
        vExportData := TsgDWGExportDataClass.CreateEx(vBits, E, TsgDXFImageEntAccess(E).GroupGet,
          Data^);
        case E.EntType of
          ceImageEnt:
            begin
              if not TsgDXFImageEntAccess(E).GroupExists then
              begin
                vExportData.Bits := nil;
                ExportImageEntAsOle(TsgDXFImageEnt(E), ExportOle2Frame,
                  vExportData, True);
              end
              else
              begin
                ExportImageEntAsOle(TsgDXFImageEnt(E), ExportOle2FrameCreateOleGroup,
                  vExportData, True);
                if not ExportGroup(E, cntDWGObjCodePOLYLINE3D, Data^) then
                  ExportUnknownObject(E, Data^);
              end;
              Exit;
            end
        else
          ExportOle2Frame(TsgDXFOle2Frame(E), vExportData);
        end;
      end;
      cntDWGObjCodeVERTEX2D, cntDWGObjCodeVERTEX3D, cntDWGObjCodeVERTEXMESH,
      cntDWGObjCodeVERTEXPFACE, cntDWGObjCodeVERTEXPFACEFACE:
        ExportVertex(Data.Owner, TsgDXFVertex(E), vCode, vBits);
      cntDWGObjCodeMTEXT:
        ExportMText(TsgDXFMText(E), vBits);
      cntDWGObjCodeTOLERANCE:
        ExportTolerance(TsgDXFTolerance(E), vBits);
      cntDWGObjCode3DFACE:
        Export3DFace(TsgDXF3dFace(E), vBits);
      cntDWGObjCodeELLIPSE:
        ExportEllipse(TsgDXFEllipse(E), vBits);
      cntDWGObjCodeLEADER:
        ExportLeader(TsgDXFLeader(E), vBits);
      cntDWGObjCodeDIMENSIONORDINATE, cntDWGObjCodeDIMENSIONANG3Pt,
      cntDWGObjCodeDIMENSIONALIGNED, cntDWGObjCodeDIMENSIONLINEAR,
      cntDWGObjCodeDIMENSIONANG2Ln, cntDWGObjCodeDIMENSIONRADIUS,
      cntDWGObjCodeDIMENSIONDIAMETER:
        ExportDimension(TsgDXFDimension(E), vBits, vCode);
      cntDWGObjCodeHATCH, cntDWGObjCodeMPOLYGON:
        begin
          if E is TsgCADFill then
          begin
            ExportCADFill(TsgCADFill(E), Data^);
            Exit;
          end
          else
            ExportHatch(TsgCADPolyPolygon(E), vBits, vCode);
        end;
      cntDWGObjCodeVIEWPORT:
        ExportViewPort(TsgDXFViewPort(E), vBits);
      cntDWGObjCodeWIPEOUT, cntDWGObjCodeIMAGE:
        begin
          ExportWipeOut(TsgCADWipeOut(E), vBits);
          if IsNeedImageDefHandle(TsgCADWipeOut(E)) then
            ProcImageDef(GetImageDef(TsgDXFImageEntAccess(E)));
        end;
      cntDWGObjCodeIMAGEBYFILE:
        begin
          vExportData := TsgDWGExportDataClass.CreateEx(nil, E, nil, Data^);
          ExportImageEntAsExternalFile(TsgDXFImageEnt(E), DoHandle,
            ExportWipeOutAsExternalFile, vExportData);
//          TsgDXFImageEntAccess(E).ImageDefExport := nil; see TsgDXFImageEntAccess.Destroy ImageDefExport clears its destructor
          Exit;
        end;
      cntDWGObjCodeREGION, cntDWGObjCode3DSOLID, cntDWGObjCodeBODY,
      cntDWGObjCodePROXY, cntDWGObjCodeFLATHATCH:
        begin
          if not ExportGroup(E, cntDWGObjCodePOLYLINE3D, Data^) then
            ExportUnknownObject(E, Data^);
           Exit;
        end;
    {$IFDEF SG_BTI}
      cntDWGObjCodePOLYPOLYLINE2D:
        begin
          ExportPolyPolyline2D(TsgCADPolyPolyline2D(E), Data^);
          Exit;
        end;
    {$ENDIF}
      cntDWGObjCodeUNKNOWNOBJ:
        begin
          ExportUnknownObject(E, Data^);
          Exit;
        end;
      cntDWGObjCodeMLINE:
         ExportMLine(TsgCADMLine(E), vBits, Data^);
      cntDWGObjCodeUNSUSED:
        Exit;
    end;
  //      ceACADTable:         ExportAcadTable(TsgDXFAcadTable(E));
  //
    AddCommonEntityHandleData(vHandle, vBits, E, Data.OwnerHandle, vCode,
      Data.EntMode, vLTypeFlags, vPlotStyeFlags, True, Data.PrevEntHandle,
      Data.NextEntHandle, Data.Owner);
  finally
    vBits.Free;
    vExportData.Free;
  end;
end;

procedure TsgCADtoDWG.ProcScale(const Handle, OwnerHandle: UInt64; const Index: Integer;
  const Name: string);
var
  vBits: TsgDWGBits;
  vScale: TsgDWGScale;
  vHandles: TsgDWGHandleArray;
  vCode: Word;
begin
  vBits := TsgDWGBits.Create;
  try
    vCode := GetDWGCodeByClass(cntClassDXFSCALE);
    AddCommonEntityData(Handle, vCode, vBits, 1);
    vScale := PsgDWGScale(FScalesDictionary.Objects[Index])^;
    vBits.WriteBS(0);
    vBits.WriteTV(Name, FCodePage);
    vBits.WriteBD(vScale.ScaleParam1);
    vBits.WriteBD(vScale.ScaleParam2);
    vBits.WriteBit(vScale.ScaleParam3);
    AddHandleToArray(CreateDWGHandle(OwnerHandle, cntDWGObjHandleSoftPointer), vHandles);
    AddHandleToArray(CreateDWGHandle(OwnerHandle, cntDWGObjHandleSoftPointer), vHandles);
    AddHandleToArray(CreateDWGHandle(cnstBadHandle, cntDWGObjHandleHardOwner), vHandles);
    AddHandlesUpdateAndFinish(vBits, vHandles, Handle, vCode);
  finally
    vBits.Free;
  end;
end;

procedure TsgCADtoDWG.ExportSectionAuxHeader(const HandsSeed: UInt64;
  const ADateCreate, ADateUpdate: TDateTime);
var
  vBits: TsgDWGBits;
  vNumSaves: Cardinal;
  vNumSaves1, vNumSaves2: Word;
  vHandSeed: Cardinal;

  procedure WriteVersion;
  begin
    vBits.WriteRS(arDWGVersions[Version]);
    vBits.WriteRS(FMaintenanceVersion);
  end;

begin
  vBits := TsgDWGBits.Create;
  try
    vBits.WriteRC($FF);
    vBits.WriteRC($77);
    vBits.WriteRC(1);

    WriteVersion;

    vNumSaves := 1;
    vBits.WriteRL(vNumSaves);// number of saves
    vBits.WriteRL(Cardinal(-1));

    vNumSaves1 := 1;
    vNumSaves2 := 0;

    vBits.WriteRS(vNumSaves1); // number of saves part 1
    vBits.WriteRS(vNumSaves2); // number of saves part 2

    vBits.WriteRL0;

    WriteVersion;
    WriteVersion;

    vBits.WriteRS(5);
    vBits.WriteRS($893);
    vBits.WriteRS(5);
    vBits.WriteRS($893);
    vBits.WriteRS(0);
    vBits.WriteRS(1);
    vBits.WriteRL0;
    vBits.WriteRL0;
    vBits.WriteRL0;
    vBits.WriteRL0;
    vBits.WriteRL0;

    WriteDateTimeAsJulian(ADateCreate, vBits, True);
    WriteDateTimeAsJulian(ADateUpdate, vBits, True);

    if HandsSeed < $7fffffff then
      vHandSeed := HandsSeed
    else
      vHandSeed := Cardinal(-1);

    vBits.WriteRL(vHandSeed);
    vBits.WriteRL0;//RL : Educational plot stamp (default value is 0)
    vBits.WriteRS(0);
    vBits.WriteRS(vNumSaves1 - vNumSaves2);
    vBits.WriteRL0;
    vBits.WriteRL0;
    vBits.WriteRL0;
    vBits.WriteRL(vNumSaves);
    vBits.WriteRL0;
    vBits.WriteRL0;
    vBits.WriteRL0;
    vBits.WriteRL0;
    SaveSectionToStream(GetAuxHeaderSectionIndex, vBits, [], []);
  finally
    vBits.Free;
  end;
end;

procedure TsgCADtoDWG.ExportTableBLOCK_RECORD;
var
  vHandles: TsgInt64List;
begin
  vHandles := TsgInt64List.Create;
  try
    vHandles.Sorted := False;
    ProcBlock(nil, GetModelSpaceName, vHandles);
    ProcBlock(nil, GetPaperSpaceName, vHandles);
    ApplyBlocksByProc(ProcBlock, vHandles);
    ProcBlockControl(vHandles);
  finally
    vHandles.Free;
  end;
end;

procedure TsgCADtoDWG.ExportTableDIMSTYLE;
var
  I: Integer;
  vDimStyles: TsgDXFTable;
  vDimStyle: TsgDXFDimensionStyle;
  vProcHandles: TsgDWGHandleArray;
  vOwnerHandle: UInt64;
begin
  vDimStyle := nil;
  try
    vOwnerHandle := GetDimStyleControlObjectHandle;
    AddOwnerAndXDiObjHandle(vProcHandles);
    vDimStyles := TsgDXFTable(Converter.Sections[csDimStyles]);
    if (vDimStyles = nil) or (vDimStyles.FindEntByName(sStandardName) = nil) then
    begin
      vDimStyle := CreateDefaultDimStyle(DoHandle);
      ProcDimStyle(vOwnerHandle, vDimStyle, vProcHandles);
    end;
    if vDimStyles <> nil then
      for I := 0 to vDimStyles.Count - 1 do
        ProcDimStyle(vOwnerHandle, TsgDXFDimensionStyle(vDimStyles.Entities[I]),
          vProcHandles);
    ProcDimStylesControlObject(vOwnerHandle, vProcHandles);
  finally
    vDimStyle.Free;
  end;
end;

procedure TsgCADtoDWG.ExportSectionClasses;
var
  vBits: TsgDWGBits;
  vClassNum: Word;

  procedure WriteClassItem(const Ver, ItemClassID: Word; const AppName,
    CPlusPlusClassName, ClassDXFName: string);
  begin
    vBits.WriteBS(vClassNum);
    vBits.WriteBS(Ver);
    vBits.WriteTV(AppName, FCodePage);
    vBits.WriteTV(CPlusPlusClassName, FCodePage);
    vBits.WriteTV(ClassDXFName, FCodePage);
    vBits.WriteBit(0);//wasazombie
    vBits.WriteBS(ItemClassID);
    FClasses.AddObject(ClassDXFName, TObject(vClassNum));
    Inc(vClassNum);
  end;

begin
  vBits := TsgDWGBits.Create;
  try
    vBits.WriteRL(cntSizeTempValue); //size will be written later

    vClassNum := 500;
    WriteClassItem(127, cntItemClassIDEntity, cntAppNameISM, cntCPlusPlusClassNameRasterImage,
      cntClassDXFIMAGE);
    WriteClassItem(0, cntItemClassIDObject, cntAppNameISM, cntCPlusPlusClassNameRasterImageDef,
      cntClassDXFIMAGEDEF);
    WriteClassItem(127, cntItemClassIDEntity, cntAppNameWipeOutDWG, cntCPlusPlusClassNameWipeout,
      cntClassDXFWIPEOUT);
    WriteClassItem(0, cntItemClassIDObject, cntAppNameWipeOutDWG, cntCPlusPlusClassNameWipeoutVariables,
      cntClassDXFWIPEOUTVARIABLES);
    WriteClassItem(3071, cntItemClassIDEntity, cntAppNameAcMPolygonObj15DWG, cntCPlusPlusClassNameMPolygon,
      cntClassDXFMPOLYGON);
    if Converter.Counts[csTableStyles] > 0 then
    begin
      WriteClassItem(4095, cntItemClassIDObject, cntAppNameObjectDBX, cntCPlusPlusClassTableStyle,
        cntClassDXFTABLESTYLE);
      WriteClassItem(1025, cntItemClassIDEntity, cntAppNameObjectDBX, cntCPlusPlusClassTable,
        cntClassDXFACAD_TABLE);
      WriteClassItem(1152, cntItemClassIDObject, cntAppNameObjectDBX, cntCPlusPlusClassTableGeometry,
        cntClassDXFTABLEGEOMETRY);
      WriteClassItem(1152, cntItemClassIDObject, cntAppNameObjectDBX, cntCPlusPlusClassCellStyleMap,
        cntClassDXFCELLSTYLEMAP);
    end;
    WriteClassItem(1153, cntItemClassIDObject, cntAppNameObjectDBX, cntCPlusPlusClassScale,
      cntClassDXFSCALE);
    WriteClassItem(0, cntItemClassIDObject, cntAppNameObjectDBX, cntCPlusPlusClassDictionaryVar,
      cntClassDXFDICTIONARYVAR);
    WriteClassItem(0, cntItemClassIDObject, cntAppNameObjectDBX, cntCPlusPlusClassPlaceHolder,
      cntClassDXFACDBPLACEHOLDER);
    WriteClassItem(0, cntItemClassIDObject, cntAppNameObjectDBX, cntCPlusPlusClassLayout,
      cntClassDXFLAYOUT);
    WriteClassItem(0, cntItemClassIDObject, cntAppNameISM, cntCPlusPlusClassRasterVariables,
      cntClassDXFRASTERVARIABLES);
    WriteSectionSize(vBits);
    vBits.WriteCRC8(cnstClassesSectionCRCInit);
    SaveSectionToStream(GetClassesSectionIndex, vBits, cnstClassesSectionBeginSentinel,
      cnstClassesSectionEndSentinel);
    if APaddingSize > 0 then
      WriteByteToStream(Sections[GetClassesSectionIndex], 0, APaddingSize);
    CreateDictionaryListByStrList(sAcadScaleListDictionary, GetDWGCodeByClass(cntClassDXFSCALE),
      FScalesDictionary);
    CreateDictionaryListByStrList(sAcDbVariableDictionary, GetDWGCodeByClass(cntClassDXFDICTIONARYVAR),
      FVariableDictionary);
  finally
    vBits.Free;
  end;
end;

procedure TsgCADtoDWG.ExportSectionENTITIES;

  procedure IterateLayout(ALayout: TsgDXFLayout);
  var
    I: Integer;
    vEntMode: Byte;
    vData: TsgDirectExportData;
  begin
    if ALayout = nil then Exit;
    vEntMode := 2;
    if not ALayout.IsModel then
      vEntMode := 1;
    for I := 0 to ALayout.Count - 1 do
    begin
      vData := CreateExportData(cnstBadHandle, vEntMode, GetPrevEntHandle(ALayout, I),
        GetNextEntHandle(ALayout, I));
      DoExport(ALayout.Entities[I], @vData);
    end;
  end;
begin
  IterateLayout(ExportCADImage.Layouts[0]);
  IterateLayout(GetPaperLayout);
end;

procedure TsgCADtoDWG.ExportTableSTYLE;
var
  vStyle: TsgDXFStyle;
  I: Integer;
  vOwnerHandle: UInt64;
  vHandles: TsgInt64List;
begin
  vHandles := TsgInt64List.Create;
  vStyle := nil;
  try
    vHandles.Sorted := False;
    vOwnerHandle := GetStyleControlObjectHandle;

    if (Converter.Sections[csStyles] = nil)
      or (TsgDXFTable(Converter.Sections[csStyles]).FindEntByName(sStandardName) = nil) then
    begin
      vStyle := TsgDXFStyle.Create;
      vStyle.Name := sStandardName;
      vStyle.Handle := DoHandle;
      vStyle.FixedHeight := 0;
      vStyle.WidthFactor := 1;
      vStyle.ObliqueAngle := 0;
      vStyle.TextGenFlags := 0;
      vStyle.LastHeightUsed := 10.0;
      vStyle.PrimaryFont := sDefaultSHXFont;
      vStyle.BigFont := '';
      ProcStyle(vOwnerHandle, vStyle, vHandles);
    end;
    for I := 0 to Converter.Counts[csStyles] - 1 do
      ProcStyle(vOwnerHandle, TsgDXFStyle(Converter.Styles[I]), vHandles);
    ProcStyleControl(vOwnerHandle, vHandles);
  finally
    vStyle.Free;
    vHandles.Free;
  end;
end;

procedure TsgCADtoDWG.ExportSectionHeaderVars(const AHandSeed: UInt64;
  const ADateCreate, ADateUpdate: TDateTime);
var
  vBits: TsgDWGBits;
  vCEPSNTYPE: Word;
  vFlags, vMJDMillSecCreate, vMJDMillSecUpdate: Cardinal;
  vConv: TsgDXFConverter;
  vHeadVar: TsgHeadVarStruct;
begin
  vBits := TsgDWGBits.Create;
  try
    vConv := Converter;
    vHeadVar := vConv.HeadVarStruct;

    vBits.WriteRL($FFFFFFFF);

//    if (Version > acR2007) and (Metadata.ReleaseVersion > 3) then
//      vBits.ReadRL;

    vBits.WriteBD(412148564080.0);
    vBits.WriteBD(1);
    vBits.WriteBD(1);
    vBits.WriteBD(1);
    vBits.WriteTV('m', FCodePage);
    vBits.WriteTV('', FCodePage);
    vBits.WriteTV('', FCodePage);
    vBits.WriteTV('', FCodePage);
    vBits.WriteBL(0);
    vBits.WriteBL(0);

    if Version in [acR13..acR14] then
      vBits.WriteBL(0);

    if Version < acR2004 then
      vBits.WriteHandle(GetCurrentViewportEntityHeaderHandle, cntDWGObjHandleHardPointer); //Handle of the current viewport entity header   Code 5 Handle 0

    vBits.WriteBit(1);//B : DIMASO              1
    vBits.WriteBit(1);//B : DIMSHO              1

    if Version in [acR13..acR14] then
      vBits.WriteBit(0);//B : DIMSAV Undocumented

    vBits.WriteBit(0);//B : PLINEGEN            0
    vBits.WriteBit(0);//B : ORTHOMODE           0
    vBits.WriteBit(1);//B : REGENMODE           1
    vBits.WriteBit(1);//B : FILLMODE            1
    vBits.WriteBit(0);//B : QTEXTMODE           0
    vBits.WriteBit(1);//B : PSLTSCALE           1
    vBits.WriteBit(0);//B : LIMCHECK            0

    if Version in [acR13..acR14] then
      vBits.WriteBit(0);//B : BLIPMODE

    if Version >= acR2004 then
      vBits.WriteBit(0);//Undocumented

    vBits.WriteBit(1);//B : USRTIMER (User timer on/off).  1
    vBits.WriteBit(0);//B : SKPOLY                         0
    vBits.WriteBit(0);//B : ANGDIR                         0
    vBits.WriteBit(0);//B : SPLFRAME                       0

    if Version in [acR13..acR14] then
    begin
      vBits.WriteBit(0);//B : ATTREQ
      vBits.WriteBit(0);//B : ATTDIA
    end;

    vBits.WriteBit(0);//B : MIRRTEXT                       0
    vBits.WriteBit(1);//B : WORLDVIEW                      1

    if Version in [acR13..acR14] then
      vBits.WriteBit(0);//B : WIREFRAME Undocumented.

    vBits.WriteBit(Byte(ExportCADImage.CurrentLayout.IsModel));//B : TILEMODE                       1
    vBits.WriteBit(0);//B : PLIMCHECK                      0
    vBits.WriteBit(1);//B : VISRETAIN                      1

    if Version in [acR13..acR14] then
      vBits.WriteBit(0);//B : DELOBJ

    vBits.WriteBit(0);//B : DISPSILH                       0
    vBits.WriteBit(0);//B : PELLIPSE (not present in DXF)  0
    vBits.WriteBS(1);//BS : PROXYGRAPHICS                  1

    if Version in [acR13..acR14] then
      vBits.WriteBS(0);//BS : DRAGMODE

    vBits.WriteBS(3020);//BS : TREEDEPTH                      3020
    vBits.WriteBS(2);//BS : LUNITS                         2
    vBits.WriteBS(4);//BS : LUPREC                         4
    vBits.WriteBS(0);//BS : AUNITS                         0
    vBits.WriteBS(0);//BS : AUPREC                         0

    if Version in [acR13..acR14] then
      vBits.WriteBS(0);//BS : OSMODE

    vBits.WriteBS(Integer(vHeadVar.AttMode));//BS : ATTMODE               1

    if Version in [acR13..acR14] then
      vBits.WriteBS(0);//BS : COORDS

    vBits.WriteBS(vHeadVar.PointDisplayMode);//BS : PDMODE                0

    if Version in [acR13..acR14] then
      vBits.WriteBS(0);//PICKSTYLE

    if Version >= acR2004 then
    begin
      vBits.WriteBL(0);//BL : Unknown
      vBits.WriteBL(0);//BL: Unknown
      vBits.WriteBL(0);//BL : Unknown
    end;

    vBits.WriteBS(0);//BS : USERI1                          0
    vBits.WriteBS(0);//BS : USERI2                          0
    vBits.WriteBS(0);//BS : USERI3                          0
    vBits.WriteBS(0);//BS : USERI4                          0
    vBits.WriteBS(0);//BS : USERI5                          0
    vBits.WriteBS(8);//BS : SPLINESEGS                      8
    vBits.WriteBS(6);//BS : SURFU                           6
    vBits.WriteBS(6);//BS : SURFV                           6
    vBits.WriteBS(6);//BS : SURFTYPE                        6
    vBits.WriteBS(6);//BS : SURFTAB1                        6
    vBits.WriteBS(6);//BS : SURFTAB2                        6
    vBits.WriteBS(6);//BS : SPLINETYPE                      6
    vBits.WriteBS(3);//BS : SHADEDGE                        3
    vBits.WriteBS(70);//BS : SHADEDIF                       70
    vBits.WriteBS(0);//BS : UNITMODE                        0
    vBits.WriteBS(64);//BS : MAXACTVP                       64
    vBits.WriteBS(4);//BS : ISOLINES                        4
    vBits.WriteBS(0);//BS : CMLJUST                         0
    vBits.WriteBS(50);//BS : TEXTQLTY                       50
    vBits.WriteBD(Converter.LTScale);//BD : LTSCALE                     1
    vBits.WriteBD(Converter.HeadVarStruct.TextSize);//BD : TEXTSIZE    2.5
    vBits.WriteBD(1);//BD : TRACEWID                        1
    vBits.WriteBD(1);//BD : SKETCHINC                       1
    vBits.WriteBD(Converter.HeadVarStruct.FilletRadius);//BD : FILLETRAD 0
    vBits.WriteBD(0);//BD : THICKNESS                       0
    vBits.WriteBD(0);//BD : ANGBASE                         0
    vBits.WriteBD(Converter.HeadVarStruct.PointDisplaySize);//BD : PDSIZE                          0
    vBits.WriteBD(0);//BD : PLINEWID                        0
    vBits.WriteBD(0);//BD : USERR1                          0
    vBits.WriteBD(0);//BD : USERR2                          0
    vBits.WriteBD(0);//BD : USERR3                          0
    vBits.WriteBD(0);//BD : USERR4                          0
    vBits.WriteBD(0);//BD : USERR5                          0
    vBits.WriteBD(0);//BD : CHAMFERA                        0
    vBits.WriteBD(0);//BD : CHAMFERB                        0
    vBits.WriteBD(0);//BD : CHAMFERC                        0
    vBits.WriteBD(0);//BD : CHAMFERD                        0
    vBits.WriteBD(0.5);//BD : FACETRES                      0.5
    vBits.WriteBD(20);//BD : CMLSCALE                       20
    vBits.WriteBD(Converter.HeadVarStruct.CELTScale);//BD : CELTSCALE                       1

    if Version in [acR13..acR2004] then
      vBits.WriteTV('.', FCodePage);//TV : MENUNAME                     '.'

    //BL : TDCREATE (Julian day)                 2455958
    //BL : TDCREATE (Milliseconds into the day)  39819107
    WriteDateTimeAsJulian(ADateCreate, vBits, False, nil, @vMJDMillSecCreate);

    //BL : TDUPDATE (Julian day)                 2455958
    //BL : TDUPDATE (Milliseconds into the day)  39887280
    WriteDateTimeAsJulian(ADateUpdate, vBits, False, nil, @vMJDMillSecUpdate);

    if Version >= acR2004 then
    begin
      vBits.WriteBL(0);//BL : Unknown
      vBits.WriteBL(0);//BL : Unknown
      vBits.WriteBL(0);//BL : Unknown
    end;

    vBits.WriteBL(0);//BL : TDINDWG (Days)                          0
    vBits.WriteBL(vMJDMillSecUpdate - vMJDMillSecCreate);//BL : TDINDWG (Milliseconds into the day)     68640
    vBits.WriteBL(0);//BL : TDUSRTIMER (Days)                       0
    vBits.WriteBL(vMJDMillSecUpdate - vMJDMillSecCreate);//BL : TDUSRTIMER (Milliseconds into the day)  68640
    vBits.WriteCMC(vHeadVar.CEColor);//CMC : CECOLOR clDXFByLayer

    vBits.WriteHandle(AHandSeed, cntDWGObjHandleType0);//H : HANDSEED The next handle, with an 8-bit length specifier preceding the handle bytes (standard hex handle form) (code 0)
    WriteEntityHandle(vBits, vConv.LayerByName(vHeadVar.CLayer), cntDWGObjHandleHardPointer); //H : CLAYER (hard pointer)       Code 5, Handle 16
    WriteEntityHandle(vBits, vConv.StyleByName(vHeadVar.TextStyle), cntDWGObjHandleHardPointer);//H : TEXTSTYLE (hard pointer)    Code 5, Handle 17
    WriteEntityHandle(vBits, vConv.LTypeByName(vHeadVar.CELType), cntDWGObjHandleHardPointer);//H : CELTYPE (hard pointer)      Code 5, Handle 21

    if Version > acR2007 then
      vBits.WriteHandle(0, cntDWGObjHandleHardPointer);//H : CMATERIAL (hard pointer)

    WriteEntityHandle(vBits, vConv.DimensionStyleByName(vHeadVar.DimStyle), cntDWGObjHandleHardPointer);//H : DIMSTYLE (hard pointer)     Code 5, Handle 39
    WriteEntityHandle(vBits, GetMLineStyle, cntDWGObjHandleHardPointer); //H : CMLSTYLE (hard pointer)  multilyne style  Code 5, Handle 24

    if Version >= acR2000 then
      vBits.WriteBD(0);// BD : PSVPSCALE                            0

    vBits.Write3BD(cnstFPointZero);//3BD : INSBASE (PSPACE)                    0, 0, 0
    vBits.Write3BD(GetExtMin(GetPaperLayout));//3BD : EXTMIN (PSPACE)                     0, 0, 0  ODA 1e+20, 1e+20, 1e+20
    vBits.Write3BD(GetExtMax(GetPaperLayout));//3BD : EXTMAX (PSPACE)                     0, 0, 0  ODA -1e+20, -1e+20, -1e+20
    vBits.Write2RD(GetLinMin(GetPaperLayout));//2RD : LIMMIN (PSPACE)                     0, 0, 0
    vBits.Write2RD(GetLinMax(GetPaperLayout));//2RD : LIMMAX (PSPACE)                 12, 9, 0
    vBits.WriteBD(0);//BD : ELEVATION (PSPACE)                    0

    vBits.Write3BD(cnstFPointZero);//3BD : UCSORG (PSPACE)                     0, 0, 0
    vBits.Write3BD(cnstXOrtAxis);//3BD : UCSXDIR (PSPACE)                    1, 0, 0
    vBits.Write3BD(cnstYOrtAxis);//3BD : UCSYDIR (PSPACE)                    0, 1, 0
    vBits.WriteHandle(0, cntDWGObjHandleHardPointer);//H : UCSNAME (PSPACE) (hard pointer)  Code 5, Handle 0

    if Version >= acR2000 then
    begin
      vBits.WriteHandle(0, cntDWGObjHandleHardPointer);//H : PUCSORTHOREF (hard pointer)      Code 5, Handle 0
      vBits.WriteBS(0);//BS : PUCSORTHOVIEW                              0
      vBits.WriteHandle(0, cntDWGObjHandleHardPointer);//H : PUCSBASE (hard pointer)          Code 5, Handle 0
      vBits.Write3BD(cnstFPointZero);//3BD : PUCSORGTOP                          0, 0, 0
      vBits.Write3BD(cnstFPointZero);//3BD : PUCSORGBOTTOM                       0, 0, 0
      vBits.Write3BD(cnstFPointZero);//3BD : PUCSORGLEFT                         0, 0, 0
      vBits.Write3BD(cnstFPointZero);//3BD : PUCSORGRIGHT                        0, 0, 0
      vBits.Write3BD(cnstFPointZero);//3BD : PUCSORGFRONT                        0, 0, 0
      vBits.Write3BD(cnstFPointZero);//3BD : PUCSORGBACK                         0, 0, 0
    end;

    vBits.Write3BD(vHeadVar.InsBase);//3BD : INSBASE (MSPACE)                    0, 0, 0
    vBits.Write3BD(GetExtMin(Converter.Layouts[0]));//3BD : EXTMIN (MSPACE)                     1239.47030326644, 1029.17491819938, 0  ODA 1e+20, 1e+20, 1e+20
    vBits.Write3BD(GetExtMax(Converter.Layouts[0]));//3BD : EXTMAX (MSPACE)                     1876.89217864485, 1387.20749547897, 0  ODA -1e+20, -1e+20, -1e+20
    vBits.Write2RD(GetLinMin(Converter.Layouts[0]));//2RD : LIMMIN (MSPACE)                     0, 0, 0
    vBits.Write2RD(GetLinMax(Converter.Layouts[0]));//2RD : LIMMAX (MSPACE)                     420, 297, 0                             ODA  12, 9, 0 !!!

    vBits.WriteBD(0);//BD : ELEVATION (MSPACE)                          0
    vBits.Write3BD(vHeadVar.UCSORG);//3BD : UCSORG (MSPACE)                   0, 0, 0
    vBits.Write3BD(vHeadVar.UCSXDir);//3BD : UCSXDIR (MSPACE)                    1, 0, 0
    vBits.Write3BD(vHeadVar.UCSYDir);//3BD : UCSYDIR (MSPACE)                    0, 1, 0
    vBits.WriteHandle(0, cntDWGObjHandleHardPointer);//H : UCSNAME (MSPACE) (hard pointer) Code 5, Handle 0

    if Version >= acR2000 then
    begin
      vBits.WriteHandle(0, cntDWGObjHandleHardPointer);//H : UCSORTHOREF (hard pointer)      Code 5, Handle 0
      vBits.WriteBS(0);//BS : UCSORTHOVIEW                              0
      vBits.WriteHandle(0, cntDWGObjHandleHardPointer);//H : UCSBASE (hard pointer)          Code 5, Handle 0
      vBits.Write3BD(cnstFPointZero);//3BD : UCSORGTOP                               0, 0, 0
      vBits.Write3BD(cnstFPointZero);//3BD : UCSORGBOTTOM                            0, 0, 0
      vBits.Write3BD(cnstFPointZero);//3BD : UCSORGLEFT                              0, 0, 0
      vBits.Write3BD(cnstFPointZero);//3BD : UCSORGRIGHT                             0, 0, 0
      vBits.Write3BD(cnstFPointZero);//3BD : UCSORGFRONT                             0, 0, 0
      vBits.Write3BD(cnstFPointZero);//3BD : UCSORGBACK                              0, 0, 0
      vBits.WriteTV(vHeadVar.DimProps.Post, FCodePage);//TV : DIMPOST               ''
      vBits.WriteTV(vHeadVar.DimProps.APost, FCodePage);//TV : DIMAPOST             ''
    end;

    if Version in [acR13..acR14] then
    begin
      vBits.WriteBit(0);//B : DIMTOL
      vBits.WriteBit(0);//B : DIMLIM
      vBits.WriteBit(vHeadVar.DimProps.Tih);//B : DIMTIH
      vBits.WriteBit(vHeadVar.DimProps.Toh);//B : DIMTOH
      vBits.WriteBit(vHeadVar.DimProps.SE1);//B : DIMSE1
      vBits.WriteBit(vHeadVar.DimProps.SE1);//B : DIMSE2
      vBits.WriteBit(vHeadVar.DimProps.Alt);//B : DIMALT
      vBits.WriteBit(0);//B : DIMTOFL
      vBits.WriteBit(0);//B : DIMSAH
      vBits.WriteBit(vHeadVar.DimProps.Tix <> 0);//B : DIMTIX
      vBits.WriteBit(0);//B : DIMSOXD
      vBits.WriteRC(0);//RC : DIMALTD
      vBits.WriteRC(0);//RC : DIMZIN
      vBits.WriteBit(0);//B : DIMSD1
      vBits.WriteBit(0);//B : DIMSD2
      vBits.WriteRC(0);//RC : DIMTOLJ
      vBits.WriteRC(0);//RC : DIMJUST
      vBits.WriteRC(0);//RC : DIMFIT
      vBits.WriteBit(0);//B : DIMUPT
      vBits.WriteRC(0);//RC : DIMTZIN
      vBits.WriteRC(0);//RC : DIMALTZ
      vBits.WriteRC(0);//RC : DIMALTTZ
      vBits.WriteRC(vHeadVar.DimProps.Tad);//RC : DIMTAD
      vBits.WriteBS(0);//BS : DIMUNIT
      vBits.WriteBS(0);//BS : DIMAUNIT
      vBits.WriteBS(vHeadVar.DimProps.Dec);//BS : DIMDEC
      vBits.WriteBS(0);//BS : DIMTDEC
      vBits.WriteBS(0);//BS : DIMALTU
      vBits.WriteBS(0);//BS : DIMALTTD
      WriteEntityHandle(vBits, vConv.StyleByName(vHeadVar.DimTextStyle), cntDWGObjHandleHardPointer); //H : DIMTXSTY (hard pointer)
    end;

    vBits.WriteBD(vHeadVar.DimProps.Scale);//BD : DIMSCALE              1
    vBits.WriteBD(vHeadVar.DimProps.Asz);//BD : DIMASZ                  2.5
    vBits.WriteBD(vHeadVar.DimProps.Exo);//BD : DIMEXO                  0.625
    vBits.WriteBD(3.75);//BD : DIMDLI                                   3.75 !!!
    vBits.WriteBD(vHeadVar.DimProps.Exe);//BD : DIMEXE                  1.25
    vBits.WriteBD(0);//BD : DIMRND                                      0    !!!
    vBits.WriteBD(0);//BD : DIMDLE                                      0    !!!
    vBits.WriteBD(0);//BD : DIMTP                                       0    !!!
    vBits.WriteBD(0);//BD : DIMTM                                       0    !!!

    if Version >= acR2007 then
    begin
      vBits.WriteBD(0);//BD : DIMFXL
      vBits.WriteBD(0);//BD : DIMJOGANG
      vBits.WriteBS(0);//BS : DIMTFILL
      vBits.WriteCMC(cnstDefaultEntityColor);//CMC : DIMTFILLCLR
    end;

    if Version >= acR2000 then
    begin
      vBits.WriteBit(0);//B : DIMTOL                                     0  !!!
      vBits.WriteBit(0);//B : DIMLIM                                     0  !!!
      vBits.WriteBit(vHeadVar.DimProps.Tih);//B : DIMTIH      0
      vBits.WriteBit(vHeadVar.DimProps.Toh);//B : DIMTOH      0
      vBits.WriteBit(vHeadVar.DimProps.SE1);//B : DIMSE1      0
      vBits.WriteBit(vHeadVar.DimProps.SE2);//B : DIMSE2      0
      vBits.WriteBS(vHeadVar.DimProps.Tad);//BS : DIMTAD                 1
      vBits.WriteBS(8);//BS : DIMZIN                                     8 !!!
      vBits.WriteBS(0);//BS : DIMAZIN                                    0 !!!
    end;

    if Version >= acR2007 then
      vBits.WriteBS(0);//BS : DIMARCSYM

    vBits.WriteBD(GetDefVal(vHeadVar.DimProps.Txt, 2.5));//BD : DIMTXT               2.5
    vBits.WriteBD(vHeadVar.DimProps.Cen);//BD : DIMCEN               2.5
    vBits.WriteBD(0);//BD : DIMTSZ                                     0  !!!
    vBits.WriteBD(vHeadVar.DimProps.AltF);//BD : DIMALTF       0.03937007874016
    vBits.WriteBD(GetDefVal(vHeadVar.DimProps.LFac, 1));//BD : DIMLFAC               1
    vBits.WriteBD(0);//BD : DIMTVP                                     0  !!!
    vBits.WriteBD(1);//BD : DIMTFAC                                    1  !!!
    vBits.WriteBD(vHeadVar.DimProps.Gap);//BD : DIMGAP                0.625

    if Version in [acR13..acR14] then
    begin
      vBits.WriteT(vHeadVar.DimProps.Post, FCodePage);//T : DIMPOST
      vBits.WriteT(vHeadVar.DimProps.APost, FCodePage);//T : DIMAPOST
      vBits.WriteT(GetNameByArrowType(Converter.HeadVarStruct.DimProps.Arrows.Blk,
        sgDimensionArrowTypeNames[Low(sgDimensionArrowTypeNames)]), FCodePage);//T : DIMBLK
      vBits.WriteT(GetNameByArrowType(Converter.HeadVarStruct.DimProps.Arrows.Blk1,
        sgDimensionArrowTypeNames[Low(sgDimensionArrowTypeNames)]), FCodePage);//T : DIMBLK1
      vBits.WriteT(GetNameByArrowType(Converter.HeadVarStruct.DimProps.Arrows.Blk2,
        sgDimensionArrowTypeNames[Low(sgDimensionArrowTypeNames)]), FCodePage);//T : DIMBLK2
    end;

    if Version >= acR2000 then
    begin
      vBits.WriteBD(0);//BD : DIMALTRND                                  0 !!!
      vBits.WriteBit(vHeadVar.DimProps.Alt);//B : DIMALT      0
      vBits.WriteBS(3);//BS : DIMALTD                                    3 !!!
      vBits.WriteBit(1);//B : DIMTOFL                                    1 !!!
      vBits.WriteBit(0);//B : DIMSAH                                     0 !!!
      vBits.WriteBit(vHeadVar.DimProps.Tix <> 0);//B : DIMTIX                 0
      vBits.WriteBit(0);//B : DIMSOXD                                    0 !!!
    end;

    vBits.WriteCMC(vHeadVar.DimProps.ClrD);//CMC : DIMCLRD         clDXFByBlock
    vBits.WriteCMC(vHeadVar.DimProps.ClrE);//CMC : DIMCLRE         clDXFByBlock
    vBits.WriteCMC(vHeadVar.DimProps.ClrT);//CMC : DIMCLRT         clDXFByBlock

    if Version >= acR2000 then
    begin
      vBits.WriteBS(0);//BS : DIMADEC                                    0 !!!
      vBits.WriteBS(vHeadVar.DimProps.Dec);//BS : DIMDEC                 2
      vBits.WriteBS(2);//BS : DIMTDEC                                    2
      vBits.WriteBS(2);//BS : DIMALTU                                    2
      vBits.WriteBS(3);//BS : DIMALTTD                                   3
      vBits.WriteBS(0);//BS : DIMAUNIT                                   0
      vBits.WriteBS(0);//BS : DIMFRAC                                    0
      vBits.WriteBS(2);//BS : DIMLUNIT                                   2
      vBits.WriteBS(44);//BS : DIMDSEP                                   44
      vBits.WriteBS(0);//BS : DIMTMOVE                                   0
      vBits.WriteBS(0);//BS : DIMJUST                                    0
      vBits.WriteBit(vHeadVar.DimProps.SD1);//B : DIMSD1      0
      vBits.WriteBit(vHeadVar.DimProps.SD2);//B : DIMSD2      0
      vBits.WriteBS(0);//BS : DIMTOLJ                                    0
      vBits.WriteBS(8);//BS : DIMTZIN                                    8
      vBits.WriteBS(0);//BS : DIMALTZ                                    0
      vBits.WriteBS(0);//BS : DIMALTTZ                                   0
      vBits.WriteBit(0);//B : DIMUPT                                     0
      vBits.WriteBS(3);//BS : DIMATFIT                                   3
    end;

    if Version >= acR2007 then
      vBits.WriteBit(0);//B : DIMFXLON

    if Version >= acR2010 then
    begin
      vBits.WriteBit(0);//B : DIMTXTDIRECTION
      vBits.WriteBD(0);//BD : DIMALTMZF
      vBits.WriteT('', FCodePage);//T : DIMALTMZS
      vBits.WriteBD(0);//BD : DIMMZF
      vBits.WriteT('', FCodePage);//T : DIMMZS
    end;

    if Version  >= acR2000 then
    begin
      WriteEntityHandle(vBits, vConv.StyleByName(vHeadVar.DimTextStyle), cntDWGObjHandleHardPointer);//H : DIMTXSTY (hard pointer)               Code 5 Handle 17
      vBits.WriteHandle(GetArrowBlockHandle(vHeadVar.DimProps.Arrows.LrBlk), cntDWGObjHandleHardPointer);//H : DIMLDRBLK (hard pointer)           Code 5 Handle 0
      vBits.WriteHandle(GetArrowBlockHandle(vHeadVar.DimProps.Arrows.Blk), cntDWGObjHandleHardPointer);//H : DIMBLK (hard pointer)                Code 5 Handle 0
      vBits.WriteHandle(GetArrowBlockHandle(vHeadVar.DimProps.Arrows.Blk1), cntDWGObjHandleHardPointer);//H : DIMBLK1 (hard pointer)              Code 5 Handle 0
      vBits.WriteHandle(GetArrowBlockHandle(vHeadVar.DimProps.Arrows.Blk2), cntDWGObjHandleHardPointer);//H : DIMBLK2 (hard pointer)              Code 5 Handle 0
    end;


    if Version >= acR2007 then
    begin
      vBits.WriteHandle(0, cntDWGObjHandleHardPointer);//H : DIMLTYPE (hard pointer)
      vBits.WriteHandle(0, cntDWGObjHandleHardPointer);//H : DIMLTEX1 (hard pointer)
      vBits.WriteHandle(0, cntDWGObjHandleHardPointer);//H : DIMLTEX2 (hard pointer)
    end;

    if Version >= acR2000 then
    begin
      vBits.WriteBS(CorrectLineWeight(vHeadVar.DimProps.LwD, False));//BS : DIMLWD                   65534
      vBits.WriteBS(CorrectLineWeight(vHeadVar.DimProps.LwE, False));//BS : DIMLWE                   65534
    end;

    vBits.WriteHandle(GetBlockControlObjectHandle, cntDWGObjHandleHardOwner);//H : BLOCK CONTROL OBJECT (hard owner)           Code 3 Handle 35
    vBits.WriteHandle(GetLayerControlObjectHandle, cntDWGObjHandleHardOwner);//H : LAYER CONTROL OBJECT (hard owner)           Code 3 Handle 11
    vBits.WriteHandle(GetStyleControlObjectHandle, cntDWGObjHandleHardOwner);//H : STYLE CONTROL OBJECT (hard owner)           Code 3 Handle 12
    vBits.WriteHandle(GetLineTypeControlObjectHandle, cntDWGObjHandleHardOwner);//H : LINETYPE CONTROL OBJECT (hard owner)     Code 3 Handle 10
    vBits.WriteHandle(GetViewControlObjectHandle, cntDWGObjHandleHardOwner);//H : VIEW CONTROL OBJECT (hard owner)             Code 3 Handle 42
    vBits.WriteHandle(GetUCSontrolObjectHandle, cntDWGObjHandleHardOwner);//H : UCS CONTROL OBJECT (hard owner)                Code 3 Handle 43
    vBits.WriteHandle(GetVPortControlObjectHandle, cntDWGObjHandleHardOwner);//H : VPORT CONTROL OBJECT (hard owner)           Code 3 Handle 40
    vBits.WriteHandle(GetAppIDControlObjectHandle, cntDWGObjHandleHardOwner);//H : APPID CONTROL OBJECT (hard owner)           Code 3 Handle 32
    vBits.WriteHandle(GetDimStyleControlObjectHandle, cntDWGObjHandleHardOwner);//H : DIMSTYLE CONTROL OBJECT (hard owner)     Code 3 Handle 13

    if Version in [acR13..acR2000] then
      vBits.WriteHandle(GetViewPortEntityHeaderControlObjectHandle, cntDWGObjHandleHardOwner);//H : VIEWPORT ENTITY HEADER CONTROL OBJECT     Code 3 Handle 497

    vBits.WriteHandle(GetDictionaryAcadGroupHandle, cntDWGObjHandleHardPointer);//H : DICTIONARY (ACAD_GROUP) (hard pointer)             Code 5 Handle 51
    vBits.WriteHandle(GetDictionaryAcadMLineStyleHandle, cntDWGObjHandleHardPointer);//H : DICTIONARY (ACAD_MLINESTYLE) (hard pointer)   Code 5 Handle 54
    vBits.WriteHandle(GetDictionaryNamedObjectHandle, cntDWGObjHandleHardOwner);//H : DICTIONARY (NAMED OBJECTS) (hard owner)          Code 3 Handle 50

    if Version >= acR2000 then
    begin
      vBits.WriteBS(1);//BS : TSTACKALIGN, default = 1 (not present in DXF)            1
      vBits.WriteBS(70);//BS : TSTACKSIZE, default = 70 (not present in DXF)           70
      vBits.WriteTV('', FCodePage);//TV : HYPERLINKBASE                                           ''
      vBits.WriteTV('', FCodePage);//TV : STYLESHEET                                              ''
      vBits.WriteHandle(GetDictionaryLayoutsHandle, cntDWGObjHandleHardPointer);//H : DICTIONARY (LAYOUTS) (hard pointer)                Code 5 Handle 57
      vBits.WriteHandle(GetDictionaryPlotSettingHandle, cntDWGObjHandleHardPointer);//H : DICTIONARY (PLOTSETTINGS) (hard pointer)       Code 5 Handle 0
      vBits.WriteHandle(GetDictionaryPlotStyleHandle, cntDWGObjHandleHardPointer);//H : DICTIONARY (PLOTSTYLES) (hard pointer)           Code 5 Handle 0
    end;

    if Version >= acR2004 then
    begin
      vBits.WriteHandle(0, cntDWGObjHandleHardPointer);//H : DICTIONARY (MATERIALS) (hard pointer)
      vBits.WriteHandle(0, cntDWGObjHandleHardPointer);//H : DICTIONARY (COLORS) (hard pointer)
    end;

    if Version >= acR2007 then
      vBits.WriteHandle(0, cntDWGObjHandleHardPointer);//H : DICTIONARY (VISUALSTYLE) (hard pointer)

    vFlags := $2A00;//we use only CELWEIGHT flag, other flags are default values $2A00
    vFlags := Cardinal((CorrectLineWeight(Converter.HeadVarStruct.CELWeight, True) and $1F)) or vFlags;
    vBits.WriteBL(vFlags);//just use BL : 10781
      //Flags:
        //CELWEIGHT Flags & 0x001F
        //ENDCAPS Flags & 0x0060
        //JOINSTYLE Flags & 0x0180
        //LWDISPLAY !(Flags & 0x0200)
        //XEDIT !(Flags & 0x0400)
        //EXTNAMES Flags & 0x0800
        //PSTYLEMODE Flags & 0x2000
        //OLESTARTUP Flags & 0x4000
    vBits.WriteBS(vHeadVar.InsUnits);//BS : INSUNITS     4
    vCEPSNTYPE := 0;
    vBits.WriteBS(vCEPSNTYPE);//BS : CEPSNTYPE                    0
    if vCEPSNTYPE = 3 then
      vBits.WriteHandle(0, cntDWGObjHandleHardPointer);//H : CPSNID (present only if CEPSNTYPE == 3) (hard pointer)
    vBits.WriteTV(GetFingerPrintGUID, FCodePage);//TV : FINGERPRINTGUID    {F536BED7-6F9E-468E-8820-242279AE2C2C}     ODA {E44D33DF-D2B9-48AE-8431-27F629E25DDD}
    vBits.WriteTV(GetVersionGUID, FCodePage);//TV : VERSIONGUID        {4C62D578-729E-4900-B98E-2D837BD6EAD7}     ODA {FAEB1C32-E019-11D5-929B-00C0DF256EC4}

    if Version >= acR2004 then
    begin
      vBits.WriteRC(0);//RC : SORTENTS
      vBits.WriteRC(0);//RC : INDEXCTL
      vBits.WriteRC(0);//RC : HIDETEXT
      vBits.WriteRC(0);//RC : XCLIPFRAME
      vBits.WriteRC(0);//RC : DIMASSOC
      vBits.WriteRC(0);//RC : HALOGAP
      vBits.WriteBS(0);//BS : OBSCUREDCOLOR
      vBits.WriteBS(0);//BS : INTERSECTIONCOLOR
      vBits.WriteRC(0);//RC : OBSCUREDLTYPE
      vBits.WriteRC(0);//RC : INTERSECTIONDISPLAY
      vBits.WriteTV('', FCodePage);//TV : PROJECTNAME
    end;

    vBits.WriteHandle(PaperSpaceBlockHandle, cntDWGObjHandleHardPointer);//H : BLOCK_RECORD (*PAPER_SPACE) (hard pointer)   Code 5 Handle 37
    vBits.WriteHandle(ModelSpaceBlockHandle, cntDWGObjHandleHardPointer);//H : BLOCK_RECORD (*MODEL_SPACE) (hard pointer)   Code 5 Handle 36
    WriteEntityHandle(vBits, vConv.LTypeByName(sByLayer), cntDWGObjHandleHardPointer);//H : LTYPE (BYLAYER) (hard pointer)           Code 5 Handle 1
    WriteEntityHandle(vBits, vConv.LTypeByName(sByBlock), cntDWGObjHandleHardPointer);//H : LTYPE (BYBLOCK) (hard pointer)           Code 5 Handle 2
    WriteEntityHandle(vBits, vConv.LTypeByName(sContinuous), cntDWGObjHandleHardPointer);//H : LTYPE (CONTINUOUS) (hard pointer)     Code 5 Handle 3

    if Version >= acR2007 then
    begin
      vBits.WriteBit(0);//B : CAMERADISPLAY
      vBits.WriteBL(0);//BL : unknown
      vBits.WriteBL(0);//BL : unknown
      vBits.WriteBD(0);//BD : unknown
      vBits.WriteBD(0);//BD : STEPSPERSEC
      vBits.WriteBD(0);//BD : STEPSIZE
      vBits.WriteBD(0);//BD : 3DDWFPREC
      vBits.WriteBD(0);//BD : LENSLENGTH
      vBits.WriteBD(0);//BD : CAMERAHEIGHT
      vBits.WriteRC(0);//RC : SOLIDHIST
      vBits.WriteRC(0);//RC : SHOWHIST
      vBits.WriteBD(0);//BD : PSOLWIDTH
      vBits.WriteBD(0);//BD : PSOLHEIGHT
      vBits.WriteBD(0);//BD : LOFTANG1
      vBits.WriteBD(0);//BD : LOFTANG2
      vBits.WriteBD(0);//BD : LOFTMAG1
      vBits.WriteBD(0);//BD : LOFTMAG2
      vBits.WriteBS(0);//BS : LOFTPARAM
      vBits.WriteRC(0);//RC : LOFTNORMALS
      vBits.WriteBD(0);//BD : LATITUDE
      vBits.WriteBD(0);//BD : LONGITUDE
      vBits.WriteBD(0);//BD : NORTHDIRECTION
      vBits.WriteBL(0);//BL : TIMEZONE
      vBits.WriteRC(0);//RC : LIGHTGLYPHDISPLAY
      vBits.WriteRC(0);//RC : TILEMODELIGHTSYNCH
      vBits.WriteRC(0);//RC : DWFFRAME
      vBits.WriteRC(0);//RC : DGNFRAME
      vBits.WriteBit(0);//B : unknown
      vBits.WriteCMC(cnstDefaultEntityColor);//CMC : INTERFERECOLOR
      vBits.WriteHandle(0, cntDWGObjHandleHardPointer);//H : INTERFEREOBJVS (hard pointer)
      vBits.WriteHandle(0, cntDWGObjHandleHardPointer);//H : INTERFEREVPVS (hard pointer)
      vBits.WriteHandle(0, cntDWGObjHandleHardPointer);//H : DRAGVS (hard pointer)
      vBits.WriteRC(0);//RC : CSHADOW
      vBits.WriteBD(0);//BD : unknown
    end;

    if Version > acR14 then
    begin
      vBits.WriteBS($FFFF);//BS : unknown short (type 5/6 only) these do not seem to be required,  65535
      vBits.WriteBS($FFFF);//BS : unknown short (type 5/6 only) even for type 5.                   65535
      vBits.WriteBS($FFFF);//BS : unknown short (type 5/6 only)                                    65535
      vBits.WriteBS($FFFF);//BS : unknown short (type 5/6 only)                                    65535
    end;

    WriteSectionSize(vBits);
    vBits.WriteCRC8(cnstHeaderVarCRCInit);//RS : CRC for the data section, starting after the sentinel. Use 0xC0C1 for the initial value.*)

    SaveSectionToStream(GetHeaderVarsSectionIndex , vBits, cnstHeaderVariablesBeginSentinel,
      cnstHeaderVariablesEndSentinel);
  finally
    vBits.Free;
  end;
end;

procedure TsgCADtoDWG.ExportSectionMeasurement(const Measurement: Word);
var
  vBits: TsgDWGBits;
begin
  vBits := TsgDWGBits.Create;
  try
    vBits.WriteRS(0);
    vBits.WriteRS(Measurement);
    SaveSectionToStream(GetMeasurementSectionIndex, vBits, [], []);
  finally
    vBits.Free
  end;
end;

procedure TsgCADtoDWG.ExportSectionObjects;
//var
//  vValue: Cardinal;
begin
  //Sections[GetObjectsSectionIndex].Clear;
//  if Version > acR2000 then
//  begin
//    vValue := $DCA;
//    Sections[GetObjectsSectionIndex].Write(vValue, 2);
//  end;
end;

procedure TsgCADtoDWG.ExportSectionObjFreeSpace(const ADateUpdate: TDateTime;
  const ObjCount, ObjOffset: Cardinal);
const
  cnstSignature: AnsiString = 'CADSoftTools';
var
  vBits: TsgDWGBits;
begin
  vBits := TsgDWGBits.Create;
  try
    vBits.WriteRL0;
    vBits.WriteRL(ObjCount);
    WriteDateTimeAsJulian(ADateUpdate, vBits, True);
    vBits.WriteRL(ObjOffset); //Offset of the objects section in the stream
(*
    ODA Watermark, unknown signature
    vBits.WriteRC(4);
    vBits.WriteRL($32);
    vBits.WriteRL(0);
    vBits.WriteRL($64);
    vBits.WriteRL(0);
    vBits.WriteRL($200);
    vBits.WriteRL(0);
    vBits.WriteRL(-1);
    vBits.WriteRL(0);
*)
//CADSoftTools signature 'CADSoftTools'
    vBits.WriteRC(4); //4 UInt64's
    vBits.WriteBytes(@cnstSignature[1], Length(cnstSignature));
    vBits.WriteBytes(0, SizeOf(UInt64) * 4 - Length(cnstSignature));
//    vBits.WriteRC(4);
//    vBits.WriteRL(0);
//    vBits.WriteRL(0);
//    vBits.WriteRL(0);
//    vBits.WriteRL(0);
//    vBits.WriteRL(0);
//    vBits.WriteRL(0);
//    vBits.WriteRL(0);
//    vBits.WriteRL(0);
    SaveSectionToStream(GetObjFreeSpaceSectionIndex, vBits, [], []);
  finally
    vBits.Free;
  end;
end;

procedure TsgCADtoDWG.ExportSectionObjMap;
var
  I: Integer;
  vOffset, vPrevLoc: Integer;
  vPrevHandle: UInt64;
  vBits: TsgDWGBits;

  procedure Save;
  begin
    vBits.UpdateRS(0, SwapBytes(vBits.Size));
    vBits.WriteCRC8(cnstSectionObjMapCRCInit, True);
    vBits.SaveToStream(Sections[GetObjectMapSectionIndex]);
    vBits.Clear;
  end;

  procedure CheckAndSplit(AFirst, ALast: Boolean); //each section is cut off at a maximum length of 2032
  var
    vFlag: Boolean;
  begin
    vFlag := vBits.Size >= cnstSectionObjMapMaxSize;
    if AFirst or ALast or vFlag then
    begin
      if (not AFirst) and (ALast or vFlag) then Save;
      vPrevHandle := 0;
      vPrevLoc := 0;
      vBits.WriteRS(Word(cntSizeTempValue));
    end;
  end;

begin
  vBits := TsgDWGBits.Create;
  try
    vOffset := GetObjectsFileOffset;
    Sections[GetObjectMapSectionIndex].Clear;
    FObjectsMap.SortBy := seHandle;
    FObjectsMap.Sort;
    CheckAndSplit(True, False);
    for I := 0 to FObjectsMap.Count - 1 do
    begin
      CheckAndSplit(False, False);
      vBits.WriteMCHandle(FObjectsMap[I].Handle - vPrevHandle);
      vBits.WriteMC(FObjectsMap[I].Location + vOffset - vPrevLoc);
      vPrevHandle := FObjectsMap[I].Handle;
      vPrevLoc := FObjectsMap[I].Location + vOffset;
    end;
    CheckAndSplit(False, True);
    Save;
  finally
    vBits.Free;
  end;
end;

procedure TsgCADtoDWG.ExportSectionPreview(const ImageOffset: Cardinal);
var
  vBits: TsgDWGBits;
  vBitmap: TBitmap;
  P: PByte;
  vStream: TMemoryStream;
  vSizeOffset, vHeaderOffsetPos, vHeaderSize, vBmpOffsetPos, vBmpDataSize: Cardinal;

  function GetRealPos: Cardinal;
  begin
    Result := vBits.Position shr cntMulDiv8 + ImageOffset;
  end;

begin
  vBits := TsgDWGBits.Create;
  try
    vBitmap := TBitmap.Create;
    try
      vBitmap.PixelFormat := pf8bit;
      vBitmap.Width := GetPreviewImageWidth;
      vBitmap.Height := GetPreviewImageHeigth;
      vBitmap.Canvas.StretchDraw(Rect(0, 0, vBitmap.Width, vBitmap.Height),
        ExportCADImage);
      vStream := TMemoryStream.Create;
      try
        vBitmap.SaveToStream(vStream);
        P := vStream.Memory;
        Inc(P, SizeOf(TBitmapFileHeader));
        vBits.WriteSentinel(cnstImageDataBeginSentinel);
        vSizeOffset := vBits.Position;
        vBits.WriteRL(cntSizeTempValue); //size will be written later
        vBits.WriteRC(2);
        vBits.WriteRC(1);
        vHeaderSize := 80;
        vHeaderOffsetPos := vBits.Position;
        vBits.WriteRL(cntOffsetTempValue);//Header offset
        vBits.WriteRL(vHeaderSize);
        vBits.WriteRC(2);
        vBmpOffsetPos := vBits.Position;
        vBits.WriteRL(cntOffsetTempValue);//Bitmap data offset
        vBmpDataSize := vStream.Size - SizeOf(TBitmapFileHeader);
        vBits.WriteRL(vBmpDataSize);
        vBits.UpdateRL(vHeaderOffsetPos, GetRealPos);
        vBits.WriteBytes(0, vHeaderSize);
        vBits.UpdateRL(vBmpOffsetPos, GetRealPos);
        vBits.WriteBytes(P, vBmpDataSize);
        WriteSectionSize(vBits, vSizeOffset, SizeOf(TsgDWGSentinel));
        SaveSectionToStream(GetPreviewSectionIndex, vBits, [], cnstImageDataEndSentinel);
      finally
        vStream.Free;
      end;
    finally
      vBitmap.Free;
    end;
  finally
    vBits.Free;
  end;
end;

procedure TsgCADtoDWG.ExportSectionSecondHeader(const AHandSeed: UInt64;
  Offset: Cardinal; const Locators: TsgDWGR15Locators);
var
  vBits: TsgDWGBits;
  S: AnsiString;
  I: Integer;
begin
  vBits := TsgDWGBits.Create;
  try
    vBits.WriteRL(cntSizeTempValue);
    vBits.WriteBL(Offset);
    S := AnsiString(sgDWGVerToString(Version));
    vBits.WriteBytes(@S[1], Length(S));
    vBits.WriteBytes(0, 5);
    vBits.WriteRC(FMaintenanceVersion);
    vBits.WriteRC(1);
    vBits.WriteBS($617);
    vBits.WriteRS(FDWGCodePage);
    vBits.WriteBS(cntDWGR15SectionsCount);
    for I := 0 to High(Locators) do
    begin
      vBits.WriteRC(I);
      vBits.WriteBL(Locators[I].Seeker);
      vBits.WriteBL(Locators[I].Size);
    end;
    vBits.WriteBS($E);
    vBits.WriteHandleRecord(AHandSeed, 0);
    vBits.WriteHandleRecord(GetBlockControlObjectHandle, 1);
    vBits.WriteHandleRecord(GetLayerControlObjectHandle, 2);
    vBits.WriteHandleRecord(GetStyleControlObjectHandle, 3);
    vBits.WriteHandleRecord(GetLineTypeControlObjectHandle, 4);
    vBits.WriteHandleRecord(GetViewControlObjectHandle, 5);
    vBits.WriteHandleRecord(GetUCSontrolObjectHandle, 6);
    vBits.WriteHandleRecord(GetVPortControlObjectHandle, 7);
    vBits.WriteHandleRecord(GetAppIDControlObjectHandle, 8);
    vBits.WriteHandleRecord(GetDimStyleControlObjectHandle, 9);
    vBits.WriteHandleRecord(GetViewPortEntityHeaderControlObjectHandle, 10);
    vBits.WriteHandleRecord(GetDictionaryNamedObjectHandle, 11);
    vBits.WriteHandleRecord(GetDictionaryAcadMLineStyleHandle, 12);
    vBits.WriteHandleRecord(GetDictionaryAcadGroupHandle, 13);
    vBits.UpdateRL(0, vBits.Size + 14);//plus 14 RL(size) + 8 * RC (signature after CRC) + RS (CRC)
    vBits.WriteCRC8(cnstSecondFileHeaderCRCInit, False);
    vBits.WriteBytes(0, 8);
    SaveSectionToStream(GetSecondHeaderSectionIndex, vBits, cnstSecondFileHeaderBeginSentinel,
      cnstSecondFileHeaderEndSentinel);
  finally
    vBits.Free;
  end;
end;

procedure TsgCADtoDWG.ExportSectionTables;
begin
  Sections[GetObjectsSectionIndex].Clear;
  FACADXDataAppID := ExportTableAppID(sACADXDataAppName);
  if XDataAppName <> '' then
    FXDataAppID := ExportTableAppID(XDataAppName);
  ExportCreatedTableRecords;
  ExportTableBLOCK_RECORD;
  ExportTableSTYLE;
  ExportTableLTYPE;
  ExportTableLAYER;
  ExportTableVPORT;
  ExportTableDIMSTYLE;
  ExportSectionENTITIES;
  ExportTableOBJECTS;
end;

function TsgCADtoDWG.ExportSeqEnd(E: TsgDXFEntity; ABits: TsgDWGBits): Boolean;
begin
  Result := True;//nothing to do
end;

function TsgCADtoDWG.ExportShape(S: TsgDXFShape; ABits: TsgDWGBits): Boolean;
begin
  ABits.Write3BD(S.Point);//Ins pt 3BD 10
  ABits.WriteBD(S.Height);//Scale BD 40 Scale factor, default value 1
  ABits.WriteBD(S.Rotation / f180DividedByPi);//Rotation BD 50 Rotation in radians, default value 0
  ABits.WriteBD(S.Scale);//Width factor BD 41 Width factor, default value 1
  ABits.WriteBD(S.ObliqueAngle / f180DividedByPi);//Oblique BD 51 Oblique angle in radians, default value 0
  ABits.WriteBD(0);//Thickness BD 39
  ABits.WriteBS(S.ShapeNumber);//Shapeno BS 2
  ABits.Write3BD(S.Extrusion);//Extrusion 3BD 210
  Result := True;
end;

function TsgCADtoDWG.ExportSolid(S: TsgDXFSolid; ABits: TsgDWGBits): Boolean;
begin
  ABits.WriteBT(S.ZThick); //Thickness BT 39
  ABits.WriteBD(S.Point.Z); //Elevation BD --- Z for 10 - 13.
  ABits.Write2RD(S.Point); //1st corner 2RD 10
  ABits.Write2RD(S.Point1); //2nd corner 2RD 11
  ABits.Write2RD(S.Point2); //3rd corner 2RD 12
  ABits.Write2RD(S.Point3); //4th corner 2RD 13
  ABits.WriteBE(S.Extrusion); //Extrusion BE 210
  Result := True;
end;

function TsgCADtoDWG.ExportSpline(Spline: TsgDXFSpline; ABits: TsgDWGBits): Boolean;
var
  vScenario: Word;
  vFitCount: Cardinal;
  vBadSpline, vWeightFlag: Boolean;
  I: Integer;
begin
  Result := True;
  vBadSpline := Spline.Knots.Count > Spline.ControlCount + 4;
  vWeightFlag := False;
  if Spline.IsByAngles or vBadSpline then
    vScenario := 2
  else
  begin
    vScenario := 1;
    vWeightFlag := Spline.WeightCount > 0;
  end;
  ABits.WriteBS(vScenario);
  ABits.WriteBS(Spline.Degree);
  case vScenario of
    2:
      begin
        ABits.WriteBD(0.0000000001);
        ABits.Write3BD(Spline.BeginningTangent);
        ABits.Write3BD(Spline.EndingTangent);
        if vBadSpline then
          vFitCount := Spline.PolyPoints.Count
        else
          vFitCount := Spline.FitCount;
        ABits.WriteBL(vFitCount);
        if vBadSpline then
          for I := 0 to Spline.PolyPoints.Count - 1 do
            ABits.Write3BD(Spline.PolyPoints[I])
        else
          for I := 0 to Spline.FitCount - 1 do
            ABits.Write3BD(Spline.FitPoints[I]);
      end;
    1:
      begin
        ABits.WriteBit(Spline.Flags, 4);
        ABits.WriteBit(Spline.Closed);
        ABits.WriteBit(Spline.Flags, 1);
        ABits.WriteBD(0.0000001);
        ABits.WriteBD(0.0000001);
        ABits.WriteBL(Spline.KnotCount);
        ABits.WriteBL(Spline.ControlCount);
        ABits.WriteBit(vWeightFlag);
        for I := 0 to Spline.KnotCount - 1 do
          ABits.WriteBD(Spline.Knot[I]);
        for I := 0 to Spline.ControlCount - 1 do
        begin
          ABits.Write3BD(Spline.ControlPoints[I]);
          if vWeightFlag then
            if I <= Spline.WeightCount - 1 then
              ABits.WriteBD(Spline.Weight[I])
            else
              ABits.WriteBD(0);
        end;
      end;
  end;
end;

function TsgCADtoDWG.ExportTableAppID(const AppInfo: string): UInt64;
var
  vBits: TsgDWGBits;
  vIndex: Integer;
  vCode: Word;
begin
  vBits := TsgDWGBits.Create;
  try
    vCode :=  cntDWGObjCodeAPPID;
    vIndex := FCreatedElements.IndexOf(Word(cntDWGObjCodeAPPIDCONTROLOBJ));
    DoError(vIndex < 0, sCannotFindTable, [sAppIDTableRecord, vCode]);
    Result := DoHandle;
    AddCommonEntityData(Result, vCode, vBits);
    vBits.WriteTV(AppInfo, FCodePage);
    vBits.WriteBit(1);
    vBits.WriteBS(0);
    vBits.WriteBit(GetXdep(AppInfo));
    vBits.WriteRC(0);
    AddHandlesUpdateAndFinish(vBits,
      [CreateDWGHandle(FCreatedElements[vIndex].Handle, cntDWGObjHandleSoftPointer),
      CreateDWGHandle(cnstBadHandle, cntDWGObjHandleHardOwner),
      CreateDWGHandle(GetEntityHandle(EntXrefBlock(nil, Converter)){cnstBadHandle}, cntDWGObjHandleHardPointer)],
      Result, vCode);
    AddCreatedElem('', nil, FCreatedElements, vCode, Result);
  finally
    vBits.Free;
  end;
end;

procedure TsgCADtoDWG.ExportTableVPORT;
var
  vOwnerHandle: UInt64;
  vVPort: TsgDXFVPort;
  vNeedsToBeDeleted: Boolean;
  vViewPortsHandles: TsgDWGHandleArray;
//  I: Integer;

  function FindActiveVPort: TsgDXFVPort;
//  var
//    I: Integer;
  begin
    Result := nil;
//    if Converter.Sections[csVPorts] = nil then Exit;
//    for I := 0 to Converter.Sections[csVPorts].Count - 1 do
//      if SameText(sActiveVPort, TsgDXFVPort(Converter.Sections[csVPorts].Entities[I]).Name) then
//      begin
//        Result := TsgDXFVPort(Converter.Sections[csVPorts].Entities[I]);
//        Break;
//      end;
  end;

begin
  vOwnerHandle := GetVPortControlObjectHandle;
  vVPort := FindActiveVPort;
  vNeedsToBeDeleted := vVPort = nil;
  if vNeedsToBeDeleted then
    vVPort := CreateDefaultVPort(DoHandle);
  try
    ProcVPort(vOwnerHandle, vVPort, vViewPortsHandles);
//    if Assigned(Converter.Sections[csVPorts]) then
//      for I := 0 to Converter.Sections[csVPorts].Count - 1 do
//        if not SameText(TsgDXFVPort(Converter.Sections[csVPorts].Entities[I]).Name, sActiveVPort) then
//          ProcVPort(vOwnerHandle, TsgDXFVPort(Converter.Sections[csVPorts].Entities[I]), vViewPortsHandles);
    AddOwnerAndXDiObjHandle(vViewPortsHandles);
    ProcViewPortControlObject(vOwnerHandle, vViewPortsHandles);
  finally
    if vNeedsToBeDeleted then
      vVPort.Free;
  end;
end;

function TsgCADtoDWG.ExportText(T: TsgDXFText; ABits: TsgDWGBits): Boolean;
var
  vFlags: Byte;
  vBitPos: Cardinal;
  vObliqueAngle: Double;
  vFirstPoint, vSecondPoint: TFPoint;

  procedure WriteRDAndChangeFlag(const Value: Double; Mask: Byte);
  begin
    if not IsZero(Value) then
    begin
      vFlags := vFlags or Mask;
      ABits.WriteRD(Value);
    end;
  end;

  procedure WriteBSAndChangeFlag(const Value: Word; Mask: Byte);
  begin
    if Value <> 0 then
    begin
      vFlags := vFlags or Mask;
      ABits.WriteBS(Value);
    end;
  end;

  procedure WriteFirstPointAndChangeFlag(const APoint: TFPoint; Mask: Byte);
  begin
    WriteRDAndChangeFlag(APoint.Z, Mask);//Elevation RD --- present if !(DataFlags & 0x01)
    ABits.Write2RD(APoint);//Insertion pt 2RD 10
  end;

begin
  vBitPos := ABits.Position;
  ABits.WriteRC($FF); //Flag for using to determine presence of subsquent data
  vFlags := 0;
  vFirstPoint := T.Point;
  if TsgDXFTextEx(T).HasSecond then//Alignment pt 2DD 11 present if !(DataFlags & 0x02), use 10 & 20 values for 2 default values.
  begin
    vSecondPoint := T.Point1;
    if T.HAlign or T.VAlign <> 0 then
      if IsEqual(vFirstPoint.X, vSecondPoint.X) and
         IsEqual(vFirstPoint.Y, vSecondPoint.Y) then
        vFirstPoint := T.StartPoint;
    WriteFirstPointAndChangeFlag(vFirstPoint, $01);
    vFlags := vFlags or $02;
    ABits.WriteDD(vSecondPoint.X, vFirstPoint.X);
    ABits.WriteDD(vSecondPoint.Y, vFirstPoint.Y);
  end
  else
    WriteFirstPointAndChangeFlag(vFirstPoint, $01);
  ABits.WriteBE(T.Extrusion);//Extrusion BE 210
  ABits.WriteBT(0);//Thickness BT 39
  vObliqueAngle := Abs(T.ObliqueAngle);
  if (vObliqueAngle > 85) and (vObliqueAngle <= 180) then
    vObliqueAngle := vObliqueAngle - 180;
  if (vObliqueAngle > 180) and (vObliqueAngle < 275) then
    vObliqueAngle := vObliqueAngle + 180;
  if T.ObliqueAngle < 0 then
    vObliqueAngle := -1 * vObliqueAngle;
  WriteRDAndChangeFlag(vObliqueAngle / f180DividedByPi, $04);//Oblique ang RD 51 present if !(DataFlags & 0x04)
  WriteRDAndChangeFlag(T.Rotation / f180DividedByPi, $08);//Rotation ang RD 50 present if !(DataFlags & 0x08)
  ABits.WriteRD(T.Height);//Height RD 40
  WriteRDAndChangeFlag(T.Scale, $10);//Width factor RD 41 present if !(DataFlags & 0x10)
  ABits.WriteTV(GetEntityStringValue(T), FCodePage);//Text value TV 1
  WriteBSAndChangeFlag(T.Generation, $20);//Generation BS 71 present if !(DataFlags & 0x20));
  WriteBSAndChangeFlag(T.HAlign, $40);//Horiz align. BS 72 present if !(DataFlags & 0x40)
  WriteBSAndChangeFlag(T.VAlign, $80);//Vert align. BS 73 present if !(DataFlags & 0x80)
  ABits.UpdateRC(vBitPos, not vFlags);
  if T.EntType <> ceText then
  begin
    ABits.WriteTV(TsgDXFAttrib(T).Tag, FCodePage);//Tag TV 2
    ABits.WriteBS(0);//Field length BS 73 unused
    ABits.WriteRC(TsgDXFAttrib(T).Flags);//Field length BS 73 unused
    if T.EntType = ceAttdef then
      ABits.WriteTV('', FCodePage);//Prompt TV 3
  end;
  Result := True;
end;

function TsgCADtoDWG.ExportTolerance(T: TsgDXFTolerance; ABits: TsgDWGBits): Boolean;
begin
  ABits.Write3BD(T.Point);//Ins pt 3BD 10
  ABits.WriteXDirection(TsgDXFToleranceEx(T).HasSecond, T.Point1);//X direction 3BD 11
  ABits.Write3BD(T.Extrusion);//Extrusion 3BD 210 etc
  ABits.WriteTV(PrepareTextForDWG(T.Text), FCodePage, True);//Text string BS 1
  Result := True;
end;

function TsgCADtoDWG.ExportUnknownObject(E: TsgDXFEntity;
  const AExportData: TsgDirectExportData): Boolean;
var
  vDummy: TsgDXFPoint;
  vData: TsgDirectExportData;
begin
  Result := True;
  if E = nil then Exit;
  vDummy := TsgDXFPoint.Create;
  try
    vData := AExportData;
    vDummy.AssignEntity(E);
    vDummy.Visible := False;
    vDummy.Visibility := False;
    if E is TsgDXFPenLine then
      vDummy.Point := TsgDXFPenLine(E).Point;
    if E is TsgDXFVertex then
      vDummy.Point := TsgDXFVertex(E).Point;
    vDummy.Handle := GetEntityHandle(E, True);
    vData.EntDWGCode := cntDWGObjCodeUNSUSED;
    DoExport(vDummy, @vData);
  finally
    vDummy.Free;
  end;
end;

function TsgCADtoDWG.ExportVertex(Owner: TsgDXFEntity; V: TsgDXFVertex;
  DWGCode: Word; ABits: TsgDWGBits): Boolean;
var
  vPoint: TFPoint;
begin
  Result := True;
  if DWGCode <> cntDWGObjCodeVERTEXPFACEFACE then
    ABits.WriteRC(V.Flags);
  case DWGCode of
    cntDWGObjCodeVERTEX2D:
      begin
        ABits.Write3BD(MakeFPoint(V.Point.X, V.Point.Y, {TsgDXFPolyline(Owner).Elevation}0));
        if (not IsZero(V.StartWidth)) and IsEqual(V.StartWidth, V.EndWidth) then
          ABits.WriteBD(-V.StartWidth)
        else
        begin
          ABits.WriteBD(V.StartWidth);
          ABits.WriteBD(V.EndWidth);
        end;
        ABits.WriteBD(V.Bulge);
        ABits.WriteBD(0);//V.FitTangent
      end;
    cntDWGObjCodeVERTEXPFACEFACE:
      begin
        ABits.WriteBS(V.PolyFaceVertexIndex1);
        ABits.WriteBS(V.PolyFaceVertexIndex2);
        ABits.WriteBS(V.PolyFaceVertexIndex3);
        ABits.WriteBS(V.PolyFaceVertexIndex4);
      end;
  else
    begin
      vPoint := V.Point;
      DoExtrusion(vPoint, TsgCADBasePolyline(Owner).Extrusion);
      ABits.Write3BD(vPoint);
    end;
  end;
end;

function TsgCADtoDWG.ExportViewPort(V: TsgDXFViewPort; ABits: TsgDWGBits): Boolean;

begin
  Result := True;
  ABits.Write3BD(V.PSpaceCenter);//Center 3BD 10
  ABits.WriteBD(V.PSpaceWidth);//Width BD 40
  ABits.WriteBD(V.PSpaceHeight);//Height BD 41
  ABits.Write3BD(V.ViewTarget); //View Target 3BD 17
  ABits.Write3BD(V.ViewDirection);// View Direction 3BD 16
  ABits.WriteBD(V.ViewTwistAngle / f180DividedByPi);// View Twist Angle BD 51
  ABits.WriteBD(V.MSpaceHeight);// View Height BD 45
  ABits.WriteBD(cntViewPortPerspectiveLensLength);// Lens Length BD 42
  ABits.WriteBD(V.FrontClipPlane);// Front Clip Z BD 43
  ABits.WriteBD(V.BackClipPlane);// Back Clip Z BD 44
  ABits.WriteBD(0);// Snap Angle BD 50
  ABits.Write2RD(V.MSpaceCenter);// View Center 2RD 12
  ABits.Write2RD(cnstFPointZero);// Snap Base 2RD 13
  ABits.Write2RD(MakeF2DPoint(0.5, 0.5));// Snap Spacing 2RD 14
  ABits.Write2RD(cnstFPointZero);//Grid Spacing 2RD 15
  ABits.WriteBS(cntViewPortCircleZoomPercent);// Circle Zoom BS 72
  if Version >= acR2007 then
    ABits.WriteBS(0);// Grid Major BS 61
  if Assigned(V.FrozenLayers) and (V.FrozenLayers.Count > 0) then
    ABits.WriteBL(V.FrozenLayers.Count)
  else
    ABits.WriteBL(0); // Frozen Layer Count BL !!! must be V.FrozenLayers.Count
  ABits.WriteBL(V.Flags);// Status Flags BL 90
  ABits.WriteTV('', FCodePage);// Style Sheet TV 1
  ABits.WriteRC(0);// Render Mode RC 281 0 - 2D Optimized (classic 2D)
  ABits.WriteBit(0);// UCS at origin B 74
  ABits.WriteBit(1);// UCS per Viewport B 71 0 - The UCS will not change when this viewport becomes active
//                                           1 - This viewport stores its own UCS which will become the current UCS whenever the viewport is activated
  ABits.Write3BD(cnstExtrusion);// UCS Origin 3BD 110
  ABits.Write3BD(cnstXOrtAxis);// UCS X Axis 3BD 111
  ABits.Write3BD(cnstYOrtAxis);// UCS Y Axis 3BD 112
  ABits.WriteBD(0);// UCS Elevation BD 146
  ABits.WriteBS(0);// UCS Ortho View Type BS 79
  if Version >= acR2004 then
    ABits.WriteBS(0);// ShadePlot Mode BS 170 0 - As Displayed
  if Version >= acR2007 then
  begin
    ABits.WriteBit(True);// Use def. lights B 292
    ABits.WriteRC(0);// Def. lighting type RC 282 0 - One distant light
    ABits.WriteBD(50);// Brightness BD 141
    ABits.WriteBD(50);// Contrast BD 142
    ABits.WriteCMC(cnstColorCADByWhite);// Ambient light color CMC 63
  end;
end;

procedure TsgCADtoDWG.ExportViewPortEntityHeaders;
var
  I, vCount, vIndex: Integer;
begin
  vCount := FCreatedElements.CountOf(Word(cntDWGObjCodeVPENTHDR), vIndex);
  if vCount = 0 then Exit;
  for I := vIndex to vIndex + vCount - 1 do
    ProcViewPortEntHeader(I);
end;

function TsgCADtoDWG.ExportWipeOut(W: TsgCADWipeout; ABits: TObject): Boolean;
var
  I, vCount: Integer;
  vBits: TsgDWGBits;
  vSize, vUVector, vVVector: TFPoint;
begin
  Result := True;
  vBits := TsgDWGBits(ABits);
  vBits.WriteBL(0);//BL 90 class version
  vBits.Write3BD(W.Point);//pt0 3BD 10 insertion point

  GetCorrectImageVectorData(TsgDXFImageEnt(W), vUVector, vVVector, vSize);
  vBits.Write3BD(vUVector);//uvec 3BD 11 u direction vector
  vBits.Write3BD(vVVector);//vvec 3BD 12 v direction vector
  vBits.Write2RD(vSize);//size 2RD 13 size of image

  vBits.WriteBS(W.Flags);//displayprops BS 70
  vBits.WriteBit(W.UseClipping);//clipping B 280 1 if on
  vBits.WriteRC(cntImageBrightness);//brightness RC 281 brightness value (0—100, default 50)
  vBits.WriteRC(cntImageContrast);//contrast RC 282 contrast value (0—100, default 50)
  vBits.WriteRC(cntImageFade);//fade RC 283 fade value (0—100, default 0)
  if Version > acR2007 then
    vBits.WriteBit(0);//Clip mode B 290 0 = outside, 1 = inside
  vBits.WriteBS(W.ClippingBoundaryType);//clipbndtype BS 71 type of clipping boundary, 1==rect, 2==polygon
  case W.ClippingBoundaryType of //!!! not sure
    1, 2:
      begin
        if W.ClippingBoundaryType > 1 then
          vBits.WriteBL(GetRealCountBoundaryPoints(W));
        vCount := W.ClipPointsCount;
        for I := 0 to vCount - 1 do
          vBits.Write2RD(W.ClipPoints[I]);
        if IsNeedAddPointForBoundary(W) then
          vBits.Write2RD(W.ClipPoints[0]);
      end;
  end;
end;

function TsgCADtoDWG.ExportWipeOutAsExternalFile(W: TsgCADWipeout;
  AData: TObject): Boolean;
var
  vData: TsgDWGExportDataClass;
  vExportData: TsgDirectExportData;
begin
  Result := True;
  vData := TsgDWGExportDataClass(AData);
  vExportData := vData.ExportData;
  vExportData.EntDWGCode := cntDWGObjCodeIMAGE;
  vExportData.UseEntCode := True;
  DoExport(TsgDXFEntity(vData.OwnerObject), @vExportData);
end;

procedure TsgCADtoDWG.ExportTableLAYER;
const
  sZeroLayer = '0';
var
  I, vFirstLayerIndex, vZeroLayerIndex: Integer;
  vOwnerHandle: UInt64;
  vZeroLayer: TsgDXFLayer;
  vProcHandles: TsgDWGHandleArray;

  vDWGHandle1, vDWGHandle2: TsgDWGHandle;
begin
  vOwnerHandle := GetLayerControlObjectHandle;
  vZeroLayer := nil;
  try
    AddOwnerAndXDiObjHandle(vProcHandles);
    vZeroLayerIndex := -1;
    vFirstLayerIndex := Length(vProcHandles);

    if TsgDXFTable(Converter.Sections[csLayers]).FindEntByName(sZeroLayer) = nil then
    begin
      vZeroLayer := TsgDXFLayer.Create;
      vZeroLayer.Handle := DoHandle;
      vZeroLayer.ColorCAD := MakeColorCAD(acIndexColor, clDXFBlackWhite);
      vZeroLayer.Name := sZeroLayer;
      vZeroLayer.LineType := TsgDXFLineType(TsgDXFTable(Converter.Sections[csLTypes]).FindEntByName(sContinuous));
      vZeroLayer.LineWeight := 0;
      vZeroLayer.Visible := True;
      vZeroLayer.Locked := False;
      vZeroLayer.Frozen := False;
      AddCreatedElem('0', nil, FCreatedElements, cntDWGObjCodeLAYER, vZeroLayer.Handle);
    end;
    if vZeroLayer <> nil then
      ProcLayer(vOwnerHandle, vZeroLayer, vProcHandles, vZeroLayerIndex);
    if Converter.Sections[csLayers] <> nil then
      for I := 0 to Converter.Counts[csLayers] - 1 do
        ProcLayer(vOwnerHandle, TsgDXFLayer(Converter.Layers[I]),
          vProcHandles, vZeroLayerIndex);

    if (vZeroLayerIndex >= 0) and (vZeroLayerIndex <> vFirstLayerIndex) then //Layer '0' must be first
    begin
      vDWGHandle1 := vProcHandles[vFirstLayerIndex];
      vDWGHandle2 := vProcHandles[vZeroLayerIndex];
      vProcHandles[vFirstLayerIndex] := vDWGHandle2;
      vProcHandles[vZeroLayerIndex] := vDWGHandle1;
    end;

    ProcLayerControlObject(vOwnerHandle, vProcHandles);
  finally
    vZeroLayer.Free;
  end;
end;

procedure TsgCADtoDWG.ExportTableLTYPE;
const
  cntByBlockIndex = 0;
  cntByLayerIndex = 1;
var
  vHasByBlock, vHasByLayer: Boolean;
  vLType: TsgDXFLineType;
  I: Integer;
  vOwnerHandle: UInt64;
  vFlag: Boolean;
  vHandles, vByLayerAndByBlockHandles: TsgDWGHandleArray;

  function CheckName(LType: TsgDXFLineType; AName, ACheckName: string;
    var Value: Boolean; Index: Integer): Boolean;
  var
    vOldVal: Boolean;
  begin
    Result := False;
    vOldVal := Value;
    Value := SameText(AName, ACheckName) or Value;
    if (vOldVal <> Value) and Assigned(LType) then
    begin
      if LType.Handle = cnstBadHandle then
        LType.Handle := DoHandle;
      vByLayerAndByBlockHandles[Index] := CreateDWGHandle(LType.Handle, cntDWGObjHandleHardOwner);
      Result := True;
    end;
  end;

  procedure AddLType(IfLTypeExists: Boolean; const Name: string; Index: Integer);
  var
    vLType: TsgDXFLineType;
  begin
    vLType := TsgDXFLineType.Create;
    try
      if not IfLTypeExists then
      begin
        vLType.Name := Name;
        CheckName(vLType, vLType.Name, Name, IfLTypeExists, Index);
        ProcLType(vOwnerHandle, vLType);
      end;
    finally
      vLType.Free;
    end;
  end;

begin
  vHasByBlock := False;
  vHasByLayer := False;
  vOwnerHandle := GetLineTypeControlObjectHandle;

  SetLength(vByLayerAndByBlockHandles, 2);
  AddOwnerAndXDiObjHandle(vHandles);
  if Converter.Sections[csLTypes] <> nil then
  begin
    for I := 0 to Converter.Counts[csLTypes] - 1 do
    begin
      vLType := TsgDXFLineType(Converter.LTypes[I]);
      vFlag := CheckName(vLType, vLType.Name, sByLayer, vHasByLayer, cntByLayerIndex);
      vFlag := CheckName(vLType, vLType.Name, sByBlock, vHasByBlock, cntByBlockIndex) or vFlag;
      if not vFlag then
      begin
        SetLength(vHandles, Length(vHandles) + 1);
        vHandles[High(vHandles)] := CreateDWGHandle(vLType.Handle, cntDWGObjHandleSoftOwner);
      end;
      ProcLType(vOwnerHandle, vLType);
    end;
  end;

  // Default entry ByBlock, ByLayer
  AddLType(vHasByLayer, sByLayer, cntByLayerIndex);
  AddLType(vHasByBlock, sByBlock, cntByBlockIndex);

  SetLength(vHandles, Length(vHandles) + Length(vByLayerAndByBlockHandles));
  vHandles[High(vHandles) - 1] := vByLayerAndByBlockHandles[0];
  vHandles[High(vHandles)] := vByLayerAndByBlockHandles[1];

  ProcLTypeControlObject(vOwnerHandle, vHandles);
end;

type
  TsgProcDictByStrList = procedure(const Handle, OwnerHandle: UInt64;
    const Index: Integer; const Name: string) of object;

procedure TsgCADtoDWG.ExportTableOBJECTS;

  procedure AddToItems(Items: TStringList; const Handle: UInt64; const Name: string);
  begin
    Items.Values[IntToHex(Handle, 2)] := Name;
  end;

  function GetItemForDictionary(Items: TStringList; var Handle, OwnerHandle: UInt64;
    const AName: string): Boolean;
  var
    I, vIndex, vCount: Integer;
    vElem: TsgDWGCreatedElement;
    vHandle: UInt64;
    vName: string;
    vRasterVariables: TsgCADRasterVariables;

    procedure ProcFromStrList(const DXFClass: string; const AList: TStringList;
      Proc: TsgProcDictByStrList);
    var
      I, vIndex, vCount: Integer;
      vName, vVal: string;
    begin
      vCount := FCreatedElements.CountOf(GetDWGCodeByClass(DXFClass), vIndex);
      DoError(vCount <> AList.Count, sListsNotEqual);
      for I := 0 to AList.Count - 1 do
      begin
        vName := AList.Names[I];
        vVal := AList.Values[vName];
        AddToItems(Items, FCreatedElements[I + vIndex].Handle, vName);
        Proc(FCreatedElements[I + vIndex].Handle, Handle, I, vVal);
      end;
    end;

  begin
    Result := True;
    Items.Clear;

    if SameText(AName, sNamedObjectsDictionary) then //main dictionary object
    begin
      OwnerHandle := 0;
      Handle := GetDictionaryNamedObjectHandle;
      vCount := FCreatedElements.CountOf(Word(cntDWGObjCodeDICTIONARY1), vIndex);
      for I := vIndex to vIndex + vCount - 1 do
      begin
        vElem := FCreatedElements[I];
        if not SameText(vElem.Name, sNamedObjectsDictionary) then
        begin
          if I = 7 then
            AddToItems(Items, cnstBadHandle, cntEmptyDictionary); //do not know why but DWG file needs an empty dictionary
          AddToItems(Items, vElem.Handle, vElem.Name);
        end;
      end;
      Exit;
    end;

    vIndex := FCreatedElements.IndexOf(AName);
    if vIndex < 0 then
    begin
      Result := False;
      Exit;
    end;

    vElem := FCreatedElements[vIndex];
    OwnerHandle := vElem.OwnerHandle;
    Handle := vElem.Handle;

    //empty dictionaries
    if SameText(AName, sAcadGroupDictionary) or SameText(AName, sAcadMaterialDictionary) or
      SameText(AName, sAcadMLeaderStyleDictionary)  then
        Exit;

    //ACAD_MLINESTYLE
    if SameText(AName, sAcadMLineStyleDictionary) then
    begin
      if Converter.Sections[csMLineStyles] <> nil then
        for I := 0 to TsgDXFTable(Converter.Sections[csMLineStyles]).Count - 1 do
        begin
          AddToItems(Items, TsgDXFTable(Converter.Sections[csMLineStyles]).Entities[I].Handle,
            (TsgDXFTable(Converter.Sections[csMLineStyles]).Entities[I] as TsgMLineStyle).Name);
          ProcMLineStyle(TsgMLineStyle(TsgDXFTable(Converter.Sections[csMLineStyles]).Entities[I]), Handle);
        end;
      Exit;
    end;

    //ACAD_IMAGE_DICT
    if SameText(AName, sAcadImageDict) then
    begin
      for I := 0 to Converter.Counts[csImageDefs] - 1 do
        AddToItems(Items, Converter.Sections[csImageDefs].Entities[I].Handle,
          TsgDXFEntityEx(Converter.Sections[csImageDefs].Entities[I]).EntName);
      for I := 0 to ImageDefList.Count - 1 do
        AddToItems(Items, TsgDXFEntity(ImageDefList[I]).Handle, TsgDXFEntity(ImageDefList[I]).EntName);
      Exit;
    end;

    //RASTERVARIABLES
    if SameText(AName, sAcadImageVars) then
    begin
      vRasterVariables := TsgCADRasterVariables(ExportCADImage.Converter.Sections[csObjects].FindEntByName(sRasterVariables));
      if Assigned(vRasterVariables) then
        ProcRasterVariables(vRasterVariables, OwnerHandle);
      Result := False; //not needed to add the RASTERVARIABLES dict to Distionary list see ACAD_WIPEOUT_VARS below
      Exit;
    end;

    //ACAD_SCALE
    if SameText(AName, sAcadScaleListDictionary) then
    begin
      ProcFromStrList(cntClassDXFSCALE, FScalesDictionary, ProcScale);
      Exit;
    end;

    //ACAD_WIPEOUT_VARS
    if SameText(AName, sAcadWipeOutVarsDictionary) then
    begin
      Result := False;
      ProcWipeoutVar(Handle, OwnerHandle);
      Exit;
    end;

    //AcDbVariableDictionary
    if SameText(AName, sAcDbVariableDictionary) then
    begin
      ProcFromStrList(cntClassDXFDICTIONARYVAR, FVariableDictionary,
        ProcVariableDictionary);
      Exit;
    end;

    //DWGPROPS
    if SameText(AName, sDWGPropsDictionary) then
    begin
      ProcDWGProps(Handle, OwnerHandle);
      Result := False;
      Exit;
    end;

    //ACAD_LAYOUT
    if SameText(AName, sAcadLayoutDictionary) then
    begin
      ProcLayout(ExportCADImage.Layouts[0], ExportCADImage.Layouts[0].Handle, Handle, 0, '');
      AddToItems(Items, ExportCADImage.Layouts[0].Handle, sModel);
      if GetPaperLayout = nil then
      begin
        vHandle := GetPaperSpaceLayoutHandle(@vIndex);
        vName := FCreatedElements[vIndex].Name;
        ProcLayout(nil, vHandle, Handle, 1, vName);
        AddToItems(Items, vHandle, vName);
      end
      else
        for I := 1 to ExportCADImage.LayoutsCount - 1 do
        begin
          ProcLayout(ExportCADImage.Layouts[I], ExportCADImage.Layouts[I].Handle, Handle, I, '');
          AddToItems(Items, ExportCADImage.Layouts[I].Handle, ExportCADImage.Layouts[I].Name);
        end;
      Result := True;
      Exit;
    end;
  end;

var
  vItems: TStringList;
  vHandle, vOwnerHandle: UInt64;
  I: Integer;
begin
  vItems := TStringList.Create;
  try
    for I := Low(cnstDWGDictionaries) to High(cnstDWGDictionaries) do
      if GetItemForDictionary(vItems, vHandle, vOwnerHandle, cnstDWGDictionaries[I]) then
        ProcDictionary(vHandle, vOwnerHandle, vItems);
  finally
    vItems.Free;
  end;
end;

procedure TsgCADtoDWG.FinishObject(const ObjHandle: UInt64; const ABits: TsgDWGBits;
  const AObjSize: Cardinal; ADWGCode: Word; AWriteCRC: Boolean = True);
begin
  ABits.InsertMS(0, AObjSize);
  if AWriteCRC then
    ABits.WriteCRC8(cnstObjectCRCInit);
  DoError(ObjHandle = cnstBadHandle, sHandleInvalid);
  SaveObjectToStream(ObjHandle, ABits, ADWGCode);
end;

function TsgCADtoDWG.Get64bitof70Group(Flags: Word): Byte;
begin
  if Flags and 64 <> 0 then
    Result := 1
  else
    Result := 0;
end;

function TsgCADtoDWG.GetActiveLayerHandle(AGetZeroLayer: Boolean = False): UInt64;
var
  vLayer: TsgDXFLayer;
  vNameFirst, vNameSecord: string;
begin
  if AGetZeroLayer then
  begin
    vNameFirst := Converter.HeadVarStruct.CLayer;
    vNameSecord := '0';
  end
  else
  begin
    vNameFirst := '0';
    vNameSecord := Converter.HeadVarStruct.CLayer;
  end;
  vLayer := Converter.LayerByName(vNameFirst);
  if vLayer = nil then
    vLayer := Converter.LayerByName(vNameSecord);
  Result := GetEntityHandle(vLayer);
end;

function TsgCADtoDWG.GetAppIDControlObjectHandle: UInt64;
begin
  Result := GetEntityHandle(nil, False, cntDWGObjCodeAPPIDCONTROLOBJ);
end;

function TsgCADtoDWG.GetArrowBlockHandle(const Value: TsgDimArrowType): UInt64;
var
  vBlockName: string;
begin
  vBlockName := GetNameByArrowType(Value, sgDimensionArrowTypeNames[Low(sgDimensionArrowTypeNames)]);
  Result := GetEntityHandle(Converter.Sections[csBlocks].FindEntByName(vBlockName));
end;

function TsgCADtoDWG.GetAuxHeaderOffset: Cardinal;
begin
  Result := cntDWGR15FileHeaderSize;
end;

function TsgCADtoDWG.GetAuxHeaderSectionIndex: Integer;
begin
  Result := 5;
end;

function TsgCADtoDWG.GetBlockControlObjectHandle: UInt64;
begin
  Result := GetEntityHandle(Converter.Sections[csBlockRecords], True,
    cntDWGObjCodeBLOCKCONTROLOBJ);
end;

function TsgCADtoDWG.GetClassesOffset: Cardinal;
begin
  Result := GetHeaderVarsOffset + Sections[GetHeaderVarsSectionIndex].Size;
end;

function TsgCADtoDWG.GetClassesSectionIndex: Integer;
begin
  Result := 1;
end;

procedure TsgCADtoDWG.GetCreateAndUpdateDateTime(var ADateCreate,
  ADateUpdate: TDateTime);
const
  cnt2Hours = 2;
var
  vYear, vMonth, vDay: Word;
  vHour, vMin, vSec, vMSec: Word;
begin
  ADateUpdate := Now;
  DecodeDateTime(ADateUpdate, vYear, vMonth, vDay, vHour, vMin, vSec, vMSec);
  while vHour < cnt2Hours do Inc(vHour);
  ADateCreate := EncodeDateTime(vYear, vMonth, vDay, vHour - cnt2Hours, vMin,
    vSec, vMSec);
  ADateUpdate := EncodeDateTime(vYear, vMonth, vDay, vHour, vMin, vSec, vMSec);
end;

function TsgCADtoDWG.GetCurrentViewportEntityHeaderHandle: UInt64;
var
  vLayout: TsgDXFLayout;
  I, vIndex: Integer;
  vViewPortHandle: UInt64;
begin
  Result := GetEntityHandle(nil);
  vLayout := GetPaperLayout;
  if vLayout <> nil then
  begin
    vViewPortHandle := cnstBadHandle;
    for I := 0 to vLayout.PaperSpaceBlock.Count - 1 do
    begin
      if vLayout.PaperSpaceBlock[I] is TsgDXFViewport then
      begin
        vViewPortHandle := vLayout.PaperSpaceBlock[I].Handle;
        Break;
      end;
    end;
    if vViewPortHandle <> cnstBadHandle then
    begin
      vIndex := FCreatedElements.IndexOf(vViewPortHandle, True);
      if vIndex >= 0 then
        Result := FCreatedElements[vIndex].Handle;
    end;
  end;
end;

function TsgCADtoDWG.GetDefVal(const Value, DefValue: Double): Double;
begin
  if IsZero(Value) then
    Result := DefValue
  else
    Result := Value;
end;

function TsgCADtoDWG.GetDictionaryAcadGroupHandle: UInt64;
begin
  Result := GetDictionaryHandle(sAcadGroupDictionary);
end;

function TsgCADtoDWG.GetDictionaryAcadImageDict: UInt64;
begin
  Result := GetDictionaryHandle(sAcadImageDict);
end;

function TsgCADtoDWG.GetDictionaryAcadMLineStyleHandle: UInt64;
begin
  Result := GetDictionaryHandle(sAcadMLineStyleDictionary);
end;

function TsgCADtoDWG.GetDictionaryHandle(AName: string): UInt64;
begin
  Result := GetEntityHandle(nil, False, cntDWGObjCodeDICTIONARY1, AName);
end;

function TsgCADtoDWG.GetDictionaryLayoutsHandle: UInt64;
begin
  Result := GetDictionaryHandle(sAcadLayoutDictionary);
end;

function TsgCADtoDWG.GetDictionaryNamedObjectHandle: UInt64;
begin
  Result := GetDictionaryHandle(sNamedObjectsDictionary);
end;

function TsgCADtoDWG.GetDictionaryPlotSettingHandle: UInt64;
begin
  Result := GetDictionaryHandle('');//!!!
end;

function TsgCADtoDWG.GetDictionaryPlotStyleHandle: UInt64;
begin
  Result := GetDictionaryHandle('');//!!!
end;

function TsgCADtoDWG.GetDimStyleControlObjectHandle: UInt64;
begin
  Result := GetEntityHandle(Converter.Sections[csDimStyles], True,
    cntDWGObjCodeDIMSTYLECONTROLOBJ);
end;

function TsgCADtoDWG.GetDWGCodeByClass(const AClassName: string): Word;
var
  vIndex: Integer;
begin
  vIndex := FClasses.IndexOf(AClassName);
  Result := Word(FClasses.Objects[vIndex]);
end;

function TsgCADtoDWG.GetDWGCodePage: Word;
begin
  Result := FDWGCodePage;
end;

function TsgCADtoDWG.GetEntHandleByIndex(Group: TsgDXFEntity; Index: Integer; AList: TList;
  EntIndex: Integer; AFirst: Boolean): UInt64;
var
  vEnt: TsgDXFEntityEx;
  vEntIndex: Integer;
begin
  Result := cnstBadHandle;
  if AList = nil then
  begin
    vEntIndex := Index;
    if (vEntIndex >= 0) and (vEntIndex < Group.Count) then
    begin
      vEnt := TsgDXFEntityEx(Group[vEntIndex]);
      Result := GetEntityHandle(vEnt, False, 0, '', False, AFirst);
    end;
  end
  else
    if (Index >= 0) and (Index <= AList.Count - 1) then
      Result := GetEntityHandle(TsgDXFEntity(AList[Index]), False, 0, '', False, AFirst);
end;

function TsgCADtoDWG.GetEntityHandle(const AEntity: TsgDXFEntity; ADoNewHandle: Boolean = False;
  ADWGCode: Word = cntDWGObjCodeUNSUSED; const AName: string = ''; ADoRaise: Boolean = False;
  AFirst: Boolean = True): UInt64;
var
  I, vCount, vIndex: Integer;
begin
  vCount := 0;
  Result := cnstBadHandle;
  if AEntity <> nil then
  begin
    if CreateGroup(AEntity) then
    begin
      if AFirst then
        Result := TsgDXFEntityEx(AEntity).Group[0].Handle
      else
        Result := TsgDXFEntityEx(AEntity).Group[TsgDXFEntityEx(AEntity).Group.Count - 1].Handle;
    end
    else
      Result := AEntity.Handle;
  end
  else
  begin
    if ADWGCode > 0 then
    begin
      vCount := FCreatedElements.CountOf(ADWGCode, vIndex);
      if vCount = 1 then
        Result := FCreatedElements[vIndex].Handle
      else
      begin
        if AName <> '' then
        begin
          for I := vIndex to vIndex + vCount - 1 do
            if SameText(AName, FCreatedElements[I].Name) then
            begin
              Result := FCreatedElements[I].Handle;
              Break;
            end;
        end;
      end;
    end;
  end;

  if (Result = cnstBadHandle) and ADoNewHandle then
  begin
    Result := DoHandle;
    if AEntity <> nil then
      AEntity.Handle := Result
    else
    begin
      if (ADWGCode > 0) and (vCount = 0) then
        FCreatedElements.AddElement(Result, 0, ADWGCode);
    end;
  end;
  if ADoRaise and (Result = cnstBadHandle) then
    raise Exception.Create(sHandleInvalid);
end;

function TsgCADtoDWG.GetExportExceptionClass: ExceptClass;
begin
  Result := EDWGExportError;
end;

function TsgCADtoDWG.GetFileHeaderSectionIndex: Integer;
begin
  Result := GetLocatorsCount;
end;

function TsgCADtoDWG.GetFingerPrintGUID: string;
begin
  Result := '{E44D33DF-D2B9-48AE-8431-27F629E25DDD}'; //AutoDesc {F536BED7-6F9E-468E-8820-242279AE2C2C} ODA {E44D33DF-D2B9-48AE-8431-27F629E25DDD}
end;

function TsgCADtoDWG.GetHandleByEntity(AEntity: TsgDXFEntity): UInt64;
begin
  if AEntity = nil then
    Result := cnstBadHandle
  else
  begin
    Result := AEntity.Handle;
    DoError(Result = cnstBadHandle, sHandleInvalid);
  end;
end;

function TsgCADtoDWG.GetHeaderVarsOffset: Cardinal;
begin
  Result := GetPreViewImageOffset + Sections[GetPreviewSectionIndex].Size;
end;

function TsgCADtoDWG.GetHeaderVarsSectionIndex: Integer;
begin
  Result := 0;
end;

function TsgCADtoDWG.GetLastActiveViewportHandle(ALayout: TsgDXFLayout): UInt64;
var
  I: Integer;
begin
  Result := cnstBadHandle;
  if ALayout = nil then
    Exit
  else
    if ALayout.IsModel then Exit;
  for I := 0 to ALayout.PaperSpaceBlock.Count - 1 do
    if ALayout.PaperSpaceBlock.Entities[I] is TsgDXFViewport then
    begin
      Result := ALayout.PaperSpaceBlock.Entities[I].Handle;
      Break;
    end;
end;

function TsgCADtoDWG.GetLayerControlObjectHandle: UInt64;
begin
  Result := GetEntityHandle(Converter.Sections[csLayers], True,
    cntDWGObjCodeLAYERCONTROLOBJ);
end;

function TsgCADtoDWG.GetLineTypeHandle(LineType: TsgDXFLineType): UInt64;
var
  vLineTypeName: string;
begin
  if LineType = nil then
    vLineTypeName := sContinuous
  else
    vLineTypeName := LineType.Name;

  Result := GetEntityHandle(Converter.LTypeByName(vLineTypeName));
end;

function TsgCADtoDWG.GetLineTypeControlObjectHandle: UInt64;
begin
  Result := GetEntityHandle(Converter.Sections[csLTypes], True,
    cntDWGObjCodeLTYPECONTROLOBJ);
end;

function TsgCADtoDWG.GetLocatorsCount: Integer;
begin
  Result := cntDWGR15SectionsCount;
end;

function TsgCADtoDWG.GetMeasurementSectionIndex: Integer;
begin
  Result := 4;
end;

function TsgCADtoDWG.GetMLineStyle: TsgMLineStyle;
begin
  Result := nil;
  if (Converter.Sections[csMLineStyles] <> nil) and (Converter.Sections[csMLineStyles].Count > 0) then
    Result := TsgMLineStyle(Converter.Sections[csMLineStyles].Entities[0]);
end;

function TsgCADtoDWG.GetModelAndPaperSpaceBlockHandle(const AIndex: Integer): UInt64;
var
  vBlock: TsgDXFEntity;
  P: ^UInt64;
  vLayout: TsgDXFLayout;
begin
  Result := 0;
  vBlock := nil;
  case AIndex of
    0:
      begin
        vBlock := ExportCADImage.Layouts[0].PaperSpaceBlock;
        P := @FModelSpaceHandle;
      end
  else
    begin
      vLayout := GetPaperLayout;
      if vLayout <> nil then
         vBlock := vLayout.PaperSpaceBlock;
      P := @FPaperSpaceHandle;
    end;
  end;
  if P^ <> cnstBadHandle then
  begin
    Result := P^;
    Exit;
  end;
  if vBlock <> nil then
    Result := vBlock.Handle;
  if Result <> cnstBadHandle then
    P^ := Result
  else
  begin
    Result := DoHandle;
    P^ := Result;
  end;
end;

function TsgCADtoDWG.GetModelSpaceBlockHandle: UInt64;
begin
  Result := GetModelAndPaperSpaceBlockHandle(0);
end;

function TsgCADtoDWG.GetNextEntHandle(Group: TsgDXFEntity; Index: Integer;
  AList: TList = nil): UInt64;
begin
  Result := GetEntHandleByIndex(Group, Index + 1, AList, Index, True);
end;

function TsgCADtoDWG.GetObjectMapSectionIndex: Integer;
begin
  Result := 2;
end;

function TsgCADtoDWG.GetObjectsFileOffset: Cardinal;
begin
  Result := Sections[GetFileHeaderSectionIndex].Size +
    Sections[GetAuxHeaderSectionIndex].Size +
    Sections[GetPreviewSectionIndex].Size +
    Sections[GetHeaderVarsSectionIndex].Size +
    Sections[GetClassesSectionIndex].Size;
end;

function TsgCADtoDWG.GetObjectsSectionIndex: Integer;
begin
  Result := GetPreviewSectionIndex + 1;
end;

function TsgCADtoDWG.GetObjFreeSpaceOffset: Cardinal;
begin
  Result := GetObjMapOffset + Sections[GetObjectMapSectionIndex].Size;
end;

function TsgCADtoDWG.GetObjFreeSpaceSectionIndex: Integer;
begin
  Result := 3;
end;

function TsgCADtoDWG.GetObjMapOffset: Cardinal;
begin
  Result := GetObjectsFileOffset + Sections[GetObjectsSectionIndex].Size;
end;

function TsgCADtoDWG.GetPaperSpaceBlockHandle: UInt64;
begin
  Result := GetModelAndPaperSpaceBlockHandle(1);
end;

function TsgCADtoDWG.GetPaperSpaceLayoutHandle(PIndex: PInteger = nil): UInt64;
var
  vIndex: Integer;
  vLayout: TsgDXFLayout;
begin
  vLayout := GetPaperLayout;
  if vLayout = nil then
  begin
    vIndex := FCreatedElements.IndexOf(cntDWGObjCodeLAYOUT);
    DoError(vIndex < 0, sPaperSpaceLayoutIsNil);
    Result := FCreatedElements[vIndex].Handle;
    if PIndex <> nil then
      PIndex^ := vIndex
  end
  else
    Result := vLayout.Handle;
end;

function TsgCADtoDWG.GetPrevEntHandle(Group: TsgDXFEntity; Index: Integer;
   AList: TList = nil): UInt64;
begin
  Result := GetEntHandleByIndex(Group, Index - 1, AList, Index, False);
end;

function TsgCADtoDWG.GetPreviewImageHeigth: Integer;
begin
  Result := 85;
end;

function TsgCADtoDWG.GetPreViewImageOffset: Cardinal;
begin
  Result := cntDWGR15FileHeaderSize + Sections[GetAuxHeaderSectionIndex].Size;
end;

function TsgCADtoDWG.GetPreviewImageRect: TRect;
begin
  Result := Rect(0, 0, GetPreviewImageWidth, GetPreviewImageHeigth);
end;

function TsgCADtoDWG.GetPreviewImageWidth: Integer;
begin
  Result := 180;
end;

function TsgCADtoDWG.GetPreviewSectionIndex: Integer;
begin
  Result := GetFileHeaderSectionIndex + 1;
end;

function TsgCADtoDWG.GetRealDWGCode(const DWGCode: Word): Word;
begin
  Result := DWGCode;
  if Result > cntDWGObjCodeUSER then
  begin
    case Result of
      cntDWGObjCodeMPOLYGON:
        Result := GetDWGCodeByClass(cntClassDXFMPOLYGON);
      cntDWGObjCodeWIPEOUT:
        Result := GetDWGCodeByClass(cntClassDXFWIPEOUT);
      cntDWGObjCodeIMAGE:
        Result := GetDWGCodeByClass(cntClassDXFIMAGE);
      cntDWGObjCodeIMAGEDEF:
        Result := GetDWGCodeByClass(cntClassDXFIMAGEDEF);
      cntDWGObjCodeFLATHATCH:
        Result := GetRealDWGCode(cntDWGObjCodeMPOLYGON); //cntDWGObjCodeHATCH;
      cntDWGObjCodeRASTERVARIABLES:
         Result := GetDWGCodeByClass(cntClassDXFRASTERVARIABLES);
      cntDWGObjCodeUNKNOWNOBJ:
        Result := cntDWGObjCodePOINT;
    end;
  end;
end;

function TsgCADtoDWG.GetSecondHeaderOffset: Cardinal;
begin
  Result := GetObjectsFileOffset + Sections[GetObjectsSectionIndex].Size +
    Sections[GetObjectMapSectionIndex].Size + Sections[GetObjFreeSpaceSectionIndex].Size;
end;

function TsgCADtoDWG.GetSecondHeaderSectionIndex: Integer;
begin
  Result := GetObjectsSectionIndex + 1;
end;

function TsgCADtoDWG.GetSection(Index: Integer): TMemoryStream;
begin
  Result := TMemoryStream(FSections[Index]);
end;

function TsgCADtoDWG.GetSectionsCount: Integer;
begin
  Result := GetLocatorsCount + 4;
end;

function TsgCADtoDWG.GetStyleControlObjectHandle: UInt64;
begin
  Result := GetEntityHandle(Converter.Sections[csStyles], True,
    cntDWGObjCodeSTYLECONTROLOBJ);
end;

function TsgCADtoDWG.GetStyleHandle(Style: TsgDXFEntity; ADimStyle: Boolean): UInt64;
var
  vStyleName: string;
begin
  vStyleName := '';
  if Assigned(Style) then
    vStyleName := TsgDXFEntityEx(Style).GetName;
  if ADimStyle then
    Result := GetEntityHandle(Converter.DimensionStyleByName(vStyleName))
  else
    Result := GetEntityHandle(Converter.StyleByName(vStyleName));
end;

function TsgCADtoDWG.GetTemplateOffset: Cardinal;
begin
  Result := GetSecondHeaderOffset + Sections[GetSecondHeaderSectionIndex].Size;
end;

function TsgCADtoDWG.GetUCSontrolObjectHandle: UInt64;
begin
  Result := GetEntityHandle(nil, False, cntDWGObjCodeUCSCONTROLOBJ);
end;

function TsgCADtoDWG.GetVersionGUID: string;
begin
  Result := '{FAEB1C32-E019-11D5-929B-00C0DF256EC4}';
end;

function TsgCADtoDWG.GetViewControlObjectHandle: UInt64;
begin
  Result := GetEntityHandle(nil, False, cntDWGObjCodeVIEWCONTROLOBJ);
end;

function TsgCADtoDWG.GetViewPortEntityHeaderControlObjectHandle: UInt64;
begin
  Result := GetEntityHandle(nil, False, cntDWGObjCodeVPENTHDRCTRLOBJ);
end;

function TsgCADtoDWG.GetVPortControlObjectHandle: UInt64;
begin
  Result := GetEntityHandle(Converter.Sections[csVPorts], True,
    cntDWGObjCodeVPORTCONTROLOBJ);
end;

function TsgCADtoDWG.GetXdep(const AName: string): Byte;
begin
  if IsXRefInName(AName) then
    Result := 1
  else
    Result := 0;
end;

function TsgCADtoDWG.IsEntityHasNotEED(const Entity: TsgDXFEntity): Boolean;
begin
  Result := (Entity.EntType = ceViewport) or {(Entity is TsgSVGContainer) or}
    (Entity.EntClass.EG = gtSVG);
end;

function TsgCADtoDWG.IsPaperLayout(const AName: string): Boolean;
begin
  Result := GetPaperIndex(AName) > 0; //Result := Pos(GetPaperSpaceName, UpperCase(AName)) > 0;
end;

function TsgCADtoDWG.IsPaperSpace(ABlock: TsgDXFBlock): Boolean;
var
  vLayout: TsgDXFLayout;
begin
  vLayout := GetPaperLayout;
  if vLayout = nil then
    Result := True
  else
    Result := vLayout.PaperSpaceBlock = ABlock;
end;

function TsgCADtoDWG.IsPaperSpace(const AName: string; ABlock: TsgDXFBlock): Boolean;
begin
  Result := False;
  if GetPaperIndex(AName) = 1 then
    Result := IsPaperSpace(ABlock);
end;

procedure TsgCADtoDWG.OnWriteDimStyleControlObject(ABits: TsgDWGBits);
begin
  if Version >= acR2000 then
    ABits.WriteRC(0);
end;

procedure TsgCADtoDWG.ProcBlock(ABlock: TsgDXFBlock; const AName: string;
  Data: Pointer; APaperSpaceIndex: Integer);
var
  vBits: TsgDWGBits;
  vCode: Word;
  vHandle, vOwnerHandle, vBlockRecordHandle, vLayoutHandle: UInt64;
  vFlags: Byte;
  vOffset: TFPoint;
  I, J, vIndex: Integer;
  vBlock: TsgDXFBlock;
  vLayout: TsgDXFLayout;
  vNeedFreeBlock, vNoNeedEntities: Boolean;
  vHandles: TsgDWGHandleArray;
  vEnt: TsgDXFEntity;
  vOwnedEntHandles: TsgInt64List;
  vInserts: TList;
  vEntity: TsgDXFEntityEx;
  vPictureUpdate: Boolean;

  function GetEntHnd(AFirst: Boolean): UInt64;
  begin
    Result := cnstBadHandle;
    if (vBlock = nil) or (vOwnedEntHandles.Count = 0) or vNoNeedEntities then Exit;
    if AFirst then
      Result := vOwnedEntHandles[0]
    else
      Result := vOwnedEntHandles[vOwnedEntHandles.Count - 1];
  end;

  function IsAnonymousBlock(AFlags: Byte): Boolean;
  begin
    Result := (AFlags and 1) <> 0;
  end;

  function GetCorrectBlockName: string;
  begin
    Result := AName;
    if IsAnonymousBlock(vFlags) then
    begin
      if (Result <> '') and (Result[1] = '*') then
        Delete(Result, 1, 1);
      case Length(Result) of
        0: Result := 'A';
      else
        Result := Copy(Result, 1, 1);
      end;
      Result := '*' + UpperCase(Result);
      Exit;
    end;
    if IsPaperLayout(AName) then
    begin
      Result := UpperCase(GetPaperSpaceName);
      Exit;
    end;
  end;

  procedure AddOwnedHandle(E: TsgDXFEntity);
  begin
    if (E <> nil) and (E.Handle  <> cnstBadHandle) then
      vOwnedEntHandles.Add(E.Handle);
  end;

  procedure AddSGInserts(const APaperSpaceBlock: TsgDXFBlock; const AInserts: TList);
  var
    I: Integer;
    vIsLoaded: Boolean;
  begin
    vIsLoaded := APaperSpaceBlock.IsLoaded;
    APaperSpaceBlock.IsLoaded := False;
    if Assigned(AInserts) then
      for I := 0 to AInserts.Count - 1 do
        APaperSpaceBlock.AddEntity(AInserts[I]);
    APaperSpaceBlock.IsLoaded := vIsLoaded;
  end;

begin
  vNeedFreeBlock := False;
  vBlock := nil;
  vLayout := nil;
  vBits := TsgDWGBits.Create;
  vOwnedEntHandles := TsgInt64List.Create;
  try
    vCode := cntDWGObjCodeBLOCKHEADER;

    vOwnerHandle := GetBlockControlObjectHandle;
    vHandle := cnstBadHandle;
    vLayoutHandle := cnstBadHandle;

    vBlock := ABlock;

    vNoNeedEntities := False;
    vInserts := nil;
    if vBlock = nil then
    begin
      I := GetPaperIndex(AName);
      case I of
        0:
          begin
            vLayout := Converter.Layouts[0];
            vBlock := vLayout.PaperSpaceBlock;
            vHandle := ModelSpaceBlockHandle;
            vLayoutHandle := vLayout.Handle;
          end;
        1:
          if APaperSpaceIndex = -1 then
          begin
            vHandle := PaperSpaceBlockHandle;
            vLayout := GetPaperLayout;
            if vLayout <> nil then
              vBlock := vLayout.PaperSpaceBlock;
            if vBlock = nil then
            begin
              vBlock := TsgDXFBlock.Create;
              vBlock.Name := AName;
              vBlock.Handle := DoHandle;
              vBlock.Layer := Converter.LayerByName('0');
              if vBlock.Layer = nil then
                vBlock.Layer := Converter.LayerByName(Converter.HeadVarStruct.CLayer);
              vBlock.BlockRecord.Handle := DoHandle;
              vBlock.BlockRecord.Layer := vBlock.Layer;
              vNeedFreeBlock := True;
            end;
          end;
      end;
      if Assigned(vLayout) then
      begin
        vInserts := ExpSGInsert(vLayout);
        AddSGInserts(vLayout.PaperSpaceBlock, vInserts);
      end;
    end
    else
    begin
      vHandle := vBlock.Handle;
      if APaperSpaceIndex <> -1 then
      begin
        vInserts := ExpSGInsert(Converter.Layouts[APaperSpaceIndex]);
        AddSGInserts(vBlock, vInserts);
      end;
    end;
    if vHandle = cnstBadHandle then
      vHandle := DoHandle;
    DoError(vBlock = nil, sBlockIsNil);
    vBlockRecordHandle := vBlock.BlockRecord.Handle;
    vIndex := FCreatedEndBlk.AddPair(vBlock.Handle, DoHandle);
    AddCommonEntityData(vHandle, vCode, vBits);

    if ABlock <> nil then
      vFlags := ABlock.Flags
    else
      vFlags := $40;

    vBits.WriteTV(GetCorrectBlockName, FCodePage);
    vBits.WriteBit(vFlags, $40); //The 64-bit of the 70 group

    vBits.WriteBS(0);

    vBits.WriteBit(vFlags, $10);// Xdep B 70 block is dependent on an xref. (16 bit)

    vBits.WriteBit(IsAnonymousBlock(vFlags));// Anonymous B 1 if this is an anonymous block (1 bit)
    vBits.WriteBit(vFlags, 2);// Hasatts B 1 if block contains attdefs (2 bit)
    vBits.WriteBit(vFlags, 4);//Blkisxref B 1 if block is xref (4 bit)
    vBits.WriteBit(vFlags, 8);//Xrefoverlaid B 1 if an overlaid xref (8 bit)

    vNoNeedEntities := Assigned(ABlock) and TsgDXFBlockEx(ABlock).IsBlockByXRef; //(vFlags and 4 <> 0) or (vFlags and 8 <> 0) or ((Assigned(ABlock) and (ABlock.XrefPath <> '')));

    vBits.WriteBit(0);// Loaded Bit B 0 indicates loaded for an xref  !!! maybe  if ABlock <> nil then vBits.WriteBit(BoolToBit(ABlock.XrefPath <> nil));

    vOwnedEntHandles.ProcCompare := TsgPointerTypeComparer.CmpUInt64;
    vOwnedEntHandles.Sorted := False;
    for I := 0 to vBlock.Count - 1 do
    begin
      vPictureUpdate := False;
      vEntity := TsgDXFEntityEx(vBlock[I]);
      try
        if (vEntity.EntType = ceImageEnt) then
          vPictureUpdate := TsgDXFImageEntAccess(vEntity).PictureUpdate(ExportCADImage);
        if vEntity.GroupExists and CreateGroup(vEntity) then
        begin
          for J := 0 to vEntity.Group.Count - 1 do
            if J = 0 then
              vOwnedEntHandles.Add(GetEntHandleByIndex(vEntity.Group, J, nil, J, True))
            else
              if J = vEntity.Group.Count - 1 then
                vOwnedEntHandles.Add(GetEntHandleByIndex(vEntity.Group, J, nil, J, False))
              else
                AddOwnedHandle(vEntity.Group[J]);
        end
        else
          AddOwnedHandle(vEntity);
      finally
        if vPictureUpdate then
          TsgDXFImageEntAccess(vEntity).PictureUpdate(nil);
      end;
    end;
//    vOwnedEntHandles.Sort; //!!!

    if Version >= acR2004 then
      vBits.WriteBL(vOwnedEntHandles.Count);//Number of objects owned by this object

    if ABlock <> nil then
      vOffset := ABlock.Offset
    else
      vOffset := cnstFPointZero;

    vBits.Write3BD(vOffset);

    if ABlock <> nil then
      vBits.WriteTV(ABlock.XrefPath, FCodePage)
    else
      vBits.WriteTV('', FCodePage);

    //Insert Count RC
    //A sequence of zero or more non-zero RC’s, followed by a terminating 0 RC.
    //The total number of these indicates how many insert handles will be present.
    for I := 0 to vBlock.References.Count - 1 do
      if TsgDXFEntity(vBlock.References[I]).EntType = ceInsert then
        vBits.WriteRC(1);
    vBits.WriteRC(0);

    vBits.WriteTV('', FCodePage);//Block Description TV 4 Block description. ''
    vBits.WriteBL(0);//Size of preview data BL Indicates number of bytes of data following.  0

    if IsPaperLayout(AName) then
    begin
      if APaperSpaceIndex <> -1 then
        vLayoutHandle := Converter.Layouts[APaperSpaceIndex].Handle
      else
        vLayoutHandle := GetPaperSpaceLayoutHandle;
    end;

    //Handles
    AddHandleToArray(CreateDWGHandle(vOwnerHandle, cntDWGObjHandleSoftPointer), vHandles);
    AddHandleToArray(CreateDWGHandle(cnstBadHandle, cntDWGObjHandleHardOwner), vHandles);
    AddHandleToArray(CreateDWGHandle(cnstBadHandle, cntDWGObjHandleHardPointer), vHandles);
    AddHandleToArray(CreateDWGHandle(vBlockRecordHandle, cntDWGObjHandleHardOwner), vHandles);
    if Version < acR2004 then
    begin
      if not vNoNeedEntities then
      begin
        AddHandleToArray(CreateDWGHandle(GetEntHnd(True), cntDWGObjHandleSoftPointer), vHandles);
        AddHandleToArray(CreateDWGHandle(GetEntHnd(False), cntDWGObjHandleSoftPointer), vHandles);
      end
    end
    else
    begin
      for I := 0 to vOwnedEntHandles.Count - 1 do
        AddHandleToArray(CreateDWGHandle(vOwnedEntHandles[I], cntDWGObjHandleHardOwner), vHandles);
    end;
    AddHandleToArray(CreateDWGHandle(FCreatedEndBlk.Second[vIndex], cntDWGObjHandleHardOwner), vHandles);
    for I := 0 to vBlock.References.Count - 1 do
    begin
      vEnt := TsgDXFEntity(vBlock.References[I]);
      if vEnt.EntType = ceInsert then
        AddHandleToArray(CreateDWGHandle(vEnt.Handle, cntDWGObjHandleSoftPointer), vHandles);
    end;
    AddHandleToArray(CreateDWGHandle(vLayoutHandle, cntDWGObjHandleHardPointer), vHandles);

    AddHandlesUpdateAndFinish(vBits, vHandles, vHandle, vCode);
    ProcBlockRecord(vBlock, AName, @vHandle);
    TsgInt64List(Data).Add(vHandle);
  finally
    vBits.Free;
    vOwnedEntHandles.Free;
    if vNeedFreeBlock then
    begin
      FreeList(vInserts);
      vBlock.Free;
    end
    else
    begin
      if Assigned(vLayout) or (APaperSpaceIndex <> -1) then
        FSGInserts.Add(vInserts)
      else
        FreeList(vInserts);
    end;
  end;
end;

procedure TsgCADtoDWG.ProcBlockControl(BlockHandles: TsgInt64List);
var
  I: Integer;
  vHandles: TsgDWGHandleArray;
begin
  //Handles

  AddOwnerAndXDiObjHandle(vHandles);

  for I := 2 to BlockHandles.Count - 1 do
    AddHandleToArray(CreateDWGHandle(BlockHandles[I], cntDWGObjHandleSoftOwner),
      vHandles);

    AddHandleToArray(CreateDWGHandle(BlockHandles[0],  //Model space
      cntDWGObjHandleHardOwner), vHandles);

    AddHandleToArray(CreateDWGHandle(BlockHandles[1],  //Paper space
      cntDWGObjHandleHardOwner), vHandles);

  ProcControlObject(GetBlockControlObjectHandle, cntDWGObjCodeBLOCKCONTROLOBJ,
    BlockHandles.Count - 2, vHandles);
end;

procedure TsgCADtoDWG.PrepareDrawingDatabase;
  procedure AddScale(const Name: string; const Param1, Param2: Double; Param3: Byte);
  var
    P: PsgDWGScale;
  begin
    New(P);
    P^.ScaleParam1 := Param1;
    P^.ScaleParam2 := Param2;
    P^.ScaleParam3 := Param3;
    FScalesDictionary.AddObject(Name, TObject(P));
  end;
begin
  inherited PrepareDrawingDatabase;

  AddScale('A0=1:1', 1, 1, 1);
  AddScale('A1=1:2', 1, 2, 0);
  AddScale('A2=1:4', 1, 4, 0);
  AddScale('A3=1:5', 1, 5, 0);
  AddScale('A4=1:8', 1, 8, 0);
  AddScale('A5=1:10', 1, 10, 0);
  AddScale('A6=1:16', 1, 16, 0);
  AddScale('A7=1:20', 1, 20, 0);
  AddScale('A8=1:30', 1, 30, 0);
  AddScale('A9=1:40', 1, 40, 0);
  AddScale('B0=1:50', 1, 50, 0);
  AddScale('B1=1:100', 1, 100, 0);
  AddScale('B2=2:1', 2, 1, 0);
  AddScale('B3=4:1', 4, 1, 0);
  AddScale('B4=8:1', 8, 1, 0);
  AddScale('B5=10:1', 10, 1, 0);
  AddScale('B6=100:1', 100, 1, 0);
  AddScale('B7=1/128" = 1''-0"', 0.0078125, 12, 0);
  AddScale('B8=1/64" = 1''-0"', 0.015625, 12, 0);
  AddScale('B9=1/32" = 1''-0"', 0.03125, 12, 0);
  AddScale('C0=1/16" = 1''-0"', 0.0625, 12, 0);
  AddScale('C1=3/32" = 1''-0"', 0.09375, 12, 0);
  AddScale('C2=1/8" = 1''-0"', 0.125, 12, 0);
  AddScale('C3=3/16" = 1''-0"', 0.1875, 12, 0);
  AddScale('C4=1/4" = 1''-0"', 0.25, 12, 0);
  AddScale('C5=3/8" = 1''-0"', 0.375, 12, 0);
  AddScale('C6=1/2" = 1''-0"', 0.5, 12, 0);
  AddScale('C7=3/4" = 1''-0"', 0.75, 12, 0);
  AddScale('C8=1" = 1''-0"', 1, 12, 0);
  AddScale('C9=1-1/2" = 1''-0"', 1.5, 12, 0);
  AddScale('D0=3" = 1''-0"', 3, 12, 0);
  AddScale('D1=6" = 1''-0"', 6, 12, 0);
  AddScale('D2=1''-0" = 1''-0"', 12, 12, 0);

  FVariableDictionary.Values['CANNOSCALE'] := '1:1';
  FVariableDictionary.Values['DIMASSOC'] := '2';
  FVariableDictionary.Values['HIDETEXT'] := '1';
end;

function TsgCADtoDWG.PrepareTextForDWG(const Text: string): string;
begin
  Result := Text;
  ReplaceAnsi(Result, '^I', #09);
  ReplaceAnsi(Result, '^J', #$0A);
end;

procedure TsgCADtoDWG.ProcRasterVariables(const ARasterVariables: TsgCADRasterVariables;
  const OwnerHandle: UInt64);
var
  vBits: TsgDWGBits;
  vCode: Word;
  vHandles: TsgDWGHandleArray;
begin
  vBits := TsgDWGBits.Create;
  try
    vCode := GetRealDWGCode(cntDWGObjCodeRASTERVARIABLES);
    AddCommonEntityData(ARasterVariables.Handle, vCode, vBits);
    vBits.WriteBL(0);
    vBits.WriteBS(Ord(ARasterVariables.DisplayImageFrame));
    vBits.WriteBS(Ord(ARasterVariables.ImageDisplayQuality));
    vBits.WriteBS(ARasterVariables.UnitsForInsertingImages);
    AddOwnerAndXDiObjHandle(vHandles, OwnerHandle);
    AddHandlesUpdateAndFinish(vBits, vHandles, ARasterVariables.Handle, vCode);
  finally
    vBits.Free;
  end;
end;

procedure TsgCADtoDWG.ProcMLineStyle(const AStyle: TsgMLineStyle; const OwnerHandle: UInt64);
var
  vBits: TsgDWGBits;
  vCode: Word;
  I: Integer;
  vHandles: TsgDWGHandleArray;
  vMLineEntry: TsgMLineEntry;

  function DXFCodesToDWG(AFlags: SmallInt): SmallInt;
    procedure ChangeBit(Source: SmallInt; var Dest: SmallInt; si, di: Word);
    var
      val: Boolean;
    begin
      val := Word(Source) and si <> 0;
      if val then
        Dest := Dest or SmallInt(di)
      else
        Dest := Dest and not SmallInt(di);
    end;
  begin
    Result := AFlags;
    ChangeBit(AFlags, Result, 1, 2);
    ChangeBit(AFlags, Result, 2, 1);

    ChangeBit(AFlags, Result, 64, 32);
    ChangeBit(AFlags, Result, 32, 64);

    ChangeBit(AFlags, Result, 1024, 512);
    ChangeBit(AFlags, Result, 512, 1024);
  end;

  function LTypeBS(const vMLineEntry: TsgMLineEntry): Word;
  begin
    Result := $7FFF;
    if vMLineEntry.LineType <> nil then
    begin
      Result := Converter.Sections[csLTypes].IndexOfEntity(vMLineEntry.LineType);
      if Result >= 2 then
        Result := Result - 2
      else
        Result := $7FFF;
      //Result := Word(vMLineEntry.LType);
    end;
  end;

begin
  vBits := TsgDWGBits.Create;
  try
    vCode := cntDWGObjCodeMLINESTYLE;
    AddCommonEntityData(AStyle.Handle, vCode, vBits);

    vBits.WriteTV(AStyle.Name, FCodePage); //Name TV Name of this style
    vBits.WriteTV('', FCodePage); //Desc TV Description of this style
    vBits.WriteBS(DXFCodesToDWG(AStyle.Flags)); // Flags BS A short which reconstitutes the mlinestyle flags as defined in DXF. Here are the bits as they relate to DXF:
    vBits.WriteCMC(AStyle.ColorCAD); //fillcolor CMC Fill color for this style
    vBits.WriteBD(1.5707963267949); //startang BD Start angle
    vBits.WriteBD(1.5707963267949);//endang BD End angle
    vBits.WriteRC(TsgMLineStyleAccess(AStyle).GetCount); //linesinstyle RC Number of lines in this style
    for I := 0 to TsgMLineStyleAccess(AStyle).GetCount - 1 do
    begin
      vMLineEntry := AStyle.Entries[I] as TsgMLineEntry;
      vBits.WriteBD(vMLineEntry.Offset); //0.5 -0.5 Offset BD Offset of this segment
      vBits.WriteCMC(vMLineEntry.ColorCAD); //Color CMC Color of this segment
      vBits.WriteBS(LTypeBS(vMLineEntry)); //Ltindex BS Linetype index (yes, index)
    end;
    AddOwnerAndXDiObjHandle(vHandles, OwnerHandle);
    AddHandlesUpdateAndFinish(vBits, vHandles, AStyle.Handle, vCode);
  finally
    vBits.Free;
  end;
end;

procedure TsgCADtoDWG.ProcBlockRecord(ABlock: TsgDXFBlock; const AName: string;
  Data: Pointer; ACurrPaperSpaceIndex: Integer = -1);
var
  vBits: TsgDWGBits;
  vCode: Word;
  vHandle, vOwnerHandle: UInt64;
  vEntMode, vLTypeFlags: Byte;
  I: Integer;
  vData: TsgDirectExportData;

begin
  vBits := TsgDWGBits.Create;
  try
    vCode := cntDWGObjCodeBLOCK;
    CheckEntHandle(ABlock.BlockRecord, True);
    vHandle := ABlock.BlockRecord.Handle;
    if Data <> nil then
      vOwnerHandle := PUInt64(Data)^
    else
      vOwnerHandle := cnstBadHandle;
    vEntMode := 0;
    I := GetPaperIndex(AName);
    case I of
      0: vEntMode := 2;
      1:
        if IsPaperSpace(ABlock) then
          vEntMode := 1;
    end;
    AddCommonEntityData(vHandle, vCode, vBits, 0, ABlock, vEntMode, @vLTypeFlags);
    vBits.WriteTV(AName, FCodePage);
    AddCommonEntityHandleData(vHandle, vBits, ABlock, vOwnerHandle, vCode,
      vEntMode, vLTypeFlags, 0, True, cnstBadHandle, cnstBadHandle, nil);
    if vEntMode = 0 then //MODEL_SPACE and PAPER_SPACE will export entites later
    begin
      for I := 0 to ABlock.Count - 1 do
      begin
        vData := CreateExportData(vOwnerHandle, 0, GetPrevEntHandle(ABlock, I),
          GetNextEntHandle(ABlock, I));
        DoExport(ABlock.Entities[I], @vData);
      end;
    end;
    vData := CreateExportData(vOwnerHandle, vEntMode, cnstBadHandle,
      cnstBadHandle, 0, nil, cntDWGObjCodeENDBLK);
    DoExport(ABlock, @vData); //exports ENDBLK
  finally
    vBits.Free;
  end;
end;

procedure TsgCADtoDWG.ProcControlObject(const AHandle: UInt64; ACode: Word;
  ANumentries: Cardinal; const AHandles: array of TsgDWGHandle; ReadEvent: TsgDWGReadEvent = nil);
var
  vBits: TsgDWGBits;
begin
  vBits := TsgDWGBits.Create;
  try
    DoError(AHandle = cnstBadHandle, sCannotFindTableCode, [ACode]);
    AddCommonEntityData(AHandle, ACode, vBits);
    vBits.WriteBL(ANumentries);
    if Assigned(ReadEvent) then
      ReadEvent(vBits);
   //Handles
    AddHandlesUpdateAndFinish(vBits, AHandles, AHandle, ACode);
  finally
    vBits.Free;
  end;
end;

procedure TsgCADtoDWG.ProcDictionary(const Handle, OwnerHandle: UInt64;
  Items: TStringList);
var
  vBits: TsgDWGBits;
  vCode: Word;
  vName, vVal: string;
  vHandles: TsgDWGHandleArray;
  I: Integer;

begin
  vBits := TsgDWGBits.Create;
  try
    vCode :=  cntDWGObjCodeDICTIONARY1;
    AddCommonEntityData(Handle, vCode, vBits);
    vBits.WriteBL(Items.Count); //Numitems BL number of dictonary items
    vBits.WriteBS(1); //Cloning flag BS 281      1
    vBits.WriteRC(0); //Hard Owner flag RC 280 0
    AddOwnerAndXDiObjHandle(vHandles, OwnerHandle);
    for I := 0 to Items.Count - 1 do
    begin
      vName := Items.Names[I];
      vVal := Items.Values[Items.Names[I]];
      if vVal = cntEmptyDictionary then
        vVal := '';
      vBits.WriteTV(vVal, FCodePage); //Text TV string name of dictionary entry, numitems entries
      AddHandleToArray(CreateDWGHandle(StrToInt64('$' + vName), cntDWGObjHandleSoftOwner),
        vHandles);
    end;
    AddHandlesUpdateAndFinish(vBits, vHandles, Handle, vCode);
  finally
    vBits.Free;
  end;
end;

procedure TsgCADtoDWG.ProcDimStyle(const AOwnerHandle: UInt64;
  ADimStyle: TsgDXFDimensionStyle; var AProcHandles: TsgDWGHandleArray);
var
  vCode: Word;
  vBits: TsgDWGBits;
  vHandles: TsgDWGHandleArray;

  function GetBlockEntHandle(const ABlock: TsgDXFBlock): UInt64;
  begin
    if ABlock <> nil then
      Result := GetEntityHandle(TsgDXFTable(Converter.Sections[csBlocks]).FindEntByName(ABlock.Name)) //GetEntityHandle(ADimStyle.DIMLDRBLK)
    else
      Result := cnstBadHandle;
  end;

begin
  if ADimStyle = nil then Exit;
  vCode := cntDWGObjCodeDIMSTYLE;
  vBits := TsgDWGBits.Create;
  try
    AddCommonEntityData(ADimStyle.Handle, vCode, vBits);
    vBits.WriteTV(ADimStyle.Name, FCodePage);

    vBits.WriteBit(1); //The 64-bit of the 70 group                1
    vBits.WriteBS(0);  //xrefindex+1 BS 70                         0
    vBits.WriteBit(GetXdep(ADimStyle.Name)); // DepXRef            0
    vBits.WriteTV('', FCodePage);//DIMPOST TV 3           ''
    vBits.WriteTV('', FCodePage);//DIMAPOST TV 4          ''

    vBits.WriteBD(ADimStyle.Scale); //DIMSCALE BD 40               1
    vBits.WriteBD(ADimStyle.ArrowSize); //DIMASZ BD 41             0,18
    vBits.WriteBD(ADimStyle.ExtLineOffset); //DIMEXO BD 42         0,0625
    vBits.WriteBD(0.38);//DIMDLI BD 43                             0,38
    vBits.WriteBD(ADimStyle.ExtLineExt);//DIMEXE BD 44             0,18
    vBits.WriteBD(0);//DIMRND BD 45                                0
    vBits.WriteBD(0);//DIMDLE BD 46                                0
    vBits.WriteBD(0);//DIMTP BD 47                                 0
    vBits.WriteBD(0);//DIMTM BD 48                                 0
    vBits.WriteBit(0);//DIMTOL B 71                                0
    vBits.WriteBit(0);//DIMLIM B 72                                0
    vBits.WriteBit(ADimStyle.DIMTIH);//DIMTIH B 73                 1
    vBits.WriteBit(ADimStyle.DIMTOH);//DIMTOH B 74                 1
    vBits.WriteBit(ADimStyle.DIMSE1);//DIMSE1 B 75                 0
    vBits.WriteBit(ADimStyle.DIMSE2);//DIMSE2 B 76                 0
    vBits.WriteBS(Ord(ADimStyle.TextPosVert));//DIMTAD BS 77      0
    vBits.WriteBS(0);//DIMZIN BS 78                                0
    vBits.WriteBS(0);//DIMAZIN BS 79                               0
    vBits.WriteBD(GetDefVal(ADimStyle.TextHeight, 2.5));//DIMTXT BD 140            0,18
    vBits.WriteBD(ADimStyle.SizeCenterMark);//DIMCEN BD 141        0
    vBits.WriteBD(0);//DIMTSZ BD 142                               0
    vBits.WriteBD(24.4);//DIMALTF BD 143                           25,4
    vBits.WriteBD(GetDefVal(ADimStyle.DIMLFAC, 1));//DIMLFAC BD 144              1
    vBits.WriteBD(0);//DIMTVP BD 145                               0
    vBits.WriteBD(1);//DIMTFAC BD 146                              1
    vBits.WriteBD(ADimStyle.TextOffset);//DIMGAP BD 147            0,0625
    vBits.WriteBD(0);//DIMALTRND BD 148                            0
    vBits.WriteBit(0);//DIMALT B 170                               0
    vBits.WriteBS(2);//DIMALTD BS 171                              2
    vBits.WriteBit(0);//DIMTOFL B 172                              0
    vBits.WriteBit(0);//DIMSAH B 173                               0
    vBits.WriteBit(ADimStyle.DIMTIX <> 0);//DIMTIX B 174                0
    vBits.WriteBit(0);//DIMSOXD B 175                              0
    vBits.WriteCMC(ADimStyle.DIMCLRD);//DIMCLRD BS 176             0
    vBits.WriteCMC(ADimStyle.DIMCLRE);//DIMCLRE BS 177             0
    vBits.WriteCMC(ADimStyle.DIMCLRT);//DIMCLRT BS 178             0
    vBits.WriteBS(0);//DIMADEC BS 179                              0
    vBits.WriteBS(ADimStyle.DIMDEC);//DIMDEC BS 271                4
    vBits.WriteBS(4);//DIMTDEC BS 272                              4
    vBits.WriteBS(2);//DIMALTU BS 273                              2
    vBits.WriteBS(2);//DIMALTTD BS 274                             2
    vBits.WriteBS(0);//DIMAUNIT BS 275                             0
    vBits.WriteBS(0);//DIMFRAC BS 276                              0
    vBits.WriteBS(2);//DIMLUNIT BS 277                             2
    vBits.WriteBS(46);//DIMDSEP BS 278                             46
    vBits.WriteBS(0);//DIMTMOVE BS 279                             0
    vBits.WriteBS(0);//DIMJUST BS 280                              0
    vBits.WriteBit(ADimStyle.DIMSD1);//DIMSD1 B 281                0
    vBits.WriteBit(ADimStyle.DIMSD2);//DIMSD2 B 282                0
    vBits.WriteBS(1);//DIMTOLJ BS 283                              1
    vBits.WriteBS(0);//DIMTZIN BS 284                              0
    vBits.WriteBS(0);//DIMALTZ BS 285                              0
    vBits.WriteBS(0);//DIMALTTZ BS 286                             0
    vBits.WriteBit(0);//DIMUPT B 288                               0
    vBits.WriteBS(3);//DIMFIT BS 287                               3
    vBits.WriteBS(CorrectLineWeight(ADimStyle.DIMLWD, False));//DIMLWD BS 371      65535
    vBits.WriteBS(CorrectLineWeight(ADimStyle.DIMLWE, False));//DIMLWE BS 372      65535
    vBits.WriteBit(0);//Unknown B 70 Seems to set the 0-bit (1) of the 70-group. 0

    AddOwnerAndXDiObjHandle(vHandles, AOwnerHandle);
    AddHandleToArray(CreateDWGHandle(GetEntityHandle(EntXrefBlock(ADimStyle, Converter)){cnstBadHandle}, cntDWGObjHandleHardPointer), vHandles);

    AddHandleToArray(CreateDWGHandle(GetStyleHandle(ADimStyle.TextStyle, False),
      cntDWGObjHandleHardPointer), vHandles);//Text Style

    AddHandleToArray(CreateDWGHandle(GetBlockEntHandle(ADimStyle.DIMLDRBLK), //blocks
      cntDWGObjHandleHardPointer), vHandles);
    AddHandleToArray(CreateDWGHandle(GetBlockEntHandle(ADimStyle.DIMBLK),
      cntDWGObjHandleHardPointer), vHandles);
    AddHandleToArray(CreateDWGHandle(GetBlockEntHandle(ADimStyle.DIMBLK1),
      cntDWGObjHandleHardPointer), vHandles);
    AddHandleToArray(CreateDWGHandle(GetBlockEntHandle(ADimStyle.DIMBLK2),
      cntDWGObjHandleHardPointer), vHandles);

    AddHandlesUpdateAndFinish(vBits, vHandles, ADimStyle.Handle, vCode);
    AddHandleToArray(CreateDWGHandle(ADimStyle.Handle, cntDWGObjHandleSoftOwner),
      AProcHandles);
  finally
    vBits.Free;
  end;
end;

procedure TsgCADtoDWG.ProcDimStylesControlObject(const AHandle: UInt64;
  const ADimStyleHandles: TsgDWGHandleArray);
begin
  ProcControlObject(AHandle, cntDWGObjCodeDIMSTYLECONTROLOBJ, Length(ADimStyleHandles) - 2,
    ADimStyleHandles, OnWriteDimStyleControlObject);
end;

procedure TsgCADtoDWG.ProcDWGProps(const Handle, OwnerHandle: UInt64);
var
  vBits, vXRecordBits: TsgDWGBits;
  vCode: Word;
  vXRecord: TsgCADExtendedData;
  I: Integer;
  vKey, vVal: string;
  vHandles: TsgDWGHandleArray;
begin
  vBits := TsgDWGBits.Create;
  vXRecordBits := TsgDWGBits.Create;
  vXRecord := TsgCADExtendedData.Create;
  try
    vCode := cntDWGObjCodeXRECORD;
    AddCommonEntityData(Handle, vCode, vBits, 1);

    vXRecord.AddString(cntXCodeDrwPropBase, sDWGPropsXRecord);
    vXRecord.AddString(cntXCodeDrwPropTitle, DrwPropTitle);
    vXRecord.AddString(cntXCodeDrwPropSubject, DrwPropSubject);
    vXRecord.AddString(cntXCodeDrwPropAuthor, DrwPropAuthor);
    vXRecord.AddString(cntXCodeDrwPropComments, DrwPropComments);
    vXRecord.AddString(cntXCodeDrwPropKeywords, DrwPropKeywords);
    vXRecord.AddString(cntXCodeDrwPropLastSavedBy, DrwPropSavedBy);
    vXRecord.AddString(cntXCodeDrwPropRevisionNumber, DrwPropRevisionNumber);

    for I := cntXCodeDrwPropCustomSummaryInfo1 to cntXCodeDrwPropCustomSummaryInfo9 do
    begin
      vKey := '';
      vVal := '';
      if I - cntXCodeDrwPropCustomSummaryInfo1 <= DrwPropCustomSummaryInfo.Count - 1 then
      begin
        vKey := DrwPropCustomSummaryInfo.Names[I - cntXCodeDrwPropCustomSummaryInfo1];
        vVal := DrwPropCustomSummaryInfo.Values[vKey];
      end;
      vXRecord.AddString(I, vKey + '=' + vVal);
    end;
    vXRecord.AddDouble(cntXCodeDrwPropUnknown40, 0);
    vXRecord.AddDouble(cntXCodeDrwPropUnknown41, 0);
    vXRecord.AddDouble(cntXCodeDrwPropUnknown42, 0);
    vXRecord.AddString(cntXCodeDrwPropHyperlinkBase, DrwPropHyperlinkBase);
    vXRecord.AddInt(cntXCodeDrwPropCustomSummaryInfoCount, Min(DrwPropCustomSummaryInfo.Count, 10));
    AddXRecords(vXRecordBits, False, vXRecord);
    vBits.WriteBL(vXRecordBits.Size);
    vBits.WriteBytes(vXRecordBits.Data, vXRecordBits.Size);
    vBits.WriteBS(1);

    AddHandleToArray(CreateDWGHandle(OwnerHandle, cntDWGObjHandleSoftPointer), vHandles);
    AddHandleToArray(CreateDWGHandle(OwnerHandle, cntDWGObjHandleSoftPointer), vHandles);
    AddHandleToArray(CreateDWGHandle(cnstBadHandle, cntDWGObjHandleHardOwner), vHandles);

    AddHandlesUpdateAndFinish(vBits, vHandles, Handle, vCode);
  finally
    vBits.Free;
    vXRecordBits.Free;
    vXRecord.Free;
  end;
end;

procedure TsgCADtoDWG.ProcessExport(Stream: TStream);
const
   arPad: array[0..6] of AnsiChar = (#0, #0, #0, #0, #0, #6, #1);

var
  vDateCreate, vDateUpdate: TDateTime;
  vHandSeed: UInt64;
  PFileHeader: PdwgFileHeader;
  vLocators: TsgDWGR15Locators;
  vStrVer: AnsiString;
  vCRC: Word;
  vSize: Cardinal;
begin
//DWG R2000 FILE STRUCTURE
//FILE HEADER                  |
//LOCATORS                     | 81 bytes
//CRC                          |
//FILE HEADER END SENTINEL     |
//AuxHeader                    | size 123 offset 97
//Preview image                | size variable offset 220 (97 + 123)
//Classes                      | size variable offset 17318
//Unknown area, padding        | $80 (128 dec) 0 32 bit UInt (Cardinal(s))

//CLASS DEFINITIONS
//TEMPLATE (R13 only, optional)
//PADDING (R13C3 AND LATER, 200 bytes, minutes the template section above if present)
//IMAGE DATA (PRE-R13C3)
//OBJECT DATA
//All entities, table entries, dictionary entries, etc. go in this
//section.
//OBJECT MAP
//OBJECT FREE SPACE (optional)
//TEMPLATE (R14-R15, optional)
//SECOND HEADER
//IMAGE DATA (R13C3 AND LATER)

  Progress(psStarting,0);
  CreateTablesRecord;
  GetCreateAndUpdateDateTime(vDateCreate, vDateUpdate);// all dates may be zeros in JD
  vStrVer := AnsiString(sgDWGVerToString(Version));

  ExportSectionClasses(cntPaddingSize); //we have to add $80 * SizeOf(UInt32) zeros to the end of Classes section, the padding
  Progress(psRunning, 10);
  ExportSectionTables; //export objects must be after classes
  vHandSeed := DoHandle; //After export Objects the HandSeed is known
  FillChar(vLocators, SizeOf(vLocators), 0);
  Progress(psRunning, 70);
    //File Header
  WriteByteToStream(Sections[GetFileHeaderSectionIndex], 0,
    cntDWGR15FileHeaderSize - SizeOf(TsgDWGSentinel));
  Sections[GetFileHeaderSectionIndex].Write(cntFileHeaderEndSentinel,
    SizeOf(cntFileHeaderEndSentinel));
  Progress(psRunning, 80);
  //Aux Header
  ExportSectionAuxHeader(vHandSeed, vDateCreate, vDateUpdate);

  //Preview
  ExportSectionPreview(Sections[GetFileHeaderSectionIndex].Size +
    Sections[GetAuxHeaderSectionIndex].Size);

  //Header Vars
  ExportSectionHeaderVars(vHandSeed, vDateCreate, vDateUpdate);

  //Classes were before

  //objects
  ExportSectionObjects;

  //handles (Objects Map)
  ExportSectionObjMap;

  //free space aka unknown section
  ExportSectionObjFreeSpace(vDateUpdate, FObjectsMap.Count + 4, GetObjectsFileOffset);

  //template
  ExportSectionMeasurement(1);
  Progress(psRunning, 90);

  //Prepare all known section locators
  //DWG files need the first four locators in the SecondHeader
  vLocators[0].RecNumber := 0; //HeaderVars
  vLocators[0].Seeker := GetHeaderVarsOffset;
  vLocators[0].Size := Sections[GetHeaderVarsSectionIndex].Size;

  vLocators[1].RecNumber := 1;//Classes
  vLocators[1].Seeker := GetClassesOffset;
  vLocators[1].Size := Sections[GetClassesSectionIndex].Size - cntPaddingSize;

  vLocators[2].RecNumber := 2;//ObjMap
  vLocators[2].Seeker := GetObjMapOffset;
  vLocators[2].Size := Sections[GetObjectMapSectionIndex].Size;

  vLocators[3].RecNumber := 3;//ObjFreeSpace
  vLocators[3].Seeker := GetObjFreeSpaceOffset;
  vLocators[3].Size := Sections[GetObjFreeSpaceSectionIndex].Size;

  vLocators[4].RecNumber := 4;//Template, data locator will be known later
  vLocators[4].Seeker := 0;
  vLocators[4].Size := Sections[GetMeasurementSectionIndex].Size;

  vLocators[5].RecNumber := 5;//AuxHeader
  vLocators[5].Seeker := GetAuxHeaderOffset;
  vLocators[5].Size := Sections[GetAuxHeaderSectionIndex].Size;

  //second header
  ExportSectionSecondHeader(vHandSeed, GetSecondHeaderOffset, vLocators);


  vLocators[4].RecNumber := 4;//Template
  vLocators[4].Seeker := GetTemplateOffset;
  vLocators[4].Size := Sections[GetMeasurementSectionIndex].Size;

  //prepare FileHeader
  PFileHeader := PdwgFileHeader(Sections[GetFileHeaderSectionIndex].Memory);
  Move(vStrVer[1], PFileHeader^.VersionID, SizeOf(PFileHeader^.VersionID)); //version
  Move(arPad, PFileHeader^.Pad, SizeOf(PFileHeader^.Pad)); //pad
  PFileHeader^.CodePage := FDWGCodePage;
  PFileHeader^.Unknown := 1565;
  PFileHeader^.Locators := cntDWGR15SectionsCount;
  PFileHeader^.ImageSeeker := GetPreViewImageOffset;

  Sections[GetFileHeaderSectionIndex].Position := SizeOf(TdwgFileHeader);
  Sections[GetFileHeaderSectionIndex].Write(vLocators, SizeOf(vLocators));

  vSize := Sections[GetFileHeaderSectionIndex].Position;

  vCRC := CRC8(Sections[GetFileHeaderSectionIndex].Memory, 0, vSize) xor cnstFileHeaderCRCXOR[cntDWGR15SectionsCount];
  Sections[GetFileHeaderSectionIndex].Write(vCRC, SizeOf(vCRC));

  Progress(psRunning, 95);
  Stream.Write(Sections[GetFileHeaderSectionIndex].Memory^, Sections[GetFileHeaderSectionIndex].Size);
  Stream.Write(Sections[GetAuxHeaderSectionIndex].Memory^, Sections[GetAuxHeaderSectionIndex].Size);
  Stream.Write(Sections[GetPreviewSectionIndex].Memory^, Sections[GetPreviewSectionIndex].Size);
  Stream.Write(Sections[GetHeaderVarsSectionIndex].Memory^, Sections[GetHeaderVarsSectionIndex].Size);
  Stream.Write(Sections[GetClassesSectionIndex].Memory^, Sections[GetClassesSectionIndex].Size);
  Stream.Write(Sections[GetObjectsSectionIndex].Memory^, Sections[GetObjectsSectionIndex].Size);
  Stream.Write(Sections[GetObjectMapSectionIndex].Memory^, Sections[GetObjectMapSectionIndex].Size);
  Stream.Write(Sections[GetObjFreeSpaceSectionIndex].Memory^, Sections[GetObjFreeSpaceSectionIndex].Size);
  Stream.Write(Sections[GetSecondHeaderSectionIndex].Memory^, Sections[GetSecondHeaderSectionIndex].Size);
  Stream.Write(Sections[GetMeasurementSectionIndex].Memory^, Sections[GetMeasurementSectionIndex].Size);
  Progress(psEnding, 100);
end;

procedure TsgCADtoDWG.ProcImageDef(AImageDef: TsgDXFImageDef);
var
  vBits: TsgDWGBits;
  vCode: Word;
  vHandles: TsgDWGHandleArray;
  vImageSize, vPixelSize: TF2DPoint;
  vAcadImageDict: UInt64;
begin
  vBits := TsgDWGBits.Create;
  try
    vImageSize := cnstF2DPointZero;
    vPixelSize := cnstF2DPointZero;
    if AImageDef.Picture.Graphic <> nil then
    begin
      vImageSize := MakeF2DPoint(AImageDef.Picture.Graphic.Width , AImageDef.Picture.Graphic.Height);
      vPixelSize :=  MakeF2DPoint(1 / AImageDef.Picture.Graphic.Width, 1 / AImageDef.Picture.Graphic.Height);
    end;
    vCode := GetRealDWGCode(cntDWGObjCodeIMAGEDEF);
    AddCommonEntityData(AImageDef.Handle, vCode, vBits, 1);
    vBits.WriteBL(0); //Clsver BL 0 class version
    vBits.Write2RD(vImageSize); //Imgsize 2RD 10 size of image in pixels
    vBits.WriteTV(AImageDef.FileName, FCodePage); //Filepath TV 1 path to file
    vBits.WriteBit(1); //Isloaded B 280 0==no, 1==yes  1
    vBits.WriteRC(0); //Resunits RC 281 0==none, 2==centimeters, 5==inches   0
    vBits.Write2RD(vPixelSize);// Pixelsize 2RD 11 size of one pixel in AutoCAD units    0.01, 0.01, 0
    vAcadImageDict := GetDictionaryAcadImageDict;
    //parenthandle Reference handle (hard owner is mistake in the documentation)
    AddHandleToArray(CreateDWGHandleRef(vAcadImageDict, AImageDef.Handle), vHandles);
    //first reactor
    AddHandleToArray(CreateDWGHandle(vAcadImageDict, cntDWGObjHandleSoftPointer), vHandles);
    //IMAGEDEF_REACTOR
    //AddHandleToArray(CreateDWGHandle(cnstBadHandle, cntDWGObjHandleSoftPointer), vHandles);
    //xdicobjhandle (hard owner)??
    AddHandleToArray(CreateDWGHandle(cnstBadHandle, cntDWGObjHandleHardOwner), vHandles);

    AddHandlesUpdateAndFinish(vBits, vHandles, AImageDef.Handle, vCode);
  finally
    vBits.Free;
  end;
end;

procedure TsgCADtoDWG.ProcLayer(const AOwnerHandle: UInt64; ALayer: TsgDXFLayer;
  var ProcHandles: TsgDWGHandleArray; var ZeroLayerIndex: Integer);
var
  vBits: TsgDWGBits;
  vFlags, vLineWeightFlag: Word;
  vHandles: TsgDWGHandleArray;
  vCode: Word;
begin
  if (ALayer = nil) or IsNameInternal(ALayer.Name) then Exit;
  CheckEntHandle(ALayer);
  vBits := TsgDWGBits.Create;
  try
    vCode := cntDWGObjCodeLAYER;
    AddCommonEntityData(ALayer.Handle, vCode, vBits);
    vBits.WriteTV(ExtractName(ALayer.Name), FCodePage); //Entry name TV 2
    vBits.WriteBit(Get64bitof70Group(ALayer.Flags)); //64-flag B 70 The 64-bit of the 70 group.
    vBits.WriteBS(0); //xrefindex+1 BS 70 subtract one from this value when read. After that, -1 indicates that this reference did not come from an xref, otherwise this value indicates the index of the blockheader for the xref from which this came
    vBits.WriteBit(GetXdep(ALayer.Name)); //Xdep B 70 dependent on an xref. (16 bit)
    vLineWeightFlag := CorrectLineWeight(ALayer.LineWeight, True) shl 5 and $3E0;
    vFlags := 0;
    if ALayer.Frozen then
      vFlags := vFlags or 1;
    if not ALayer.Visible then
      vFlags := vFlags or 2;
    if ALayer.IsFrozenByNewViewPort then
      vFlags := vFlags or 4;
    if ALayer.Locked then
      vFlags := vFlags or 8;
    if ALayer.IsPlotting and (not SameText(ALayer.Name, sLayerDefPoints)) then
      vFlags := vFlags or $10;
    vFlags := vFlags or vLineWeightFlag;
    vBits.WriteBS(vFlags); //Values BS 70,290,370 contains frozen (1 bit), on (2 bit), frozen by default in new viewports (4 bit), locked (8 bit), plotting flag (16 bit), and lineweight (mask with 0x03E0)
    vBits.WriteCMC(ALayer.ColorCAD);

    AddOwnerAndXDiObjHandle(vHandles, AOwnerHandle);

    AddHandleToArray(CreateDWGHandle(GetEntityHandle(EntXrefBlock(ALayer, Converter)){cnstBadHandle}, cntDWGObjHandleHardPointer), vHandles); //External reference block handle
    AddHandleToArray(CreateDWGHandle(cnstBadHandle, cntDWGObjHandleHardPointer), vHandles); //Plotstyle (hard pointer), by default points to PLACEHOLDER with handle 0x0f

    AddHandleToArray(CreateDWGHandle(GetLineTypeHandle(ALayer.LineType),
      cntDWGObjHandleHardPointer), vHandles);

    AddHandlesUpdateAndFinish(vBits, vHandles, ALayer.Handle, vCode);
    AddHandleToArray(CreateDWGHandle(ALayer.Handle, cntDWGObjHandleSoftOwner), ProcHandles);
    if ALayer.Name = '0' then
      ZeroLayerIndex := High(ProcHandles);
  finally
    vBits.Free;
  end;
end;

procedure TsgCADtoDWG.ProcLayerControlObject(const AHandle: UInt64;
  const ProcLayerHandles: TsgDWGHandleArray);
begin
  ProcControlObject(AHandle, cntDWGObjCodeLAYERCONTROLOBJ, Length(ProcLayerHandles) - 2,
    ProcLayerHandles);
end;

procedure TsgCADtoDWG.ProcLayout(ALayout: TsgDXFLayout; const Handle, OwnerHandle: UInt64;
  AIndex: Integer; AName: string);
var
  vBits: TsgDWGBits;
  vCode: Word;
  vName: string;
  vBox: TFRect;
  vHandles: TsgDWGHandleArray;
  vBlockHandle: UInt64;
//  vEntity: TsgDXFEntity;
  vPlotFlags: Word;

  function IsPaperSpace: Boolean;
  begin
    Result := (ALayout <> nil) and (not ALayout.IsModel);// = GetPaperLayout);
  end;

  procedure SavePlotSettingToDWG(const APlotSetting: TsgDXFPlotSettings);
  var
    vPS: TsgDXFPlotSettings;
    vFlags: TsgPlotLayoutFlags;
  begin
    vPS := TsgDXFPlotSettings.Create;
    try
      if Assigned(APlotSetting) then
        vPS.AssignEntity(APlotSetting)
      else
        vPS.ResetForDefaultValue;

      vBits.WriteTV('', FCodePage); //Page setup name TV 1 plotsettings page setup name ''
      vBits.WriteTV(vPS.PrintOrConfigName, FCodePage); //Printer/Config TV 2 plotsettings printer or configuration file 'none_device'

      vPlotFlags := 688;
      if ALayout <> nil then
      begin
        if ALayout.IsModel then
          vPlotFlags := 11952;//vPlotFlags or $400;
      end;
      vFlags :=  ConvertIntegerToPlotLayoutFlags(vPlotFlags);
      if plfUseStandardScale in vPS.PlotLayoutFlags then
        vFlags := vFlags + [plfUseStandardScale]
      else
        vFlags := vFlags - [plfUseStandardScale];
      vPlotFlags := ConvertPlotLayoutFlagsToInteger(vFlags);

      vBits.WriteBS(vPlotFlags); //Plot layout flags BS 70 plotsettings plot layout flag 688
      vBits.WriteBD(vPS.UnprintableMargin.Left); //Left Margin BD 40 plotsettings left margin in millimeters
      vBits.WriteBD(vPS.UnprintableMargin.Bottom); //Bottom Margin BD 41 plotsettings bottom margin in millimeters
      vBits.WriteBD(vPS.UnprintableMargin.Right); //Right Margin BD 42 plotsettings right margin in millimeters
      vBits.WriteBD(vPS.UnprintableMargin.Top); //Top Margin BD 43 plotsettings top margin in millimeters
      vBits.WriteBD(vPS.PlotPaperSize.X); //Paper Width BD 44 plotsettings paper width in millimeters
      vBits.WriteBD(vPS.PlotPaperSize.Y); //Paper Height BD 45 plotsettings paper height in millimeters
      vBits.WriteTV(vPS.PaperSize, FCodePage); //Paper Size TV 4 plotsettings paper size
      vBits.Write2BD(vPS.PlotOrigin); //Plot origin 2BD 46,47 plotsettings origin offset in millimeters
      vBits.WriteBS(Word(vPS.PlotPaperUnits)); //Paper units BS 72 plotsettings plot paper units
      vBits.WriteBS(Word(vPS.PlotRotation)); //Plot rotation BS 73 plotsettings plot rotation
      vBits.WriteBS(Word(vPS.PlotType)); //Plot type BS 74 plotsettings plot type
      vBits.Write2BD(vPS.PlotWindowAreaMin); //Window min 2BD 48,49 plotsettings plot window area lower left
      vBits.Write2BD(vPS.PlotWindowAreaMax); //Window max 2BD 140,141 plotsettings plot window area upper right
      vBits.WriteT('', FCodePage); //Plot view name T 6 plotsettings plot view name
      vBits.WriteBD(vPS.NumeratorOfCustomPrintScale); //Real world units BD 142 plotsettings numerator of custom print scale
      vBits.WriteBD(vPS.DenominatorOfCustomPrintScale); //Drawing units BD 143 plotsettings denominator of custom print scale
      vBits.WriteTV('', FCodePage); //Current style sheet TV 7 plotsettings current style sheet
      vBits.WriteBS(0); //Scale type BS 75 plotsettings standard scale type
      vBits.WriteBD(vPS.FloatingPointScaleFactor); //Scale factor BD 147 plotsettings scale factor
      vBits.Write2BD(vPS.PaperImageOrigin); //Paper image origin 2BD 148,149 plotsettings paper image origin
    finally
      vPS.Free;
    end;
  end;

var
  vPlotSetting: TsgDXFPlotSettings;

begin
  vBits := TsgDWGBits.Create;
  try
    vCode := GetDWGCodeByClass(cntClassDXFLAYOUT);
    if ALayout = nil then
    begin
      vName := AName;
      vBlockHandle := PaperSpaceBlockHandle;
      vPlotSetting := nil;
    end
    else
    begin
      if AIndex > 0 then
      begin
        vName := ALayout.Name;
        if GetPaperLayout = ALayout then
          vBlockHandle := PaperSpaceBlockHandle
        else
          vBlockHandle := ALayout.PaperSpaceBlock.Handle;
      end
      else
      begin
        vName := sModel;
        vBlockHandle := ModelSpaceBlockHandle;
      end;
      vPlotSetting := ALayout.PlotSettings;
    end;

    DoError(vBlockHandle = cnstBadHandle, sHandleInvalid);
    vBox.TopLeft := cnstFPointZero;
    vBox.BottomRight := cnstFPointZero;
    if ALayout <> nil then
      vBox := ALayout.Box;
    AddCommonEntityData(Handle, vCode, vBits, 1);

    SavePlotSettingToDWG(vPlotSetting);

    vBits.WriteTV(vName, FCodePage); //Layout name TV 1 layout name                                          'Model' 'Layout1'
    vBits.WriteBS(AIndex); //Tab order BS 71 layout tab order                                      0 1
    vBits.WriteBS(1); //Flag BS 70 layout flags                                               1
    vBits.Write3BD(cnstFPointZero); //Ucs origin 3BD 13 layout ucs origin                          0, 0, 0
    vBits.Write2RD(GetLinMin(ALayout)); //Limmin 2RD 10 layout minimum limits                                  0, 0, 0
    vBits.Write2RD(GetLinMax(ALayout)); //Limmax 2RD 11 layout maximum limits                                  0, 0, 0
    if IsPaperSpace then
      vBits.Write3BD(cnstExtrusion)
    else
      vBits.Write3BD(cnstFPointZero); //Inspoint 3BD 12 layout insertion base point                          0, 0, 0
    vBits.Write3BD(cnstXOrtAxis); //Ucs x axis 3BD 16 layout ucs x axis direction                        1, 0, 0
    vBits.Write3BD(cnstYOrtAxis); //Ucs y axis 3BD 17 layout ucs y axis direction                        0, 1, 0
    vBits.WriteBD(0); //Elevation BD 146 layout elevation                                     0
    vBits.WriteBS(0); //Orthoview type BS 76 layout orthographic view type of UCS             0
    vBits.Write3BD(GetExtMin(ALayout)); //Extmin 3BD 14 layout extent min                                      0, 0, 0
    vBits.Write3BD(GetExtMax(ALayout)); //Extmax 3BD 15 layout extent max                                      0, 0, 0

    //Handles
    AddHandleToArray(CreateDWGHandle(OwnerHandle, cntDWGObjHandleSoftPointer), vHandles);// parenthandle (soft pointer)
    AddHandleToArray(CreateDWGHandle(OwnerHandle, cntDWGObjHandleSoftPointer), vHandles);// [Reactors (soft pointer])
    AddHandleToArray(CreateDWGHandle(cnstBadHandle, cntDWGObjHandleHardOwner), vHandles);// xdicobjhandle (hard owner)
    if Version >= acR2004 then
      AddHandleToArray(CreateDWGHandle(cnstBadHandle, cntDWGObjHandleHardPointer), vHandles); //plot view handle (hard pointer)
    if Version >= acR2007 then
      AddHandleToArray(CreateDWGHandle(cnstBadHandle, cntDWGObjHandleSoftPointer), vHandles); //Visual Style handle (soft pointer)
    AddHandleToArray(CreateDWGHandle(vBlockHandle, cntDWGObjHandleSoftPointer), vHandles);
    AddHandleToArray(CreateDWGHandle(GetLastActiveViewportHandle(ALayout), cntDWGObjHandleSoftPointer), vHandles);// last active viewport handle (soft pointer)
    AddHandleToArray(CreateDWGHandle(cnstBadHandle, cntDWGObjHandleHardPointer), vHandles);// base ucs handle (hard pointer)
    AddHandleToArray(CreateDWGHandle(cnstBadHandle, cntDWGObjHandleHardPointer), vHandles);// named ucs handle (hard pointer)
//    if Version >= acR2004 then !!!
//      for I := 0 to ALayout.Viewports.Count - 1 do
//        AddHandleToArray(CreateDWGHandle(ALayout.Viewports[I].Handle, cntDWGObjHandleSoftPointer), vHandles); //Viewport handle (repeats Viewport count times) (soft pointer)
    AddHandlesUpdateAndFinish(vBits, vHandles, Handle, vCode);
  finally
    vBits.Free;
  end;
end;

procedure TsgCADtoDWG.ProcLType(AOwnerHandle: UInt64; ALType: TsgDXFLineType);
var
  I, vCount: Integer;
  vLen: Double;
  vElement: TsgLTypeElement;
  vHandles: TsgInt64List;
  vBits: TsgDWGBits;
  vElemText: AnsiString;
  vStringArea: array [0..255] of AnsiChar;
  vHandlesArray: array of TsgDWGHandle;
begin
  if ALType = nil then Exit;
  CheckEntHandle(ALType);

  vHandles := TsgInt64List.Create;
  vBits := TsgDWGBits.Create;
  try
    vHandles.Sorted := False;
    FillChar(vStringArea, SizeOf(vStringArea), #0);
    AddCommonEntityData(ALType.Handle, cntDWGObjCodeLTYPE1, vBits);
    vCount := ALType.Lines.ElementsCount;

    vBits.WriteTV(ExtractName(ALType.Name), FCodePage); //Entry name TV 2
    vBits.WriteBit(0); //64-flag B 70 The 64-bit of the 70 group
    vBits.WriteBS(0); //xrefindex+1 BS 70 subtract one from this value when read. After that, -1 indicates that this reference did not come from an xref, otherwise this value indicates the index of the blockheader for the xref from which this came
    vBits.WriteBit(GetXdep(ALType.Name)); //Xdep B 70 dependent on an xref. (16 bit)
    vBits.WriteTV(GenLTypeDiscriptText(ALType, vLen), FCodePage); //Description TV 3
    vBits.WriteBD(vLen); //Pattern Len BD 40
    vBits.WriteRC(Byte(AnsiChar('A'))); //Alignment RC 72 Always 'A'
    vBits.WriteRC(vCount); //Numdashes RC 73 The number of repetitions of the 49...74 data.

    vElemText := '';

    for I := 0 to vCount - 1 do
    begin
      vElement := ALType.Lines.Elements[I]^;
      if (vElement.ComplexType and 2 <> 0) and (Length(vElement.Text) > Length(vElemText)) then //writes only 1 text to the strings area
        vElemText := AnsiString(vElement.Text);
      vBits.WriteBD(vElement.Dash);
      vBits.WriteBS(vElement.ShapeNumber);
      vBits.WriteRD(vElement.XOffset);
      vBits.WriteRD(vElement.YOffset);
      vBits.WriteBD(vElement.Scale);
      vBits.WriteBD(Radian(vElement.Rotation));
      vBits.WriteBS(vElement.ComplexType);
      vHandles.Add(GetHandleByEntity(vElement.Style));
    end;

    if vElemText <> '' then
      Move(vElemText[1], vStringArea[0], Min(Length(vElemText), SizeOf(vStringArea) - 1));
    vBits.WriteBytes(@vStringArea[0], SizeOf(vStringArea));

    SetLength(vHandlesArray, 3);

    vHandlesArray[0] := CreateDWGHandle(AOwnerHandle, cntDWGObjHandleSoftPointer);
    vHandlesArray[1] := CreateDWGHandle(cnstBadHandle, cntDWGObjHandleHardOwner);
    vHandlesArray[2] := CreateDWGHandle(GetEntityHandle(EntXrefBlock(ALType, Converter)){cnstBadHandle}, cntDWGObjHandleHardPointer);

    for I := 0 to vHandles.Count - 1 do
    begin
      SetLength(vHandlesArray, Length(vHandlesArray) + 1);
      vHandlesArray[High(vHandlesArray)] := CreateDWGHandle(vHandles[I], cntDWGObjHandleHardPointer);
    end;

    AddHandlesUpdateAndFinish(vBits, vHandlesArray, ALType.Handle, cntDWGObjCodeLTYPE1);
  finally
    vHandles.Free;
    vBits.Free;
  end;
end;

procedure TsgCADtoDWG.ProcLTypeControlObject(const AHandle: UInt64;
  const ALTypesHandles: array of TsgDWGHandle);
begin
  ProcControlObject(AHandle, cntDWGObjCodeLTYPECONTROLOBJ, Length(ALTypesHandles) - 4,
    ALTypesHandles);
end;

procedure TsgCADtoDWG.ProcStyle(const AOwner: UInt64; const AStyle: TsgDXFStyle;
  AHandles: TsgInt64List);
var
  vName: string;
  vBits: TsgDWGBits;
  vCode: Word;

begin
  if AStyle = nil then Exit;

  if AStyle.Flags and 1 <> 0 then
    vName := ''
  else
    vName := AStyle.Name;
  vCode := cntDWGObjCodeSTYLE1;

  vBits := TsgDWGBits.Create;
  try
    AddCommonEntityData(AStyle.Handle, vCode, vBits, 0, AStyle);

    vBits.WriteTV(ExtractName(vName), FCodePage); //Entry name TV 2
    vBits.WriteBit(Get64bitof70Group(AStyle.Flags)); //64-flag B 70 The 64-bit of the 70 group.
    vBits.WriteBS(0); //xrefindex+1 BS 70 subtract one from this value when read. After that, -1 indicates that this reference did not come from an xref, otherwise this value indicates the index of the blockheader for the xref from which this came.
    vBits.WriteBit(GetXdep(AStyle.Name)); //Xdep B 70 dependent on an xref. (16 bit)
    vBits.WriteBit(AStyle.Flags, 1); //Vertical B 1 if vertical (1 bit of flag)
    vBits.WriteBit(AStyle.Flags, 8); //shape file B 1 if a shape file rather than a font (4 bit)
    vBits.WriteBD(AStyle.FixedHeight); //Fixed height BD 40
    vBits.WriteBD(AStyle.WidthFactor); //Width factor BD 41
    vBits.WriteBD(AStyle.ObliqueAngle / f180DividedByPi); //Oblique ang BD 50
    vBits.WriteRC(AStyle.TextGenFlags); //Generation RC 71 Generation flags (not bit-pair coded)
    vBits.WriteBD(AStyle.LastHeightUsed); //Last height BD 42
    vBits.WriteTV(AStyle.PrimaryFont, FCodePage); //Font name TV 3
    vBits.WriteTV(AStyle.BigFont, FCodePage); //Bigfont name TV 4

    AddHandlesUpdateAndFinish(vBits,
      [CreateDWGHandle(AOwner, cntDWGObjHandleSoftPointer),
      CreateDWGHandle(cnstBadHandle, cntDWGObjHandleHardOwner),
      CreateDWGHandle(GetEntityHandle(EntXrefBlock(AStyle, Converter)){cnstBadHandle}, cntDWGObjHandleHardPointer)],
      AStyle.Handle, vCode);

    AHandles.Add(AStyle.Handle);
  finally
    vBits.Free;
  end;
end;

procedure TsgCADtoDWG.ProcStyleControl(const AHandle: UInt64; StylesHandles: TsgInt64List);
var
  vHandles: array of TsgDWGHandle;
  I: Integer;
begin
  SetLength(vHandles, StylesHandles.Count + 2);
  vHandles[0] := CreateDWGHandle(cnstBadHandle, cntDWGObjHandleSoftPointer);
  vHandles[1] := CreateDWGHandle(cnstBadHandle, cntDWGObjHandleHardOwner);
  for I := 2 to High(vHandles) do
    vHandles[I] := CreateDWGHandle(StylesHandles[I - 2], cntDWGObjHandleSoftOwner);
  ProcControlObject(AHandle, cntDWGObjCodeSTYLECONTROLOBJ, StylesHandles.Count,
    vHandles);
end;

procedure TsgCADtoDWG.ProcVariableDictionary(const Handle,
  OwnerHandle: UInt64; const Index: Integer; const Name: string);
var
  vBits: TsgDWGBits;
  vCode: Word;
  vHandles: TsgDWGHandleArray;
begin
  vBits := TsgDWGBits.Create;
  try
    vCode := GetDWGCodeByClass(cntClassDXFDICTIONARYVAR);
    AddCommonEntityData(Handle, vCode, vBits, 1);
    vBits.WriteRC(0);
    vBits.WriteTV(Name, FCodePage);

    AddHandleToArray(CreateDWGHandle(OwnerHandle, cntDWGObjHandleSoftPointer), vHandles);
    AddHandleToArray(CreateDWGHandle(OwnerHandle, cntDWGObjHandleSoftPointer), vHandles);
    AddHandleToArray(CreateDWGHandle(cnstBadHandle, cntDWGObjHandleHardOwner), vHandles);

    AddHandlesUpdateAndFinish(vBits, vHandles, Handle, vCode);
  finally
    vBits.Free;
  end;
end;

procedure TsgCADtoDWG.ProcVPort(const AOwnerHandle: UInt64; AVPort: TsgDXFVPort;
  var ProcVPortHandles: TsgDWGHandleArray);
var
  vBits: TsgDWGBits;
  V: TsgDXFViewPort;
begin
  vBits := TsgDWGBits.Create;
  try
    V := CreateDefaultViewPort(cnstBadHandle);
    try
      AddCommonEntityData(AVPort.Handle, cntDWGObjCodeVPORT, vBits);
      vBits.WriteTV(AVPort.Name, FCodePage);//Entry name TV 2
      vBits.WriteBit(0); //64-flag B 70 The 64-bit of the 70 group
      vBits.WriteBS(0);  // xrefindex+1 BS 70
      vBits.WriteBit(GetXdep(AVPort.Name)); //Xdep B 70 dependent on an xref. (16 bit)
      vBits.WriteBD(V.PSpaceHeight); //View height BD 40 2
      vBits.WriteBD(V.PSpaceWidth);//Aspect ratio BD 41
      vBits.Write2RD(V.MSpaceCenter); //View Center 2RD 12 DCS
      vBits.Write3BD(V.ViewTarget); //View target 3BD 17
      vBits.Write3BD(V.ViewDirection);//View dir 3BD 16
      vBits.WriteBD(V.ViewTwistAngle / f180DividedByPi); //View twist BD 51
      vBits.WriteBD(cntViewPortPerspectiveLensLength); //Lens length BD 42
      vBits.WriteBD(V.FrontClipPlane); //Front clip BD 43
      vBits.WriteBD(V.BackClipPlane); //Back clip BD 44
      vBits.WriteBB(0); //View mode X 71 2 bits
      vBits.WriteBB(0); //View mode X 71 2 bits
      vBits.WriteRC(0); //Render Mode RC 281 0 2D Optimized (classic 2D)
      vBits.Write2RD(cnstF2DPointZero); //Lower left 2RD 10 In fractions of screen width and height
      vBits.Write2RD(MakeF2DPoint(1, 1)); //Upper right 2RD 11 In fractions of screen width and height.
      vBits.WriteBit(0); //UCSFOLLOW B 71 UCSFOLLOW. Bit 3 (8) of the 71-group.
      vBits.WriteBS(cntViewPortCircleZoomPercent); //Circle zoom BS 72 Circle zoom percent.
      vBits.WriteBit(1); //Fast zoom B 73
      vBits.WriteBB(2); //UCSICON X 74 2 bits: 10
      vBits.WriteBit(0); //Grid on/off B 76
      vBits.Write2RD(MakeF2DPoint(1, 1)); //Grd spacing 2RD 15
      vBits.WriteBit(0); //Snap on/off B 75
      vBits.WriteBit(0); //Snap style B 77
      vBits.WriteBS(0); //Snap isopair BS 78
      vBits.WriteBD(0); //Snap rot BD 50
      vBits.Write2RD(cnstF2DPointZero); //Snap base 2RD 13
      vBits.Write2RD(MakeF2DPoint(1,1)); //Snp spacing 2RD 14
      vBits.WriteBit(0); //Unknown B
      vBits.WriteBit(AVPort.UCSVP); //UCS per Viewport B 71
      vBits.Write3BD(AVPort.UCSOrigin); //UCS Origin 3BD 110
      vBits.Write3BD(AVPort.UCSXDir); //UCS X Axis 3BD 111
      vBits.Write3BD(AVPort.UCSYDir); //UCS Y Axis 3BD 112
      vBits.WriteBD(0); //UCS Elevation BD 146
      vBits.WriteBS(0); //UCS Orthographic type BS 79
    finally
      V.Free;
    end;
    AddHandlesUpdateAndFinish(vBits,
      [CreateDWGHandle(AOwnerHandle, cntDWGObjHandleSoftPointer),
      CreateDWGHandle(cnstBadHandle, cntDWGObjHandleHardOwner),
      CreateDWGHandle(cnstBadHandle, cntDWGObjHandleHardPointer),
      CreateDWGHandle(cnstBadHandle, cntDWGObjHandleHardPointer),
      CreateDWGHandle(cnstBadHandle, cntDWGObjHandleHardPointer)],
      AVPort.Handle, cntDWGObjCodeVPORT);
    AddHandleToArray(CreateDWGHandle(AVPort.Handle, cntDWGObjHandleSoftOwner),
      ProcVPortHandles);
  finally
    vBits.Free;
  end;
end;

procedure TsgCADtoDWG.ProcViewPortControlObject(const AHandle: UInt64;
  const ProcViewPortHandles: TsgDWGHandleArray);
begin
  ProcControlObject(AHandle, cntDWGObjCodeVPORTCONTROLOBJ, Length(ProcViewPortHandles) - 2,
    ProcViewPortHandles);
end;

procedure TsgCADtoDWG.ProcViewPortEntHeader(const AIndex: Integer);
var
  vBits: TsgDWGBits;
  vCode: Word;
  vElem: TsgDWGCreatedElement;
  vName: string;
begin
  vBits := TsgDWGBits.Create;
  try
    vElem := FCreatedElements[AIndex];
    vCode := cntDWGObjCodeVPENTHDR;
    AddCommonEntityData(vElem.Handle, vCode, vBits);
    vName := '';
    if vElem.Location = 1 then //location is ThisID
      vName := '1';
    vBits.WriteTV(vName, FCodePage); //Entry name TV 2
    vBits.WriteBit(1); //64-flag B 70 The 64-bit of the 70 group.
    vBits.WriteBS(0); //xrefindex+1 BS 70 subtract one from this value when read. After that, -1 indicates that this reference did not come from an xref, otherwise this value indicates the index of the blockheader for the xref from which this came.
    vBits.WriteBit(0); //Xdep B 70 dependent on an xref. (16 bit)
    vBits.WriteBit(0); //1 flag B The 1 bit of the 70 group
    AddHandlesUpdateAndFinish(vBits, vElem.Handles, vElem.Handle, vCode);
  finally
    vBits.Free;
  end;
end;

procedure TsgCADtoDWG.ProcWipeoutVar(const Handle, OwnerHandle: UInt64);
var
  vBits: TsgDWGBits;
  vCode: Word;
  vHandles: TsgDWGHandleArray;
begin
  vBits := TsgDWGBits.Create;
  try
    vCode := GetDWGCodeByClass(cntClassDXFWIPEOUTVARIABLES);
    AddCommonEntityData(Handle, vCode, vBits);
    vBits.WriteBL(Ord(not Converter.HideWipeOuts));
    AddOwnerAndXDiObjHandle(vHandles, OwnerHandle);
    AddHandlesUpdateAndFinish(vBits, vHandles, Handle, vCode);
  finally
    vBits.Free;
  end;
end;

procedure TsgCADtoDWG.SaveObjectToStream(const AHandle: UInt64; const ABits: TsgDWGBits;
  DWGCode: Word);
begin
  FObjectsMap.AddElement(AHandle, Sections[GetObjectsSectionIndex].Position,
    DWGCode, '', cnstBadHandle, nil, ABits.Size);
  ABits.SaveToStream(Sections[GetObjectsSectionIndex]);
end;

procedure TsgCADtoDWG.SaveSectionToStream(const ASectNum: Integer;
  const ABits: TsgDWGBits; const ABeginSentinel, AEndSentinel: array of Byte;
  ANeedToClear: Boolean = True);
var
  vMemoryStream: TMemoryStream;

  procedure WriteSentinelToStream(const ASentinel: array of Byte);
  var
    vSentinelSize: Integer;
    P: Pointer;
  begin
    vSentinelSize := SizeOf(ASentinel);
    if vSentinelSize > 0 then
    begin
      P := @ASentinel[Low(ASentinel)];
      vMemoryStream.Write(P^, vSentinelSize);
    end;
  end;

begin
  DoError((ASectNum < 0) or (ASectNum >= FSections.Count), sInvalidSectNumber);
  vMemoryStream := Sections[ASectNum];
  if ANeedToClear then
    vMemoryStream.Clear;
  WriteSentinelToStream(ABeginSentinel);
  ABits.SaveToStream(vMemoryStream);
  WriteSentinelToStream(AEndSentinel);
end;

procedure TsgCADtoDWG.SetVersion(const Value: TsgDWGVersion);
begin
  if Value <> acR2000 then
    raise EDWGUnsupportedExportVersion.Create(sInvalidVersion);
  inherited SetVersion(Value);
end;

procedure TsgCADtoDWG.WriteByteToStream(const Stream: TStream; const Byte: Byte;
  const Count: Integer);
var
  P: PByte;
begin
  GetMem(P, Count);
  try
    FillChar(P^, Count, Byte);
    Stream.Write(P^, Count);
  finally
    FreeMem(P);
  end;
end;

function TsgCADtoDWG.Export3DFace(F: TsgDXF3dFace; ABits: TsgDWGBits): Boolean;
var
  vHasFlags, vZNilBit: Boolean;
  vFlags: Integer;
begin
  vFlags := TsgDXF3dFaceAccess(F).Flags;
  vHasFlags := vFlags <> 0;
  vZNilBit := IsZero(F.Point.Z);
  ABits.WriteBit(not vHasFlags);
  ABits.WriteBit(vZNilBit);
  ABits.Write2RD(F.Point);
  if not vZNilBit then
    ABits.WriteRD(F.Point.Z);
  ABits.Write3DD(F.Point1, F.Point);
  ABits.Write3DD(F.Point2, F.Point1);
  ABits.Write3DD(F.Point3, F.Point2);
  if vHasFlags then
    ABits.WriteBS(vFlags);
  Result := True;
end;

(*
function TsgCADtoDWG.ExportACISEntity(A: TsgDXFACISEntity;
  const AExportData: TsgDWGExportData): Boolean;
begin
  Result := ExportGroup(A, AExportData);
end;

function TsgCADtoDWG.ExportChildEntities(E: TsgDXFEntity;
  const AExportData: TsgDWGExportData): Boolean;
begin
  Result := ExportGroup(E, AExportData);
end;

function TsgCADtoDWG.ExportFlatHatch(FlatHatch: TsgFlatHatch; Data: TsgDWGExportData): Boolean;
begin
  Result := ExportGroup(FlatHatch, Data);
end;
*)

{$IFDEF SG_BTI}
function TsgCADtoDWG.ExportPolyPolyline2D(Poly: TsgCADPolyPolyline2D;
  const AExportData: TsgDirectExportData): Boolean;
begin
  Result := ExportGroup(Poly, cntDWGObjCodePOLYLINE3D, AExportData);
end;
{$ENDIF}

function TsgCADtoDWG.ExportCADFill(CADFill: TsgCADFill;
  const Data: TsgDirectExportData): Boolean;
begin
  Result := ExportGroup(CADFill, cntDWGObjCodePOLYLINE3D, Data);
end;

function TsgCADtoDWG.ExportCircle(C: TsgDXFCircle; ABits: TsgDWGBits): Boolean;
begin
  Result := True;
  ABits.Write3BD(C.Point);
  ABits.WriteBD(C.Radius);
  ABits.WriteBT(C.ZThick);
  ABits.WriteBE(C.Extrusion);
  case C.EntType of
    ceArc:
      begin
        ABits.WriteBD(TsgDXFArc(C).StartAngle / f180DividedByPi);
        ABits.WriteBD(TsgDXFArc(C).EndAngle / f180DividedByPi);
      end;
  end;
end;

procedure TsgCADtoDWG.ExportCreatedTableRecords;
var
  vBits: TsgDWGBits;
  vItem: TsgDWGCreatedElement;
  I: Integer;
  vHandles: array of TsgDWGHandle;

  function GetChildrenCount(ACode: Word): Cardinal;
  var
    I, vIndex: Integer;
    vCode: Word;
  begin
    Result := 0;
    vCode := ACode + 1; //tables children DWG code are equal CONTROL_OBJECT_CODE + 1, see DWG documentation
    vIndex := FCreatedElements.IndexOf(vCode);
    SetLength(vHandles, 2);
    vHandles[0] := CreateDWGHandle(cnstBadHandle, cntDWGObjHandleSoftPointer);
    vHandles[1] := CreateDWGHandle(cnstBadHandle, cntDWGObjHandleHardOwner);
    if vIndex >= 0 then
    begin
      for I := vIndex to FCreatedElements.Count - 1 do
      begin
        if FCreatedElements.Element[I].DWGObjCode <> vCode then Break;
        Inc(Result);
        SetLength(vHandles, Length(vHandles) + 1);
        vHandles[High(vHandles)] := CreateDWGHandle(FCreatedElements[I].Handle,
          cntDWGObjHandleSoftOwner);
      end;
    end;
  end;

begin
  vBits := TsgDWGBits.Create;
  try
    FCreatedElements.SortBy := seDWGObjCode;
    for I := 0 to FCreatedElements.Count - 1 do
    begin
      vBits.Clear;
      vItem := FCreatedElements.Element[I];
      if (vItem.Handle <> cnstBadHandle) and
         ((vItem.Obj is TsgDXFPenTableItem) or (vItem.Obj is TsgDXFBlockRecord)) then
      begin
        if AddCommonEntityData(vItem.Handle, vItem.DWGObjCode, vBits) = 0 then Continue;
        vBits.WriteBL(GetChildrenCount(vItem.DWGObjCode));
        AddHandlesUpdateAndFinish(vBits, vHandles, vItem.Handle, vItem.DWGObjCode);
      end;
    end;
  finally
    vBits.Free;
  end;
  ExportViewPortEntityHeaders;
end;

function TsgCADtoDWG.ExportDimension(D: TsgDXFDimension; ABits: TsgDWGBits;
  DWGCode: Word): Boolean;
var
  vFlags: Byte;

  procedure SetBitFlag(Mask, FlagMask: Byte; SetAnyTime: Boolean = False);
  begin
    if (D.Flags and Mask = 1) or SetAnyTime then
      vFlags := vFlags or FlagMask;
  end;

begin
  if Version > acR2007 then
    ABits.WriteRC(0);
  ABits.Write3BD(D.Extrusion);//Extrusion 3BD 210
  ABits.Write2RD(D.MiddlePoint);//Text midpt 2RD 11
  ABits.WriteBD(0); //Elevation BD 11
  vFlags := 8;//not sure
  SetBitFlag(128, 1);
  SetBitFlag(32, 2, True);//Bit 1 : Same as bit 5 (32) of the 70
  ABits.WriteRC(vFlags);//Flags 1 RC 70
  ABits.WriteTV(D.TextOverride, FCodePage);//User text TV 1
  ABits.WriteBD(0);//Text rot BD 53
  ABits.WriteBD(0);//Horiz dir BD 51
  ABits.Write3BD(D.Scale);//Ins X, Y, Z-scale
  ABits.WriteBD(D.Angle / f180DividedByPi);//Ins rotation
  if Version >= acR2000 then
  begin
    ABits.WriteBS(5);//Attachment Point BS
    ABits.WriteBS(1);//Linespacing Style BS
    ABits.WriteBD(1);//Linespacing Factor BD 41
    ABits.WriteBD(-1);//Actual Measurement BD 42
  end;
  if Version >= acR2007 then //b73
  begin
    ABits.WriteBit(0);//Unknown B 73
    ABits.WriteBit(0);//Flip arrow1 B 74
    ABits.WriteBit(0);//Flip arrow2 B 75
  end;
  ABits.Write2RD(D.Point);
  case DWGCode of
    cntDWGObjCodeDIMENSIONORDINATE, cntDWGObjCodeDIMENSIONANG3Pt:
      begin
        ABits.Write3BD(D.DefPoint);//10-pt 3BD 10
        ABits.Write3BD(D.LinDefPoint1);//13-pt 3BD 13
        ABits.Write3BD(D.LinDefPoint2);//14-pt 3BD 14
        case DWGCode of
          cntDWGObjCodeDIMENSIONORDINATE:
            begin
              vFlags := 0;
              SetBitFlag(64, 1);
              ABits.WriteRC(vFlags);
            end;
          cntDWGObjCodeDIMENSIONANG3Pt:
            ABits.Write3BD(D.RadDefPoint);//15-pt 3BD 15
        end;
      end;
    cntDWGObjCodeDIMENSIONALIGNED, cntDWGObjCodeDIMENSIONLINEAR:
      begin
        ABits.Write3BD(D.LinDefPoint1);//13-pt 3BD 13
        ABits.Write3BD(D.LinDefPoint2);//14-pt 3BD 14
        ABits.Write3BD(D.DefPoint);//10-pt 3BD 10
        ABits.WriteBD(0);//Ext ln rot BD 52
        if DWGCode = cntDWGObjCodeDIMENSIONLINEAR then
          {ABits.WriteBD(0)//;}ABits.WriteBD(D.Angle);//Dim rot BD 50  //!!!
      end;
    cntDWGObjCodeDIMENSIONANG2Ln:
      begin
        ABits.Write2RD(D.ArcDefPoint);//16-pt 2RD 16
        ABits.Write3BD(D.LinDefPoint1);//13-pt 3BD 13
        ABits.Write3BD(D.LinDefPoint2);//14-pt 3BD 14
        ABits.Write3BD(D.RadDefPoint);//15-pt 3BD 15
        ABits.Write3BD(D.DefPoint);//10-pt 3BD 10
      end;
    cntDWGObjCodeDIMENSIONRADIUS, cntDWGObjCodeDIMENSIONDIAMETER:
      begin
        ABits.Write3BD(D.DefPoint);//10-pt 3BD 10
        ABits.Write3BD(D.RadDefPoint);//15-pt 3BD 15
        ABits.WriteBD(0);//Leader len D 40
      end;
  end;
  Result := True;
end;

function TsgCADtoDWG.ExportEllipse(E: TsgDXFEllipse; ABits: TsgDWGBits): Boolean;
var
  vStartAngle, vEndAngle: Double;

  function CheckAngle(const Value: Double): Double;
  begin
    Result := Value;
    if Value > 360 then
      Result := Value - 360;
  end;

begin
  ABits.Write3BDPreExtruded(E.Point, E.Extrusion);//Center 3BD 10 (WCS)
  ABits.Write3BDPreExtruded(E.RadPt, E.Extrusion);//SM axis vec 3BD 11 Semi-major axis vector (WCS)
  ABits.Write3BD(E.Extrusion);//Extrusion 3BD 210
  ABits.WriteBD(E.Ratio);//Axis ratio BD 40 Minor/major axis ratio
  vStartAngle := E.StartAngle;
  vEndAngle := E.EndAngle;
  if IsZero(vStartAngle - vEndAngle) then
  begin
    vStartAngle := 0;
    vEndAngle := 360;
  end;
  ABits.WriteBD(Radian(vStartAngle));//Beg angle BD 41 Starting angle (eccentric anomaly, radians)
  ABits.WriteBD(Radian(vEndAngle));//End angle BD 42 Ending angle (eccentric anomaly, radians)
  Result := True;
end;

function TsgCADtoDWG.ExportFlatPoly(FlatPoly: TsgFlatPoly; const Data: TsgDirectExportData): Boolean;
begin
  Result := ExportGroup(FlatPoly, cntDWGObjCodePOLYLINE3D, Data);
end;

function TsgCADtoDWG.ExportHatch(H: TsgCADPolyPolygon; ABits: TsgDWGBits;
  DWGCode: Word): Boolean;
const
  cntMPoligonsTypes = [cePolyPolygon];

var
  vDoubleVal: Double;
  vFPoint: TFPoint;
  I: Integer;
  vPixSize, vIsCADCurvePolygon: Boolean;

  procedure WriteGradietParams;
  begin
    if (H.EntType = ceMPolygon) or ((H is TsgCADGradientPolygon) and
      (Length(TsgCADGradientPolygon(H).GradientName) > 0)) then
    begin
      DoError(True, sGradientIsNotSupported);
//      AddInt(450, Integer(PP.EntType <> ceMPolygon));
//      AddInt(451, 0);
//      AddFloat(460, vGradient.GradientAngle * fPiDividedBy180);
//      AddFloat(461, Integer(not vGradient.GradientUseCenter));
//      AddInt(452, 1);//Single-color gradient
//      AddFloat(462, 1.0);
//      AddInt(453, 2);
//      AddFloat(463, 0.0);
//      AddInt(421, GetGradientColor(vGradient.GradientColor[0]));
//      AddFloat(463, 1.0);
//      AddInt(421, GetGradientColor(vGradient.GradientColor[1]));
//      AddString(470, vGradient.GradientName);
//
//  vGrad := ReadBL(APBit) <> 0;
//  SeekGeneral(APBit,[seBL]);
//  vCurvePolygon.GradientAngle := RadToDeg(ReadBD(APBit));
//  vCurvePolygon.GradientUseCenter :=  Abs(ReadBD(APBit)) < fAccuracy;
//  // | seBL - Gradient one color mode Boolean
//  // v seBD - Luminance value
//  SeekGeneral(APBit,[seBL,seBD]);
//  vNumColor := ReadBL(APBit);//Number of colors
//  for I := 1 to vNumColor do
//  begin
//    SeekGeneral(APBit,[seBD]);
//    case I of
//      1, 2: vCurvePolygon.GradientColorCAD[I-1] := ReadColorCAD(Self, APBit);
//    else
//      ReadCMC(Self, APBit);
//    end;
//  end;
//  vCurvePolygon.GradientName := ReadText(Self, APBit);
//  if vGrad then
//    FColor := MakeColorCAD(acRGBColor, clEmpty)
//  else
//    vCurvePolygon.GradientName := '';
    end;
  end;

  procedure AddPolylineBoundary(ABoundaryList: TF2DPointList);
  var
    I: Integer;
  begin
    ABits.WriteBit(True);//closed
    ABits.WriteBit(False);//bulges
    ABits.WriteBL(ABoundaryList.Count);
    for I := 0 to ABoundaryList.Count - 1 do
      ABits.Write2RD(ABoundaryList[I]);
  end;

  procedure AddPatternData;
  var
    vHatch: TsgCADHatch absolute H;
    vPatternData: TsgHatchPatternData;
    vDashLengths: TsgDoubleList;
    I, J: Integer;
  begin
    ABits.WriteBD(vHatch.PatternAngle / f180DividedByPi);
    ABits.WriteBD(vHatch.PatternScale);
    ABits.WriteBit(0);
    ABits.WriteBS(vHatch.HatchPatternData.Count);
    for I := 0 to vHatch.HatchPatternData.Count - 1 do
    begin
      vPatternData := PsgHatchPatternData(vHatch.HatchPatternData[I])^;
      ABits.WriteBD(vPatternData.LineAngle / f180DividedByPi);//angle BD 53 line angle
      ABits.Write2BD(vPatternData.BaseP);//pt0 2BD 43/44 pattern through this point (X,Y)
      ABits.Write2BD(vPatternData.Offset);//offset 2BD 45/56 pattern line offset
      // Dash length (multiple entries)
      vDashLengths := vPatternData.Lines;
      if vDashLengths <> nil then
      begin
        ABits.WriteBS(vDashLengths.Count);//numdashes BS 79 number of dash length items
        for J := 0 to vDashLengths.Count - 1 do
          ABits.WriteBD(vDashLengths[J]);
      end
      else
        ABits.WriteBS(0);
    end;
  end;

  procedure Write2DLine(Boundary: Tsg2DCurve);
  begin
    ABits.Write2RD(Boundary.StartPoint);
    ABits.Write2RD(Boundary.EndPoint);
  end;

  procedure Write2DArc(const ACircle: Boolean; Boundary: Tsg2DCurve);
  begin
    if ACircle then
      ABits.Write2RD(Tsg2DArc(Boundary).CenterPoint)
    else
    begin
      ABits.Write2RD(Tsg2DEllipse(Boundary).CenterPoint);
      ABits.Write2RD(Tsg2DEllipse(Boundary).MajorPoint);
    end;
    ABits.WriteBD(Tsg2DArc(Boundary).Radius);
    ABits.WriteBD(Tsg2DArc(Boundary).StartParam / f180DividedByPi);
    ABits.WriteBD(Tsg2DArc(Boundary).EndParam / f180DividedByPi);
    ABits.WriteBit(Tsg2DArc(Boundary).CounterClockWise);
  end;

  procedure Write2DSpline(Boundary: Tsg2DSplineEx);
  var
    I: Integer;
  begin
    ABits.WriteBL(Boundary.Degree);
    ABits.WriteBit(0);//rational
    ABits.WriteBit(0);//periodic
    ABits.WriteBL(Boundary.KnotsCount);
    ABits.WriteBL(Boundary.ControlsCount);
    for I := 0 to Boundary.KnotsCount - 1 do
      ABits.WriteBD(Boundary.Knots[I]);
    for I := 0 to Boundary.ControlsCount - 1 do
      ABits.Write2RD(Boundary.Controls[I]);
//    if Version > acR2007 then
//    begin
//      ABits.WriteBL(FitPtsNum); //new feature builds curve by fit points
//      if FitPtsNum > 0 then
//      begin
//        for I := 0 to FitPtsNum - 1 do
//          ABits.Write2RD(); SeekGeneral(APBit,[se2RD]);
//        ABits.Write2RD();
//        ABits.Write2RD();
//      end;
//    end;
  end;

  procedure Write2DPolyline(Boundary: Tsg2DPolylineEx;
    APointList: TF2DPointList = nil);
  var
    I, vCount: Integer;
    vBulges, vClosed: Boolean;
  begin

    if APointList = nil then
    begin
      vBulges := Boundary.BulgesCount > 0;
      vCount := Boundary.VertexesCount;
      vClosed := Boundary.Closed;
    end
    else
    begin
      vBulges := False;
      vCount := APointList.Count;
      vClosed := True;
    end;
    ABits.WriteBit(vBulges);//bulges
    ABits.WriteBit(vClosed);//closed
    ABits.WriteBL(vCount);
    for I := 0 to vCount - 1 do
    begin
      if APointList = nil then
      begin
        ABits.Write2RD(Boundary.Vertexes[I]);
        if vBulges then
          ABits.WriteBD(Boundary.Bulges[I]);
      end
      else
        ABits.Write2RD(APointList[I]);
    end;
  end;

  procedure AddBoundaryPathData(ABoundaryList: Tsg2DBoundaryList;
    APointList: TF2DPointList = nil);
  var
    vBoundary: Tsg2DCurve;
    I: Integer;
    vBoundaryType: Byte;
  begin
    if APointList = nil then
    begin
      vBoundaryType := ABoundaryList.BoundaryType;
      vPixSize := vPixSize or (ABoundaryList.BoundaryType and 4 <> 0);
    end
    else
      vBoundaryType := 2;
    ABits.WriteBL(vBoundaryType);
    if vBoundaryType and 2 = 0 then
    begin
      ABits.WriteBL(ABoundaryList.Count);
      for I := 0 to ABoundaryList.Count - 1 do
      begin
        vBoundary := Tsg2DCurve(ABoundaryList[I]);
        ABits.WriteRC(vBoundary.EdgeType);
        case vBoundary.EdgeType of
          1: Write2DLine(vBoundary);
          2: Write2DArc(True, vBoundary);
          3: Write2DArc(False, vBoundary);
          4: Write2DSpline(Tsg2DSplineEx(vBoundary));
        end;
      end;
    end
    else
      if APointList = nil then
        Write2DPolyline(Tsg2DPolylineEx(ABoundaryList[0]), nil)
      else
        Write2DPolyline(nil, APointList);
    ABits.WriteBL(0);
  end;

  function IsMPoligonHatch: Boolean;
  begin
    Result := (DWGCode = cntDWGObjCodeMPOLYGON) or (H.EntType = cePolyPolygon);
  end;

begin
  vPixSize := False;
  vIsCADCurvePolygon := H is TsgCADCurvePolygon;

  if DWGCode = cntDWGObjCodeMPOLYGON then
    ABits.WriteBL(1);
  if Version >= acR2004 then
    WriteGradietParams;
  if Version >= acR2007 then
    ABits.WriteTV(H.HatchName, FCodePage);
  vDoubleVal := 0;
  vFPoint := cnstZOrtAxis;
  if H is TsgCADCurvePolygon then
  begin
    vDoubleVal := TsgCADCurvePolygon(H).Elevation.Z;
    vFPoint := TsgCADCurvePolygon(H).Extrusion;
  end;
  ABits.WriteBD(vDoubleVal);//Z coord BD 30 X, Y always 0.0
  ABits.Write3BD(vFPoint);//Extrusion 3BD 210
  if Version < acR2007 then
    ABits.WriteTV(H.HatchName, FCodePage);

  if DWGCode = cntDWGObjCodeMPOLYGON then
    ABits.WriteBit(H.SolidFill)
  else
  begin
    ABits.WriteBit(H.SolidFill);
    ABits.WriteBit(0);
  end;
  //boundary data
  if DWGCode <> cntDWGObjCodeMPOLYGON then
  begin
    if vIsCADCurvePolygon then
    begin
      ABits.WriteBL(TsgCADCurvePolygon(H).BoundaryDataCount);
      for I := 0 to TsgCADCurvePolygon(H).BoundaryDataCount - 1 do
        AddBoundaryPathData(TsgCADCurvePolygon(H).BoundaryData[I]);
    end
    else
    begin
      ABits.WriteBL(H.Boundaries.Count);
      for I := 0 to H.Boundaries.Count - 1 do
        AddBoundaryPathData(nil, H.Boundaries[I]);
    end;
    ABits.WriteBS(0);//Hatch style
  end
  else
  begin
    ABits.WriteBL(H.Boundaries.Count);
    for I := 0 to H.Boundaries.Count - 1 do
      AddPolylineBoundary(H.Boundaries[I]);
  end;
  ABits.WriteBS(1);// Hatch pattern type (1 = predefined)
  if not H.SolidFill then
    AddPatternData;
  if vPixSize then
    ABits.WriteBD(0.000001);
  if DWGCode = cntDWGObjCodeMPOLYGON then
  begin
    ABits.WriteCMC(TsgCADMPolygon(H).FillColor);
    ABits.Write2RD(TsgCADMPolygon(H).Offset);
  end;
  ABits.WriteBL(0);
  Result := True;
end;

function TsgCADtoDWG.ExportInsert(Insert: TsgDXFInsert; ABits: TsgDWGBits;
  EEData: TsgCADExtendedData): Boolean;
var
  vPoint, vScale: TFPoint;
  vAngle: Double;
  vScaleFlag: Byte;
  I: Integer;
  vHasAttribs: Boolean;
  vData: TsgDirectExportData;
begin
  Result := True;

  vPoint := Insert.Point;
  vScale := Insert.Scale;
  vAngle := Insert.Angle;

  if Insert.EntClass.EG = gtSVG then
  begin
    Insert.ExtractParamsFromMatrix2D(vPoint, vScale, vAngle);
    if IsEqual(vScale.X, 0) or IsEqual(vScale.Y, 0) or IsEqual(vScale.Z, 0) then
      vScale := Insert.Scale;
  end;

  ABits.Write3BD(vPoint);// Ins pt 3BD 10

  if IsEqualFPoints(vScale, cnstFPointSingle) then
    vScaleFlag := 3
  else
    if IsEqual(vScale.X, vScale.Y) and IsEqual(vScale.X, vScale.Z) then
      vScaleFlag := 2
    else
      if IsEqual(vScale.X, 1) then
        vScaleFlag := 1
      else
        vScaleFlag := 0;
  ABits.WriteBB(vScaleFlag);
  case vScaleFlag of
    0:
      begin
        ABits.WriteRD(vScale.X);
        ABits.WriteDD(vScale.Y, vScale.X);
        ABits.WriteDD(vScale.Z, vScale.X);
      end;
    1:
      begin
        ABits.WriteDD(vScale.Y, 1);
        ABits.WriteDD(vScale.Z, 1);
      end;
    2: ABits.WriteRD(vScale.X);
  end;

  ABits.WriteBD(vAngle / f180DividedByPi);
  ABits.Write3BD(Insert.Extrusion);
  vHasAttribs := Insert.HasAttribs;
  ABits.WriteBit(vHasAttribs);

  if Insert is TsgCADMInsert then
  begin
    ABits.WriteBS(TsgCADMInsert(Insert).NumCols);//Numcols BS 70
    ABits.WriteBS(TsgCADMInsert(Insert).NumRows);//Numrows BS 71
    ABits.WriteBD(TsgCADMInsert(Insert).ColSpacing);//Col spacing BD 44
    ABits.WriteBD(TsgCADMInsert(Insert).RowSpacing);//Row spacing BD 45
  end;

  if vHasAttribs then
  begin
    vData := CreateExportData(Insert.Handle, 0, cnstBadHandle, cnstBadHandle, 0, Insert);
    DoExport(Insert, @vData);//for exporting SeqEnd
    for I := 0 to Insert.Attribs.Count - 1 do
    begin
      vData := CreateExportData(Insert.Handle, 0, GetPrevEntHandle(nil, I,
        Insert.Attribs), GetNextEntHandle(nil, I, Insert.Attribs), 0, Insert);
      DoExport(TsgDXFEntity(Insert.Attribs[I]), @vData);
    end;
  end;
end;

function TsgCADtoDWG.ExportLeader(L: TsgDXFLeader; ABits: TsgDWGBits): Boolean;
var
  I: Integer;
  vPoint: TFPoint;
begin
  ABits.WriteBit(0);//Unknown bit B
  ABits.WriteBS(3);// Annot type BS Created without any annotation
  ABits.WriteBS(Ord(L.IsSpline));//path type BS
  if L.ControlCount = 0 then
  begin
    ABits.WriteBL(1);//number of points
    ABits.Write3BD(cnstFPointZero);
  end
  else
  begin
    ABits.WriteBL(L.ControlCount);//number of points
    for I := 0 to L.ControlCount - 1 do
      ABits.Write3BD(L.Controls[I]);
  end;
  vPoint := cnstFPointZero;
  if L.ControlCount > 0 then
    vPoint := L.Controls[0]; //not sure, experimentally
  ABits.Write3BD(vPoint);//Endptproj 3BD
  ABits.Write3BD(L.Extrusion);//Extrusion 3BD
  ABits.Write3BD(cnstXOrtAxis);//x direction 3BD
  ABits.Write3BD(cnstFPointZero);//offsettoblockinspt 3BD
  ABits.Write3BD(cnstFPointZero);//Unknown 3BD
  if Version < acR2010 then
  begin
    ABits.WriteBD(0);//Box height BD 40
    ABits.WriteBD(0);//Box width BD 41
  end;
  ABits.WriteBit(0);//Hooklineonxdir B
  ABits.WriteBit(L.Arrowhead);//Arrowheadon B
  ABits.WriteBS(8);
  ABits.WriteBit(0);
  ABits.WriteBit(0);
  Result := True;
end;

function TsgCADtoDWG.ExportLine(L: TsgDXFLine; ABits: TsgDWGBits): Boolean;
var
  vNotNeedZ: Boolean;
begin
  vNotNeedZ := IsZero(L.Point.Z) and IsZero(L.Point1.Z);
  ABits.WriteBit(vNotNeedZ);
  ABits.WriteRD(L.Point.X); //Start Point x RD 10
  ABits.WriteDD(L.Point1.X, L.Point.X); //End Point x DD 11 Use 10 value for default
  ABits.WriteRD(L.Point.Y); //Start Point y RD 20
  ABits.WriteDD(L.Point1.Y, L.Point.Y); //End Point y DD 21 Use 20 value for default
  if not vNotNeedZ then
  begin
    ABits.WriteRD(L.Point.Z); //Start Point z RD 30 Present only if “Z’s are zero bit” is 0
    ABits.WriteDD(L.Point1.Z, L.Point.Z); //End Point z DD 31 Present only if “Z’s are zero bit” is 0, use 30 value for default.
  end;
  ABits.WriteBT(L.ZThick); //Thickness BT 39
  ABits.WriteBE(L.Extrusion); //Extrusion BE 210
  Result := True;
end;

function TsgCADtoDWG.ExportLWPolyline(LWPolyline: TsgDXFLWPolyline; ABits: TsgDWGBits): Boolean;
var
  vFlags: Word;
  vPoint: TFPoint;
  vBulgesCount, vWidthsCount: Cardinal;
  I: Integer;
  vFlagNoVertex: Boolean;

  procedure SetFlagsBit(const Mask: Word; const Value: Double);
  begin
    if not IsZero(Value) then
      vFlags := vFlags or Mask;
  end;

  procedure CheckBitAndWriteBD(Mask: Word; const Value: Double);
  begin
    if Mask and vFlags <> 0 then
      ABits.WriteBD(Value);
  end;

  function GetNumPoints: Cardinal;
  begin
    Result := LWPolyline.Count;
  end;

  procedure CountBulgesAndWidths;
  var
    I: Integer;
    vVertex: TsgDXFVertex;
  begin
    vBulgesCount := 0;
    vWidthsCount := 0;
    for I := 0 to LWPolyline.Count - 1 do
    begin
      vVertex := LWPolyline.Vertexes[I];
      if not IsZero(vVertex.Bulge) then
        vBulgesCount := GetNumPoints;
      if (not IsZero(vVertex.StartWidth)) or (not IsZero(vVertex.EndWidth)) then
        vWidthsCount := GetNumPoints;
      if (vBulgesCount <> 0) and (vWidthsCount <> 0) then
        Break;
    end;
  end;

begin
  Result := True;
  vFlags := 0;
  vFlagNoVertex := False;
  vPoint := cnstFPointZero;
  if LWPolyline.Count > 0 then
    vPoint := LWPolyline.Vertexes[0].Point
  else
    vFlagNoVertex := True;
  CountBulgesAndWidths;
  SetFlagsBit(4, LWPolyline.GlobalWidth);
  SetFlagsBit(8, LWPolyline.Elevation);
  SetFlagsBit(2, LWPolyline.ZThick);
  if LWPolyline.Closed then
    vFlags := vFlags or 512;
  if not IsEqualFPoints(LWPolyline.Extrusion, cnstExtrusion)  then
    vFlags := vFlags or 1;
  if vBulgesCount <> 0 then
    vFlags := vFlags or 16;
  if vWidthsCount <> 0 then
    vFlags := vFlags or 32;
  ABits.WriteBS(vFlags);
  CheckBitAndWriteBD(4, LWPolyline.GlobalWidth);
  CheckBitAndWriteBD(8, LWPolyline.Elevation);
  CheckBitAndWriteBD(2, LWPolyline.ZThick);
  if vFlags and 1 <> 0 then
    ABits.Write3BD(LWPolyline.Extrusion);
  if vFlagNoVertex then
    ABits.WriteBL(2)
  else
    ABits.WriteBL(GetNumPoints);
  if vBulgesCount <> 0 then
    ABits.WriteBL(vBulgesCount);
  if vWidthsCount <> 0 then
    ABits.WriteBL(vWidthsCount);
  ABits.Write2RD(vPoint);
  if vFlagNoVertex then
  begin
      ABits.WriteDD(0,0);
      ABits.WriteDD(0,0);
  end
  else
  begin
    for I := 1 to GetNumPoints - 1 do
    begin
      ABits.WriteDD(LWPolyline.Vertexes[I].Point.X, LWPolyline.Vertexes[I - 1].Point.X);
      ABits.WriteDD(LWPolyline.Vertexes[I].Point.Y, LWPolyline.Vertexes[I - 1].Point.Y);
    end;
  end;

  for I := 0 to vBulgesCount - 1 do
    ABits.WriteBD(LWPolyline.Vertexes[I].Bulge);
  for I := 0 to vWidthsCount - 1 do
    ABits.Write2BD(MakeF2DPoint(LWPolyline.Vertexes[I].StartWidth, LWPolyline.Vertexes[I].EndWidth));
end;

function TsgCADtoDWG.ExportMLine(M: TsgCADMLine; const ABits: TsgDWGBits;
  const AExportData: TsgDirectExportData): Boolean;
var
  vVertex: TsgMVertex;
  I, J, K, vLinesInStyle: Integer;
begin
  ABits.WriteBD(M.ScaleFactor);//Scale BD 40
  ABits.WriteRC(M.Justify);//Just EC top (0), bottom(2), or center(1)
  ABits.Write3BD(M.StartPoint);//Base point 3BD 10
  ABits.Write3BD(M.Extrusion);//Extrusion 3BD 210 etc.
  ABits.WriteBS(M.Flags);//Openclosed BS open (1), closed(3)
  if M.Count > 0 then
    vLinesInStyle := TsgMVertex(M[0]).ParamsCount
  else
    vLinesInStyle := 0;
  ABits.WriteRC(vLinesInStyle);//Linesinstyle RC 73
  ABits.WriteBS(M.Count); //Numverts BS 72
  for I := 0 to M.Count - 1 do
  begin
    vVertex := M[I];
    ABits.Write3BD(vVertex.Point);
    ABits.Write3BD(vVertex.Direction);
    ABits.Write3BD(vVertex.Miter);
    for J := 0 to vVertex.ParamsCount - 1 do
    begin
      ABits.WriteBS(vVertex.PCounts[J]);
      for K := 0 to vVertex.PCounts[J] - 1 do
        ABits.WriteBD(vVertex.Params[J, K]);
      ABits.WriteBS(0);
    end;
  end;
  Result := True;
end;

function TsgCADtoDWG.ExportMText(M: TsgDXFMText; ABits: TsgDWGBits): Boolean;
begin
  ABits.Write3BD(M.Point);// Insertion pt3 BD 10 First picked point
  ABits.Write3BD(M.Extrusion);//Extrusion 3BD 210
  if TsgDXFMTextEx(M).HasSecond then//X-axis dir 3BD 11
    ABits.WriteXDirection(True, M.Point1)
  else
    ABits.WriteXDirection(M.Angle, M.Extrusion);
  ABits.WriteBD(M.RectWidth);
  if Version >= acR2007 then
    ABits.WriteBD(M.RectHeight);//R2007+: Rect height BD 46 Reference rectangle height
  ABits.WriteBD(M.Height);//Text height BD 40
  ABits.WriteBS(M.Align);//Attachment BS 71
  ABits.WriteBS(1);//Drawing dir BS 72
  ABits.WriteBD(0);//Extents ht BD --- Undocumented and not present in DXF or entget
  ABits.WriteBD(0);//Extents wid BD --- Undocumented and not present in DXF or entget
  ABits.WriteTV(PrepareTextForDWG(GetEntityStringValue(M)), FCodePage, True);//Text TV 1 All text in one long string
  ABits.WriteBS(M.LineSpacingStyle);//Linespacing Style BS 73
  ABits.WriteBD(M.LineSpacingFactor);//Linespacing Factor BD 44
  ABits.WriteBit(0);
  if Version >= acR2004 then
    ABits.WriteBB(0);//Background flags
  Result := True;
end;

function TsgCADtoDWG.ExportOle2Frame(OLE2: TsgDXFOle2Frame;
  ExportData: TObject): Boolean;
var
  vOleHeader: PsgOle2FrameHeaderData;
  vBits: TsgDWGBits;
  vExportData: TsgDWGExportDataClass;
begin
  vExportData := TsgDWGExportDataClass(ExportData);
  if vExportData.Bits <> nil then
    vBits := TsgDWGBits(vExportData.Bits)
  else
    vBits := nil;
  if vBits = nil then
  begin
    DoExport(OLE2, vExportData.PExportData);
    Result := True;
    Exit;
  end;
  vBits.AllocBlock := vBits.AllocBlock + Cardinal(Length(OLE2.BinaryData));
  vBits.WriteBS(OLE2.OLEObjectType);
  vBits.WriteBS(0);
  vBits.WriteBL(Length(OLE2.BinaryData) + SizeOf(TsgOle2FrameHeaderData));
  New(vOleHeader);
  try
    PrepareOLEHeader(OLE2, vOleHeader);
    vBits.WriteBytes(vOleHeader, SizeOf(TsgOle2FrameHeaderData));
  finally
    Dispose(vOleHeader);
  end;
  vBits.WriteBytes(@OLE2.BinaryData[1], Length(OLE2.BinaryData));
  vBits.WriteRC(1);
  Result := True;
end;

function TsgCADtoDWG.ExportOle2FrameCreateOleGroup(OLE2: TsgDXFOle2Frame;
  ExportData: TObject): Boolean;
var
  vData: TsgDWGExportDataClass;
  vOLE: TsgDXFOle2Frame;
  vEnt: TsgDXFEntity;
begin
  Result := True;
  vData := TsgDWGExportDataClass(ExportData);
  vOLE := TsgDXFOle2Frame.Create;
  vOLE.AssignEntity(OLE2);
  vOLE.Handle := OLE2.Handle;
  vEnt := TsgDXFGroup(vData.Group)[vData.GroupIndex];
  TsgDXFGroup(vData.Group).DeleteEntity(vData.GroupIndex);
  TsgDXFGroup(vData.Group).InsertEntity(vData.GroupIndex, vOLE);
  vEnt.Free;
end;

function TsgCADtoDWG.ExportPoint(P: TsgDXFPoint; ABits: TsgDWGBits): Boolean;
begin
  ABits.Write3BD(P.Point);
  ABits.WriteBT(P.ZThick);
  ABits.WriteBE(P.Extrusion);
  ABits.WriteBD(0);
  Result := True;
end;

function TsgCADtoDWG.ExportPolyline(PLine: TsgDXFPolyline; DWGCode: Word;
  ABits: TsgDWGBits; const AIsTempObject: Boolean = False): Boolean;
var
  vFlags: Byte;
  I: Integer;
  vData: TsgDirectExportData;
begin
  Result := True;
  if PLine.Closed then
    vFlags := 1
  else
    vFlags := 0;
  case DWGCode of
    cntDWGObjCodePOLYLINE2D:
      begin
        ABits.WriteBS(vFlags);
        ABits.WriteBS(0);
        if IsZero(PLine.GlobalWidth) then
        begin
          ABits.WriteBD(PLine.StartWidth);
          ABits.WriteBD(PLine.EndWidth);
        end
        else
        begin
          ABits.WriteBD(PLine.GlobalWidth);
          ABits.WriteBD(PLine.GlobalWidth);
        end;
        ABits.WriteBT(PLine.ZThick);
        ABits.WriteBD(PLine.Elevation);
        ABits.WriteBE(PLine.Extrusion);
      end;
    cntDWGObjCodePOLYLINE3D:
      begin
        ABits.WriteRC(0);
        ABits.WriteRC(vFlags);
      end;
    cntDWGObjCodePOLYLINEPFACE:
      begin
        ABits.WriteBS(PLine.MeshM); //Numverts BS 71 Number of vertices in the mesh.
        ABits.WriteBS(PLine.MeshN); //Numfaces BS 72 Number of faces
      end;
    cntDWGObjCodePOLYLINEMESH:
      begin
        ABits.WriteBS(PLine.Flags or vFlags);//Flags BS 70
        ABits.WriteBS(0);//BS 75 Curve and smooth surface type.
        ABits.WriteBS(PLine.MeshM);//M vert count BS 71 M vertex count
        ABits.WriteBS(PLine.MeshN);//N vert count BS 72 N vertex count
        ABits.WriteBS(0);//M density BS 73 M vertex count
        ABits.WriteBS(0);//N density BS 74 N vertex count
      end;
  end;
  //EntMode = 0 for SeqEnd entity export
  vData := CreateExportData(PLine.Handle, 0, cnstBadHandle, cnstBadHandle, 0, PLine);
  DoExport(PLine, @vData);
  for I := 0 to PLine.Count - 1 do //check to be sure all vertexes have Handle
  begin
    if PLine.Entities[I].Handle = cnstBadHandle then
    begin
      if not AIsTempObject then
        FEntitiesWithAddedHandles.Add(PLine.Entities[I]);
      PLine.Vertexes[I].Handle := DoHandle;
    end;
  end;
  for I := 0 to PLine.Count - 1 do //export Vertexes EntMode = 0
  begin
    vData := CreateExportData(PLine.Handle, 0, GetPrevEntHandle(PLine, I),
      GetNextEntHandle(PLine, I), DWGCode, PLine);
    DoExport(PLine.Entities[I], @vData);
  end;
end;

function TsgCADtoDWG.WriteDateTimeAsJulian(const ADate: TDateTime; const ABits: TsgDWGBits;
  AUseRL: Boolean; PJDate: PCardinal = nil; PMilSec: PCardinal = nil;
  AWriteMilSec: Boolean = True): Integer;
var
  vJDate, vJMilSec: Cardinal;
  vFuncWrite: function (const Value: Cardinal): Integer of object;
begin
  if IsZero(ADate) then
  begin
    vJDate := 0;
    vJMilSec := 0;
  end
  else
    DateTimeToJulianDateInt(ADate, vJDate, vJMilSec);
  vFuncWrite := ABits.WriteBL;
  if AUseRL then
    vFuncWrite := ABits.WriteRL;
  Result := vFuncWrite(vJDate);
  if AWriteMilSec then
    Inc(Result, vFuncWrite(vJMilSec));
  if PJDate <> nil then
    PJDate^ := vJDate;
  if PMilSec <> nil then
    PMilSec^ := vJMilSec;
end;

function TsgCADtoDWG.WriteEntityHandle(const ABits: TsgDWGBits; const Entity: TsgDXFEntity;
  const ACode: Byte; AHandle: Boolean = True): Integer;
var
  vHandle: UInt64;
begin
  vHandle := cnstBadHandle;
  if Assigned(Entity) then
    vHandle := Entity.Handle;
  if AHandle then
    Result := ABits.WriteHandle(vHandle, ACode)
  else
    Result := ABits.WriteHandleRecord(vHandle, ACode);
end;

procedure TsgCADtoDWG.WriteSectionSize(const ABits: TsgDWGBits;
  const ASizePos: Cardinal = 0; const ASizeDelta: Integer = 0);
var
  vSize: Integer;
begin
  vSize := Integer(ABits.Size) - 4 - ASizeDelta; //minus SizeOf(RL) 4 the cell where the size will be written
  ABits.UpdateRL(ASizePos, vSize);
end;

{ TsgDWGCreatedElements }

function TsgDWGCreatedElements.AddElement(const AHandle: UInt64; ALocation: Integer;
  ADWGObjCode: Word; AName: string = ''; AOwnerHandle: UInt64 = cnstBadHandle;
  AObject: TObject = nil; ASize: Integer = 0): Integer;
var
  vVal: TsgDWGCreatedElement;
begin
  SortBy := seHandle;
  ClearElem(vVal);
  vVal.Handle := AHandle;
  vVal.Location := ALocation;
  vVal.DWGObjCode := ADWGObjCode;
  vVal.Obj := AObject;
  vVal.OwnerHandle := AOwnerHandle;
  vVal.Size := ASize;
  vVal.Name := AName;
  Result := AddElement(vVal);
end;

function TsgDWGCreatedElements.AddElement(const AValue: TsgDWGCreatedElement): Integer;
var
  P: PsgDWGCreatedElement;
  vIndex: Integer;

  function Find: Integer;
  var
    I: Integer;
  begin
    Result := -1;
    for I := 0 to Count - 1 do
      if Element[I].Handle = AValue.Handle then
      begin
        Result := I;
        Break;
      end;
  end;

begin
  New(P);
  P^ := AValue;
  SortBy := seHandle;
  if FFindBeforeAdd then
  begin
    if FElements.Sorted then
      vIndex := IndexOf(AValue.Handle)
    else
      vIndex := Find;
    if vIndex >= 0 then
      Result := vIndex
    else
      Result := FElements.Add(P);
  end
  else
    Result := FElements.Add(P);
end;

procedure TsgDWGCreatedElements.Clear;
var
  I: Integer;
  Elem: PsgDWGCreatedElement;
begin
  for I := 0 to FElements.Count - 1 do
  begin
    Elem := PsgDWGCreatedElement(FElements[I]);
    ClearElem(Elem^);
    Dispose(FElements[I]);
  end;
  FElements.Clear;
end;

procedure TsgDWGCreatedElements.ClearElem(var Elem: TsgDWGCreatedElement);
begin
  Elem.Handle := cnstBadHandle;
  Elem.Location := -1;
  Elem.DWGObjCode := cntDWGObjCodeUNSUSED;
  Elem.Obj := nil;
  Elem.OwnerHandle := cnstBadHandle;
  Elem.Size := 0;
  Elem.Name := '';
  Finalize(Elem.Name);
  Finalize(Elem.Handles);
end;

function TsgDWGCreatedElements.CompareElements(const Element1,
  Element2: Pointer): Integer;
var
  vVal1, vVal2: TsgDWGCreatedElement;
begin
  vVal1 := PsgDWGCreatedElement(Element1)^;
  vVal2 := PsgDWGCreatedElement(Element2)^;
  case FSortBy of
    seLocation: Result := TsgTypeComparer.CmpInteger(vVal1.Location, vVal2.Location);
    seDWGObjCode: Result := TsgTypeComparer.CmpCardinal(vVal1.DWGObjCode, vVal2.DWGObjCode);
    seObject: Result := TsgTypeComparer.CmpPointer(vVal1.Obj, vVal2.Obj);
    seOwnerHandle: Result := sgCompareHandles(vVal1.OwnerHandle, vVal2.OwnerHandle);
    seName: Result := TsgTypeComparer.CmpStr(vVal1.Name, vVal2.Name, False);
  else //seHandle
    Result := sgCompareHandles(vVal1.Handle, vVal2.Handle);
  end;
end;

function TsgDWGCreatedElements.CountOf(const ALocation: Integer; var AIndex: Integer): Integer;
var
  vElem: TsgDWGCreatedElement;
begin
  AIndex := IndexOf(ALocation, @vElem);
  Result := CountElem(AIndex, vElem);
end;

function TsgDWGCreatedElements.CountOf(const OwnerHandle: UInt64; var AIndex: Integer): Integer;
var
  vElem: TsgDWGCreatedElement;
begin
  AIndex := IndexOf(OwnerHandle, True, @vElem);
  Result := CountElem(AIndex, vElem);
end;

function TsgDWGCreatedElements.CountOf(const ADWGObjCode: Word; var AIndex: Integer): Integer;
var
  vElem: TsgDWGCreatedElement;
begin
  AIndex := IndexOf(ADWGObjCode, @vElem);
  Result := CountElem(AIndex, vElem);
end;

function TsgDWGCreatedElements.CountOf(const AName: string; var AIndex: Integer): Integer;
var
  vElem: TsgDWGCreatedElement;
begin
  AIndex := IndexOf(AName, @vElem);
  Result := CountElem(AIndex, vElem);
end;

function TsgDWGCreatedElements.CountOf(const AObject: TObject; var AIndex: Integer): Integer;
var
  vElem: TsgDWGCreatedElement;
begin
  AIndex := IndexOf(AObject, @vElem);
  Result := CountElem(AIndex, vElem);
end;

function TsgDWGCreatedElements.CountElem(AIndex: Integer; Elem: TsgDWGCreatedElement): Integer;
var
  I: Integer;
begin
  if AIndex < 0 then
    Result := 0
  else
  begin
    Result := 1;
    for I := AIndex + 1 to Count - 1 do
      if CompareElements(@Elem, FElements[I]) = 0 then
        Inc(Result)
      else
        Break;
  end;
end;

constructor TsgDWGCreatedElements.Create;
begin
  FElements := TsgList.Create;
  //FElements.Sorted := True;
  FElements.Duplicates := dupError;
  FElements.Capacity := 1024;
  FElements.ProcCompare := CompareElements;
  FSortBy := seHandle;
  FFindBeforeAdd := True;
end;

destructor TsgDWGCreatedElements.Destroy;
begin
  Clear;
  FElements.Free;
  inherited Destroy;
end;

function TsgDWGCreatedElements.Find(const Elem: TsgDWGCreatedElement;
  ASortBy: TsgSortElemBy; AGotoFirstElem: Boolean = False): Integer;
begin
  SortBy := ASortBy;
  Sort;
  Result := FElements.IndexOf(@Elem);
  if AGotoFirstElem and (Result >= 0) then
    GotoFirstElem(Element[Result], Result);
end;

function TsgDWGCreatedElements.GetCount: Integer;
begin
  Result := FElements.Count;
end;

function TsgDWGCreatedElements.GetElement(AIndex: Integer): TsgDWGCreatedElement;
begin
  Result := GetPtrElement(AIndex)^;
end;

function TsgDWGCreatedElements.GetFindBeforeAdd: Boolean;
begin
  Result := FFindBeforeAdd;
end;

function TsgDWGCreatedElements.GetPtrElement(AIndex: Integer): PsgDWGCreatedElement;
begin
  Result := PsgDWGCreatedElement(FElements[AIndex]);
end;

procedure TsgDWGCreatedElements.GotoFirstElem(const AElem: TsgDWGCreatedElement;
  var AIndex: Integer);
begin
  GotoFirstLastElem(AElem, AIndex, True);
end;

procedure SelfDec(var X: Integer);
begin
  System.Dec(X);
end;

procedure SelfInc(var X: Integer);
begin
  System.Inc(X);
end;

procedure TsgDWGCreatedElements.GotoFirstLastElem(const AElem: TsgDWGCreatedElement;
  var AIndex: Integer; AFirst: Boolean);
type
  TsgDecIncFunc = procedure(var X: Integer);
var
  vElem: TsgDWGCreatedElement;
  vDecIncFunc, vNotDecIncFunc: TsgDecIncFunc;
begin
  if AFirst then
  begin
    vDecIncFunc := SelfDec;
    vNotDecIncFunc := SelfInc;
  end
  else
  begin
    vDecIncFunc := SelfInc;
    vNotDecIncFunc := SelfDec;
  end;
  vDecIncFunc(AIndex);
  while True do
  begin
     if (AIndex < 0) or (AIndex > Count - 1) then Break;
     vElem := Element[AIndex];
     if CompareElements(@vElem, @AElem) <> 0 then
     begin
       vNotDecIncFunc(AIndex);
       Break;
     end;
     vDecIncFunc(AIndex);
  end;
  if AIndex < 0 then AIndex := 0;
  if AIndex > Count - 1 then AIndex := Count - 1;
end;

procedure TsgDWGCreatedElements.GotoLastElem(const AElem: TsgDWGCreatedElement;
  var AIndex: Integer);
begin
  GotoFirstLastElem(AElem, AIndex, False);
end;

function TsgDWGCreatedElements.IndexOf(const AName: string;
  PElem: PsgDWGCreatedElement = nil): Integer;
var
  vVal: TsgDWGCreatedElement;
begin
  ClearElem(vVal);
  vVal.Name := AName;
  Result := Find(vVal, seName, True);
  if PElem <> nil then PElem^ := vVal;
end;

function TsgDWGCreatedElements.IndexOf(const ALocation: Integer;
  PElem: PsgDWGCreatedElement = nil): Integer;
var
  vVal: TsgDWGCreatedElement;
begin
  ClearElem(vVal);
  vVal.Location := ALocation;
  Result := Find(vVal, seLocation, True);
  if PElem <> nil then PElem^ := vVal;
end;

function TsgDWGCreatedElements.IndexOf(const AHandle: UInt64; OwnerHandle: Boolean = False;
  PElem: PsgDWGCreatedElement = nil): Integer;
var
  vVal: TsgDWGCreatedElement;
  vSortBy: TsgSortElemBy;
  vGotoFirstElem: Boolean;
begin
  ClearElem(vVal);
  if OwnerHandle then
  begin
    vSortBy := seOwnerHandle;
    vVal.OwnerHandle := AHandle;
    vGotoFirstElem := True;
  end
  else
  begin
    vVal.Handle := AHandle;
    vSortBy := seHandle;
    vGotoFirstElem := False;
  end;
  Result := Find(vVal, vSortBy, vGotoFirstElem);
  if PElem <> nil then PElem^ := vVal;
end;

function TsgDWGCreatedElements.IndexOf(const AObject: TObject;
  PElem: PsgDWGCreatedElement = nil): Integer;
var
  vVal: TsgDWGCreatedElement;
begin
  ClearElem(vVal);
  vVal.Obj := AObject;
  Result := Find(vVal, seObject, True);
  if PElem <> nil then PElem^ := vVal;
end;

function TsgDWGCreatedElements.IndexOf(const ADWGObjCode: Word;
  PElem: PsgDWGCreatedElement = nil): Integer;
var
  vVal: TsgDWGCreatedElement;
begin
  ClearElem(vVal);
  vVal.DWGObjCode := ADWGObjCode;
  Result := Find(vVal, seDWGObjCode, True);
  if PElem <> nil then PElem^ := vVal;
end;

procedure TsgDWGCreatedElements.SetFindBeforeAdd(const Value: Boolean);
begin
  if Value <> FFindBeforeAdd then
    FFindBeforeAdd := Value;
end;

procedure TsgDWGCreatedElements.SetSortBy(const Value: TsgSortElemBy);
begin
  if Value <> FSortBy then
  begin
    FSortBy := Value;
    if FElements.Sorted then
      FElements.Sort{$IFNDEF SGDEL_5}(0, FElements.Count - 1){$ENDIF};
  end;
end;

procedure TsgDWGCreatedElements.Sort;
begin
  if not FElements.Sorted then
    FElements.Sorted := True;
end;

end.
