{************************************************************}
{                   Delphi VCL Extensions                    }
{                                                            }
{                    Export CAD to DXF                       }
{                                                            }
{      Copyright (c) 2002-2014 SoftGold software company     }
{                                                            }
{************************************************************}
unit CADtoDXF;
{$INCLUDE SGDXF.INC}

interface

uses
  Windows, Graphics, Classes, CADExport, CADImage, DXFConv, sgConsts, ExtData,
  MVFont, ActiveX, sgOle, sgBitmap, sgUnicode, sgLists, CADDirectExport
{$IFDEF SG_BTI}
  , BTICommon
{$ENDIF}
{$IFDEF SG_ENCRYPT_FILES}
  , sgStmCrpt
{$ENDIF}
{$IFDEF SGDEL_XE2}
  , System.Types
{$ENDIF}
  ;

type
  TsgCADtoDXF = class(TsgCADDirectExport)
  private
    FBlockList: TStringList;
    FBlockRecordsListExported: TsgList;
    FContentOleByImage: Boolean;
    FHasViewPortWindow: Boolean;
    FPaperMode: Boolean;
    FStream: TStream;
    function CreateBlockRecord(const ABlock: TsgDXFBlock;
      const AName: string): TsgDXFBlockRecord;
    function GetFlagsByName(const AFlags: Integer; const AName: string) : Integer;
    function GetBlockRecordByBlock(const ABlock: TsgDXFBlock;
      const AName: string): TsgDXFBlockRecord;
    function GetBlockRecord(const ABlock: TsgDXFBlock): TsgDXFBlockRecord;
    function GetEntityLayerName(const AEntity: TsgDXFEntity): string;
    function GetHandleByEntity(AEntity: TsgDXFEntity): UInt64;
    procedure ProcBlockRecord(ABlock: TsgDXFBlock; const AName: string; Data: Pointer;
      ACurrPaperSpaceIndex: Integer = -1);
    procedure ProcBlock(ABlock: TsgDXFBlock; const AName: string; Data: Pointer;
      ACurrPaperSpaceIndex: Integer = -1);
  protected
    procedure Add2DFlatPoint(const Code: Integer; const Pt: TFPoint);
    procedure Add2DPoint(const Code: Integer; const Pt: TF2DPoint);
    procedure Add3DPoint(const Code: Integer; const Pt: TFPoint);
    procedure Add3DPointExtruded(const Code: Integer; const Pt, Extr: TFPoint);
    procedure Add3DPointPreExtruded(const Code: Integer; const Pt, Extr: TFPoint);
    procedure AddCode(const AValue: Integer); virtual;
    procedure AddCommonEntityGroup(AEntity: TsgDXFEntity);
    procedure AddCommonEntityGroupEx(AEntity: TsgDXFEntity; const AName, ASubName: string);
    procedure AddCommonTableGroup(AEntity: TsgDXFEntity; const ABaseName, ASub, AName: string;
      const AHandleCode, AFlags: Integer);
    procedure AddDXFColor(const AValue: TsgColorCAD; const AVisible: Boolean = True);
    procedure AddEntName(AEntity: TsgDXFEntity; const AName: string;
      ALayerName: string = '');
    procedure AddExtrusion(const Pt: TFPoint);
    procedure AddFloat(const Code: Integer; Value: Double); virtual;
    procedure AddHandle(AEntity: TsgDXFEntity; Code: Integer; const AParentHandle: UInt64);
    procedure AddHexInt(const Code: Integer; const Value: UInt64);
    procedure AddInt(const Code, Value: Integer); virtual;
    procedure AddLineWeight(const AValue: Double);
    procedure AddLineType(ALineType: TsgDXFLineType);
    procedure AddString(const Code: Integer; const Str: string); virtual;
    procedure AddStringBig(const ACode, ASubCode, AExtCode: Integer;
      const AString: string);
    procedure AddRawByteString(const Code: Integer;
      const ARawByteString: sgRawByteString); virtual;
    procedure AddSubclassMarker(const Str: string);
    procedure AddThickness(const AValue: Double);
    procedure BeginSection(const AName: string);
    procedure BeginTable(AGroup: TsgDXFGroup; const AName: string);
    function CorrectLineWeight(const ALineWeight: Double;
      ANeedToConvert: Boolean): Integer; override;
    procedure DoExport(const E: TsgDXFEntity; const Data: PsgDirectExportData = nil;
      const AIsTempObject: Boolean = False); override;
    procedure EndOfFile(APos: {$IFDEF SGDEL_4}Int64{$ELSE}Integer{$ENDIF});
    procedure EndSection;
    procedure EndTable;
    function Export3DFace(F3D: TsgDXF3DFace): Boolean;
    function ExportAcadTable(AcadTable: TsgDXFAcadTable): Boolean;
    function ExportACISEntity(ACIS: TsgDXFACISEntity): Boolean;
    function ExportArc(A: TsgDXFArc): Boolean;
    function ExportCircle(C: TsgDXFCircle): Boolean;
    function ExportDimension(D: TsgDXFDimension): Boolean;
    function ExportEllipse(E: TsgDXFEllipse): Boolean;
    function ExportEntityAsGroup(const E: TsgDXFEntity): Boolean;
    function ExportFlatHatch(FH: TsgFlatHatch): Boolean;
    function ExportFlatPoly(FP: TsgFlatPoly): Boolean;
    function ExportHatch(PP: TsgCADPolyPolygon): Boolean;
    function ExportCADFill(const ACADFill: TsgCADFill): Boolean;
    function ExportInsert(INS: TsgDXFInsert): Boolean;
    function ExportImageEnt(W: TsgDXFImageEnt): Boolean;
    function ExportImageEntByFile(W: TsgDXFImageEnt): Boolean;
    function ExportImageEntByOle(W: TsgDXFImageEnt): Boolean;
    function ExportLeader(L: TsgDXFLeader): Boolean;
    function ExportLine(L: TsgDXFLine): Boolean;
    function ExportMText(MT: TsgDXFMText): Boolean;
    function ExportMLine(M: TsgCADMLine): Boolean;
    function ExportOle2Frame(OLE2: TsgDXFOle2Frame; Data: TObject = nil): Boolean;
    function ExportPoint(P: TsgDXFPoint): Boolean;
    function ExportPolyLine(BasePL: TsgCADBasePolyline): Boolean;
{$IFDEF SG_BTI}
    function ExportPolyPolyline2D(PL2D: TsgCADPolyPolyline2D): Boolean;
{$ENDIF}
    function ExportChildEntities(AEntity: TsgDXFEntity): Boolean;
    function ExportShape(S: TsgDXFShape): Boolean;
    function ExportSolid(S: TsgDXFSolid): Boolean;
    function ExportSpline(SPL: TsgDXFSpline): Boolean;
    function ExportText(T: TsgDXFText): Boolean;
    function ExportTolerance(T: TsgDXFTolerance): Boolean;
    function ExportViewPort(V: TsgDXFViewPort): Boolean;
    function ExportWipeOut(W: TsgCADWipeOut; AData: TObject = nil): Boolean;
    function ExportExtendedData(const AEntity: TsgDXFEntity): Boolean;
    procedure ExportSectionBLOCKS;
    procedure ExportSectionCLASSES;
    procedure ExportSectionENTITIES;
    function  ExportSectionHEADER: Integer;
    procedure ExportSectionOBJECTS;
    procedure ExportSectionTABLES;
    procedure ExportTablesAPPID;
    procedure ExportTablesBLOCK_RECORD;
    procedure ExportTablesDIMSTYLE;
    procedure ExportTablesLAYER;
    procedure ExportTablesLTYPE;
    procedure ExportTablesSTYLE;
    procedure ExportTablesVPORT;
    procedure ExportTablesVIEW;
    procedure ExportTablesUCS;
    function GetStringDXFVersion: string;
    function GetCorrectBlockName(const AName: string): string; override;
    procedure ProcessExport(Stream: TStream); override;
    procedure SetOleFrameVariable(const AValue: Integer); override;
    procedure WriteBuffer(const ABuffer; ACount: Integer); virtual;
    procedure WriteRawByteStr(AString: sgRawByteString); virtual;
    procedure WriteStr(const AString: string); virtual;
  public
    constructor Create(ACADImage: TsgCADImage); override;
    destructor Destroy; override;
  end;

  TsgCADtoBin = class(TsgCADtoDXF)
  protected
    procedure AddCode(const AValue: Integer); override;
    procedure AddFloat(const Code: Integer; Value: Double); override;
    procedure AddInt(const Code, Value: Integer); override;
    procedure AddString(const Code: Integer; const Str: string); override;
    procedure WriteRawByteStr(AString: sgRawByteString); override;
    procedure SaveToStreamCustom(S: TStream); override;
  end;

implementation

uses
  Math, SysUtils, sgFunction, sgLines;

const
  cnstBufferSize = 1048576;
  // Constants
  cnstHexDigits = 16;
  sEnter = #13#10;
  // DXF Codes
  cFlag_70          = 70;
  cHandle_5         = 5;
  cHandle_105       = 105;
  cParentHandle_330 = 330;

  sByBlock = 'ByBlock';
  sByLayer = 'ByLayer';

   // Table names
  sTableAPPID = 'APPID';
  sTableBLOCK_RECORD = 'BLOCK_RECORD';
  sTableDIMSTYLE = 'DIMSTYLE';
  sTableLAYER = 'LAYER';
  sTableLTYPE = 'LTYPE';
  sTableSTYLE = 'STYLE';
  sTableVPORT = 'VPORT';
  sTableVIEW = 'VIEW';
  sTableUCS = 'UCS';


  { TODO: Group 1
    Uncomment 'ACAD_TABLE' and 'Table' }
  // See unit sgConsts.pas "The entities to be drawn"
  sCADEntityNames: array[TsgCADEntities] of string = ('#ENTITY', 'POINT', 'LINE',
     'SOLID', 'TRACE', 'CIRCLE', 'ARC', 'ELLIPSE', 'POLYLINE', 'LWPOLYLINE', 'SPLINE', 'SPLINE'{'HELIX'},
     'LEADER', 'INSERT', 'DIMENSION', 'TOLERANCE', 'MTEXT', 'SHAPE', 'TEXT', 'ATTDEF', 'ATTRIB',
     '3DFACE', 'IMAGE', 'VIEWPORT', 'REGION', 'BODY', '3DSOLID',
     '#PATTERN', 'HATCH', 'OLE2FRAME', 'HATCH', 'HATCH', 'HATCH', 'HATCH',
     'INSERT'{'ACAD_TABLE'}, 'LWPOLYLINE'{FlatPoly}, 'HATCH'{FlatHatch}, 'XREF', 'ACAD_PROXY_ENTITY',
     'POLYLINE', 'WIPEOUT', 'MLINE', 'MPOLYGON'{$IFDEF SG_BTI}, 'POLYLINE'{$ENDIF},
     'SURFACE', 'ENDSEC', '#ENTITY', '3DSOLID', '3DSOLID', '3DSOLID', 'POLYLINE'{FlatPoly3D});
  sCADEntitySubNames: array[TsgCADEntities] of string = ('#Entity', 'Point', 'Line',
     'Trace', 'Trace', 'Circle', 'Circle', 'Ellipse', '3dPolyline', 'Polyline', 'Spline', 'Spline'{'Helix'},
     'Leader', 'BlockReference', 'Dimension', 'Fcf', 'MText', 'Shape', 'Text', 'Text', 'Text',
     'Face', 'RasterImage', 'Viewport', 'ModelerGeometry', 'ModelerGeometry', 'ModelerGeometry',
     '#Pattern', 'Hatch', 'Ole2Frame', 'Hatch', 'Hatch', 'Hatch', 'Hatch',
     'BlockReference'{'Table'}, 'Polyline'{FlatPoly}, 'Hatch'{FlatHatch}, 'Xref', 'ProxyEntity',
     '3dPolyline', 'Wipeout', 'Mline', 'MPolygon' {$IFDEF SG_BTI}, '3dPolyline'{$ENDIF},
     'Surface', 'Endsec', '#Entity', 'ModelerGeometry', 'ModelerGeometry',
     'ModelerGeometry', '3dPolyline'{FlatPoly3D});

type
  TsgCADImageEx = class(TsgCADImage);
  TsgDXFConverterEx = class(TsgDXFConverter);
  Tsg2DPolylineEx = class(Tsg2DPolyline);
  Tsg2DSplineEx = class(Tsg2DSpline);
  TsgDXFEntityAccess = class(TsgDXFEntity);
  TsgDXFBlockEx = class(TsgDXFBlock);
  TsgDXFInsertEx = class(TsgDXFInsert);
  TsgDXFDimensionEx = class(TsgDXFDimension);
  TsgDXfDimStyleAccess = class(TsgDXFDimensionStyle);
  TsgDXFMTextEx = class(TsgDXFMText);
  TsgDXFTextEx = class(TsgDXFText);
  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);
  TsgDXFPlotSettingsAccess = class(TsgDXFPlotSettings);
  TsgDXFBlockAccess = class(TsgDXFBlock);
  TsgDXF3dFaceAccess = class(TsgDXF3dFace);

const
  cnstRawEnter = $0A0D;
{$IFDEF SG_DXF_EXPORT_OPTIMIZE}
  RawEnter: Word = cnstRawEnter;
  MaxRawBufferLenInt = 11;
  RawBufferLen = 2 * MaxRawBufferLenInt + 4; // 4 = 2 * SizeOf(Word(cnstRawEnter))

var
  RawBuffer: array[0 .. RawBufferLen - 1] of AnsiChar;

function _itosA(AValue, APrecision, ABufferOffset: Integer): Pointer; register;
asm
{$IFDEF CPUX64}
  push rsi
  push rdi
  push rbx

  mov rax,rcx
  mov rsi,rcx   // rsi - AValue
  mov rbx,rdx   // RBX - APrecision
  mov rcx,r8    // RCX - ABufferOffset

  or rax,rax
  jns @positive
  neg rax

@positive:
  mov rdi,10

@divide:
  xor rdx,rdx
  div rdi
  add rdx,'0'
  dec rcx
  mov byte ptr [rcx],dl
  dec rbx
  test rax,rax
  jnz @divide

  or rsi,rsi
  jns @positive1
  dec rcx
  mov byte ptr [rcx],'-'
@positive1:

  cmp rbx,0
  jng @end
@space:
  dec rcx
  mov byte ptr [rcx],' '
  dec rbx
  cmp rbx,0
  jg @space

@end:
  mov rax,rcx

  pop rbx
  pop rdi
  pop rsi
{$ELSE}
  push esi
  push edi
  push ebx

  mov esi,eax
  mov ebx,edx

  or eax,eax
  jns @positive
  neg eax

@positive:
  mov edi,10

@divide:
  xor edx,edx
  div edi
  add edx,'0'
  dec ecx
  mov byte ptr [ecx],dl
  dec ebx
  test eax,eax
  jnz @divide

  or esi,esi
  jns @positive1
  dec ecx
  mov byte ptr [ecx],'-'
@positive1:

  cmp ebx,0
  jng @end
@space:
  dec ecx
  mov byte ptr [ecx],' '
  dec ebx
  cmp ebx,0
  jg @space

@end:
  mov eax,ecx

  pop ebx
  pop edi
  pop esi
{$ENDIF}
end;
function GetCode(ACode, APrecision: Integer): Pointer; register; assembler;
asm
{$IFDEF CPUX64}
  lea r8,RawBuffer
  add r8,RawBufferLen - 2
  mov word ptr [r8],cnstRawEnter
{$ELSE}
  lea ecx,RawBuffer
  add ecx,RawBufferLen - 2
  mov word ptr [ecx],cnstRawEnter
{$ENDIF}
  call _itosA
end;

function GetInt(ACode, AValue: Integer): Pointer; register; assembler;
asm
{$IFDEF CPUX64}
  push rcx

  lea r8,RawBuffer
  add r8,RawBufferLen

  movsx rcx,edx
  xor rdx,rdx

  sub r8,2
  mov word ptr [r8],cnstRawEnter
  call _itosA

  mov r8,rcx
  pop rcx
  mov rdx,3

  sub r8,2
  mov word ptr [r8],cnstRawEnter
  call _itosA
{$ELSE}
  push eax

  lea ecx,RawBuffer
  add ecx,RawBufferLen

  mov eax,edx
  xor edx,edx

  sub ecx,2
  mov word ptr [ecx],cnstRawEnter
  call _itosA

  mov ecx,eax
  pop eax
  mov edx,3

  sub ecx,2
  mov word ptr [ecx],cnstRawEnter
  call _itosA
{$ENDIF}
end;

function GetSize(const ABufPointer: Pointer): TsgNativeInt;
begin
  Result := SizeOf(RawBuffer) - (TsgNativeInt(ABufPointer) - TsgNativeInt(@RawBuffer[0]));
end;
{$ENDIF}

function GetDXFEntColor(const AEntity: TsgDXFEntity;
  const AVersion: TsgDWGVersion = acR2004): TsgColorCAD;
begin
  if AVersion <= acR2000 then
  begin
    if IsCADGradient(AEntity) then
      Result := TsgCADGradientPolygon(AEntity).GradientColorCAD[0]
    else
      Result := AEntity.ColorCAD
  end
  else
    Result := AEntity.ColorCAD;
end;

{ TsgCADtoDXF }

constructor TsgCADtoDXF.Create(ACADImage: TsgCADImage);
begin
  inherited Create(ACADImage);
  FBlockList := TStringList.Create;
  FBlockList.Sorted := True;
  FBlockRecordsListExported := TsgList.Create;
  FBlockRecordsListExported.Sorted := True;
  FBlockRecordsListExported.Duplicates := dupIgnore;
  ConverImageToOLE := True;
  FContentOleByImage := False;
end;

procedure TsgCADtoDXF.Add2DFlatPoint(const Code: Integer; const Pt: TFPoint);
begin
  AddFloat(Code, Pt.X);
  AddFloat(Code+10, Pt.Y);
end;

procedure TsgCADtoDXF.Add2DPoint(const Code: Integer; const Pt: TF2DPoint);
begin
  AddFloat(Code, Pt.X);
  AddFloat(Code+10, Pt.Y);
end;

procedure TsgCADtoDXF.Add3DPoint(const Code: Integer; const Pt: TFPoint);
begin
  AddFloat(Code, Pt.X);
  AddFloat(Code+10, Pt.Y);
  AddFloat(Code+20, Pt.Z);
end;

procedure TsgCADtoDXF.Add3DPointExtruded(const Code: Integer; const Pt, Extr: TFPoint);
var
  vPt: TFPoint;
begin
  if Extruded(Extr) then
  begin
    vPt := Pt;
    DoPreExtrusion(vPt, Extr);
    Add3DPoint(Code, vPt);
  end
  else
    Add3DPoint(Code, Pt);
end;

procedure TsgCADtoDXF.Add3DPointPreExtruded(const Code: Integer; const Pt, Extr: TFPoint);
var
  vPt: TFPoint;
begin
  if Extruded(Extr) then
  begin
    vPt := Pt;
    DoExtrusion(vPt, Extr);
    Add3DPoint(Code, vPt);
  end
  else
    Add3DPoint(Code, Pt);
end;

procedure TsgCADtoDXF.AddCode(const AValue: Integer);
var
{$IFDEF SG_DXF_EXPORT_OPTIMIZE}
  P: Pointer;
{$ELSE}
  S: string;
{$ENDIF}
begin
{$IFDEF SG_DXF_EXPORT_OPTIMIZE}
  P := GetCode(AValue, 3);
  WriteBuffer(P^, GetSize(P));
{$ELSE}
  S := Format('%3d%s', [AValue, sEnter]);
  WriteStr(S);
{$ENDIF}
end;

procedure TsgCADtoDXF.AddCommonEntityGroup(AEntity: TsgDXFEntity);
begin
  AddCommonEntityGroupEx(AEntity, sCADEntityNames[AEntity.EntType],
    sCADEntitySubNames[AEntity.EntType]);
end;

procedure TsgCADtoDXF.AddCommonEntityGroupEx(AEntity: TsgDXFEntity; const AName, ASubName: string);
begin
  AddEntName(AEntity, AName);
  AddSubclassMarker(ASubName);
  if AEntity.EntType = ceMPolygon then
    AddInt(70, 1);//the version of MPolygon
  if not AEntity.Visibility then
    AddInt(60, 1);
  AddLineWeight(AEntity.LineWeight);
  AddDXFColor(AEntity.ColorCAD);
  if AEntity.LineTypeScale <> 1 then
    AddFloat(48, AEntity.LineTypeScale);
  if AEntity is TsgDXFPenLine then
    AddLineType(TsgDXFPenLine(AEntity).LineType);
  // Only for entities whose coordinates are set in OCS (or 2D)
  if (AEntity.EntType = ceArc) or (AEntity.EntType = ceCircle)
    or (AEntity.EntType = ceEllipse) or (AEntity.EntType = ceSolid) then
    AddExtrusion(TsgDXFPenLine(AEntity).Extrusion);
end;

procedure TsgCADtoDXF.AddCommonTableGroup(AEntity: TsgDXFEntity;
  const ABaseName, ASub, AName: string; const AHandleCode, AFlags: Integer);
begin
  AddString(0, ABaseName);
  AddHandle(AEntity, AHandleCode, 0);
  AddSubclassMarker('SymbolTableRecord');
  AddSubclassMarker(ASub+'TableRecord');
  AddString(2, AName);
  if AFlags >= 0 then
    AddInt(cFlag_70, AFlags);
end;

procedure TsgCADtoDXF.AddDXFColor(const AValue: TsgColorCAD;
  const AVisible: Boolean = True);
const
  cnstSingColor: array [Boolean] of Integer = (-1, 1);
var
  vColorIndex, vColorRgb: Integer;
begin
  case AValue.Active of
    acIndexColor:
      begin
        if AValue.Color <> clDXFByLayer then
          AddInt(62, cnstSingColor[AVisible] * Integer(AValue.Color));
      end;
  else//acRGBColor
    vColorIndex := ConvertColorCADToIndexColor(AValue, True);
    AddInt(62, cnstSingColor[AVisible] * vColorIndex);
    // in 2000 format no rgb color, but since it dxf we can leave it there.
//    if Version >= acR2004 then
//    begin
      vColorRgb := (AValue.Color and $FF0000 shr 16) or (AValue.Color and $FF00)
        or (AValue.Color and $FF shl 16);
      AddInt(420, vColorRgb);
//    end;
  end;
end;

procedure TsgCADtoDXF.AddEntName(AEntity: TsgDXFEntity;
  const AName: string; ALayerName: string = '');
begin
  AddString(0, AName);
  AddHandle(AEntity, cHandle_5, 0);
  AddSubclassMarker('Entity');
  if FPaperMode then
    AddInt(67, 1);
  if Length(ALayerName) = 0 then
    ALayerName := GetEntityLayerName(AEntity);
  AddString(8, ALayerName);
end;

procedure TsgCADtoDXF.AddExtrusion(const Pt: TFPoint);
begin
  if Extruded(Pt) then
    Add3DPoint(210, Pt);
end;

procedure TsgCADtoDXF.AddFloat(const Code: Integer; Value: Double);
{$IFNDEF SG_DXF_EXPORT_OPTIMIZE}
var
  S: string;
{$ENDIF}
begin
{$IFDEF SG_DXF_EXPORT_OPTIMIZE}
  AddRawByteString(Code, sgRawByteString(FloatToStr(Value)));
{$ELSE}
  S := Format('%3d', [Code]) + sEnter + FloatToStr(Value) + sEnter;
  WriteStr(S);
{$ENDIF}
end;

procedure TsgCADtoDXF.AddHandle(AEntity: TsgDXFEntity; Code: Integer; const AParentHandle: UInt64);
var
  H: UInt64;
begin
  if Ord(Version) >= Ord(acR14) then
  begin
    H := cnstBadHandle;
    if AEntity <> nil then
      H := AEntity.Handle;
    if H = cnstBadHandle then
      H := DoHandle;
    AddHexInt(Code, H);
    if (Ord(Version) >= Ord(acR2000)) and (AParentHandle > 0) then
      AddHexInt(cParentHandle_330, AParentHandle);
  end;
end;

procedure TsgCADtoDXF.AddHexInt(const Code: Integer; const Value: UInt64);
begin
{$IFDEF SG_DXF_EXPORT_OPTIMIZE}
  AddRawByteString(Code, sgRawByteString(IntToHex(Value, 0)));
{$ELSE}
  AddString(Code, IntToHex(Value, 0));
{$ENDIF}
end;

procedure TsgCADtoDXF.AddInt(const Code, Value: Integer);
var
{$IFDEF SG_DXF_EXPORT_OPTIMIZE}
  P: Pointer;
{$ELSE}
  S: string;
{$ENDIF}
begin
{$IFDEF SG_DXF_EXPORT_OPTIMIZE}
  P := GetInt(Code, Value);
  WriteBuffer(P^, GetSize(P));
{$ELSE}
  S := Format('%3d%s%d%s', [Code, sEnter, Value, sEnter]);
  WriteStr(S);
{$ENDIF}
end;

procedure TsgCADtoDXF.AddLineWeight(const AValue: Double);
begin
  if (AValue <> 0) and (Ord(Version) >= Ord(acR2000)) then
    AddInt(370, CorrectLineWeight(AValue, False));
end;

procedure TsgCADtoDXF.AddRawByteString(const Code: Integer;
  const ARawByteString: sgRawByteString);
begin
  AddCode(Code);
{$IFDEF SG_DXF_EXPORT_OPTIMIZE}
  WriteBuffer(PPointer(ARawByteString)^, Length(ARawByteString));
  WriteBuffer(RawEnter, SizeOf(RawEnter));
{$ELSE}
  WriteRawByteStr(ARawByteString);
{$ENDIF}
end;

procedure TsgCADtoDXF.AddLineType(ALineType: TsgDXFLineType);
begin
  if ALineType <> nil then
    AddString(6, ExtractName(ALineType.Name))
  //else AddString(6, 'ByLayer');// for future versions
end;

procedure TsgCADtoDXF.AddString(const Code: Integer; const Str: string);
{$IFNDEF SG_DXF_EXPORT_OPTIMIZE}
var
  S: string;
{$ENDIF}
begin
{$IFDEF SG_DXF_EXPORT_OPTIMIZE}
  AddCode(Code);
  WriteStr(Str);
  WriteBuffer(RawEnter, SizeOf(RawEnter));
{$ELSE}
  S := Format('%3d%s%s%s', [Code, sEnter, Str, sEnter]);
  WriteStr(S);
{$ENDIF}
end;

procedure TsgCADtoDXF.AddStringBig(const ACode, ASubCode, AExtCode: Integer;
  const AString: string);

  procedure ExportString(const AStrCode: Integer; const AStr: string);
  begin
    if AExtCode > 0 then
    begin
      AddInt(Integer_1070, AStrCode);
      AddString(AExtCode, AStr);
    end
    else
      AddString(AStrCode, AStr);
  end;

var
  vStr: string;
begin
  if Length(AString) <= cnstMaxStringLen then
    ExportString(ACode, AString)
  else
  begin
    ExportString(ACode, Copy(AString, 1, cnstMaxStringLen));
    vStr := AString;
    repeat
      Delete(vStr, 1 ,cnstMaxStringLen);
      if Length(vStr) <= cnstMaxStringLen then
        ExportString(ASubCode, vStr)
      else
        ExportString(ASubCode, Copy(vStr, 1, cnstMaxStringLen));
    until Length(vStr) <= cnstMaxStringLen;
  end;
end;

procedure TsgCADtoDXF.AddSubclassMarker(const Str: string);
begin
  if Ord(Version) >= Ord(acR14) then
    AddString(100, cntAcDb + Str);
end;

procedure TsgCADtoDXF.AddThickness(const AValue: Double);
begin
  if AValue <> 0 then
    AddFloat(39, AValue);
end;

function TsgCADtoDXF.CorrectLineWeight(const ALineWeight: Double;
  ANeedToConvert: Boolean): Integer;
begin
  Result := ConvertLineWeightToDXF(ALineWeight);
end;

function TsgCADtoDXF.CreateBlockRecord(const ABlock: TsgDXFBlock;
  const AName: string): TsgDXFBlockRecord;
var
  vBlock: TsgDXFBlock;
begin
  Result := GetBlockRecord(ABlock);
  if Result = nil then
  begin
    vBlock := TsgDXFBlock.Create;
    Result := vBlock.BlockRecord;
    if ABlock <> nil then
      Result.Name := vBlock.Name
    else
      Result.Name := AName;
    FBlockList.AddObject(vBlock.Name, vBlock);
    ExportCADImage.Converter.Loads(Result);
  end;
end;

destructor TsgCADtoDXF.Destroy;
begin
  FBlockRecordsListExported.Free;
  ClearObjects(FBlockList);
  FBlockList.Free;
  inherited Destroy;
end;

procedure TsgCADtoDXF.DoExport(const E: TsgDXFEntity; const Data: PsgDirectExportData = nil;
  const AIsTempObject: Boolean = False);
begin
  case E.EntType of
    ceLine:              ExportLine(TsgDXFLine(E));
    cePoint:             ExportPoint(TsgDXFPoint(E));
    ceSolid, ceTrace:    ExportSolid(TsgDXFSolid(E));
    ceCircle:            ExportCircle(TsgDXFCircle(E));
    ceArc:               ExportArc(TsgDXFArc(E));
    ceEllipse:           ExportEllipse(TsgDXFEllipse(E));
    ceLWPolyline,
      cePolyline,
      cePath:            ExportPolyline(TsgDXFPolyline(E));
    ceSpline, ceHelix:   ExportSpline(TsgDXFSpline(E));
    ceACADTable:         ExportAcadTable(TsgDXFAcadTable(E));
    ceInsert:            ExportInsert(TsgDXFInsert(E));
    ceAttdef,
      ceAttrib, ceText:  ExportText(TsgDXFText(E));
    ceShape:             ExportShape(TsgDXFShape(E));
    ceMText:             ExportMText(TsgDXFMText(E));
    ceTolerance:         ExportTolerance(TsgDXFTolerance(E));
    ceDimension:         ExportDimension(TsgDXFDimension(E));
    ce3dFace:            Export3DFace(TsgDXF3DFace(E));
    ceLeader:            ExportLeader(TsgDXFLeader(E));
    cePolyPolygon,
      ceGradient,
      ceGradientPolygon,
      ceCurvePolygon,
      ceHatch,
      ceMPolygon:        ExportHatch(TsgCADPolyPolygon(E));
    ceViewport:          ExportViewPort(TsgDXFViewPort(E));
    ceImageEnt:          ExportImageEnt(TsgDXFImageEnt(E));
    ceIges, ceStep, ceBrep,
    ceRegion,
      ceBody, ce3DSolid: ExportACISEntity(TsgDXFACISEntity(E));

    ceOle2Frame:         ExportOle2Frame(TsgDXFOle2Frame(E));
    ceProxy:             ExportChildEntities(TsgDXFEntity(E));
{
    cePattern:           ExportPattern(TsgSVGPattern(E));
}
    ceFlatPoly, ceFlatPoly3D: ExportFlatPoly(TsgFlatPoly(E));
    ceFlatHatch:         ExportFlatHatch(TsgFlatHatch(E));
    ceWipeOut{,
      ceImageEnt}:        ExportWipeOut(TsgCADWipeOut(E));
{$IFDEF SG_BTI}
    cePolyPolyline2D:    ExportPolyPolyline2D(TsgCADPolyPolyline2D(E));
{$ENDIF}
    ceMLine:             ExportMLine(TsgCADMLine(E));
  end;
end;

function TsgCADtoDXF.GetBlockRecordByBlock(const ABlock: TsgDXFBlock;
  const AName: string): TsgDXFBlockRecord;
var
  vIndex: Integer;
  vName: string;
begin
  Result := GetBlockRecord(ABlock);
  if Result = nil then
  begin
    if ABlock <> nil then
      vName := ABlock.Name
    else
      vName := AName;
    Result := TsgDXFBlockRecord(ExportCADImage.Converter.Sections[csBlockRecords].FindEntByName(vName));
    if Result = nil then
    begin
      vIndex := FBlockList.IndexOf(vName);
      if vIndex > -1 then
        Result := TsgDXFBlockRecord(FBlockList.Objects[vIndex]);
    end;
  end;
end;

procedure TsgCADtoDXF.ProcBlockRecord(ABlock: TsgDXFBlock; const AName: string; Data: Pointer;
  ACurrPaperSpaceIndex: Integer = -1);
var
  vBlockRecord: TsgDXFBlockRecord;
  Cnt: Integer;
begin
  vBlockRecord := GetBlockRecordByBlock(ABlock, AName);
  if vBlockRecord = nil then
    vBlockRecord := CreateBlockRecord(ABlock, AName);
  Cnt := FBlockRecordsListExported.Add(vBlockRecord);
  if FBlockRecordsListExported.Count <> Cnt then
  begin
    AddString(0, sTableBLOCK_RECORD);
    AddHexInt(cHandle_5, vBlockRecord.Handle);
    AddSubclassMarker('SymbolTableRecord');
    AddSubclassMarker('BlockTableRecord');
    AddString(2, AName);
  end;
end;

procedure TsgCADtoDXF.ProcessExport(Stream: TStream);
var
  vPos: {$IFDEF SGDEL_4}Int64{$ELSE}Integer{$ENDIF};
  DS: Char;
  vMS: TStream;
{$IFDEF SG_ENCRYPT_FILES}
  vEncryptNeeded: Boolean;
{$ENDIF}
begin
    vMS := Stream;
{$IFDEF SG_ENCRYPT_FILES}
    vEncryptNeeded := Assigned(FSGBlock);
    if vEncryptNeeded then
      vMS := TMemoryStream.Create;
    try
{$ENDIF}
      FStream := TBufferedStream.Create(vMS, cnstBufferSize);
      DS := SetDecimalSeparator('.');
      try
        Progress(psStarting,0);
        vPos := ExportSectionHEADER;
        Progress(psRunning, 1);
        ExportSectionCLASSES;
        ExportSectionTABLES;
        Progress(psRunning, 9);
        ExportSectionBLOCKS;
        Progress(psRunning, 34);
        ExportSectionENTITIES;
        Progress(psRunning, 99);
        ExportSectionOBJECTS;
        EndOfFile(vPos);
        Progress(psEnding, 100);
      finally
        FStream.Free;
        FStream := nil;
        SetDecimalSeparator(DS);
      end;
{$IFDEF SG_ENCRYPT_FILES}
    finally
      if vEncryptNeeded then
      begin
        sgStmCrpt.EnctyptStm(Stream, TMemoryStream(vMS));
        vMS.Free;
      end;
    end;
{$ENDIF}
end;

procedure TsgCADtoDXF.ProcBlock(ABlock: TsgDXFBlock; const AName: string; Data: Pointer;
  ACurrPaperSpaceIndex: Integer = -1);
  procedure BeginBlock(const AName: string; const AFlags: Integer);
  begin
    // nil (see BLOCK_RECORDS)
    AddEntName(ABlock, 'BLOCK');
    AddSubclassMarker('BlockBegin');
    if Ord(Version) > Ord(acR14) then
      AddString(2, AName)
    else
      AddString(2, AnsiUpperCase(AName));
    AddInt(cFlag_70, AFlags);
  end;
var
  J: Integer;
begin
  if ABlock <> nil then
  begin
    BeginBlock(AName, TsgDXFBlockAccess(ABlock).Flags);
    Add3DPoint(10, ABlock.Offset);
    AddString(3, AName);
    AddString(1, ABlock.XrefPath);
    if XDataAppName <> '' then
      ExportExtendedData(ABlock);
    for J := 0 to ABlock.Count - 1 do
      DoExport(TsgDXFEntity(ABlock.Entities[J]));
  end
  else
  begin
    BeginBlock(AName, 0);
    Add2DPoint(10, cnstF2DPointZero);
  end;
  AddEntName(nil, 'ENDBLK');
  AddSubclassMarker('BlockEnd');
end;

function TsgCADtoDXF.GetCorrectBlockName(const AName: string): string;
var
  vPos: Integer;
begin
  vPos := AnsiPos(sInternalDimension, AName);
  if vPos <= 0 then
    Result := AName
  else
  begin
    if AName[1] <> cnstInternalBlockPrefix then
      Result := cnstInternalBlockPrefix + AName
    else
      Result := AName;
  end;
end;

procedure TsgCADtoDXF.SetOleFrameVariable(const AValue: Integer);
const
  cnstDictionaryVarOLEFRAME = 'OLEFRAME';
var
  vDict: TsgDXFEntity;
  vOleFrame: TsgDXFEntity;
begin
  FContentOleByImage := True;
  vDict := ExportCADImage.Converter.Sections[csObjects].FindEntByName(sAcDbVariableDictionary);
  if Assigned(vDict) then
  begin
    vOleFrame := vDict.FindEntByName(cnstDictionaryVarOLEFRAME);
    if Assigned(vOleFrame) then
      TsgDXFDictionaryVar(vOleFrame).Value := IntToStr(AValue);
  end;
end;

function TsgCADtoDXF.GetBlockRecord(const ABlock: TsgDXFBlock): TsgDXFBlockRecord;
begin
  Result := nil;
  if ABlock <> nil then
    Result := ABlock.BlockRecord;
end;

procedure TsgCADtoDXF.WriteBuffer(const ABuffer; ACount: Integer);
begin
  FStream.Write(ABuffer, ACount);
end;

procedure TsgCADtoDXF.WriteRawByteStr(AString: sgRawByteString);
begin
  if AString <> '' then
    FStream.Write(AString[1], Length(AString) * SizeOf(AString[1]));
end;

procedure TsgCADtoDXF.WriteStr(const AString: string);
var
  vStr: sgRawByteString;
begin
  case Version of
    acR2007:
{$IFDEF SGDEL_2009}
      vStr := UTF8Encode(AString); // correct save to dxf 2007 only in Delphi 2009
{$ELSE}
      vStr := AString;
{$ENDIF}
  else
    vStr := StringToACADPresentation(AString, CP_ACP); // AutoCAD always uses system locale (CP_ACP)
  end;
  WriteRawByteStr(vStr);
end;

procedure TsgCADtoDXF.BeginSection(const AName: string);
begin
  AddString(0, 'SECTION');
  AddString(2, AName);
end;

procedure TsgCADtoDXF.BeginTable(AGroup: TsgDXFGroup; const AName: string);
begin
  AddString(0, 'TABLE');
  AddString(2, AName);
  AddHandle(AGroup, cHandle_5, 0);
  AddSubclassMarker('SymbolTable');
end;

procedure TsgCADtoDXF.EndOfFile(APos: {$IFDEF SGDEL_4}Int64{$ELSE}Integer{$ENDIF});
var
  vStr: string;
begin
  AddString(0, 'EOF');
  if APos > 0 then
  begin
    // Setting correct value of next available handle
    FStream.Seek(APos, soFromBeginning);
    vStr := IntToHex(DoHandle, cnstHexDigits);
    SetLength(vStr, cnstHexDigits);
    AddString(5, vStr);
  end;
end;

procedure TsgCADtoDXF.EndSection;
begin
  AddString(0, 'ENDSEC');
end;

procedure TsgCADtoDXF.EndTable;
begin
  AddString(0, 'ENDTAB');
end;

{ Export Entities }

{ 3DFACE }
function TsgCADtoDXF.Export3DFace(F3D: TsgDXF3DFace): Boolean;
begin
  AddCommonEntityGroup(F3D);
  Add3DPoint(10, F3D.Point);
  Add3DPoint(11, F3D.Point1);
  Add3DPoint(12, F3D.Point2);
  Add3DPoint(13, F3D.Point3);
  AddInt(cFlag_70, TsgDXF3dFaceAccess(F3D).Flags);
  Result := True;
end;

function TsgCADtoDXF.ExportAcadTable(AcadTable: TsgDXFAcadTable): Boolean;
var
  I, J: Integer;
  vBlockRecordHandle: UInt64;
  vCell: TsgAcadTableCellAccess;

  procedure ExportOverriden(const AIndex: Integer; ACell: TsgAcadTableCellAccess);
  begin
    if ACell.Flags and ACell.GetFlagsMask(AIndex) <> 0 then
    begin
      AddInt(AIndex + 274, CorrectLineWeight(ACell.BorderLineWeight[AIndex], False));
      AddInt(AIndex + 284, Ord(ACell.BorderVisible[AIndex]));
      AddInt(AIndex + 64, ColorToDXF(ACell.BorderColor[AIndex]));
    end;
  end;

begin
  if not Assigned(AcadTable.Style) then
    Result := ExportInsert(AcadTable)
  else
  begin
    { TODO: Group 1
      AddCommonEntityGroupEx(AcadTable, sCADEntityNames[AcadTable.EntType],
      'BlockReference'); }
    AddCommonEntityGroupEx(AcadTable, 'ACAD_TABLE', 'BlockReference');
    AddLineType(AcadTable.LineType);
    if AcadTable.Attribs.Count > 0 then
      AddInt(66, 1);
    AddString(2, AnsiUpperCase(AcadTable.Block.Name));
    Add3DPoint(10, AcadTable.Point);
    if IsScaled(AcadTable.Scale) then
    begin
      AddFloat(41, AcadTable.Scale.X);
      AddFloat(42, AcadTable.Scale.Y);
      AddFloat(43, AcadTable.Scale.Z);
    end;
    if AcadTable.Angle <> 0 then
      AddFloat(50, AcadTable.Angle);
    { TODO: Group 1
      AddSubclassMarker(sCADEntitySubNames[AcadTable.EntType]); }
    AddSubclassMarker('Table');
    AddHexInt(342, AcadTable.Style.Handle);
    vBlockRecordHandle := GetHandleByEntity(AcadTable.Block);
    if vBlockRecordHandle <> 0 then
      AddHexInt(343, vBlockRecordHandle);
    AddInt(90, AcadTable.Flags);
    AddInt(91, AcadTable.NumRows);
    AddInt(92, AcadTable.NumCols);
    // Flags for an override
    //AddInt(93, 0);
    //AddInt(94, 0);  // of border color
    //AddInt(95, 0);  // of border lineweight
    //AddInt(96, 0);  // of border visibility
    for I := 0 to AcadTable.NumRows - 1 do
      AddFloat(141, AcadTable.RowHeight[I]);
    for I := 0 to AcadTable.NumCols - 1 do
      AddFloat(142, AcadTable.ColWidth[I]);
    for I := 0 to AcadTable.NumRows - 1 do
      for J := 0 to AcadTable.NumCols - 1 do
      begin
        vCell := TsgAcadTableCellAccess(AcadTable.Cell[J, I]);
        AddInt(171, Ord(not vCell.IsTextType) + 1);
        AddInt(172, vCell.Flags);
        AddInt(173, vCell.MergedValue);
        AddInt(174, Ord(vCell.AutoFit));
        AddInt(175, vCell.MergedWidth);
        AddInt(176, vCell.MergedHeight);
        AddInt(177, vCell.OverrideFlag);
        AddInt(178, Ord(vCell.VirtualEgdeFlag));
        AddFloat(145, vCell.Rotation);
        if vCell.IsTextType then
          AddString(1, vCell.Text);
        if Assigned(vCell.TextStyle) then
          AddString(7, ExtractName(vCell.TextStyle.Name));
        if (vCell.OverrideFlag and $20 <> 0) or not vCell.HasOwnerStyle then
          AddFloat(140, vCell.TextHeight);
        if vCell.IsPropInit(cpCellAllignment) or not vCell.HasOwnerStyle then
          AddInt(170, vCell.CellAlignment);
        if vCell.IsPropInit(cpTextColor) or not vCell.HasOwnerStyle then
          AddInt(64, ColorToDXF(vCell.TextColor));
        if vCell.BkColorOn then
          AddInt(63, ColorToDXF(vCell.FillColor));
        ExportOverriden(5, vCell);
        ExportOverriden(1, vCell);
        ExportOverriden(2, vCell);
        ExportOverriden(4, vCell);
      end;
    Result := True;
  end;
end;

function TsgCADtoDXF.ExportCADFill(const ACADFill: TsgCADFill): Boolean;
var
  vImageEnt: TsgDXFImageEnt;
begin
  Result := False;
  if not Assigned(DXFConv.LoadEntityProc) then
  begin
    vImageEnt := ACADFill.ConvertToImageEnt(ExportCADImage.Converter);
    try
      if vImageEnt <> nil then
        Result := ExportImageEnt(vImageEnt);
    finally
      vImageEnt.Free;
    end;
  end;
end;

function TsgCADtoDXF.ExportChildEntities(AEntity: TsgDXFEntity): Boolean;
var
  I: Integer;
begin
  for I := 0 to AEntity.Count-1 do
    DoExport(AEntity[I]);
  Result := True;
end;

{ ACIS (REGION, BODY, 3DSOLID) }
function TsgCADtoDXF.ExportACISEntity(ACIS: TsgDXFACISEntity): Boolean;
begin
  Result := ExportEntityAsGroup(ACIS);
end;

{ ARC }
function TsgCADtoDXF.ExportArc(A: TsgDXFArc): Boolean;
begin
  AddCommonEntityGroup(A);
  AddThickness(A.ZThick);
  Add3DPoint(10, A.Point);//  Add3DPointExtruded(10, A.Point, A.Extrusion);
  AddFloat(40, A.Radius);
  AddSubclassMarker('Arc');
  AddFloat(50, A.StartAngle);
  AddFloat(51, A.EndAngle);
  Result := True;
end;

{ CIRCLE }
function TsgCADtoDXF.ExportCircle(C: TsgDXFCircle): Boolean;
begin
  AddCommonEntityGroup(C);
  AddThickness(C.ZThick);
  Add3DPoint(10, C.Point);//  Add3DPointExtruded(10, C.Point, C.Extrusion);
  AddFloat(40, C.Radius);
  Result := True;
end;

{ HATCH }
function TsgCADtoDXF.ExportHatch(PP: TsgCADPolyPolygon): Boolean;
var
  K: Integer;
  vIsDerived: Boolean;
  vGradient: TsgCADGradientPolygon;
  vColor: TsgColorCAD;

  procedure AddPatternData;
  var
    H: TsgCADHatch absolute PP;
    vPatternData: TsgHatchPatternData;
    vDashLengths: TsgDoubleList;
    I, J: Integer;
  begin
    AddInt(76, Ord(AnsiUpperCase(TsgCADHatch(PP).HatchName) <> 'USER'));// Hatch pattern type (1 = predefined)
    AddFloat(52, H.PatternAngle);// Hatch pattern angle
    AddFloat(41, H.PatternScale);// Hatch pattern scale or spacing
    AddInt(77, 0);// Hatch pattern double flag (pattern fill only): 0 = not double; 1 = double
    AddInt(78, H.HatchPatternData.Count);
    for I := 0 to H.HatchPatternData.Count - 1 do
    begin
      vPatternData := PsgHatchPatternData(H.HatchPatternData[I])^;
      AddFloat(53, vPatternData.LineAngle);
      AddFloat(43, vPatternData.BaseP.X);
      AddFloat(44, vPatternData.BaseP.Y);
      AddFloat(45, vPatternData.Offset.X);
      AddFloat(46, vPatternData.Offset.Y);
      // Dash length (multiple entries)
      vDashLengths := vPatternData.Lines;
      if vDashLengths <> nil then
      begin
        AddInt(79, vDashLengths.Count);
        for J := 0 to vDashLengths.Count - 1 do
          AddFloat(49, vDashLengths[J]);
      end
      else
        AddInt(79, 0);
    end;
  end;

  procedure AddPolylineBoundary(ABoundaryList: TF2DPointList);
  var
    I: Integer;
  begin
    (*// Polyline edge type
    vHasPolyBoundary := True;
    AddInt(92, 7);
    AddInt(72, 0);
    AddInt(73, 0);
    AddInt(93, ABoundaryList.Count);
    for I := 0 to ABoundaryList.Count - 1 do
      Add2DPoint(10, PF2DPoint(ABoundaryList[I])^);
    AddInt(97, 0); *)
    // Line edge type
    AddInt(92, 1);
    AddInt(93, ABoundaryList.Count);
    for I := 1 to ABoundaryList.Count - 1 do
    begin
      AddInt(72, 1);// Edge type = Line
      Add2DPoint(10, ABoundaryList[I-1]);
      Add2DPoint(11, ABoundaryList[I]);
    end;
    // To close
    AddInt(72, 1);
    Add2DPoint(10, ABoundaryList.Last);// last point
    Add2DPoint(11, ABoundaryList.First);// first point
    AddInt(97, 0);
  end;

  procedure AddBoundaryPathData(ABoundaryList: Tsg2DBoundaryList);
  var
    vBoundary: Tsg2DCurve;
    vPoly: Tsg2DPolylineEx;
    vSpline: Tsg2DSplineEx;
    I, J: Integer;
  begin
    AddInt(92, ABoundaryList.BoundaryType);
    vIsDerived := vIsDerived or (ABoundaryList.BoundaryType and 4 <> 0);
    if ABoundaryList.BoundaryType and 2 <> 0 then
    begin
      vPoly := Tsg2DPolylineEx(ABoundaryList[0]);
      if PP.EntType = ceMPolygon then
      begin
        AddInt(73, 1);//undefined
        AddInt(72, Ord(vPoly.BulgesCount > 0));
      end
      else
      begin
        AddInt(72, Ord(vPoly.BulgesCount > 0));
        AddInt(73, Ord(vPoly.Closed));
      end;
      AddInt(93, vPoly.VertexesCount);
      for J := 0 to vPoly.VertexesCount - 1 do
      begin
        Add2DPoint(10, vPoly.Vertexes[J]);
        if vPoly.BulgesCount > 0 then
          AddFloat(42, vPoly.Bulges[J]);
      end;
      if PP.EntType <> ceMPolygon  then
        AddInt(97, 0);// Number of source boundary objects
      // Reference to source boundary objects
      //AddString(cParentHandle_330, '0');// default = 0 - not source
    end
    else
    begin
      AddInt(93, ABoundaryList.Count);
      for I := 0 to ABoundaryList.Count - 1 do
      begin
        vBoundary := Tsg2DCurve(ABoundaryList[I]);
        AddInt(72, vBoundary.EdgeType);
        case vBoundary.EdgeType of
          1:// Line
            begin
              Add2DPoint(10, vBoundary.StartPoint);
              Add2DPoint(11, vBoundary.EndPoint);
            end;
          2:// Circular arc
            begin
              Add2DPoint(10, Tsg2DArc(vBoundary).CenterPoint);
              AddFloat(40, Tsg2DArc(vBoundary).Radius);
              AddFloat(50, Tsg2DArc(vBoundary).StartParam);
              AddFloat(51, Tsg2DArc(vBoundary).EndParam);
              AddInt(73, Ord(Tsg2DArc(vBoundary).CounterClockWise));
            end;
          3:// Ellipse
            begin
              Add2DPoint(10, Tsg2DEllipse(vBoundary).CenterPoint);
              Add2DPoint(11, Tsg2DEllipse(vBoundary).MajorPoint);
              AddFloat(40, Tsg2DEllipse(vBoundary).Radius);
              AddFloat(50, Tsg2DEllipse(vBoundary).StartParam);
              AddFloat(51, Tsg2DEllipse(vBoundary).EndParam);
              AddInt(73, Ord(Tsg2DEllipse(vBoundary).CounterClockWise));
            end;
          4:// Spline
            begin
              vSpline := Tsg2DSplineEx(vBoundary);
              AddInt(94, vSpline.Degree);
              AddInt(73, 0);
              AddInt(74, 0);
              AddInt(95, vSpline.KnotsCount);
              AddInt(96, vSpline.ControlsCount);
              for J := 0 to vSpline.KnotsCount - 1 do
                AddFloat(40, vSpline.Knots[J]);
              for J := 0 to vSpline.ControlsCount - 1 do
                Add2DPoint(10, vSpline.Controls[J]);
            end;
        end;
      end;// end of for (ABoundaryList.Count)
      AddInt(97, 0);
    end;
  end;

begin
  if PP is TsgCADFill then
  begin
    Result := ExportCADFill(TsgCADFill(PP));//change in future version
    Exit;
  end;
  vIsDerived := False;
  if Version <= acR2000 then
  begin
    vColor := PP.ColorCAD;
    try
      PP.ColorCAD := GetDXFEntColor(PP, Version);
      AddCommonEntityGroup(PP);
    finally
      PP.ColorCAD := vColor;
    end;
  end
  else
    AddCommonEntityGroup(PP);
  if PP is TsgCADCurvePolygon then
  begin
    Add3DPoint(10, TsgCADCurvePolygon(PP).Elevation);
    Add3DPoint(210, TsgCADCurvePolygon(PP).Extrusion);// always to be added Extrusion
  end
  else
  begin
    Add3DPoint(10, cnstFPointZero);
    Add3DPoint(210, cnstZOrtAxis);
  end;
  AddString(2, PP.HatchName);
  if PP.EntType <> ceMPolygon then
  begin
    AddInt(cFlag_70, Integer(PP.SolidFill));
    AddInt(71, 0);//associativity flag
  end
  else
    AddInt(71, Integer(PP.SolidFill));
  if PP is TsgCADCurvePolygon then
  begin
    AddInt(91, TsgCADCurvePolygon(PP).BoundaryDataCount);
    for K := 0 to TsgCADCurvePolygon(PP).BoundaryDataCount-1 do
      AddBoundaryPathData(TsgCADCurvePolygon(PP).BoundaryData[K]);
    if PP.EntType <> ceMPolygon then
      AddInt(75, 0);
    if (not PP.SolidFill) and (TsgCADHatch(PP).HatchPatternData.Count > 0) then
      AddPatternData
    else
      AddInt(76, 1);// Hatch pattern type (1 = predefined)
  end
  else
  begin
    AddInt(91, PP.Boundaries.Count);
    for K := 0 to PP.Boundaries.Count-1 do
      AddPolylineBoundary(PP.Boundaries[K]);
    AddInt(75, 0);
    AddInt(76, 1);
  end;
  if PP.EntType = ceMPolygon then
  begin
    if TsgCADCurvePolygon(PP).FillColor.Active = acIndexColor then
    begin
      AddInt(IfThen(Ord(Version) >= Ord(acR2004), 63, 94),
       TsgCADCurvePolygon(PP).FillColor.Color);
    end
    else if TsgCADCurvePolygon(PP).FillColor.Active = acRGBColor then
    begin
      AddInt(IfThen(Ord(Version) >= Ord(acR2004), 63, 94),
        ColorToDXF(TsgCADCurvePolygon(PP).FillColor));
    end;
    Add2DFlatPoint(11, TsgCADCurvePolygon(PP).Offset);
    AddInt(99, 0);
  end
  else
  begin
    if vIsDerived then
      AddFloat(47, 0.000001);
    AddInt(98, 0);// Number of seed points (usually one point)
    //Add3DPoint(10, MakeFPoint(0,0,0));// Seed point, i.e. point inside area "for filling"
  end;
  if Ord(Version) >= Ord(acR2004) then
  begin
    if (PP.EntType = ceMPolygon) or IsCADGradient(PP) then// Add gradient
    begin
      vGradient := TsgCADGradientPolygon(PP);
      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, BGRToRGB(vGradient.GradientColor[0]));
      AddFloat(463, 1.0);
      AddInt(421, BGRToRGB(vGradient.GradientColor[1]));
      AddString(470, vGradient.GradientName);
    end;
  end;
  Result := True;
end;

function TsgCADtoDXF.ExportImageEntByFile(W: TsgDXFImageEnt): Boolean;
begin
  Result := ExportImageEntAsExternalFile(W, DoHandle, ExportWipeOut, nil);
end;

function TsgCADtoDXF.ExportImageEntByOle(W: TsgDXFImageEnt): Boolean;
begin
 Result := ExportImageEntAsOle(W, ExportOle2Frame, nil);
end;

function TsgCADtoDXF.ExportImageEnt(W: TsgDXFImageEnt): Boolean;
begin
  case GetExportImageIndex(W, ExportImageFileIndex) of
    cntImageExportAsImage:
      Result := ExportWipeOut(TsgCADWipeOut(W));
    cntImageExportAsOLE2Frame:
      Result := ExportImageEntByOle(W);
    cntImageExportAsFile:
      Result := ExportImageEntByFile(W);
  else
    Result := False;
  end;
end;

{ INSERT }
function TsgCADtoDXF.ExportInsert(INS: TsgDXFInsert): Boolean;
var
  I, vAttribsCount: Integer;
  MINS: TsgCADMInsert absolute INS;
  P, S: TFPoint;
  A: Double;
begin
  Result := False;
  if INS.Block = nil then Exit;
  if IsNameInternal(INS.Block.Name) then
    Exit;
  if Assigned(FSGBlock) and (INS.Block.Name = FSGBlock.Name) then
{$IFNDEF SG_ENCRYPT_FILES}
    if INS.Block <> FSGBlock then Exit;
{$ELSE}
      Exit;
{$ENDIF}
  vAttribsCount := INS.Attribs.Count;
  AddCommonEntityGroup(INS);
  AddLineType(INS.LineType);
  if vAttribsCount > 0 then
    AddInt(66, 1);
  AddString(2, AnsiUpperCase(INS.Block.Name));

  if INS.EntClass.EG = gtSVG then
  begin
    INS.ExtractParamsFromMatrix2D(P, S, A);
    Add3DPoint(10, P);
    AddFloat(41, S.X);
    AddFloat(42, S.Y);
    AddFloat(43, S.Z);
    if A <> 0 then
      AddFloat(50, A);
    // Add column and raw here
    if Assigned(DXFConv.LoadEntityProc) then
      ExportExtendedData(INS);
  end
  else
  begin
    Add3DPoint(10, INS.Point);//  Add3DPointExtruded(10, INS.Point, INS.Extrusion);
    AddFloat(41, INS.Scale.X);
    AddFloat(42, INS.Scale.Y);
    AddFloat(43, INS.Scale.Z);
    if INS.Angle <> 0 then
      AddFloat(50, INS.Angle);
    // Add column and raw here
    AddExtrusion(INS.Extrusion);
    // Extended data before Attribs
    if XDataAppName <> '' then
      ExportExtendedData(INS);
  end;
  if INS.ClassType = TsgCADMInsert then
  begin
    AddInt(70, MINS.NumCols);
    AddInt(71, MINS.NumRows);
    AddFloat(44, MINS.ColSpacing);
    AddFloat(45, MINS.RowSpacing);
  end;
  if vAttribsCount > 0 then
  begin
    for I := 0 to vAttribsCount - 1 do
      ExportText(TsgDXFAttrib(INS.Attribs[I]));
    AddEntName(nil, 'SEQEND');
  end;
  Result := True;
end;

{ DIMENSION }
function TsgCADtoDXF.ExportDimension(D: TsgDXFDimension): Boolean;
const
  cnstDimension = 'Dimension';
  cnstDimSubclasses: array [0..6] of string = ('Rotated', 'Aligned',
    '2LineAngular', 'Diametric', 'Radial', '3PointAngular', 'Ordinate');
var
  DimEx: TsgDXFDimensionEx absolute D;
  I: Integer;
begin
  Result := False;
  if D.Block = nil then Exit;
  AddCommonEntityGroup(D);
  if D.TextOverride <> '' then
    AddString(1, D.TextOverride);
  if D.Style <> nil then AddString(3, D.Style.Name);
  AddString(2, GetCorrectBlockName(D.Block.Name));
  Add3DPoint(10, D.DefPoint);
  Add3DPoint(11, D.MiddlePoint);
  AddExtrusion(D.Extrusion);
  AddInt(cFlag_70, D.Flags);
  if D.TextRotation <> 0 then
    AddFloat(53, D.TextRotation);
  I := D.Flags and 7;
  case I of
    2, 5: //'2LineAngular' '3PointAngular'
      begin
        AddSubclassMarker(cnstDimSubclasses[I]+cnstDimension);
        Add3DPoint(13, D.LinDefPoint1);
        Add3DPoint(14, D.LinDefPoint2);
        Add3DPoint(15, D.RadDefPoint);
        if I <> 5 then
          Add3DPoint(16, D.ArcDefPoint);
      end;
    3, 4: //'Diametric' 'Radial'
      begin
        AddSubclassMarker(cnstDimSubclasses[I]+cnstDimension);
        Add3DPoint(15, D.RadDefPoint);
        //AddFloat(40, 0);
      end;
    6:    //'Ordinate'
      begin
        AddSubclassMarker(cnstDimSubclasses[I]+cnstDimension);
        Add3DPoint(13, D.LinDefPoint1);
        Add3DPoint(14, D.LinDefPoint2);
      end;
  else
    Add3DPointExtruded(12, D.Point, D.Extrusion);
    AddSubclassMarker(cnstDimSubclasses[1]+cnstDimension);
    Add3DPoint(13, D.LinDefPoint1);
    Add3DPoint(14, D.LinDefPoint2);
    if D.Angle <> 0 then
      AddFloat(50, D.Angle);
    if I = 0 then
      AddSubclassMarker(cnstDimSubclasses[0]+cnstDimension);
  end;
  ExportExtendedData(D);
  Result := True;
end;

{ ELLIPSE }
function TsgCADtoDXF.ExportEllipse(E: TsgDXFEllipse): Boolean;
begin
  if Ord(Version) > Ord(acR12) then
  begin
    AddCommonEntityGroup(E);
    //AddThickness(E.ZThick);
    Add3DPointPreExtruded(10, E.Point, E.Extrusion);
    Add3DPointPreExtruded(11, E.RadPt, E.Extrusion);
    AddFloat(40, E.Ratio);
    if Abs(E.StartAngle - E.EndAngle) > fAccuracy then
    begin
      AddFloat(41, Radian(E.StartAngle));
      AddFloat(42, Radian(E.EndAngle));
    end;
  end
  else
    ExportPolyLine(E);
  Result := True;
end;

function TsgCADtoDXF.ExportEntityAsGroup(const E: TsgDXFEntity): Boolean;
begin
  Result := ExportGroup(E, 0, CreateExportData);
end;

function TsgCADtoDXF.ExportExtendedData(const AEntity: TsgDXFEntity): Boolean;
var
  I: Integer;
  vEED: TsgCADExtendedData;
begin
  vEED := TsgCADExtendedData.Create;
  try
    if AEntity.GetExtData(vEED) then
    begin
      I := 0;
      while I < vEED.DataCount do
      begin
        case vEED.DataType[I] of
          edtByte:      AddInt(vEED.DataCode[I], vEED.DataByte[I]);
          edtInt16:     AddInt(vEED.DataCode[I], vEED.DataInt16[I]);
          edtInt:
            case AEntity.EntClass.EG of
              gtBTI:
                if vEED.GroupCode[I] = Integer_1070 then
                  AddInt(vEED.GroupCode[I], vEED.DataInt[I])
                else
                  AddInt(vEED.DataCode[I], vEED.DataInt[I]);
            else
              AddInt(vEED.DataCode[I], vEED.DataInt[I]);
            end;
          edtSingle:    AddFloat(vEED.DataCode[I], vEED.DataSingle[I]);
          edtDouble:    AddFloat(vEED.DataCode[I], vEED.DataDouble[I]);
          edtString:
            case AEntity.EntClass.EG of
              gtBTI:
                if vEED.GroupCode[I] = String_1005 then
                  AddString(vEED.GroupCode[I], vEED.DataString[I])
                else
                  AddString(vEED.DataCode[I], vEED.DataString[I]);
            else
              AddString(vEED.DataCode[I], vEED.DataString[I]);
            end;
          edtF2DPoint:  Add2DPoint(vEED.DataCode[I], vEED.DataPoint2D[I]);
          edtF3DPoint:  Add3DPoint(vEED.DataCode[I], vEED.DataPoint[I]);
          edtInt64:     AddHexInt(vEED.DataCode[I], vEED.DataInt64[I]);
          edtObject:    AddHexInt(vEED.DataCode[I], GetHandleByEntity(TsgDXFEntity(vEED.DataObject[I])));
        end;
        Inc(I);
      end;
      Result := True;
    end
    else
      Result := False;
  finally
    vEED.Free;
  end;
end;

{ FlatHatch entity }
function TsgCADtoDXF.ExportFlatHatch(FH: TsgFlatHatch): Boolean;
var
  I, J, K, vCount, vSubCount, vIndex: Integer;
begin
  vIndex := 0;
  I := 0;
  while I < FH.Counts.Count do
  begin
    vCount := Integer(FH.Counts[I]);
    Inc(I);
    //if (vIndex + vCount) > FH.PCount then Break;
    if vCount = 0 then Break;
    AddCommonEntityGroup(FH);
    Add3DPoint(10, cnstFPointZero);
    Add3DPoint(210, cnstZOrtAxis);
    AddString(2, sSOLID);
    AddInt(cFlag_70, 1);
    AddInt(71, 0);
    AddInt(91, vCount);
    (*// Polyline does not work in AutoCAD (AutoCAD bug)
    AddInt(92, 2);
    for J := 0 to vCount - 1 do
    begin
      AddInt(72, 0);
      AddInt(73, 1);
      vSubCount := Integer(FH.Counts[I]);
      Inc(I);
      AddInt(93, vSubCount);
      for K := vIndex to (vIndex + vSubCount - 1) do
        Add2DFlatPoint(10, FH.XY[K]);
      AddInt(97, 0);
      Inc(vIndex, vSubCount);
    end;  *)
    // 'Line'-boundarytype works in AutoCAD
    for J := 0 to vCount - 1 do
    begin
      AddInt(92, 1);
      vSubCount := Integer(FH.Counts[I]);
      Inc(I);
      AddInt(93, vSubCount);
      for K := vIndex + 1 to (vIndex + vSubCount - 1) do
      begin
        AddInt(72, 1);// Edge type = Line
        Add2DFlatPoint(10, FH.XY[K-1]);
        Add2DFlatPoint(11, FH.XY[K]);
      end;
      // To close
      AddInt(72, 1);
      Add2DFlatPoint(10, FH.XY[vIndex + vSubCount - 1]);// last point
      Add2DFlatPoint(11, FH.XY[vIndex]);// first point
      AddInt(97, 0);
      Inc(vIndex, vSubCount);
    end;
    AddInt(75, 0);
    AddInt(76, 1);
    AddInt(98, 0);
    Inc(I);// see TsgFlatHatch.Add below full count of points
  end;
  Result := True;
end;

{ FlatPoly entity }
function TsgCADtoDXF.ExportFlatPoly(FP: TsgFlatPoly): Boolean;
begin
  Result := ExportEntityAsGroup(FP);
end;

{ LEADER }
function TsgCADtoDXF.ExportLeader(L: TsgDXFLeader): Boolean;
var
  I: Integer;
begin
  AddCommonEntityGroup(L);
  AddString(3, L.DimStyle.Name);
  AddInt(71, Ord(L.Arrowhead));
  AddInt(72, Ord(L.IsSpline));
  AddInt(73, 3);// Created without any annotation
  AddInt(74, 0);
  AddFloat(40, 1);
  AddFloat(41, 1);
  if L.ControlCount = 0 then
  begin
    AddInt(76, 1);
    Add3DPoint(10, cnstFPointZero);
  end
  else
  begin
    AddInt(76, L.ControlCount);
    for I := 0 to L.ControlCount - 1 do
      Add3DPoint(10, L.Controls[I]);
  end;
  AddString(340, '0');
  // Dimension style
  ExportExtendedData(L);
  Result := True;
end;

{ LINE }
function TsgCADtoDXF.ExportLine(L: TsgDXFLine): Boolean;
begin
  AddCommonEntityGroup(L);
  AddThickness(L.ZThick);
  Add3DPoint(10, L.Point);//  Add3DPointExtruded(10, L.Point, L.Extrusion);
  Add3DPoint(11, L.Point1);//  Add3DPointExtruded(11, L.Point1, L.Extrusion);
  AddExtrusion(L.Extrusion);
  Result := True;
end;

{MLINE}

function TsgCADtoDXF.ExportMLine(M: TsgCADMLine): Boolean;
var
  vVertex: TsgMVertex;
  I, J, K, vLinesInStyle: Integer;
begin
  AddEntName(M, sCADEntityNames[M.EntType]);
  AddSubclassMarker(sCADEntitySubNames[M.EntType]);

  if Assigned(M.Style) then
  begin
    AddString(2, AnsiUpperCase(M.Style.Name));
    AddHexInt(340, M.Style.Handle);
  end
  else
  begin
    AddString(2, sStandardName);
    AddString(340, '0');
  end;
  AddFloat(40, M.ScaleFactor);
  AddInt(cFlag_70, M.Justify);
  Add3DPoint(10, M.StartPoint);
  Add3DPoint(210, M.Extrusion);
  AddInt(71, M.Flags);
  if M.Count > 0 then
    vLinesInStyle := TsgMVertex(M[0]).ParamsCount
  else
    vLinesInStyle := 0;
  AddInt(73, vLinesInStyle);
  AddInt(72, M.Count);
  for I := 0 to M.Count - 1 do
  begin
    vVertex := M[I];
    Add3DPoint(11, vVertex.Point);
    Add3DPoint(12, vVertex.Direction);
    Add3DPoint(13, vVertex.Miter);
    for J := 0 to vVertex.ParamsCount - 1 do
    begin
      AddInt(74, vVertex.PCounts[J]);
      for K := 0 to vVertex.PCounts[J] - 1 do
        AddFloat(41, vVertex.Params[J, K]);
      AddInt(75, 0);
    end;
  end;
  Result := True;
end;

{ MTEXT }

function TsgCADtoDXF.ExportMText(MT: TsgDXFMText): Boolean;
var
  I, vCount: Integer;
  vText: string;

  procedure AddStringByCount(const Code, Count: Integer; const Str: string);
  var
    S: string;
  begin
    S := Str;
    if Length(S) > Count then SetLength(S, Count);
    AddString(Code, S);
  end;

begin
  AddCommonEntityGroup(MT);
  Add3DPoint(10, MT.Point);
  AddFloat(40, MT.Height);
  vText := GetEntityStringValue(MT);
  vCount := Floor(Length(vText)/cnstMaxStringLen);
  for I := 1 to vCount do
  begin
    AddStringByCount(3, cnstMaxStringLen, vText);
    vText := PChar(@vText[cnstMaxStringLen+1]);
  end;
  AddString(1, vText);
  AddFloat(50, MT.Angle);
  AddFloat(41, MT.RectWidth);
  if MT.Style <> nil then
    AddString(7, MT.Style.Name);
  AddInt(71, MT.Align);
  if TsgDXFMTextEx(MT).HasSecond then
    Add3DPoint(11, MT.Point1);
  AddExtrusion(MT.Extrusion);
  AddInt(73, MT.LineSpacingStyle);
  AddFloat(44, MT.LineSpacingFactor);
  Result := True;
end;

{ OLE2FRAME }
const
  cnstLineSize = 71;

procedure AddHexBinData(const ABinData: AnsiString; ABuf: Pointer; ASelf: Pointer); register;
{$IFDEF CPUX64}
const
  cnstDataLen = $20; // AnsiChar pairs
  cnstDataLenMask = $1F;
var
  I, vInpDataLen: Integer;
  vPInpBinDataPos: PByte;
  vPOutBinLinePos: PWord;
begin
  InitByteBinToHex;
  vInpDataLen := Length(ABinData); // always a multiple of cnstDataLen (?)
  vPOutBinLinePos := ABuf;
  vPInpBinDataPos := PPointer(@ABinData)^;
  // make string 310#13#10 ... #13#10
  PCardinal(vPOutBinLinePos)^ := $0D303133; // '310'#13
  Inc(PCardinal(vPOutBinLinePos));
  PByte(vPOutBinLinePos)^ := $0A;           // #10
  // line end #13#10
  Inc(PByte(vPOutBinLinePos), cnstDataLen shl 1 + 1);
  PWord(vPOutBinLinePos)^ := cnstRawEnter;  // #13#10
  // start data position
  Dec(vPOutBinLinePos, cnstDataLen);

  // filling the output buffer
  I := 0;
  while I < vInpDataLen do
  begin
    // put translated word to out
    vPOutBinLinePos^ := ByteBinToHex^[vPInpBinDataPos^];
    // next out position
    Inc(vPOutBinLinePos);
    // next input position
    Inc(vPInpBinDataPos);
    // is line ready
    if I and cnstDataLenMask = cnstDataLenMask then // (I + 1) mod 32 = 0
    begin
      // write output line to stream
      TsgCADtoDXF(ASelf).WriteBuffer(ABuf^, cnstLineSize);
      // start data position
      Dec(vPOutBinLinePos, cnstDataLen);
    end;
    Inc(I);
  end;
end;
{asm
    push rbx                    // save registers
    push rsi
    push rdi
    push r9                     // output line
    push r11                    // offset binary data
    push r12                    // ASelf storage

    mov r12,r8                  // save ASelf

    mov rbx,sBinToHex           // RBX - offset hexdecimal
    mov rax,ABinData            // rax - address of binary data
    movsx rsi,dword ptr [rax - 4] // rsi - length binary data in bytes
    shr rsi,5                   // RSI - 64-bytes output data lines count
    mov rcx,rax                 // RCX - address of binary data

    mov dword ptr [rdx],$0D303133 // set string
    mov byte ptr [rdx + 4],$0A    //  '310'#13#10
    mov word ptr [rdx + 69],$0A0D // #13#10
    add rdx,5                   // offset to begining of output data line
    mov r9,rdx                  // RDX - output line start
@nextline:                     // begin loop for next line
    mov rdx,r9
// ----------- fill line with hexdecimal characters ----------------------------
    mov rdi,32                  // RDI - count of bindata bytes translated to output line
@nextbyte:                      // begin loop for next data byte
    mov ah,[rcx]                // mov data byte to AH
    mov al,ah                   // copy AH to AL
    shr al,4                    // shift AL (requires higher tetrad)
    xlatb                       // translate [RBX + AL] to AL
    mov [rdx],al                // write char to line
    mov al,ah                   // copy AH to AL
    and al,$F                   // mask lower tetrad
    xlatb                       // translate [RBX + AL] to AL
    inc rdx                     // seek next char in line
    mov [rdx],al                // write char to line
    inc rdx                     // seek next char in line
    inc rcx                     // seek next data byte
    dec rdi                     // next data byte counter
    jnz @nextbyte               // if line not fill goto next data byte translate
// ----------- fill line with hexdecimal characters ----------------------------

    mov r11,rcx                 // save default offset of binary data
    mov rcx,r8                  // prepare params
    mov rdx,r9                  // for calling
    sub rdx,5
    mov rax,[rcx]               // TsgCADToDXF.WriteBuffer method
    mov r8,cnstLineSize         // line size
    call [rax + VMTOFFSET TsgCADToDXF.WriteBuffer] // write to buffer
    mov r8,r12                  // restore ASelf
    mov rcx,r11                 // restore default offset of binary data

    dec rsi                     // next line counter
    jnz @nextline               // if not end of line count goto next line fill

    pop r12
    pop r11
    pop r9
    pop rdi
    pop rsi
    pop rbx                     // restore registers
end;}
{$ELSE}
asm
// EAX - input binary data
// EDX - output line start
// ECX - TsgCADToDXF object

    pushad                    // save all registers
    mov ebp,ecx               // save ASelf

    mov ebx,sBinToHex         // EBX - offset hexdecimal
    mov esi,[eax - 4]         // esi - length binary data in bytes
    shr esi,5                 // ESI - 64-bytes output data lines count
    mov ecx,eax               // ECX - address of binary data

    mov dword ptr [edx],$0D303133 // set string
    mov byte ptr [edx + 4],$0A    //  '310'#13#10
    mov word ptr [edx + 69],$0A0D // #13#10
    add edx,5                 // offset to begining of output data line

@nextline:                    // begin loop for next line
    push edx                  // save line buffer offset
// ----------- fill line with hexdecimal characters ----------------------------
    mov edi,32                // EDI - count of bindata bytes translated to output line
@nextbyte:                    // begin loop for next data byte
    mov ah,[ecx]              // mov data byte to AH
    mov al,ah                 // copy AH to AL
    shr al,4                  // shift AL (requires higher tetrad)
    xlat                      // translate [EBX + AL] to AL
    mov [edx],al              // write char to line
    inc edx                   // seek next char in line
    mov al,ah                 // copy AH to AL
    and al,$F                 // mask lower tetrad
    xlat                      // translate [EBX + AL] to AL
    mov [edx],al              // write char to line
    inc edx                   // seek next char in line
    inc ecx                   // seek next data byte
    dec edi                   // next data byte counter
    jnz @nextbyte             // if line not fill goto next data byte translate
// ----------- fill line with hexdecimal characters ----------------------------

    push ecx                  // save default offset of binary data
    mov eax,ebp               // prepare params for calling TsgCADToDXF.WriteBuffer method
    mov edi,[eax]             // EDI = object offset
    sub edx,69                // EDX = ABuffer
    mov ecx,cnstLineSize      // ECX = count
{$IFDEF SGDEL_6}
    call [edi + VMTOFFSET TsgCADToDXF.WriteBuffer] // write to buffer
{$ELSE}
    call [edi + TsgCADToDXF.WriteBuffer]           // write to buffer
{$ENDIF}
    pop ecx                   // restore default offset of binary data

    pop edx                   // restore line buffer offset

    dec esi                   // next line counter
    jnz @nextline             // if not end of line count goto next line fill

    popad                     // restore all registers
end;
{$ENDIF}

function TsgCADtoDXF.ExportOle2Frame(OLE2: TsgDXFOle2Frame; Data: TObject = nil): Boolean;
var
  vBuf: array[0 .. cnstLineSize - 1] of Byte;
  vSelf: Pointer;
  vBinData: AnsiString;
  vOleHeader: PsgOle2FrameHeaderData;
begin
  vSelf := Self;
  AddCommonEntityGroup(OLE2);
  AddInt(70, 2);
  Add3DPoint(10, MakeFPoint(OLE2.Point.X, OLE2.Point.Y, 0.0));
  Add3DPoint(11, MakeFPoint(OLE2.Point1.X, OLE2.Point1.Y, 0.0));
  //Add3DPoint(10, OLE2.Point);
  //Add3DPoint(11, OLE2.Point1);
  AddInt(71, OLE2.OLEObjectType);
  AddInt(72, 1);
  AddInt(90, Length(OLE2.BinaryData) + 128);
  SetLength(vBinData, 128);
  vOleHeader := PsgOle2FrameHeaderData(PPointer(@vBinData)^);
  PrepareOLEHeader(OLE2, vOleHeader);
  AddHexBinData(vBinData, @vBuf[0], vSelf);
  if Length(OLE2.BinaryData) > 0 then
    AddHexBinData(OLE2.BinaryData, @vBuf[0], vSelf);
  AddString(1, 'OLE');
  Result := True;
end;

{ POINT }
function TsgCADtoDXF.ExportPoint(P: TsgDXFPoint): Boolean;
begin
  AddCommonEntityGroup(P);
  AddThickness(P.ZThick);
  Add3DPoint(10, P.Point);
  AddExtrusion(P.Extrusion);
  Result := True;
end;

{ POLYLINE }
function TsgCADtoDXF.ExportPolyLine(BasePL: TsgCADBasePolyline): Boolean;
var
  PL: TsgDXFPolyline absolute BasePL;
  vFaceMesh, vPolyMesh: Boolean;
  vVertex: TsgDXFVertexEx;
  I, vCount: Integer;
  vEntType: TsgCADEntities;
  vLayer: string;

  procedure Add3dVertex(AVertex: TsgDXFVertexEx; const ALayer: string);
  var
    vPoint: TFPoint;
  begin
    AddEntName(nil, 'VERTEX', ALayer);
    if vFaceMesh and (AVertex.Flags = 128) then
      AddSubclassMarker('FaceRecord')
    else
    begin
      AddSubclassMarker('Vertex');
      if vPolyMesh and ((AVertex.Flags and 64) <> 0) then
        AddSubclassMarker('PolygonMeshVertex')
      else
        if vFaceMesh and (AVertex.Flags <> 128) then
          AddSubclassMarker('PolyFaceMeshVertex')
        else
          AddSubclassMarker('3dPolylineVertex');
    end;
    AddDXFColor(PL.ColorCAD);
    vPoint := AVertex.Point;
    DoExtrusion(vPoint, PL.Extrusion);
    //Location point (in OCS when 2D, and WCS when 3D)
    Add3DPoint(10, vPoint);
    if AVertex.StartWidth <> 0 then
      AddFloat(40, AVertex.StartWidth);
    if AVertex.EndWidth <> 0 then
      AddFloat(41, AVertex.EndWidth);
    if AVertex.Bulge <> 0 then
      AddFloat(42, AVertex.Bulge);
    AddInt(cFlag_70, AVertex.Flags);
    //AddFloat(50, AVertex.FitTangent);
    if AVertex.FPolyFaceIndexes <> nil then
    begin
      AddInt(71, AVertex.PolyFaceVertexIndex1);
      AddInt(72, AVertex.PolyFaceVertexIndex2);
      AddInt(73, AVertex.PolyFaceVertexIndex3);
      AddInt(74, AVertex.PolyFaceVertexIndex4);
    end;
  end;

begin
  Result := (BasePL.Count > 0) or (BasePL.PolyPoints.Count > 0);
  if not Result then
    Exit;
  vEntType := BasePL.EntType;
  if (Ord(Version) < Ord(acR14)) and (vEntType = ceLWPolyline) then
    vEntType := cePolyline;
  case vEntType of
    cePolyline:
      begin
        vPolyMesh := PL.IsPolygonMesh;
        vFaceMesh := PL.IsPolyFaceMesh;
        if vPolyMesh then
          AddCommonEntityGroupEx(PL, sCADEntityNames[cePolyline], 'PolygonMesh')
        else
          if vFaceMesh then
            AddCommonEntityGroupEx(PL, sCADEntityNames[cePolyline], 'PolyFaceMesh')
          else// for correct export CIRCLE, ELLIPSE, SPLINE to POLYLINE
            AddCommonEntityGroupEx(PL, sCADEntityNames[cePolyline], '3dPolyline');
        AddInt(66, 1);
        Add3DPoint(10, MakeFPoint(0, 0, PL.Elevation));
        AddThickness(PL.ZThick);
        AddInt(cFlag_70, PL.Flags);
        if PL.GlobalWidth = 0 then
        begin
          AddFloat(40, PL.StartWidth);
          AddFloat(41, PL.EndWidth);
        end
        else
        begin
          AddFloat(40, PL.GlobalWidth);
          AddFloat(41, PL.GlobalWidth);
        end;
        if PL.MeshM > 0 then
          AddInt(71, PL.MeshM);
        if PL.MeshN > 0 then
          AddInt(72, PL.MeshN);
        vCount := PL.Count-1;
        vLayer := GetEntityLayerName(BasePL);
        for I := 0 to vCount do
          Add3dVertex(TsgDXFVertexEx(PL.Entities[I]), vLayer);
        AddEntName(nil, 'SEQEND');
      end;
    ceLWPolyline:
      begin
        AddCommonEntityGroup(PL);
        AddThickness(PL.ZThick);
        if PL.Count > 0 then
          AddFloat(38, PL.Elevation);// Elevation
        AddInt(90, PL.Count);
        AddInt(cFlag_70, PL.Flags);
        if PL.GlobalWidth <> 0 then
          AddFloat(43, PL.GlobalWidth);
        vCount := PL.Count-1;
        for I := 0 to vCount do
        begin
          vVertex := TsgDXFVertexEx(PL.Entities[I]);
          Add2DFlatPoint(10, vVertex.Point);
          if (vVertex.StartWidth <> 0) or (vVertex.EndWidth <> 0) then
          begin
            AddFloat(40, vVertex.StartWidth);
            AddFloat(41, vVertex.EndWidth);
          end;
          if vVertex.Bulge <> 0 then
            AddFloat(42, vVertex.Bulge);
        end;
        AddExtrusion(PL.Extrusion);
      end;
  else
    // for correct export CIRCLE, ELLIPSE, SPLINE to POLYLINE
    AddCommonEntityGroupEx(BasePL, sCADEntityNames[cePolyline], '3dPolyline');
    AddInt(66, 1);
    Add3DPoint(10, cnstFPointZero);
    AddThickness(BasePL.ZThick);
    AddInt(cFlag_70, BasePL.Flags or 8);// 8 = 3DPolyline
    vCount := BasePL.PolyPoints.Count - 1;
    for I := 0 to vCount do
    begin
      AddEntName(nil, 'VERTEX');
      AddSubclassMarker('Vertex');
      AddSubclassMarker('3dPolylineVertex');
      Add3DPoint(10, BasePL.PolyPoints[I]);
      AddInt(cFlag_70, 32);// 32 = 3D polyline vertex
    end;
    AddEntName(nil, 'SEQEND');
  end;
end;

{$IFDEF SG_BTI}
{ POLYPOLYLINE }
function TsgCADtoDXF.ExportPolyPolyline2D(PL2D: TsgCADPolyPolyline2D): Boolean;
var
  I, vCount: Integer;

  procedure Export2DLine(L: TsgLine);
  begin
    AddCommonEntityGroupEx(PL2D, 'LINE', 'Line');
    AddLineType(PL2D.LineType);// only if PL2D is not a TsgDXFPenLine, see code in AddCommonEntityGroupEx
    Add2DFlatPoint(10, L.Point1);
    Add2DFlatPoint(11, L.Point2);
  end;

  procedure Export2DArc(A: TsgArcR);
  begin
    AddCommonEntityGroupEx(PL2D, 'ARC', 'Circle');
    AddLineType(PL2D.LineType);// only if PL2D is not a TsgDXFPenLine, see code in AddCommonEntityGroupEx
    Add3DPoint(10, A.Center);
    AddFloat(40, A.Radius);
    AddSubclassMarker('Arc');
    AddFloat(50, A.AngleS);
    AddFloat(51, A.AngleE);
  end;

begin
  vCount := PL2D.CurvesCount-1;
  for I := 0 to vCount do
    if PL2D.CurveVisible[I] then
    begin
      if PL2D.IsCurveArc(I) then
        Export2DArc(PL2D.Arcs[I])
      else
        Export2DLine(PL2D.Lines[I]);
    end;
  Result := True;
end;
{$ENDIF}

{ SHAPE }
function TsgCADtoDXF.ExportShape(S: TsgDXFShape): Boolean;
begin
  AddCommonEntityGroup(S);
  Add3DPoint(10, S.Point);
  AddFloat(40, S.Height);
  AddString(2, S.ShapeName);
  AddFloat(50, S.Rotation);
  AddFloat(41, S.XScale);
  AddFloat(51, S.ObliqueAngle);
  Result := True;
end;

{ SOLID }
function TsgCADtoDXF.ExportSolid(S: TsgDXFSolid): Boolean;
begin
  AddCommonEntityGroup(S);
  Add3DPoint(10, S.Point);
  Add3DPoint(11, S.Point1);
  Add3DPoint(12, S.Point2);
  Add3DPoint(13, S.Point3);
  AddExtrusion(S.Extrusion);
  Result := True;
end;

{ SPLINE }
function TsgCADtoDXF.ExportSpline(SPL: TsgDXFSpline): Boolean;
var
  I: Integer;
begin
  if Ord(Version) > Ord(acR12) then
  begin
    AddCommonEntityGroup(SPL);
    AddInt(cFlag_70, SPL.Flags);
    AddInt(71, SPL.Degree);
    if SPL.Knots.Count <= SPL.ControlCount+4 then
    begin
      AddInt(72, SPL.Knots.Count);
      AddInt(73, SPL.ControlCount);
      //AddFloat(42, 0.0000001); AddFloat(43, 0.0000001); AddFloat(44, 0.0000001);
      if SPL.IsByAngles then
      begin
        AddInt(74, SPL.FitCount);
        Add3DPoint(12, SPL.BeginningTangent);
        Add3DPoint(13, SPL.EndingTangent);
      end;
      for I := 0 to SPL.Knots.Count - 1 do
        AddFloat(40, Single(SPL.Knots[I]));
      for I := 0 to SPL.ControlCount - 1 do
        Add3DPoint(10, SPL.ControlPoints[I]);
      for I := 0 to SPL.WeightCount - 1 do
        AddFloat(41, SPL.Weight[I]);
      if SPL.IsByAngles then
        for I := 0 to SPL.FitCount - 1 do
          Add3DPoint(11, SPL.FitPoints[I]);
    end
    else// for bad SPLINE
    begin
      AddInt(74, SPL.PolyPoints.Count);
      for I := 0 to SPL.PolyPoints.Count - 1 do
        Add3DPoint(11, SPL.PolyPoints[I]);
    end;
    ExportExtendedData(SPL);
  end
  else
    ExportPolyLine(SPL);
  Result := True;
end;

{ ATTDEF, ATTRIB, TEXT }
function TsgCADtoDXF.ExportText(T: TsgDXFText): Boolean;
var
  vEntType: TsgCADEntities;
  vText: string;
  vLockPosition: Integer;
begin
  vEntType := T.EntType;
  AddCommonEntityGroup(T);
  Add3DPoint(10, T.Point);
  AddFloat(40, T.Height);
  vText := GetEntityStringValue(T);
  if vEntType = ceText then
    ReplaceAnsi(vText, cnstCaret, cnstCaretAndSpace);
  AddString(1, vText);
  AddFloat(50, T.Rotation);
  AddFloat(41, T.Scale);
  AddFloat(51, T.ObliqueAngle);
  if T.Style <> nil then
    AddString(7, ExtractName(T.Style.Name));
  AddInt(71, T.Generation);
  AddInt(72, T.HAlign);
  if TsgDXFTextEx(T).HasSecond then
    Add3DPoint(11, T.Point1);
  AddExtrusion(T.Extrusion);
  if vEntType = ceText then
  begin
    AddSubclassMarker('Text');
    AddInt(73, T.VAlign);
  end
  else
  begin
    if vEntType = ceAttrib then
      AddSubclassMarker('Attribute')
    else
    begin
      AddSubclassMarker('AttributeDefinition');
      AddString(3, TsgDXFAttdef(T).Tag);
    end;
    AddString(2, TsgDXFAttrib(T).Tag);
    AddInt(cFlag_70, TsgDXFAttrib(T).Flags);
    AddInt(74, T.VAlign);
    vLockPosition := Integer(TsgDXFAttrib(T).LockPosition);
    if Version >= acR2007 then
      AddInt(Word_280, vLockPosition)
    else
    begin
       AddString(String_1001, sACADXDataAttribAppName);
       AddInt(Integer_1070, 0);
       AddInt(Integer_1070, vLockPosition);
    end;
  end;
  ExportExtendedData(T);
  Result := True;
end;

{ TOLERANCE }
function TsgCADtoDXF.ExportTolerance(T: TsgDXFTolerance): Boolean;
begin
  AddCommonEntityGroup(T);
  AddString(3, T.DimStyle.Name);
  Add3DPoint(10, T.Point);
  AddString(1, T.Text);
  if TsgDXFToleranceEx(T).HasSecond then
    Add3DPoint(11, T.Point1);
  AddExtrusion(T.Extrusion);
  ExportExtendedData(T);
  Result := True;
end;

{ VIEWPORT }
function TsgCADtoDXF.ExportViewPort(V: TsgDXFViewPort): Boolean;
var
  vIndex: UInt64;
  I: Integer;
begin
  if FHasViewPortWindow = False then
    FHasViewPortWindow := (V.ThisID = 1);
  AddCommonEntityGroup(V);
  Add3DPoint(10, V.PSpaceCenter);
  AddFloat(40, V.PSpaceWidth);
  AddFloat(41, V.PSpaceHeight);
  AddInt(68, V.StatusField);
  AddInt(69, V.ThisID);
  if Ord(Version) > Ord(acR14) then
  begin
    Add3DPoint(12, V.MSpaceCenter);
    Add3DPoint(16, V.ViewDirection);
    Add3DPoint(17, V.ViewTarget);
    AddFloat(42, cntViewPortPerspectiveLensLength);
    AddFloat(43, V.FrontClipPlane);
    AddFloat(44, V.BackClipPlane);
    AddFloat(45, V.MSpaceHeight);
    AddFloat(51, V.ViewTwistAngle);
    AddInt(90, V.Flags);
    if Assigned(V.FrozenLayers) then
      for I := 0 to V.FrozenLayers.Count - 1 do
        if Version <=  acR2000 then
          AddHexInt(341, V.FrozenLayers[I])
        else
          AddHexInt(331, V.FrozenLayers[I]);
    vIndex := GetHandleByEntity(V.GetBoundary(ExportCADImage.Converter));
    if vIndex > 0 then
      AddHexInt(340, vIndex)
    else
      AddHexInt(340, 0);
  end
  else
    ExportExtendedData(V);
  Result := True;
end;

function TsgCADtoDXF.ExportWipeOut(W: TsgCADWipeOut; AData: TObject = nil): Boolean;
var
  I, Cnt:  Integer;
  vSize, vUVector, vVVector: TFPoint;
  vColorCadOld: TsgColorCAD;
begin
  // necessary for HPGL
  vColorCadOld := W.ColorCAD;
  try
    if IsNeedImageDefHandle(W) and Assigned(TsgDXFImageEntAccess(W).ImageDefExport) then
      W.ColorCAD := cnstColorCADByBlackWhite;
    AddCommonEntityGroup(W);
  finally
    W.ColorCAD := vColorCadOld;
  end;
  Add3DPoint(10, W.Point);

  GetCorrectImageVectorData(TsgDXFImageEnt(W), vUVector, vVVector, vSize);
  Add3DPoint(11, vUVector);
  Add3DPoint(12, vVVector);
  Add2DFlatPoint(13, vSize);

  AddHexInt(340, GetImageDefHandle(W)); // IMAGEDEF
  AddInt(70, W.Flags);
  AddInt(280, Ord(W.UseClipping));
  AddInt(281, cntImageBrightness);
  AddInt(282, cntImageContrast);
  AddInt(283, cntImageFade);
  AddHexInt(360, 0);      // IMAGEDEF_REACTOR
  if W.ClippingBoundaryType <> 0 then
  begin
    AddInt(71, W.ClippingBoundaryType);
    AddInt(91, GetRealCountBoundaryPoints(W));
    Cnt := W.ClipPointsCount - 1;
    for I := 0 to Cnt do
      Add2DPoint(14, W.ClipPoints[I]);
    if (W.ClippingBoundaryType <> 1) and (Cnt > 0) and (not IsEqualF2DPoints(W.ClipPoints[0], W.ClipPoints[Cnt])) then
      Add2DPoint(14, W.ClipPoints[0]);
  end;
  Result := True;
end;

procedure TsgCADtoDXF.ExportTablesAPPID;
begin
  BeginTable(nil, sTableAPPID);
  // Default entry ACAD
  AddCommonTableGroup(nil, sTableAPPID, 'RegApp', sACADXDataAppName, cHandle_5, 0);
  if Version < acR2007 then
    AddCommonTableGroup(nil, sTableAPPID, 'RegApp', sACADXDataAttribAppName, cHandle_5, 0);
  if XDataAppName <> '' then
    AddCommonTableGroup(nil, sTableAPPID, 'RegApp', XDataAppName, cHandle_5, 0);
  EndTable;
end;

procedure TsgCADtoDXF.ExportTablesBLOCK_RECORD;
var
  vBlock: TsgDXFBlock;
begin
  BeginTable(nil, sTableBLOCK_RECORD);
  // Default entry *MODEL_SPACE and *PAPER_SPACE
  ProcBlockRecord(ExportCADImage.Layouts[0].PaperSpaceBlock, GetModelSpaceName, nil);
  if GetPaperLayout <> nil then
    vBlock := GetPaperLayout.PaperSpaceBlock
  else
    vBlock := nil;
  ProcBlockRecord(vBlock, GetPaperSpaceName, nil);
  // BLOCK_RECORDs
  ApplyBlocksByProc(ProcBlockRecord);
  EndTable;
end;

procedure TsgCADtoDXF.ExportTablesDIMSTYLE;

  function ExportDimDtyle(ADimStyle: TsgDXFDimensionStyle): Boolean;

    function AddReference(const ARefCode: Integer; AEntity: TsgDXFEntity): UInt64;
    begin
      Result := 0;
      if (AEntity <> nil) then
      begin
        Result := GetHandleByEntity(AEntity);
        if Result > 0 then
          AddHexInt(ARefCode, Result);
//      else
//        AddString(ARefCode, '0');
      end;
    end;

    procedure ExportArrow(ADimBlk, ADimBlk1, ADimBlk2, ADimLrBlk: TsgDXFEntity);
      procedure CheckBlock(var ABlock: TsgDXFEntity);
      begin
        if (ABlock <> nil) and (ABlock.EntName = sgDimensionArrowTypeNames[datClosedfilled]) then
          ABlock := nil;
      end;
    begin
      CheckBlock(ADimBlk);
      CheckBlock(ADimBlk1);
      CheckBlock(ADimBlk2);
      CheckBlock(ADimLrBlk);
      AddReference(341, ADimLrBlk);
      AddReference(342, ADimBlk);
      AddReference(343, ADimBlk1);
      AddReference(344, ADimBlk2);
    end;


  begin
    AddCommonTableGroup(ADimStyle, sTableDIMSTYLE, 'DimStyle', ADimStyle.Name, cHandle_105, 0{ADimDtyle.Flags});
    AddFloat(40, ADimStyle.Scale);
    AddFloat(41, ADimStyle.ArrowSize);
    AddFloat(42, ADimStyle.ExtLineOffset);
    AddFloat(44, ADimStyle.ExtLineExt);
    AddInt(73, Ord(ADimStyle.DIMTIH));
    AddInt(74, Ord(ADimStyle.DIMTOH));
    AddInt(75, Ord(ADimStyle.DIMSE1));
    AddInt(76, Ord(ADimStyle.DIMSE2));
    AddInt(77, Ord(ADimStyle.TextPosVert));
    AddFloat(140, ADimStyle.TextHeight);
    AddFloat(141, ADimStyle.SizeCenterMark);
    AddFloat(144, ADimStyle.DIMLFAC);
    AddFloat(147, ADimStyle.TextOffset);
    AddInt(Integer_173, Ord(ADimStyle.DIMSAH));
    AddInt(Integer_174, ADimStyle.DIMTIX);
    AddInt(Integer_176, ColorToDXF(ADimStyle.DIMCLRD));
    AddInt(177, ColorToDXF(ADimStyle.DIMCLRE));
    AddInt(178, ColorToDXF(ADimStyle.DIMCLRT));
    AddInt(281, Ord(ADimStyle.DIMSD1));
    AddInt(282, Ord(ADimStyle.DIMSD2));
    AddInt(Integer_271, ADimStyle.DIMDEC);
    AddReference(340, ADimStyle.TextStyle);
    ExportArrow(TsgDXfDimStyleAccess(ADimStyle).GetBlocks(vnDIMBLK),
      TsgDXfDimStyleAccess(ADimStyle).GetBlocks(vnDIMBLK1),
      TsgDXfDimStyleAccess(ADimStyle).GetBlocks(vnDIMBLK2),
      TsgDXfDimStyleAccess(ADimStyle).GetBlocks(vnDIMLRBLK));
    AddInt(371, CorrectLineWeight(ADimStyle.DIMLWD, False));
    AddInt(372, CorrectLineWeight(ADimStyle.DIMLWE, False));
    Result := True;
  end;
var
  I: Integer;
  vDimStyles: TsgDXFTable;
begin
  vDimStyles := TsgDXFTable(ExportCADImage.Converter.Sections[csDimStyles]);
  BeginTable(vDimStyles, sTableDIMSTYLE);
  if Ord(Version) >= Ord(acR2000) then
  begin
    AddInt(cFlag_70, vDimStyles.Count);
    AddSubclassMarker('DimStyleTable');
    AddInt(71, 0);
  end;
  if (vDimStyles = nil) or (vDimStyles.FindEntByName(sStandardName) = nil) then
  begin// Default entry 'STANDARD'
    AddCommonTableGroup(nil, sTableDIMSTYLE, 'DimStyle', sStandardName, cHandle_105, 0);
    AddString(340, '0');
  end;
  if vDimStyles <> nil then
    for I := 0 to vDimStyles.Count - 1 do
      ExportDimDtyle(TsgDXFDimensionStyle(vDimStyles.Entities[I]));
  EndTable;
end;

procedure TsgCADtoDXF.ExportTablesLAYER;
var
  I: Integer;

  function ExportLayer(ALayer: TsgDXFLayer): Boolean;
  var
    vName: string;
  begin
    Result := False;
    vName := ExtractName(ALayer.Name);
    if IsNameInternal(vName) then
      Exit;
    AddCommonTableGroup(ALayer, sTableLAYER, 'Layer', vName,
       cHandle_5, GetFlagsByName(ALayer.Flags, ALayer.Name));
    // Add Color and Visible properties (with correcting for 'ByLayer' color)
    if ALayer.Color = clByLayer then
    begin
      if ALayer.Visible then
        AddInt(62, 7)
      else
        AddInt(62, -7);// Black/White
    end
    else
      AddDXFColor(ALayer.ColorCAD, ALayer.Visible);
    if ALayer.LineType <> nil then
      AddLineType(ALayer.LineType)
    else
      if Ord(Version) <= Ord(acR12) then
        AddString(6, sContinuous);
    if Ord(Version) > Ord(acR14) then
    begin
      // The 'DEFPOINTS'-layer cannot be plotted
      if AnsiUpperCase(ALayer.Name) <> sLayerDefPoints then
        AddInt(290, Ord(ALayer.IsPlotting))
      else
        AddInt(290, 0);
      AddLineWeight(ALayer.LineWeight);
      AddString(390, '0');// reference to 'ACDBPLACEHOLDER'
    end;
    Result := True;
  end;
begin
  BeginTable(ExportCADImage.Converter.Sections[csLayers], sTableLAYER);
  // Default entry 0
  if TsgDXFTable(ExportCADImage.Converter.Sections[csLayers]).FindEntByName('0') = nil then
  begin
    AddCommonTableGroup(nil, sTableLAYER, 'Layer', '0', cHandle_5, 0);
    AddInt(62, clDXFBlackWhite);
    AddString(6, sContinuous);
    if Ord(Version) > Ord(acR14) then
    begin
      AddInt(370, -3);// Lineweight
      AddString(390, '0');// reference to 'ACDBPLACEHOLDER'
    end;
  end;
  // Layers
  if ExportCADImage.Converter.Sections[csLayers] <> nil then
    for I := 0 to ExportCADImage.Converter.Counts[csLayers] - 1 do
      ExportLayer(TsgDXFLayer(ExportCADImage.Converter.Layers[I]));
  EndTable;
end;

procedure TsgCADtoDXF.ExportTablesLTYPE;
var
  vHasByBlock, vHasByLayer: Boolean;
  vLType: TsgDXFLineType;

  procedure ExportLType(ALType: TsgDXFLineType);
  var
    J, vCount: Integer;
    vLen: Double;
    vDescriptiveText: string;
    vElement: TsgLTypeElement;
    vIndex: UInt64;
  begin
    AddCommonTableGroup(ALType, sTableLTYPE, 'Linetype', ExtractName(ALType.Name),
      cHandle_5, GetFlagsByName(ALType.Flags, ALType.Name));
    if not vHasByBlock then vHasByBlock := AnsiUpperCase(ALType.Name) = AnsiUpperCase(sByBlock);
    if not vHasByLayer then vHasByLayer := AnsiUpperCase(ALType.Name) = AnsiUpperCase(sByLayer);
    vCount := ALType.Lines.ElementsCount;
    vDescriptiveText := GenLTypeDiscriptText(ALType, vLen);
    AddString(3, vDescriptiveText);
    AddInt(72, 65);
    AddInt(73, vCount);
    AddFloat(40, vLen);
    for J := 0 to vCount - 1 do
    begin
      vElement := ALType.Lines.Elements[J]^;
      AddFloat(49, vElement.Dash);
      if Ord(Version) > Ord(acR12) then
      begin
        AddInt(74, vElement.ComplexType);// 0 = no embedded shape/text
        if vElement.ComplexType > 0 then
        begin
          AddInt(75, vElement.ShapeNumber);
          vIndex := GetHandleByEntity(vElement.Style);
          if vIndex > 0 then
            AddHexInt(340, vIndex)
          else
            AddHexInt(340, 0);
          AddFloat(46, vElement.Scale);
          AddFloat(50, vElement.Rotation);
          AddFloat(44, vElement.XOffset);
          AddFloat(45, vElement.YOffset);
          if vElement.ComplexType and 2 <> 0 then
            AddString(9, vElement.Text);
        end;
      end;
    end;
  end;
var
  I: Integer;
begin
  BeginTable(ExportCADImage.Converter.Sections[csLTypes], sTableLTYPE);

  vLType := TsgDXFLineType(ExportCADImage.Converter.Sections[csLTypes].FindEntByName(sContinuous));
  if Assigned(vLType) then
  begin
    // first write Continuous !!!
    ExportLType(vLType);
  end;

  vHasByBlock := False;
  vHasByLayer := False;
  if ExportCADImage.Converter.Sections[csLTypes] <> nil then
    for I := 0 to ExportCADImage.Converter.Counts[csLTypes] - 1 do
    begin
      // write LTypes excluding Continuous
      if vLType <> ExportCADImage.Converter.LTypes[I] then
        ExportLType(TsgDXFLineType(ExportCADImage.Converter.LTypes[I]));
    end;
  // Default entry ByBlock, ByLayer
  vLType := TsgDXFLineType.Create;
  if not vHasByBlock then
  begin
    vLType.Name := sByBlock;
    ExportLType(vLType);
  end;
  if not vHasByLayer then
  begin
    vLType.Name := sByLayer;
    ExportLType(vLType);
  end;
  vLType.Free;
  EndTable;
end;

procedure TsgCADtoDXF.ExportTablesSTYLE;
  procedure ExportStyle(AStyle: TsgDXFStyle);
  var
    vName: string;
  begin
    if AStyle.Flags and 1 <> 0 then
      vName := ''
    else
      vName := AStyle.Name;
    AddCommonTableGroup(AStyle, sTableSTYLE, 'TextStyle', ExtractName(vName),
      cHandle_5, GetFlagsByName(AStyle.Flags, vName));
    AddFloat(40, AStyle.FixedHeight);
    AddFloat(41, AStyle.WidthFactor);
    AddFloat(50, AStyle.ObliqueAngle);
    AddInt(71, AStyle.TextGenFlags);
    AddFloat(42, AStyle.LastHeightUsed);
    AddString(3, AStyle.PrimaryFont);
    AddString(4, AStyle.BigFont);
    if Version >= acR14 then
      ExportExtendedData(AStyle);
  end;
var
  I: Integer;
begin
  BeginTable(ExportCADImage.Converter.Sections[csStyles], sTableSTYLE);
  if (ExportCADImage.Converter.Sections[csStyles] = nil)
    or (TsgDXFTable(ExportCADImage.Converter.Sections[csStyles]).FindEntByName(sStandardName) = nil) then
  begin// Default entry 'STANDARD'
    AddCommonTableGroup(nil, sTableSTYLE, 'TextStyle', sStandardName, cHandle_5, 0);
    AddFloat(40, 0);
    AddFloat(41, 1);
    AddFloat(50, 0);
    AddInt(71, 0);
    AddFloat(42, 10.0);
    AddString(3, sDefaultSHXFont);
    AddString(4, '');// no bigfont
  end;
  if ExportCADImage.Converter.Sections[csStyles] <> nil then
    for I := 0 to ExportCADImage.Converter.Counts[csStyles] - 1 do
      ExportStyle(TsgDXFStyle(ExportCADImage.Converter.Styles[I]));
  EndTable;
end;

procedure TsgCADtoDXF.ExportTablesVPORT;
  procedure ExportVPort(AVPort: TsgDXFVPort);
  var
    V: TsgDXFViewPort;
  begin
    V := CreateDefaultViewPort(DoHandle);
    try
      AddCommonTableGroup(AVPort, sTableVPORT, 'Viewport', sActiveVPort{AVPort.Name}, cHandle_5, 0{AVPort.Flags});
      Add2DPoint(10, cnstF2DPointZero);
      Add2DPoint(11, MakeF2DPoint(1,1));
      if Ord(Version) <= Ord(acR12) then
        Add2DFlatPoint(12, V.MSpaceCenter)
      else
        Add3DPoint(12, V.MSpaceCenter);
      Add2DPoint(13, cnstF2DPointZero);
      Add2DPoint(14, MakeF2DPoint(1,1));
      Add2DPoint(15, MakeF2DPoint(1,1));
      Add3DPoint(16, V.ViewDirection);
      Add3DPoint(17, V.ViewTarget);
      AddFloat(40, V.PSpaceHeight);
      AddFloat(41, V.PSpaceWidth/V.PSpaceHeight);
      AddFloat(42, 50);
      AddFloat(43, V.FrontClipPlane);
      AddFloat(44, V.BackClipPlane);
      AddFloat(50, 0);
      AddFloat(51, V.ViewTwistAngle);
      AddInt(71, 0);
      AddInt(72, cntViewPortCircleZoomPercent);
      AddInt(73, 1);
      AddInt(74, 1);
      AddInt(75, 0);
      AddInt(76, 0);
      AddInt(77, 0);
      AddInt(78, 0);
    finally
      V.Free;
    end;
  end;
begin
  BeginTable(nil, sTableVPORT);
  ExportVPort(nil);
  EndTable;
end;

procedure TsgCADtoDXF.ExportTablesVIEW;
begin
  BeginTable(nil, sTableVIEW);
  EndTable;
end;

procedure TsgCADtoDXF.ExportTablesUCS;
begin
  BeginTable(nil, sTableUCS);
  EndTable;
end;

procedure TsgCADtoDXF.ExportSectionBLOCKS;
begin
  BeginSection('BLOCKS');
  // Default entry *MODEL_SPACE and *PAPER_SPACE ("*" => "$" for R12)
  ProcBlock(nil, GetModelSpaceName, nil);
  ProcBlock(nil, GetPaperSpaceName, nil);
  // Blocks
  ApplyBlocksByProc(ProcBlock);
  EndSection;
end;

procedure TsgCADtoDXF.ExportSectionCLASSES;
var
  vInstCount: Integer;

  vDict: TsgDXFDictionary;
  vDictItem: TsgDXFOwneredItem;


  procedure AddCommonCLASSGroup(const ARecordName, AClassName, AAppName: string;
    const AFlags, AInstCount: Integer; const AIsEntity: Boolean);
  begin
    AddString(0, 'CLASS');
    AddString(1, ARecordName);
    AddString(2, cntAcDb + AClassName);
    AddString(3, AAppName);
    AddInt(90, AFlags);
    if Version >= acR2004 then
      AddInt(91, AInstCount);// Instance count for a custom class
    AddInt(280, 0);// Was-a-proxy flag. Set to 1 if class was not loaded when this DXF file was created, and 0 otherwise
    AddInt(281, Ord(AIsEntity));
  end;
begin
  if Ord(Version) <= Ord(acR12) then Exit;
  BeginSection('CLASSES');
  // Default classes
  AddCommonCLASSGroup('IMAGE', 'RasterImage', 'ISM', 2175{127}, 1, True);
  AddCommonCLASSGroup('IMAGEDEF', 'RasterImageDef', 'ISM', 0, 1, False);
  AddCommonCLASSGroup('WIPEOUT', 'Wipeout', '"WipeOut"', 2175{127}, 1, True);
  AddCommonCLASSGroup('WIPEOUTVARIABLES', 'WipeoutVariables', '"WipeOut"', 0, 1, False);
  AddCommonCLASSGroup('MPOLYGON', 'MPolygon', '"AcMPolygonObj15"', 3071, 1, True);
  vInstCount := ExportCADImage.Converter.Counts[csTableStyles];
  if vInstCount > 0 then
  begin
    AddCommonCLASSGroup('TABLESTYLE', 'TableStyle', 'ObjectDBX Classes', 2047,
      vInstCount, False);
    AddCommonCLASSGroup('ACAD_TABLE', 'Table', 'ObjectDBX Classes', 1025, 1, True);
  end;

  vDict := TsgDXFDictionary(ExportCADImage.Converter.Sections[csObjects].FindEntByName(cnstDictionary));
  if Assigned(vDict) then
  begin
    vDictItem := TsgDXFOwneredItem(vDict.FindEntByName('ACAD_PLOTSETTINGS'));
    if Assigned(vDictItem) then
    begin
      AddCommonCLASSGroup('PLOTSETTINGS', 'PlotSettings', 'ObjectDBX Classes', 0,
        vDictItem.Count, False);
    end;

    vDictItem := TsgDXFOwneredItem(vDict.FindEntByName('ACAD_IMAGE_VARS'));
    if Assigned(vDictItem)then
    begin
      AddCommonCLASSGroup('RASTERVARIABLES', 'RasterVariables', 'ISM', 0,
        1, False);
    end;
  end;
  if FContentOleByImage then
  begin
    AddCommonCLASSGroup('DICTIONARYVAR', 'DictionaryVar', 'ObjectDBX Classes', 0,
      1, False);
  end;
  EndSection;
end;

procedure TsgCADtoDXF.ExportSectionENTITIES;

  procedure IterateLayout(ALayout: TsgDXFLayout);
  var
    I: Integer;
    V: TsgDXFViewPort;
    vInserts: TList;
  begin
    FHasViewPortWindow := False;
    if ALayout = nil then Exit;
    FPaperMode := not ALayout.IsModel;
    for I := 0 to ALayout.Count - 1 do
      DoExport(ALayout.Entities[I]);

    vInserts := ExpSGInsert(ALayout);
    try
      if Assigned(vInserts) then
        for I := 0 to vInserts.Count - 1 do
          DoExport(vInserts[I]);
    finally
      FreeList(vInserts);
    end;
    if not ALayout.IsModel and not FHasViewPortWindow then
    begin
      // Add VIEWPORT as ACAD window
      V := CreateViewPortAsACADWindow(ALayout);
      try
        DoExport(V);
      finally
        V.Free;
      end;
    end;
  end;
begin
  BeginSection('ENTITIES');
  IterateLayout(ExportCADImage.Layouts[0]);
  IterateLayout(GetPaperLayout);
  FPaperMode := False;
  EndSection;
end;

function TsgCADtoDXF.ExportSectionHEADER: Integer;
var
  vCPName: string;
  vExts: TFRect;

  procedure ExportReferens(const AName: TsgDimNameVal; ArrowType: TsgDimArrowType);
  var
    vNameValue, vValue: string;
  begin
    case AName of
      vnDIMBLK1:  vNameValue := '$DIMBLK1';
      vnDIMBLK2:  vNameValue := '$DIMBLK2';
      vnDIMLRBLK: vNameValue := '$DIMLDRBLK';
    else
      vNameValue := '$DIMBLK';
    end;
    if (ArrowType = datUndefined) or (ArrowType = datClosedfilled) then
      vValue := ''
    else
      vValue := sgDimensionArrowTypeNames[ArrowType];
    AddString(9, vNameValue);
    AddString(1, vValue);
  end;

  procedure ExportArrows(Arrows: TsgArrows);
  begin
    if (Arrows.Blk1 = Arrows.Blk2) then
    begin
      if Arrows.Blk = datUndefined then
        Arrows.Blk := datClosedfilled;
      ExportReferens(vnDIMBLK, Arrows.Blk);
      ExportReferens(vnDIMBLK1, datClosedfilled);
      ExportReferens(vnDIMBLK2, datClosedfilled);
    end
    else
    begin
      ExportReferens(vnDIMBLK, datClosedfilled);
      ExportReferens(vnDIMBLK1, Arrows.Blk1);
      ExportReferens(vnDIMBLK2, Arrows.Blk2);
    end;
    ExportReferens(vnDIMLRBLK, Arrows.LrBlk);
  end;

begin
  Result := 0;
  if OutFileInfo then
  begin
    AddString(999, cnstCreatedFileInfo);
    AddString(999, TsgCADImageEx(ExportCADImage).FileInfo);
  end;
  BeginSection('HEADER');
  AddString(9, '$ACADVER');
  AddString(1, GetStringDXFVersion);
  AddString(9, '$DWGCODEPAGE');
  vCPName := sgDXFCodePageName(ExportCADImage.Converter.HeadVarStruct.CodePage);
  AddString(3, vCPName);
  if ExportCADImage.Converter.HeadVarStruct.CEColor.Active = acIndexColor then
  begin
    if ExportCADImage.Converter.HeadVarStruct.CEColor.Color <> clDXFByLayer then
    begin
      AddString(9, '$CECOLOR');
      AddInt(62, ExportCADImage.Converter.HeadVarStruct.CEColor.Color);
    end;
  end;

  AddString(9, '$CLAYER');
  AddString(8, ExportCADImage.Converter.HeadVarStruct.CLayer);
  AddString(9, '$CELTYPE');
  AddString(6, ExportCADImage.Converter.HeadVarStruct.CELType);
  AddString(9, '$CELTSCALE');
  AddFloat(40, ExportCADImage.Converter.HeadVarStruct.CELTScale);
  AddString(9, '$CELWEIGHT');
  AddInt(370, CorrectLineWeight(ExportCADImage.Converter.HeadVarStruct.CELWeight, False));
  AddString(9, '$DIMALT');
  AddInt(cFlag_70, Ord(ExportCADImage.Converter.HeadVarStruct.DimProps.Alt));
  AddString(9, '$DIMALTF');
  AddFloat(40, ExportCADImage.Converter.HeadVarStruct.DimProps.AltF);
  AddString(9, '$DIMAPOST');
  AddString(1, ExportCADImage.Converter.HeadVarStruct.DimProps.APost);
  AddString(9, '$DIMSCALE');//
  AddFloat(40, ExportCADImage.Converter.HeadVarStruct.DimProps.Scale);//
  AddString(9, '$DIMASZ');
  AddFloat(40, ExportCADImage.Converter.HeadVarStruct.DimProps.Asz);
  AddString(9, '$DIMCLRD');
  AddInt(70, ColorToDXF(ExportCADImage.Converter.HeadVarStruct.DimProps.Clrd));
  AddString(9, '$DIMCLRE');
  AddInt(70, ColorToDXF(ExportCADImage.Converter.HeadVarStruct.DimProps.Clre));
  AddString(9, '$DIMCLRT');
  AddInt(70, ColorToDXF(ExportCADImage.Converter.HeadVarStruct.DimProps.Clrt));
  AddString(9, '$DIMEXE');
  AddFloat(40, ExportCADImage.Converter.HeadVarStruct.DimProps.Exe);
  AddString(9, '$DIMEXO');
  AddFloat(40, ExportCADImage.Converter.HeadVarStruct.DimProps.Exo);
  AddString(9, '$DIMGAP');
  AddFloat(40, ExportCADImage.Converter.HeadVarStruct.DimProps.Gap);
  AddString(9, '$DIMLFAC');
  AddFloat(40, ExportCADImage.Converter.HeadVarStruct.DimProps.LFac);
  AddString(9, '$DIMDEC');
  AddInt(70, ExportCADImage.Converter.HeadVarStruct.DimProps.Dec);
  AddString(9, '$DIMTAD');
  AddInt(70, ExportCADImage.Converter.HeadVarStruct.DimProps.Tad);
  AddString(9, '$DIMCEN');//
  AddFloat(40, ExportCADImage.Converter.HeadVarStruct.DimProps.Cen);//
  AddString(9, '$DIMTIH');
  AddInt(70, Ord(ExportCADImage.Converter.HeadVarStruct.DimProps.Tih));
  AddString(9, '$DIMTIX');
  AddInt(70, ExportCADImage.Converter.HeadVarStruct.DimProps.Tix);
  AddString(9, '$DIMTOH');
  AddInt(70, Ord(ExportCADImage.Converter.HeadVarStruct.DimProps.Toh));
  AddString(9, '$DIMSE1');
  AddInt(70, Ord(ExportCADImage.Converter.HeadVarStruct.DimProps.SE1));
  AddString(9, '$DIMSE2');
  AddInt(70, Ord(ExportCADImage.Converter.HeadVarStruct.DimProps.SE2));
  AddString(9, '$DIMSD1');
  AddInt(70, Ord(ExportCADImage.Converter.HeadVarStruct.DimProps.SD1));
  AddString(9, '$DIMSD2');
  AddInt(70, Ord(ExportCADImage.Converter.HeadVarStruct.DimProps.SD2));
  AddString(9, '$DIMLWD');
  AddInt(70, CorrectLineWeight(ExportCADImage.Converter.HeadVarStruct.DimProps.LwD, False));
  AddString(9, '$DIMLWE');
  AddInt(70, CorrectLineWeight(ExportCADImage.Converter.HeadVarStruct.DimProps.LwE, False));
  AddString(9, '$DIMPOST');
  AddString(1, ExportCADImage.Converter.HeadVarStruct.DimProps.POST);
  AddString(9, '$DIMSAH');
  AddInt(70, Ord(ExportCADImage.Converter.HeadVarStruct.DimProps.Sah));
  ExportArrows(ExportCADImage.Converter.HeadVarStruct.DimProps.Arrows);
  AddString(9, '$DIMSTYLE');
  AddString(2, ExportCADImage.Converter.HeadVarStruct.DimStyle);
  AddString(9, '$DIMTXT');
  AddFloat(40, ExportCADImage.Converter.HeadVarStruct.DimProps.Txt);
  AddString(9, '$DIMTXSTY');
  AddString(7, ExtractName(ExportCADImage.Converter.HeadVarStruct.DimTextStyle));
  AddString(9, '$TEXTSIZE');
  AddFloat(40, ExportCADImage.Converter.HeadVarStruct.TextSize);
  AddString(9, '$TEXTSTYLE');
  AddString(7, ExtractName(ExportCADImage.Converter.HeadVarStruct.TextStyle));
  if Ord(Version) > Ord(acR12) then
  begin
    // Setting dummy value of next available handle
    AddString(9, '$HANDSEED');
    Result := FStream.Position;// $HANDSEED position
    AddString(5, Format('%16d', [0]));//digits = cnstDigitsInHandle
  end;
  AddString(9, '$FILLETRAD');
  AddFloat(40, ExportCADImage.Converter.HeadVarStruct.FilletRadius);
  AddString(9, '$INSUNITS');
  AddInt(70, ExportCADImage.Converter.HeadVarStruct.InsUnits);
  vExts := ExportCADImage.Extents;
  AddString(9, '$LIMMIN');
  Add2DPoint(10, MakeF2DPoint(vExts.Left, vExts.Bottom));
  AddString(9, '$LIMMAX');
  Add2DPoint(10, MakeF2DPoint(vExts.Right, vExts.Top));
  AddString(9, '$LTSCALE');
  AddFloat(40, ExportCADImage.Converter.LTScale);
  AddString(9, '$MEASUREMENT');
  AddInt(cFlag_70, Integer(ExportCADImage.Converter.HeadVarStruct.Measurement));
  AddString(9, cnstAttMode);
  AddInt(cFlag_70, Integer(ExportCADImage.Converter.HeadVarStruct.AttMode));
  AddString(9, '$PDMODE');
  AddInt(cFlag_70, ExportCADImage.Converter.HeadVarStruct.PointDisplayMode);
  AddString(9, '$PDSIZE');
  AddFloat(40, ExportCADImage.Converter.HeadVarStruct.PointDisplaySize);
  if (ExportCADImage.Converter.LayoutsCount > 2) and (ExportCADImage.Layouts[1] <> nil) then
  begin
    vExts := ExportCADImage.Layouts[1].Box;
    AddString(9, '$PLIMMIN');
    Add2DPoint(10, MakeF2DPoint(vExts.Left, vExts.Bottom));
    AddString(9, '$PLIMMAX');
    Add2DPoint(10, MakeF2DPoint(vExts.Right, vExts.Top));
  end;
  AddString(9, '$TILEMODE');
  AddInt(cFlag_70, Ord(ExportCADImage.CurrentLayout.IsModel));
  AddString(9, '$UCSORG');
  Add3DPoint(10, ExportCADImage.Converter.HeadVarStruct.UCSORG);
  AddString(9, '$UCSXDIR');
  Add3DPoint(10, ExportCADImage.Converter.HeadVarStruct.UCSXDIR);
  AddString(9, '$UCSYDIR');
  Add3DPoint(10, ExportCADImage.Converter.HeadVarStruct.UCSYDIR);
  AddString(9, '$INSBASE');
  Add3DPoint(10, ExportCADImage.Converter.HeadVarStruct.InsBase);
  EndSection;
end;

procedure TsgCADtoDXF.ExportSectionOBJECTS;
const
  cnstDictSubClass = 'Dictionary';
  cnstDictionaryVariables = 'DictionaryVariables';

  function AddDictRefs(const AName: string; const AHandle: UInt64): UInt64;
  begin
    Result := AHandle;
    AddString(3, AName);
    AddHexInt(350, Result);
  end;

  function AddDict(const AName, ASubClassName: string; const AHandle: UInt64): UInt64;
  begin
    Result := AHandle;
    AddString(0, AName);
    AddHexInt(cHandle_5, Result);
    AddSubclassMarker(ASubClassName);
  end;

  procedure ExportPlotSettings(APlotSettings: TsgDXFPlotSettings;
    AInline: Boolean = False; AIsModel: Boolean = False;
    AOwnerDictHandle: UInt64 = 0);
  var
    vPlotData: PsgPlotSettingsData;
    vPlotFlag: Integer;
  begin
    vPlotData := TsgDXFPlotSettingsAccess(APlotSettings).PlotData;
    if not AInline then
    begin
      AddString(0, cnstObjectsPLOTSETTINGS);
      AddHexInt(cHandle_5, APlotSettings.Handle);
      if AOwnerDictHandle <> 0 then
        AddHexInt(cParentHandle_330, AOwnerDictHandle);
    end;
    AddSubclassMarker(sPlotSettingsMarker);
    AddString(1,vPlotData^.PageSetupName);
    AddString(2,vPlotData^.PrintOrConfigName);
    AddString(4,vPlotData^.PaperSize);
    AddString(6,vPlotData^.PlotViewName);
    AddFloat(40,vPlotData^.UnprintableMargin.Left);
    AddFloat(41,vPlotData^.UnprintableMargin.Bottom);
    AddFloat(42,vPlotData^.UnprintableMargin.Right);
    AddFloat(43,vPlotData^.UnprintableMargin.Top);

    AddFloat(44,vPlotData^.PlotPaperSize.X);
    AddFloat(45,vPlotData^.PlotPaperSize.Y);
    AddFloat(46,vPlotData^.PlotOrigin.X);
    AddFloat(47,vPlotData^.PlotOrigin.Y);
    AddFloat(48,vPlotData^.PlotWindowAreaMin.X);
    AddFloat(49,vPlotData^.PlotWindowAreaMin.Y);

    vPlotFlag := ConvertPlotLayoutFlagsToInteger(vPlotData^.PlotLayoutFlags);
    if AIsModel then
      vPlotFlag := vPlotFlag or 1024;
    AddInt(70, vPlotFlag);
    AddInt(72, Integer(vPlotData^.PlotPaperUnits));
    AddInt(73, Integer(vPlotData^.PlotRotation));
    AddInt(74, Integer(vPlotData^.PlotType));
    AddInt(75, vPlotData^.StandardScaleType);
    AddInt(76, vPlotData^.ShadePlotMode);
    AddInt(77, vPlotData^.ShadePlotResolutionLevel);
    AddInt(78, vPlotData^.ShadePlotCustomDPI);

    AddFloat(140,vPlotData^.PlotWindowAreaMax.X);
    AddFloat(141,vPlotData^.PlotWindowAreaMax.Y);
    AddFloat(142,vPlotData^.NumeratorOfCustomPrintScale);
    AddFloat(143,vPlotData^.DenominatorOfCustomPrintScale);
    AddFloat(147,vPlotData^.FloatingPointScaleFactor);
    AddFloat(148,vPlotData^.PaperImageOrigin.X);
    AddFloat(149,vPlotData^.PaperImageOrigin.Y);
  end;

  procedure ExportLayout(ALayout: TsgDXFLayout; AIndex: Integer);
  var
    vBox: TFRect;
  begin
    AddString(0, cntClassDXFLAYOUT);
    AddHandle(ALayout, cHandle_5, 0);
    ExportPlotSettings(ALayout.PlotSettings, True, ALayout.IsModel);
    AddSubclassMarker('Layout');
    AddString(1, ALayout.Name);
    AddInt(70, 1);
    AddInt(71, AIndex);
    vBox := ALayout.Box;
    Add2DPoint(10, MakeF2DPoint(vBox.Left, vBox.Bottom));
    Add2DPoint(11, MakeF2DPoint(vBox.Right, vBox.Top));
    Add3DPoint(12, cnstFPointZero);
    Add3DPoint(14, MakeFPoint(vBox.Left, vBox.Bottom, vBox.Z1));
    Add3DPoint(15, MakeFPoint(vBox.Right, vBox.Top, vBox.Z2));
    AddFloat(146,0);
    Add3DPoint(13, cnstFPointZero);
    Add3DPoint(16, MakeFPoint(1,0,0));
    Add3DPoint(17, MakeFPoint(0,1,0));
    AddInt(76, 0);
    AddHexInt(cParentHandle_330, GetHandleByEntity(ALayout.PaperSpaceBlock));// !!!
  end;

  procedure ExportImageDef(const AImageDef: TsgDXFImageDef;
    const AOwnerHandle: UInt64 = 0; const APicture: TPicture = nil);
  var
    vPicture: TPicture;
  begin
    if (AImageDef.Picture = nil) and (APicture = nil) then
      Exit;
    AddString(0, cntClassDXFIMAGEDEF);
    AddHandle(AImageDef, cHandle_5, AOwnerHandle);
    AddSubclassMarker('RasterImageDef');
    AddInt(90, 0);
    AddString(1, AImageDef.FileName);
    vPicture := AImageDef.Picture;
    if APicture <> nil then
      vPicture := APicture;
    if vPicture.Graphic = nil then
    begin
      Add2DPoint(10, cnstF2DPointZero);
      Add2DPoint(11, cnstF2DPointZero);
    end
    else
    begin
      Add2DPoint(10, MakeF2DPoint(vPicture.Graphic.Width , vPicture.Graphic.Height));
      Add2DPoint(11, MakeF2DPoint(1 / vPicture.Graphic.Width, 1 / vPicture.Graphic.Height));
    end;
    AddInt(280, 1);
    AddInt(281, 0);//2);
  end;

var
  I, K, vLayoutsCount, vTableStylesCount: Integer;
  vMLineStylesCount: Integer;
  J: TsgAcadTableCellType;
  vOwnerTblStyleHandle: UInt64;
  vOwnerPlotSettingsHandle: UInt64;
  vOwnerRasterVariablesHandle: UInt64;
  vAcDbVariableDictionaryHandle: UInt64;
  vOleFrameHandle: UInt64;
  vDicHandle: UInt64;
  vGroupHandle, vMatHandle, vWipeoutHandle, vMLineHandle, vLayoutHandle: UInt64;
  vEnt: TsgDXFEntity;
  vAcadTable: TsgDXFAcadTableStyle;
  vCellStyle: TsgAcadTableCellStyle;
  vObjects: TsgDXFEntity;
  vPlotSettingsDictionary: TsgDXFEntity;
  vRasterVariablesDictionary: TsgDXFEntity;
  vAcDbVariableDictionary: TsgDXFEntity;
  vOleFrame: TsgDXFEntity;
  vRasterVariables: TsgCADRasterVariables;
  vImageDefHandle: UInt64;
begin
  vOwnerTblStyleHandle := 0;
  vLayoutHandle := 0;
  vOwnerPlotSettingsHandle := 0;
  vOwnerRasterVariablesHandle:= 0;
  vAcDbVariableDictionaryHandle := 0;
  vPlotSettingsDictionary := nil;
  vAcDbVariableDictionary := nil;
  vLayoutsCount := ExportCADImage.Converter.LayoutsCount;
  vTableStylesCount := ExportCADImage.Converter.Counts[csTableStyles];
  BeginSection(cnstSectionOBJECTS);
  // Default entry "NamedObject dictionary"
  vDicHandle := AddDict(cnstDictionary, cnstDictSubClass, DoHandle);
  vImageDefHandle := cnstBadHandle;
  if (ImageDefList.Count > 0) or (ExportCADImage.Converter.Counts[csImageDefs] > 0) then
    vImageDefHandle := AddDictRefs(sAcadImageDict, DoHandle);
  vGroupHandle := AddDictRefs(sAcadGroupDictionary, DoHandle);
  vMatHandle := AddDictRefs(sAcadMaterialDictionary, DoHandle);
  vWipeoutHandle := AddDictRefs(sAcadWipeOutVarsDictionary, DoHandle);
  vMLineHandle := AddDictRefs(sAcadMLineStyleDictionary, DoHandle);
  vObjects := ExportCADImage.Converter.Sections[csObjects];

  if Assigned(vObjects) then
  begin
    // plotsettings
    vPlotSettingsDictionary := vObjects.FindEntByName(cnstObjectsPLOTSETTINGS);
    if Assigned(vPlotSettingsDictionary) and (vPlotSettingsDictionary.Count > 0) then
      vOwnerPlotSettingsHandle := AddDictRefs(sAcadPlotSettingsDictionary, DoHandle);
    // rastervariables
    vRasterVariablesDictionary := TsgDXFOwneredItem(vObjects.FindEntByName(sRasterVariables));
    if Assigned(vRasterVariablesDictionary)then
      vOwnerRasterVariablesHandle := AddDictRefs(sAcadImageVars, DoHandle);
    // variabledictionary
    vAcDbVariableDictionary := vObjects.FindEntByName(sAcDbVariableDictionary);
    if Assigned(vAcDbVariableDictionary) then
      vAcDbVariableDictionaryHandle := AddDictRefs(sAcDbVariableDictionary, DoHandle);
  end;

  if (FContentOleByImage) and (vAcDbVariableDictionaryHandle = 0) then
    vAcDbVariableDictionaryHandle := AddDictRefs(sAcDbVariableDictionary, DoHandle);

  // Add table styles only if TableStylesCount > 0 !
  if vTableStylesCount > 0 then
    vOwnerTblStyleHandle := AddDictRefs(sAcadTableStyleDictionary, DoHandle);
  // Add Layouts only if LayoutsCount > 1 !
  if (Ord(Version) > Ord(acR14)) and (vLayoutsCount >= 1) then
    vLayoutHandle := AddDictRefs(sAcadLayoutDictionary, DoHandle);

  AddDict(cnstDictionary, cnstDictSubClass, vGroupHandle);
  AddDict(cnstDictionary, cnstDictSubClass, vMatHandle);
  AddDict(cntClassDXFWIPEOUTVARIABLES, 'WipeoutVariables', vWipeoutHandle);
  AddInt(70, Ord(not ExportCADImage.Converter.HideWipeOuts));

  { MLINESTYLE }

  vMLineStylesCount := ExportCADImage.Converter.Counts[csMLineStyles];
  AddDict(cnstDictionary, cnstDictSubClass, vMLineHandle);
  if vMLineStylesCount = 0 then
  begin
    vMLineHandle := AddDictRefs(sStandardName, DoHandle);
    AddDict(AnsiUpperCase(sMLineStyle), sMLineStyle, vMLineHandle);
    AddString(2, sStandardName);
    AddInt(cFlag_70, 0);
    AddString(3, '');
    AddInt(62, clDXFByLayer);
    AddFloat(51, 90.0);
    AddFloat(52, 90.0);
    AddInt(71, 2);
    AddFloat(49, 0.5);
    AddInt(62, clDXFByLayer);
    AddString(6, sByLayer);
    AddFloat(49, -0.5);
    AddInt(62, clDXFByLayer);
    AddString(6, sByLayer);
  end
  else
  begin
    for I := 0 to vMLineStylesCount - 1 do
    begin
      vEnt := ExportCADImage.Converter.Sections[csMLineStyles].Entities[I];
      AddString(3, TsgMLineStyle(vEnt).Name);
      AddHexInt(350, vEnt.Handle);
    end;
    for I := 0 to vMLineStylesCount - 1 do
    begin
      vEnt := ExportCADImage.Converter.Sections[csMLineStyles].Entities[I];
      AddString(0, AnsiUpperCase(sMLineStyle));
      AddHexInt(cHandle_5, vEnt.Handle);
      AddHexInt(cParentHandle_330, vMLineHandle);
      AddSubclassMarker(sMLineStyle);
      AddString(2, TsgMLineStyle(vEnt).Name);
      AddInt(cFlag_70, TsgMLineStyle(vEnt).Flags);
      AddString(3, '');
      AddInt(62, ColorToDXF(TsgMLineStyle(vEnt).ColorCAD));
      AddFloat(51, 90.0);
      AddFloat(52, 90.0);
      AddInt(71, TsgMLineStyle(vEnt).Count);
      for K := 0 to TsgMLineStyle(vEnt).Count-1 do
      begin
        AddFloat(49, TsgMLineEntry(TsgMLineStyle(vEnt).Entries[K]).Offset);
        AddInt(62, ColorToDXF(TsgMLineEntry(TsgMLineStyle(vEnt).Entries[K]).ColorCAD));
        if Assigned(TsgMLineEntry(TsgMLineStyle(vEnt).Entries[K]).LineType) then
          AddString(6, TsgMLineEntry(TsgMLineStyle(vEnt).Entries[K]).LineType.Name)
        else
          AddString(6, '');
      end;
    end;
  end;

  { TABLESTYLE }
  if vOwnerTblStyleHandle <> 0 then
  begin
    AddDict(cnstDictionary, cnstDictSubClass, vOwnerTblStyleHandle);
    AddInt(281, 1);
    for I := 0 to vTableStylesCount - 1 do
    begin
      vEnt := ExportCADImage.Converter.Sections[csTableStyles].Entities[I];
      AddString(3, TsgDXFAcadTableStyle(vEnt).Name);
      AddHexInt(350, vEnt.Handle);
    end;
    for I := 0 to vTableStylesCount - 1 do
    begin
      vEnt := ExportCADImage.Converter.Sections[csTableStyles].Entities[I];
      AddString(0, cntClassDXFTABLESTYLE);
      AddHexInt(cHandle_5, vEnt.Handle);
      AddHexInt(cParentHandle_330, vOwnerTblStyleHandle);
      AddSubclassMarker('TableStyle');
      vAcadTable := TsgDXFAcadTableStyle(vEnt);
      AddString(3, vAcadTable.Description);
      AddInt(70, vAcadTable.FlowDirection);
      AddInt(71, vAcadTable.Flags);
      AddFloat(40, vAcadTable.HorzCellMargin);
      AddFloat(41, vAcadTable.VertCellMargin);
      AddInt(280, Ord(vAcadTable.TitleSuppressed));
      AddInt(281, Ord(vAcadTable.HeaderSuppressed));
      for J := Low(TsgAcadTableCellType) to High(TsgAcadTableCellType) do
      begin
        vCellStyle := vAcadTable.CellStyle[J];
        if Assigned(vCellStyle.TextStyle) then
          AddString(7, ExtractName(vCellStyle.TextStyle.Name));
        AddFloat(140, vCellStyle.TextHeight);
        AddInt(170, vCellStyle.CellAlignment);
        AddInt(62, ColorToDXF(vCellStyle.TextColor));
        AddInt(63, ColorToDXF(vCellStyle.FillColor));
        AddInt(283, Ord(vCellStyle.BkColorOn));
        //AddInt(90, vCellStyle.DataType); // ??
        //AddInt(91, vCellStyle.UnitType); // ??
        for K := 0 to vCellStyle.BorderCount - 1 do
        begin
          AddInt(K + 274, CorrectLineWeight(vCellStyle.BorderLineWeight[K], False));
          AddInt(K + 284, Ord(vCellStyle.BorderVisible[K]));
          AddInt(K + 64, ColorToDXF(vCellStyle.BorderColor[K]));
        end;
      end;
    end;
  end;
  { LAYOUTS }
  if vLayoutHandle <> 0 then
  begin
    AddDict(cnstDictionary, cnstDictSubClass, vLayoutHandle);
    for I := 0 to vLayoutsCount - 1 do
    begin
      AddString(3, ExportCADImage.Layouts[I].Name);
      AddHexInt(350, ExportCADImage.Layouts[I].Handle);
    end;
    for I := 0 to vLayoutsCount - 1 do
      ExportLayout(ExportCADImage.Layouts[I], I + 1);
  end;
  {RASTERVARIABLE}
  if vOwnerRasterVariablesHandle <> 0 then
  begin
    vRasterVariables := TsgCADRasterVariables(vObjects.FindEntByName(sRasterVariables));
    if Assigned(vRasterVariables) then
    begin
      AddString(0, sRasterVariables);
      AddHexInt(cHandle_5, vOwnerRasterVariablesHandle);
      AddHexInt(cParentHandle_330, vDicHandle);
      AddSubclassMarker('RasterVariables');
      AddInt(90, 0);
      AddInt(70, Ord(vRasterVariables.DisplayImageFrame));
      AddInt(71, Ord(vRasterVariables.ImageDisplayQuality));
      AddInt(72, vRasterVariables.UnitsForInsertingImages);
    end;
  end;
  {AcDbVariableDictionary}
  if vAcDbVariableDictionaryHandle <> 0 then
  begin
    if FContentOleByImage then
    begin
      AddDict(cnstDictionary, cnstDictSubClass, vAcDbVariableDictionaryHandle);
      AddInt(281, 1);
      vOleFrameHandle := DoHandle;
      AddDictRefs(sDictionaryVarOLEFRAME, vOleFrameHandle);
      AddString(0, cnstDictionaryVar);
      AddHexInt(cHandle_5, vOleFrameHandle);
      AddHexInt(cParentHandle_330, vAcDbVariableDictionaryHandle);
      AddString(100, cnstDictionaryVariables);
      AddInt(280, 0);
      AddString(1, '0');
    end
    else
    begin
      AddDict(cnstDictionary, cnstDictSubClass, vAcDbVariableDictionaryHandle);
      AddInt(281, 1);
      if Assigned(vAcDbVariableDictionary) then
      begin
        vOleFrame := vAcDbVariableDictionary.FindEntByName(sDictionaryVarOLEFRAME);
        if Assigned(vOleFrame) then
        begin
          AddDictRefs(vOleFrame.Name, vOleFrame.Handle);
          AddString(0, cnstDictionaryVar);
          AddHexInt(cHandle_5, vOleFrame.Handle);
          AddHexInt(cParentHandle_330, vAcDbVariableDictionaryHandle);
          AddString(100, cnstDictionaryVariables);
          AddInt(280, 0);
          AddString(1, TsgDXFDictionaryVar(vOleFrame).Value);
        end;
      end;
    end;
  end;

  {PLOT}
  if vOwnerPlotSettingsHandle <> 0 then
  begin
    AddDict(cnstDictionary, cnstDictSubClass, vOwnerPlotSettingsHandle);
    AddInt(281, 1);
    for I := 0 to vPlotSettingsDictionary.Count - 1 do
    begin
      AddString(3, vPlotSettingsDictionary[I].Name);
      AddHexInt(350, vPlotSettingsDictionary[I].Handle);
    end;
    for I := 0 to vPlotSettingsDictionary.Count - 1 do
    begin
      ExportPlotSettings(TsgDXFPlotSettings(vPlotSettingsDictionary[I]), False,
        False,
        vOwnerPlotSettingsHandle);
    end;
  end;
  { IMAGEDEFS }
  if vImageDefHandle <> cnstBadHandle then
  begin
    AddDict(cnstDictionary, cnstDictSubClass, vImageDefHandle);
    AddInt(281, 1);
    for I := 0 to ExportCADImage.Converter.Counts[csImageDefs] - 1 do
    begin
      AddString(3, ExportCADImage.Converter.ImageDefs[I].EntName);
      AddHexInt(350, ExportCADImage.Converter.ImageDefs[I].Handle);
    end;
    for I := 0 to ImageDefList.Count - 1 do
    begin
      AddString(3, TsgDXFImageDef(ImageDefList.List[I]).EntName);
      AddHexInt(350, TsgDXFImageDef(ImageDefList.List[I]).Handle);
    end;
    for I := 0 to ExportCADImage.Converter.Counts[csImageDefs] - 1 do
    begin
      ExportImageDef(ExportCADImage.Converter.ImageDefs[I], vImageDefHandle);
    end;
    { Free Temp ImageDEFs}
    for I := 0 to ImageDefList.Count - 1 do
    begin
      ExportImageDef(TsgDXFImageDef(ImageDefList.List[I]),
        vImageDefHandle,
        TsgDXFImageDefExport(ImageDefList.List[I]).ImageEnt.Picture);
      TsgDXFImageDef(ImageDefList.List[I]).Free;
    end;
    ImageDefList.Count := 0;
  end;
  EndSection;
end;

procedure TsgCADtoDXF.ExportSectionTABLES;
begin
  BeginSection('TABLES');
  ExportTablesAPPID;
  if Ord(Version) >= Ord(acR14) then
    ExportTablesBLOCK_RECORD;
  ExportTablesSTYLE;
  ExportTablesLTYPE;
  ExportTablesLAYER;
  ExportTablesVPORT;
  ExportTablesVIEW;
  ExportTablesUCS;
  if Ord(Version) >= Ord(acR14) then
    ExportTablesDIMSTYLE;
{
  ExportTablesVPORT;
  ExportTablesLTYPE;
  ExportTablesLAYER;
  ExportTablesSTYLE;
  ExportTablesVIEW;
  ExportTablesUCS;
  ExportTablesAPPID;
  ExportTablesDIMSTYLE;
  if Ord(Version) >= Ord(acR14) then
    ExportTablesBLOCK_RECORD;
}
  EndSection;
end;

function TsgCADtoDXF.GetStringDXFVersion: string;
begin
  Result := sgDWGVerToString(Version);
end;

function TsgCADtoDXF.GetHandleByEntity(AEntity: TsgDXFEntity): UInt64;
var
  vBlockRecord: TsgDXFBlockRecord;
begin
  if AEntity = nil then
    Result := 0
  else
  begin
    Result := AEntity.Handle;
    if AEntity is TsgDXFBlock then
    begin
      vBlockRecord := GetBlockRecordByBlock(TsgDXFBlock(AEntity), '');
      if vBlockRecord <> nil then
        Result := vBlockRecord.Handle;
    end;
    if Result = cnstBadHandle then
      raise EWriteError.CreateFmt('No handle: %s', [AEntity.EntName]);
  end;
end;

function TsgCADtoDXF.GetEntityLayerName(const AEntity: TsgDXFEntity): string;
begin
  if (AEntity <> nil) and (AEntity.Layer <> nil) then
    Result := ExtractName(AEntity.Layer.Name)
  else
    Result := '0';
end;

function TsgCADtoDXF.GetFlagsByName(const AFlags: Integer; const AName: string): Integer;
const
  cnstXrefFlags = 16 or 32 or 64;
begin
  Result := AFlags;
  if not IsXRefInName(AName) then
    Result := Result and (not cnstXrefFlags)
  else
    Result := Result or cnstXrefFlags;
end;

{ TsgCADtoBin }

procedure TsgCADtoBin.AddCode(const AValue: Integer);
begin
  FStream.Write(AValue, 2);
end;

procedure TsgCADtoBin.AddFloat(const Code: Integer; Value: Double);
begin
  FStream.Write(Code, 2);
  FStream.Write(Value, 8);
end;

procedure TsgCADtoBin.AddInt(const Code, Value: Integer);
var L: Integer;
begin
  case Code of
    290..299:               L := 1;
    90..99, 450..459, 1071: L := 4;
    else                    L := 2;
  end;
  FStream.Write(Code, 2);
  FStream.Write(Value, L);
end;

procedure TsgCADtoBin.AddString(const Code: Integer; const Str: string);
begin
  if Code=999 then Exit;
  FStream.Write(Code, 2);
  WriteStr(Str);
end;

procedure TsgCADtoBin.SaveToStreamCustom(S: TStream);
const Bin: array[0..21] of AnsiChar = 'AutoCAD Binary DXF'#13#10#26#0;
begin
  S.Write(Bin, 22);
  inherited SaveToStreamCustom(S);
end;

procedure TsgCADtoBin.WriteRawByteStr(AString: sgRawByteString);
var
  vNil: Byte;
begin
  if AString <> '' then
    FStream.Write(AString[1], Length(AString) * SizeOf(AString[1]));
  vNil := 0;
  FStream.Write(vNil, 1);
end;

end.
