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

unit DWG;
{$INCLUDE SGDXF.INC}
{.$DEFINE SG_DWG_IMPORT_ACAD_TABLE}
interface

uses Windows, SysUtils, Classes, Graphics, DXFConv, CADImage, sgFunction,
  sgConsts, sgLines, sgLists, MVFont, TTF, ExtData, sgDataSegFile
{$IFDEF SGDEL_6}
  , StrUtils
{$ENDIF}
{$IFDEF SGDEL_XE4}
  , AnsiStrings
{$ENDIF}
  , sgDWGBits
  {$IFDEF SGFPC}
    , FPimage
  {$ENDIF}
  ;

//For working with SaveToStream the definition sgFR should be uncommented.
//This is necessary for Fast Report Add-in.
//{$DEFINE sgFR}

type
  TdwgHeaderHandles = packed record
    CLAYER: UInt64;
    CELTYPE: UInt64;
    CMLSTYLE: UInt64;
    DIMSTYLE: UInt64;
    DIMBLK: UInt64;
    DIMBLK1: UInt64;
    DIMBLK2: UInt64;
    DIMLDRBLK: UInt64;
    DIMTXTSTY: UInt64;
    TEXTSTYLE: UInt64;
  end;

  EdwgError = class(Exception);
  EsgRSCoderError = class(Exception);

  TdwgObject = class;
  TdwgReader = class;
  TdwgProgressEvent = procedure(AStage: TProgressStage; ADone, ACount: Integer) of object;

  TsgExtendedDataList = class(TList)
  end;

//  TdwgCustomObjectReader = class
//  private
//    FOwner: TdwgObject;
//  protected
//    constructor Create(AOwner: TdwgObject); virtual;
//  end;
//
//  Tdwg13_15ObjectReader = class(TdwgCustomObjectReader)
//  end;
//
//  Tdwg2004ObjectReader = class(TdwgCustomObjectReader)
//  end;

  TdwgStringReader = class
  private
    FPBit: PsgInt64;
    FCodePage: Word;
    procedure DoReadUnicodeText(ALen: Integer; var S: sgUnicodeStr);
    procedure DoReadRawText(ALen: Integer; ACP: Word;
      var S: sgRawByteString);
    procedure TrimTextLen(ALen: Integer; var S: string);
  protected
    function ReadCodePage: Word; virtual;
    function ReadXrecordTextLen: Integer; virtual;
    function ReadTextLen: Integer; virtual;
    function ReadText: string; virtual; abstract;
    function ReadXrecordText: string; virtual; abstract;
  public
    constructor Create(APPBit: PsgInt64; ACodePage: Word); virtual;
  end;

  TdwgObject = class
  private
    FChildren: TsgInt64List;
    FChildIndex: Integer;
//    FColorBlockName: string;
//    FColorName: string;
    FEEDataList: TsgExtendedDataList;
    FDataEnd: TsgInt64;
    FEntity: TsgDXFEntity;
    FHandle: UInt64;
    FHndsStart: TsgInt64;
    FPHnds: PsgInt64;
    FIdsStrart: TsgInt64;
    FOwner: UInt64;
    FOwnerObject: TsgDXFEntity;
    FReactors: TsgInt64List;
    FReactorsCount: Integer;
    FReader: TdwgReader;
    FStrsStart: TsgInt64;
    FSubEnts: Integer;
    FXDicHandlePresent: Boolean;
    FXDict: UInt64;
    //FObj: TdwgObject;
    FLineWeight: Double;
    FSibling: UInt64;
    FFirstChildHandle: UInt64;
    FLastChildHandle: UInt64;
    FCorrectData: Boolean;
    FAnnotativeFlags: Integer;
//    FSwapped: Boolean;
//    FObjMap: TsgObjectsMap;
    FStringReader: TdwgStringReader;
    function ReadID(var APBit: TsgInt64): UInt64; overload;
    function ReadID(var APBit: TsgInt64; var ACode: Byte): UInt64; overload;
    function ReadID: UInt64; overload;
  protected
    function ApplyEED(const AEEData: TsgCADExtendedData;
      const AAppID: UInt64): Boolean; virtual;
    procedure ApplyAnnotativeData(const AEEData: TsgCADExtendedData); virtual;
    function CanEEDApply(const AAppID: UInt64): Boolean; virtual;
    function CreateStringReader(var APBit: TsgInt64; AVersion: TsgDWGVersion): TdwgStringReader; virtual;
    function Find(AHandle: UInt64; var I: Integer): Boolean; virtual;
    function GetBitSize: Integer; virtual;
    function GetChild(Handle: UInt64): TsgDXFEntity; virtual;
    function GetChildEx(Handle: UInt64; MapIndex: Integer): TsgDXFEntity; virtual;
    function GetChildren(Index: Integer): UInt64; virtual;
    function GetChildrenCount: Integer; virtual;
    function GetEEDataList: TsgExtendedDataList; virtual;
    function GetObjectBeginning: TsgInt64; virtual;
    function GetOwner(AReader: TdwgReader): TsgDXFEntity; virtual;
    procedure ReadData(var APosition: TsgInt64); virtual; abstract;
    function ReadEED(var APBit, APEnd: TsgInt64;
      const AAppID: UInt64): TsgCADExtendedData; virtual;
    function ReadEEDItems(var APBit: TsgInt64): TsgExtendedDataList; virtual;
    procedure ReadObjHeader(var APBit: TsgInt64); virtual;
    function ReadObjName(var APBit: TsgInt64; var Flags: Integer): string; virtual;
    procedure ReadLineWeight(AIndex: Integer);
    procedure References(AReader: TdwgReader); virtual;
    procedure SetBitSize(const AValue: Integer); virtual;
    procedure SetObjectBeginning(const APosition: TsgInt64); virtual;
    procedure SkipHandles(var APBit: TsgInt64);
    procedure ReadError;
    procedure ReadOwner(AReader: TdwgReader); virtual;
    procedure ReadSubEntIDs(var APBit: TsgInt64; const AFlags: Integer = 0); virtual;
    procedure ReadSubEnts(AReader: TdwgReader); virtual;
    procedure ReadSubEntsR2000(AReader: TdwgReader); virtual;
    procedure ReadSubEntsR2004(AReader: TdwgReader); virtual;
    procedure ReadHandleRefs(var APBit: TsgInt64); virtual;

    function ReadChild(ASeek: Integer; AHandle: UInt64;
      AIndex: Integer): TdwgObject; virtual;

    procedure ReadPredefined(ASeek: Integer; AObj: TdwgObject;
      AIndex: Integer); virtual;

    procedure NewObject(ACode: Integer; AHandle: UInt64; var AObj: TdwgObject); virtual;
    function IsEntity: Boolean; virtual;

    function OwnerAdd(AOwner: TsgDXFEntity): Integer; virtual;
    property BitSize: Integer read GetBitSize write SetBitSize;
    property EEDataList: TsgExtendedDataList read GetEEDataList;
    property ObjectBeginning: TsgInt64 read GetObjectBeginning write SetObjectBeginning;
    property Reader: TdwgReader read FReader write FReader;
    property Child[Handle: UInt64]: TsgDXFEntity read GetChild;
    property Children[Index: Integer]: UInt64 read GetChildren;
    property ChildrenCount: Integer read GetChildrenCount;
  public
    constructor Create; virtual;
    destructor Destroy; override;
  end;

  TsgDWGMeatadata = record
    ReleaseVersion: Byte;
    PreviewAddress: Cardinal;
    OrigFileSavedVer: Byte;
    OrigFileSavedReleaseVer: Byte;
    CodePage: Word;
    SecurityFlags: Cardinal;
    SummaryInfoAddress: Cardinal;
    VBAProjectAddress: Cardinal;
  end;

  TdwgReader = class
  private
    FAcDbClasses: TsgStringList;
    FClasses: TsgIntegerList;
    FConverter: TsgDXFConverter;
    FHeaderHandles: TdwgHeaderHandles;
    FExceptionClass: ExceptClass;
    FExceptionEntityHandle: UInt64;
    FImage: Integer;
    FMaxHandle: UInt64;
    FMem: PAnsiChar;
    FObjMap: TsgObjectsMap;
    FOnProgress: TdwgProgressEvent;
    FSize: Integer;
    FSource: TCustomMemoryStream;
    FStream: TStream;
    FUnits: Integer;
    FVersion: TsgDWGVersion;
    FMetadata: TsgDWGMeatadata;
    FSegmentedFile: TsgSegmentedFile;
    FBlockRecords: TdwgObject;
    FLayerControl: UInt64;
    FLTypeControl: UInt64;
    FStyleControl: UInt64;
    FAppIDControl: UInt64;
    FDimStyleControl: UInt64;
    FLayoutsDict: UInt64;
    FImageDefDict: UInt64;
    FMLStylesDict: UInt64;
    FVariableDict: UInt64;
    FMaterialDict: UInt64;
    FStylesByFont: TStringList;
    FModel: TsgDXFBlock;
    FPaper: TsgDXFBlock;
    FLTByLayer: UInt64;
    FLTByBlock: UInt64;
    FLTContinious: UInt64;
    FNamedObjects: UInt64;
    FTables: TdwgObject;
    FDataBase: TdwgObject;
    FACADAppID: UInt64;
    FAnnotativeAppID: UInt64;
    FAppID: UInt64;
    FColors: UInt64;
    FViewports: TsgCollection;
    FActiveViewport: UInt64;
    FArrows: TStringList;
    FDummy: TsgDXFGroupName;
    FStringReader: TdwgStringReader;
    function Code2007ByClassName(const AObjectBeginning, APBit: TsgInt64;
      AReadedCode: Integer): Integer;
    procedure CRead(ASeek, ASize: Integer);
    function CheckSentinel(P: Pointer; const ASentinel: TsgDWGSentinel): Boolean;
    procedure DoException;
    procedure DoProgress(AStage: TProgressStage);
    function DoReadData(AObj: TdwgObject; var APBit: TsgInt64): Boolean;
//    function FindLocation(const AHandle: UInt64; var AIndex: Integer): Integer;
//    function FinishObject(AObj: TdwgObject; AOwner: TsgDXFEntity;
//      AIndex: Integer): TsgDXFEntity;
    function GetArrowTypeByHandle(const ABlockRecordHandle: UInt64): TsgDimArrowType;
    function GetTableNameByHandle(const AHandle: UInt64;
      AClass: TsgDXFEntityClass): string;
    procedure Init2007ObjectData(var AStartBit, APStrStart,
      APHndStart: TsgInt64; var AEndBit: Cardinal;
      ANeedReadEndBit: Boolean = True);
    procedure Init2010ObjectData(var AStartBit, APStrStart,
      APHndStart: TsgInt64; const AIdsPos: Cardinal; var AEndBit: Cardinal);
    procedure LoadHeaderHandles;
//    function LoadEntity(const AObject: TdwgObject): Boolean;
    function LTypeByIndex(AIndex: Integer): TsgDXFLineType;
//    procedure NewObject(ACode: Integer; var AObj: TdwgObject);
    function ObjByHandle(AHandle: UInt64;
      AClass: TsgDXFEntityClass): TsgDXFEntity;
    function PMSpace(var APBit: TsgInt64; AObj: TdwgObject;
      var APHeadVar: PsgHeadVarStruct): TFRect;
    procedure Read(ASeek, ASize: Integer);
    procedure Read2007StrDataLength(const APStart: TsgInt64; var AEndBit,
      AStrSize: Cardinal);
    procedure ReadClasses(ASeek, ASize: Integer);
    procedure ReadHeadVars(ASeek, ASize: Integer);
    procedure ReadMeasurement(ASeek: Integer);
    procedure ReadMetadata(const Stream: TStream; const FileHeader: TdwgFileHeader);
//    function ReadObject(ASeek: Integer; AHandle: UInt64;
//      AIndex: Integer): TsgDXFEntity;
    procedure ReadObjMap(ASeek, ASize: Integer);
//    procedure ReadPart(AFirst, ALast: Integer);
    procedure ReadSummaryInfo(ASeek, ASize: Integer);
    procedure ReadTemplate(ASeek, ASize: Integer);
    procedure ReadPrototype(ASeek, ASize: Integer);
    procedure ReadPlotSettings(Obj: TdwgObject;
      const APlotSettings: PsgPlotSettingsData; var APBit: TsgInt64);
    function VarCode(ACode: Integer): Integer;
    function GetPHeadVarStruct: PsgHeadVarStruct;
    procedure InitLayouts;
    function ForceDictionarySection(const ADictName: string;
      const ASection: TsgDXFEntity; const ASectionName: string): TsgDXFEntity;
    function GetDictionary(Name: string): TsgDXFDictionary;
    procedure InitViewportsByList;
    function EntAddRef(AEnt: TsgDXFEntity): Integer;
    function EntRelease(AEnt: TsgDXFEntity): Integer;
    function GetStringReader(var APBit: TsgInt64): TdwgStringReader;
  protected
    function IsFamiliarApplication(const AAppID, AHandle: UInt64): Boolean;
    procedure ReadHeader; virtual;
    procedure ReadImage; virtual;
    procedure ReadObjects; virtual;
    function Stopped: Boolean;

    property MaxHandle: UInt64 read FMaxHandle;
    property Version: TsgDWGVersion read FVersion write FVersion;
    property Model: TsgDXFBlock read FModel;
    property Paper: TsgDXFBlock read FPaper;
  public
    constructor Create(AConv: TsgDXFConverter; S: TStream);
    destructor Destroy; override;
    procedure ReadFile;
    property Conv: TsgDXFConverter read FConverter;
    property OnProgress: TdwgProgressEvent read FOnProgress write FOnProgress;
    property Stream: TStream read FStream;
    property Dictionary[Name: string]: TsgDXFDictionary read GetDictionary;
  end;

  TsgDWGConverter = class(TsgDXFConverter)
  private
    FImage: TBitmap;
    FStopped: Boolean;
  protected
    function GetDWGVersion(const AString: AnsiString;
      var AVersion: TsgDWGVersion): Integer; override;
    procedure Initialize; override;
  public
    destructor Destroy; override;
    procedure StopLoading; override;
  end;

  TsgDWGImage = class(TsgImageWithHandles)
  private
    function Bitmap: TBitmap;
  protected
    function CreateConverter: TsgDXFConverter; override;
    procedure Draw(ACanvas: TCanvas; const ARect: TRect); override;
    function GetEmpty: Boolean; override;
    function GetHeight: Integer; override;
    function GetWidth: Integer; override;
    function IsAutocadLType: Boolean; override;
  public
    procedure Assign(ASource: TPersistent); override;
    procedure LoadFromStream(AStream: TStream); override;
    procedure LoadPreviewFromFile(const AFileName: string);
    procedure SaveToStream(AStream: TStream); override;
    property Preview: TBitmap read Bitmap;
  end;

function ObjStreamPos(const ABegin, ACurr: TsgInt64): TsgInt64;

var
  CF_DWG: Word;
implementation

uses
  Math, DWG12, sgSATBinToTextConv;

const
  cnstProxyObjectIndex = 83;

//  cnstSnHeaderVariables: array[0..15] of Byte = ($CF, $7B, $1F, $23, $FD, $DE, $38, $A9, $5F,
//    $7C, $68, $B8, $4E, $6D, $33, $5F);
//  cnstSnImageData: array[0..15] of Byte = ($1F, $25, $6D, $07, $D4, $36, $28, $28, $9D, $57,
//    $CA, $3F, $9D, $44, $10, $2B);



  cnstNameToCodeCount = {$IFDEF DATA_LINK}28{$ELSE}27{$ENDIF};
  cnstNameToCode: array[0 .. cnstNameToCodeCount - 1] of record
    Name: string;
    Code: Byte;
  end = ((Name:'LWPOLYLINE'; Code: 77), (Name:'HATCH'; Code: 78),
         (Name:'LAYOUT'; Code: 82), (Name:'IMAGE'; Code: 54),
         (Name:'IMAGEDEF'; Code: 55), (Name:'SORTENTSTABLE'; Code: 58),
         (Name:'OLE2FRAME'; Code: 74), (Name:'ACAD_TABLE'; Code: 84),
         (Name:'WIPEOUT'; Code: 85), (Name:'WIPEOUTVARIABLES'; Code: 86),
         (Name:'MPOLYGON'; Code: 87), (Name:'SURFACE'; Code: 88),
         (Name:'DBCOLOR'; Code: 89), (Name:'TABLESTYLE'; Code: 90),
         (Name:sRasterVariables; Code: 91), (Name:'PLOTSETTINGS'; Code: 92),
         (Name:'ACIDBLOCKREFERENCE'; Code: 7), (Name:'DICTIONARYVAR'; Code: 93),
         (Name:'XRECORD'; Code: 79),
         (Name:'MESH'; Code: 94),
         (Name:'SCALE'; Code: 95),
         (Name:'MATERIAL'; Code: 96),
         (Name:'ACDB_MTEXTATTRIBUTEOBJECTCONTEXTDATA_CLASS'; Code: 97),
         (Name:'ACDB_TEXTOBJECTCONTEXTDATA_CLASS'; Code: 97),
         (Name:'ACDB_LEADEROBJECTCONTEXTDATA_CLASS'; Code: 97),
         (Name:'ACDB_MTEXTOBJECTCONTEXTDATA_CLASS'; Code: 97),
         (Name:'ACDB_ALDIMOBJECTCONTEXTDATA_CLASS'; Code: 97)
{$IFDEF DATA_LINK}
         ,(Name:'DATALINK'; Code: 98)
{$ENDIF}
          );

  cnstAPPID = 'APPID';
  cnstEntityHandle = ': Entity handle = $';

type
  TdwgImage = packed record
    Sentinel: array[0..15] of Byte;
    Size: Integer;
    Count: Byte;
    Images: array[Byte] of TdwgLocator;
  end;

{ Begin DWG 2004 support }

  TdwgLocators = packed array[0..cntDWGSectMaxIndex] of TdwgLocator;

  Pdwg2004FileHeader = ^Tdwg2004FileHeader;
  Tdwg2004FileHeader = packed record
    VersionID: array[0..5] of AnsiChar;
    Pad: array[0..6] of AnsiChar;
    ImageSeeker: Integer;
    Unknown: Word;
    CodePage: Word;
    LocCount: Integer;
    Locators: TdwgLocators;
  end;

  PHead2004Rec = ^THead2004Rec;
  THead2004Rec = packed record
    UnpackSize: Integer;
    Empty: Integer;
    Extra: Integer;
    Unused: array[0..24] of Byte;
    Name: array[0..58] of AnsiChar;
    Index: Integer;
    PackSize: Integer;
  end;

  TdwgStream = class(TMemoryStream)
  end;

  TsgTableArray = array[0..4095] of Integer;
  TsgSectionsArray = array[0..4] of PHead2004Rec;


{ End DWG 2004 support }

{ Begin DWG 2007 support }

  TsgDwg2007ChData = packed record
    Crc1: Int64;
    Crc2: Int64;
    Random1: Int64;
    Random2: Int64;
    CrcSeedEncoded: Int64;
  end;

  TsgDwg2007FileHeader = packed record
    HeaderSize: Int64;
    FileSize: Int64;
    PagesMapCrcCompr: Int64;
    PagesMapFactor: Int64;
    PagesMapCrcSeed: Int64;
    PagesMap2Offset: Int64;
    PagesMap2Id: Int64;
    PagesMapOffset: Int64;
    PagesMapId: Int64;
    Header2Offset: Int64;
    PagesMapSizeCompr: Int64;
    PagesMapSizeSrc: Int64;
    PagesAmount: Int64;
    PagesMaxId: Int64;
    Unknown15: Int64;
    Unknown16: Int64;
    PagesMapCrcSrc: Int64;
    Unknown18: Int64;
    Unknown19: Int64;
    Unknown20: Int64;
    SectionsAmount: Int64;
    SectionsMapCrcSrc: Int64;
    SectionsMapSizeCompr: Int64;
    SectionsMap2Id: Int64;
    SectionsMapId: Int64;
    SectionsMapSizeSrc: Int64;
    SectionsMapCrcCompr: Int64;
    SectionsMapFactor: Int64;
    SectionsMapCrcSeed: Int64;
    StreamVersion: Int64;
    CrcSeed: Int64;
    CrcSeedEncoded: Int64;
    RandomSeed: Int64;
    HeaderCrc64: Int64;
  end;

  PsgDWG2007Page = ^TsgDWG2007Page;
  TsgDWG2007Page = record
    Id: Int64;
    Size: Int64;
    Offset: Int64;
  end;

  TsgDWG2007Section = packed record
    DataSize: Int64;
    PageSize: Int64;
    Encrypted: Int64;
    Unknown1: Int64;
    SecNameLen: Int64;
    Unknown2: Int64;
    Encoded: Int64;
    PagesAmount: Int64;
    SecName: WideString;
    Pages: TList;
    Data: TMemoryStream;
  end;

  PsgDWG2007StreamPage = ^TsgDWG2007StreamPage;
  TsgDWG2007StreamPage = packed record
    DataOffset: Int64;
    PageSize: Int64;
    PageId: Int64;
    DataSize: Int64;
    ComprSize: Int64;
    Checksum: Int64;
    Crc: Int64;
  end;

  TsgDWG2007Decompressor = class
  private
    FDstEnd: PAnsiChar;
    FLength: Cardinal;
    FOffset: Cardinal;
    FOpCode: Cardinal;
    FSrc: PAnsiChar;
    FSrcEnd: PAnsiChar;
    procedure GetCmpData(ADest: PAnsiChar; ALength, AOffset: Integer);
    procedure GetCmpOpcode;
    procedure GetLiteralData(ADest, ASource: PAnsiChar; ALength: Integer);
    procedure GetLiteralOpcode;
  public
    constructor Create; virtual;
    procedure Clear; virtual;
    procedure Decompress(ASource: PAnsiChar; ASrcSize: Cardinal;
      ADest: PAnsiChar; ADstSize: Cardinal); virtual;
  end;

  TsgRSCoder = class
  private
    FAlfaTo: array[0..255] of Cardinal;
    FBlockSize: Cardinal;
    FDSize: Cardinal;
    FErr: Integer;
    FGPoly: array[0..16] of Cardinal;
    FIndexOf: array[0..255] of Cardinal;
    FMod255: PAnsiChar;
    FPSize: Integer;
    procedure Generate(const APoly: array of Byte; AM, AErrors: Cardinal);
    function GetDSize: Integer;
    procedure InitRSCoder1100;
    procedure InitRSCoder500;
  public
    constructor Create;
    destructor Destroy; override;
    function Decode(AData: PAnsiChar): Integer;
    property DSize: Integer read GetDSize;
  end;

{ End DWG 2007 support }

{ Begin DWG 2010 support }

  TsgDWG2010FileHeader = packed record
    GpsRtId: Integer;
    GpsLeftId: Integer;
    GpsRightId: Integer;
    GpsUnknown: Integer;
    LastPageId: Integer;
    LastPageEndOffset: UInt64;
    Hdr2Offset: UInt64;
    GapsAmount: Cardinal;
    PagesAmount: Cardinal;
    PagesMapId: Cardinal;
    PagesMapOffset: UInt64;
    SectionsMapId: Cardinal;
    PagesMaxId: Cardinal;
    GapsMaxId: Cardinal;
  end;

  TsgDWG2010SysPage = record
    PageType: Cardinal;
    DecompSize: Cardinal;
    CompSize: Cardinal;
    CompType: Cardinal;
    CRC: Cardinal;
  end;

  TsgDWG2010Decompressor = class(TsgDWG2007Decompressor)
  private
   FDstCurr: PAnsiChar;
   FHashTable: PAnsiChar;
   FSrcCurr: PAnsiChar;
   FSrcEnd: PAnsiChar;
   FSrcPrev: PAnsiChar;
   FSrcStart: PAnsiChar;
   FTarget: PAnsiChar;
   procedure GetCompressed(ALength, AOffset: Integer);
   procedure GetLength(var ALength: Integer; AOpCode, AMask: Integer);
   procedure GetLiteral(AOpCode: Integer);
   procedure GetLongLength(var ALength: Integer);
   procedure GetOffset(var AOpCode1, AOpCode2, AOffset: Integer);
  public
    constructor Create; override;
    procedure Clear; override;
    procedure Decompress(ASource: PAnsiChar; ASrcSize: Cardinal; ADest: PAnsiChar;
      ADstSize: Cardinal); override;
  end;

{
    End DWG 2010 support
}

  TDWGProxyReader = class(TCustomAlignedDataReader)
  protected
    function ReadDouble: Double; override;
    function ReadInteger: Integer; override;
    function ReadSmallInt: SmallInt; override;
    function ReadWord: Word; override;
    function ReadByte: Byte; override;
    procedure PushPosition; override;
    procedure PopPosition; override;
    procedure Seek(ASize: Integer); override;
    function ReadHandle: UInt64; override;
    procedure ReadBytes(var Dest; const ACount: UInt64); override;
  public
    constructor Create(APos: Pointer; AVersion: TsgDWGVersion); override;
    destructor Destroy; override;
  end;

  TdwgClass = class of TdwgObject;
  TsgDXFEntityAccess = class(TsgDXFEntity);
  TsgCADHatchAccess = class(TsgCADHatch);
  TsgDXFConverterAccess = class(TsgDXFConverter);
  TsgDXFGroupAccess = class(TsgDXFGroup);
  TsgDXFTextAccess = class(TsgDXFText);
  TsgDXFLeaderAccess = class(TsgDXFLeader);
  TsgDXFDimensionStyleAccess = class(TsgDXFDimensionStyle);
  TsgDXFBlockAccess = class(TsgDXFBlock);
  TsgDXFBlockRecordAccess = class(TsgDXFBlockRecord);
  TsgDXFBlockRecordsAccess = class(TsgDXFBlockRecords);
  TsgDXFPlotSettingsAccess = class(TsgDXFPlotSettings);
  TsgDXFSplineAccess = class(TsgDXFSpline);
  TsgDXFGroupNameAccess = class(TsgDXFGroupName);
  TsgDXFObjectEntityAccess = class(TsgDXFObjectEntity);
  TsgDXFLayoutAccess = class(TsgDXFLayout);

  TdwgBlock = class;
  TdwgBitmap = class(TBitmap)
  end;

  TdwgWideStringReader = class(TdwgStringReader)
  protected
    function ReadText: string; override;
    function ReadXrecordText: string; override;
  end;
  TdwgWideStringReaderParse = class(TdwgWideStringReader)
  protected
    function ReadText: string; override;
  end;

  TdwgAnsiStringReader = class(TdwgStringReader)
  protected
    function ReadCodePage: Word; override;
    function ReadText: string; override;
    function ReadXrecordText: string; override;
  end;
  TdwgAnsiStringReaderParse = class(TdwgAnsiStringReader)
  protected
    function ReadText: string; override;
  end;

  TdwgCustomControl = class(TdwgObject)
  protected
    function GetOwner(AReader: TdwgReader): TsgDXFEntity; override;
    procedure InitializeTable(ASection: TConvSection; AName: string);
    procedure ReadOwner(AReader: TdwgReader); override;
    procedure ReadData(var APBit: TsgInt64); override;
    procedure References(AReader: TdwgReader); override;
    procedure ReadSubEnts(AReader: TdwgReader); override;
    procedure ReadSubEntIDs(var APBit: TsgInt64; const AFlags: Integer = 0); override;
  end;

  TdwgTables = class(TdwgCustomControl)
  protected
    function GetOwner(AReader: TdwgReader): TsgDXFEntity; override;
    procedure NewObject(ACode: Integer; AHandle: UInt64; var AObj: TdwgObject); override;
  end;

  TdwgDataBase = class(TdwgObject)
  private
  protected
    function GetChildren(Index: Integer): UInt64; override;
    function GetChildrenCount: Integer; override;
    procedure ReadData(var APBit: TsgInt64); override;
    procedure ReadSubEnts(AReader: TdwgReader); override;
  end;

  TdwgTableItem = class(TdwgObject)
  private
    FEntryName: string;
    FFlags: Integer;
  protected
    procedure ReadData(var APBit: TsgInt64); override;
    procedure ReadHandleRefs(var APBit: TsgInt64); override;
  end;

  TdwgBlockRecord = class(TdwgTableItem)
  private
    FBlockEnd: UInt64;
    FBlock: TdwgBlock;
    FLayout: UInt64;
    function IsAnonymous: Boolean;
  protected
    function GetOwner(AReader: TdwgReader): TsgDXFEntity; override;
    procedure ReadData(var APBit: TsgInt64); override;
    procedure References(AReader: TdwgReader); override;
    function OwnerAdd(AOwner: TsgDXFEntity): Integer; override;
  public
    constructor Create; override;
    destructor Destroy; override;
  end;

  TdwgDimStyle = class(TdwgTableItem)
  private
    FBlockArrow: TsgLinkObject;
    FBlockArrowL: TsgLinkObject;
    FBlockArrow1: TsgLinkObject;
    FBlockArrow2: TsgLinkObject;
    FTextStyle: UInt64;
  protected
    function GetOwner(AReader: TdwgReader): TsgDXFEntity; override;
    procedure ReadData(var APBit: TsgInt64); override;
    procedure References(AReader: TdwgReader); override;
  public
    constructor Create; override;
    destructor Destroy; override;
  end;

  TdwgEntity = class(TdwgObject)
  private
    FColor: TsgColorCAD;
    FDbColor: UInt64;
    FLayer: UInt64;
    FLType: UInt64;
    FMode: Byte;
    FStandardLType: UInt64;
    FLineTypeScale: Double;
    FVisibility: Boolean;
  protected
    function IsEntity: Boolean; override;
    procedure ReadData(var APBit: TsgInt64); override;
    procedure ReadEntData(var APBit: TsgInt64); virtual;
    procedure ReadEntProxyData(var APBit: TsgInt64); virtual;
    procedure ReadOwner(AReader: TdwgReader); override;
    procedure ReadHandleRefs(var APBit: TsgInt64); override;
    procedure References(AReader: TdwgReader); override;
  end;

  TdwgBlock = class(TdwgEntity)
  protected
    function GetOwner(AReader: TdwgReader): TsgDXFEntity; override;
    procedure ReadEntData(var APBit: TsgInt64); override;
    function OwnerAdd(AOwner: TsgDXFEntity): Integer; override;
  end;

  TdwgLayer = class(TdwgTableItem)
  private
    FLType: UInt64;
    FColor: TsgColorCAD;
    FIsPlotting: Boolean;
    FVisible: Boolean;
  protected
    function GetOwner(AReader: TdwgReader): TsgDXFEntity; override;
    procedure ReadData(var APBit: TsgInt64); override;
    procedure References(AReader: TdwgReader); override;
  public
    constructor Create; override;
  end;

  TdwgAppIDControl = class(TdwgCustomControl)
  protected
    procedure ReadData(var APBit: TsgInt64); override;
    procedure References(AReader: TdwgReader); override;
  end;

  TdwgLTControl = class(TdwgCustomControl)
  private
    FByLayer: UInt64;
    FByBlock: UInt64;
  protected
    procedure ReadData(var APBit: TsgInt64); override;
    procedure References(AReader: TdwgReader); override;
  end;

  TdwgStyleControl = class(TdwgCustomControl)
  protected
    procedure ReadData(var APBit: TsgInt64); override;
    procedure References(AReader: TdwgReader); override;
  end;

  TdwgLayerControl = class(TdwgCustomControl)
  protected
    procedure ReadData(var APBit: TsgInt64); override;
    procedure References(AReader: TdwgReader); override;
  end;

  TdwgBlockControl = class(TdwgCustomControl)
  private
    FModel: UInt64;
    FPaper: UInt64;
  protected
    procedure NewObject(ACode: Integer; AHandle: UInt64; var AObj: TdwgObject); override;
    procedure ReadData(var APBit: TsgInt64); override;
  end;

  TdwgDimStyleControl = class(TdwgCustomControl)
  protected
    procedure ReadData(var APBit: TsgInt64); override;
  end;

  TdwgVPortControl = class(TdwgCustomControl)
  protected
    procedure ReadData(var APBit: TsgInt64); override;
  end;

  TdwgLType = class(TdwgTableItem)
  protected
    function GetOwner(AReader: TdwgReader): TsgDXFEntity; override;
    procedure ReadData(var APBit: TsgInt64); override;
    procedure References(AReader: TdwgReader); override;
  end;

  TdwgMLStyle = class(TdwgObject)
  private
    FLTypes: TsgIntegerList;
  protected
    constructor Create; override;
    destructor Destroy; override;
    function GetOwner(AReader: TdwgReader): TsgDXFEntity; override;
    procedure ReadData(var APBit: TsgInt64); override;
    procedure References(AReader: TdwgReader); override;
  end;

  TdwgSortEntsTable = class(TdwgObject)
  private
    FObject: UInt64;
  protected
    function GetOwner(AReader: TdwgReader): TsgDXFEntity; override;
    procedure ReadData(var APBit: TsgInt64); override;
    procedure References(AReader: TdwgReader); override;
  end;

  TdwgVPort = class(TdwgTableItem)
  protected
    function GetOwner(AReader: TdwgReader): TsgDXFEntity; override;
    procedure ReadData(var APBit: TsgInt64); override;
    procedure References(AReader: TdwgReader); override;
  end;

  TdwgWipeoutVar = class(TdwgObject)
  protected
    function GetOwner(AReader: TdwgReader): TsgDXFEntity; override;
    procedure ReadData(var APBit: TsgInt64); override;
  end;

  Tdwg3DFace = class(TdwgEntity)
  protected
    procedure ReadEntData(var APBit: TsgInt64); override;
  end;

  TdwgCircle = class(TdwgEntity)
  protected
    procedure ReadEntData(var APBit: TsgInt64); override;
  end;

  TdwgDbColor = class(TdwgObject)
  protected
    function GetOwner(AReader: TdwgReader): TsgDXFEntity; override;
    procedure ReadData(var APBit: TsgInt64); override;
  end;

  TdwgXRecord = class(TdwgObject)
  protected
    procedure ReadData(var APBit: TsgInt64); override;
    procedure References(AReader: TdwgReader); override;
  end;

  TdwgDictionary = class(TdwgObject)
  private
    FNames: TStringList;
    procedure PerformName;
  protected
    destructor Destroy; override;
    function GetOwner(AReader: TdwgReader): TsgDXFEntity; override;
    procedure ReadData(var APBit: TsgInt64); override;
    procedure ReadSubEnts(AReader: TdwgReader); override;
    procedure ReadSubEntIDs(var APBit: TsgInt64; const AFlags: Integer = 0); override;
    procedure References(AReader: TdwgReader); override;
    procedure NewObject(ACode: Integer; AHandle: UInt64;
      var AObj: TdwgObject); override;
    function OwnerAdd(AOwner: TsgDXFEntity): Integer; override;
    property Names: TStringList read FNames;
  end;

{$IFDEF DATA_LINK}
  TdwgDataLink = class(TdwgObject)
  protected
    procedure ReadData(var APBit: TsgInt64); override;
  end;
{$ENDIF}

  TdwgEllipse = class(TdwgEntity)
  protected
    procedure ReadEntData(var APBit: TsgInt64); override;
  end;

  TdwgHatch = class(TdwgEntity)
  private
    procedure AddBoundaryDataCurve(const ABoundaryList: Tsg2DBoundaryList;
      const ACurve: Tsg2DCurve);
    function Read2DArc(const ACircle: Boolean; var APBit: TsgInt64): Tsg2DArc;
    function Read2DLine(var APBit: TsgInt64): Tsg2DLine;
    function Read2DPolyline(var APBit: TsgInt64; AIsMPolygon: Boolean): Tsg2DPolyline;
    function Read2DSpline(var APBit: TsgInt64): Tsg2DSpline;
    procedure ReadGradietParams(var APBit: TsgInt64);
    procedure ReadPatternData(var APBit: TsgInt64);
  protected
    function DoSolidHatch(const AIsSolid: Boolean): TsgCADCurvePolygon; virtual;
    procedure ReadAssociative(var APBit: TsgInt64); virtual;
    function ReadBoundaryData(var APBit: TsgInt64): Boolean; virtual;
    procedure ReadEntData(var APBit: TsgInt64); override;
    procedure ReadFillColorAndOffset(var APBit: TsgInt64); virtual;
    procedure ReadStyleAndPatternType(var APBit: TsgInt64); virtual;
  end;

  TdwgMPolygon = class(TdwgHatch)
  protected
    function DoSolidHatch(const AIsSolid: Boolean): TsgCADCurvePolygon; override;
    procedure ReadAssociative(var APBit: TsgInt64); override;
    function ReadBoundaryData(var APBit: TsgInt64): Boolean; override;
    procedure ReadEntData(var APBit: TsgInt64); override;
    procedure ReadFillColorAndOffset(var APBit: TsgInt64); override;
    procedure ReadStyleAndPatternType(var APBit: TsgInt64); override;
  end;

  TdwgImageDef = class(TdwgObject)
  protected
    function GetOwner(AReader: TdwgReader): TsgDXFEntity; override;
    procedure ReadData(var APBit: TsgInt64); override;
  end;

  TdwgInsert = class(TdwgEntity)
  private
    FComplex: Boolean;
    FBlockRecord: UInt64;
  protected
    procedure ReadData(var APBit: TsgInt64); override;
    procedure ReadEntData(var APBit: TsgInt64); override;
    procedure References(AReader: TdwgReader); override;
  end;

  TdwgLayout = class(TdwgObject)
  private
    FActiveViewport: UInt64;
    FPaperSpaceHandle: UInt64;
    FViewports: TsgInt64List;
  protected
    procedure ReadData(var APBit: TsgInt64); override;
    procedure References(AReader: TdwgReader); override;
  end;

  TdwgLeader = class(TdwgEntity)
  private
    FAnnotationType: Integer;
    FArrowSize: Double;
    FArrowSizeOverrides: Double;
    FArrowScaleOverrides: Double;
    FTextAnnotationWidth: Double;
    FGAP: Double;
    FDimStyle: UInt64;
    FHooklineDirectional: Integer;
    FHooklineVector: TFPoint;
    FTAD: Integer;
    FCanApplyEED: Boolean;
    FOverrides: TsgDimNameVals;
    function GetBlockLink(AVal: TsgDimNameVal; AName: string): TsgDXFBlock;
  protected
    function ApplyEED(const AEEData: TsgCADExtendedData;
      const AAppID: UInt64): Boolean; override;
    function CanEEDApply(const AAppID: UInt64): Boolean; override;
    procedure ReadData(var APBit: TsgInt64); override;
    procedure ReadEntData(var APBit: TsgInt64); override;
    procedure References(AReader: TdwgReader); override;
  public
    constructor Create; override;
  end;

  TdwgLine = class(TdwgEntity)
  protected
    function ApplyEED(const AEEData: TsgCADExtendedData;
      const AAppID: UInt64): Boolean; override;
    function CanEEDApply(const AAppID: UInt64): Boolean; override;
    procedure ReadEntData(var APBit: TsgInt64); override;
  end;

  TdwgLWPline = class(TdwgEntity)
  protected
    procedure ReadEntData(var APBit: TsgInt64); override;
  end;

  TdwgMLine = class(TdwgEntity)
  private
    FStyle: UInt64;
  protected
    procedure ReadData(var APBit: TsgInt64); override;
    procedure ReadEntData(var APBit: TsgInt64); override;
    procedure References(AReader: TdwgReader); override;
  end;

  TdwgMText = class(TdwgEntity)
  private
    FStyle: UInt64;
  protected
    function CreateStringReader(var APBit: TsgInt64;
      AVersion: TsgDWGVersion): TdwgStringReader; override;
    procedure ReadData(var APBit: TsgInt64); override;
    procedure ReadEntData(var APBit: TsgInt64); override;
    procedure References(AReader: TdwgReader); override;
  end;

  TdwgOLE2Frame = class(TdwgEntity)
  protected
    procedure ReadEntData(var APBit: TsgInt64); override;
  end;

  TdwgPoint = class(TdwgEntity)
  protected
    procedure ReadEntData(var APBit: TsgInt64); override;
  end;

  TdwgPolyline = class(TdwgEntity)
  protected
    procedure ReadData(var APBit: TsgInt64); override;
    procedure ReadEntData(var APBit: TsgInt64); override;
  public
    constructor Create; override;
  end;

  TdwgPlotSettings = class(TdwgObject)
  protected
    function GetOwner(AReader: TdwgReader): TsgDXFEntity; override;
    procedure ReadData(var APBit: TsgInt64); override;
  end;

  TdwgRasterVariables = class(TdwgObject)
  protected
    function GetOwner(AReader: TdwgReader): TsgDXFEntity; override;
    procedure ReadData(var APBit: TsgInt64); override;
  end;

  TdwgSolid = class(TdwgEntity)
  protected
    procedure ReadEntData(var APBit: TsgInt64); override;
  end;

  TdwgSpline = class(TdwgEntity)
  protected
    function ApplyEED(const AEEData: TsgCADExtendedData;
      const AAppID: UInt64): Boolean; override;
    function CanEEDApply(const AAppID: UInt64): Boolean; override;
    procedure ReadEntData(var APBit: TsgInt64); override;
  end;

  TdwgStyle = class(TdwgTableItem)
  private
  protected
    function ApplyEED(const AEEData: TsgCADExtendedData;
      const AAppID: UInt64): Boolean; override;
    function CanEEDApply(const AAppID: UInt64): Boolean; override;
    function GetOwner(AReader: TdwgReader): TsgDXFEntity; override;
    procedure ReadData(var APBit: TsgInt64); override;
  end;

  TdwgText = class(TdwgEntity)
  private
    FExtrusion: TFPoint;
    FFlags: Integer;
    FGeneration: Byte;
    FHAlign: Byte;
    FHeight: Double;
    FObliqueAngle: Single;
    FPoint: TFPoint;
    FPoint1: TFPoint;
    FRotation: Single;
    FScale: Double;
    FStyle: UInt64;
    FText: string;
    FVAlign: Byte;
  protected
    procedure ApplyValue; virtual;
    function CreateStringReader(var APBit: TsgInt64;
      AVersion: TsgDWGVersion): TdwgStringReader; override;
    procedure ReadData(var APBit: TsgInt64); override;
    procedure ReadEntData(var APBit: TsgInt64); override;
    procedure References(AReader: TdwgReader); override;
  public
    constructor Create; override;
  end;

  TdwgTolerance = class(TdwgEntity)
  private
    FDimlineColor: TsgColorCAD;
    FDimStyle: UInt64;
    FGAP: Double;
  protected
    function ApplyEED(const AEEData: TsgCADExtendedData;
      const AAppID: UInt64): Boolean; override;
    function CanEEDApply(const AAppID: UInt64): Boolean; override;
    function CreateStringReader(var APBit: TsgInt64;
      AVersion: TsgDWGVersion): TdwgStringReader; override;
    procedure ReadData(var APBit: TsgInt64); override;
    procedure ReadEntData(var APBit: TsgInt64); override;
    procedure References(AReader: TdwgReader); override;
  public
    constructor Create; override;
  end;

  TdwgUndefinedEntity = class(TdwgEntity)
  private
    FBitSize: Integer;
    FObjectBeginning: TsgInt64;
  protected
    function GetBitSize: Integer; override;
    function GetObjectBeginning: TsgInt64; override;
    procedure ReadEntData(var APBit: TsgInt64); override;
    procedure SetBitSize(const AValue: Integer); override;
    procedure SetObjectBeginning(const AValue: TsgInt64); override;
  end;

  TdwgVertex = class(TdwgEntity)
  protected
    procedure ReadEntData(var APBit: TsgInt64); override;
  end;

  TdwgViewport = class(TdwgEntity)
  private
    FCount_10: Integer;
    FCount_40: Integer;
    FEntHeaderHandle: UInt64;
    FFrozenLayerCount: Integer;
  protected
    function ApplyEED(const AEEData: TsgCADExtendedData;
      const AAppID: UInt64): Boolean; override;
    function CanEEDApply(const AAppID: UInt64): Boolean; override;
    procedure ReadData(var APBit: TsgInt64); override;
    procedure ReadEntData(var APBit: TsgInt64); override;
    procedure References(AReader: TdwgReader); override;
  end;

  (*// For future versions
  TdwgViewportEntHeader = class(TdwgEntity)
  protected
    FFlags: Integer;
    procedure References(Reader: TdwgReader); override;
    procedure ReadData(var APBit: TsgInt64); override;
  end;
  *)

  TdwgWipeOut = class(TdwgEntity)
  private
    procedure ReadEntDataEx(var APBit: TsgInt64);
  protected
    procedure ReadEntData(var APBit: TsgInt64); override;
  end;

  TdwgAppID = class(TdwgTableItem)
  protected
    procedure ReadData(var APBit: TsgInt64); override;
  end;

  TdwgAcadTable = class(TdwgUndefinedEntity)
  private
    FBlockRecord: UInt64;
    FTableStyle: UInt64;
  protected
    procedure ReadData(var APBit: TsgInt64); override;
    procedure ReadEntData(var APBit: TsgInt64); override;
    procedure References(AReader: TdwgReader); override;
  end;

  TdwgAcadTableStyle = class(TdwgObject)
  private
    FDataTextStyle: UInt64;
    FTitleTextStyle: UInt64;
    FHeaderTextStyle: UInt64;
  protected
    function GetOwner(AReader: TdwgReader): TsgDXFEntity; override;
    procedure ReadData(var APBit: TsgInt64); override;
    procedure References(AReader: TdwgReader); override;
  end;

  TdwgACISEntity = class(TdwgUndefinedEntity)
  protected
    procedure ReadEntData(var APBit: TsgInt64); override;
  end;

  TdwgArc = class(TdwgCircle)
  protected
    procedure ReadEntData(var APBit: TsgInt64); override;
  end;

  TdwgAttdef = class(TdwgText)
  private
    FLockPosition: Boolean;
    FTag: string;
  protected
    procedure ApplyValue; override;
    procedure ReadPrompt(var APBit: TsgInt64); virtual;
    procedure ReadEntData(var APBit: TsgInt64); override;
    procedure References(AReader: TdwgReader); override;
  end;

  TdwgAttrib = class(TdwgAttdef)
  protected
    procedure ReadPrompt(var APBit: TsgInt64); override;
  end;

  TdwgDimension = class(TdwgInsert)
  private
    FStyle: UInt64;
  protected
    procedure ReadData(var APBit: TsgInt64); override;
    procedure ReadEntData(var APBit: TsgInt64); override;
    procedure References(AReader: TdwgReader); override;
  end;

  TdwgImageEnt = class(TdwgWipeout)
  private
    FImageDef: UInt64;
  protected
    procedure ReadData(var APBit: TsgInt64); override;
    procedure References(AReader: TdwgReader); override;
  end;

  TdwgPolyMesh = class(TdwgPolyline)
  protected
    procedure ReadEntData(var APBit: TsgInt64); override;
  end;

  TdwgMInsert = class(TdwgInsert)
  protected
    procedure ReadEntData(var APBit: TsgInt64); override;
  end;

  TdwgPFace = class(TdwgPolyline)
  protected
    procedure ReadEntData(var APBit: TsgInt64); override;
  end;

  TdwgPolyline3D = class(TdwgPolyline)
  protected
    procedure ReadEntData(var APBit: TsgInt64); override;
  end;

  TdwgProxy = class(TdwgUndefinedEntity)
  private
    FList: TList;
    FProps: TList;
  protected
    procedure ReadEntProxyData(var APBit: TsgInt64); override;
    procedure References(AReader: TdwgReader); override;
  public
    constructor Create; override;
    destructor Destroy; override;
  end;

  TdwgMesh = class(TdwgProxy)
  private
    FVertexArray: TFPointList;
    FFaceIndex: TsgIntegerList;
  protected
    procedure ReadEntData(var APBit: TsgInt64); override;
    procedure References(AReader: TdwgReader); override;
  public
    constructor Create; override;
    destructor Destroy; override;
  end;

  TdwgShape = class(TdwgText)
  private
    FShapeNumber: Integer;
  protected
    procedure ReadEntData(var APBit: TsgInt64); override;
    procedure References(AReader: TdwgReader); override;
  end;

  TdwgTrace = class(TdwgSolid)
  end;

  TdwgVertex2D = class(TdwgVertex)
  protected
    procedure ReadEntData(var APBit: TsgInt64); override;
  end;

  TdwgVertexFace = class(TdwgVertex)
  protected
    procedure ReadEntData(var APBit: TsgInt64); override;
  end;

  Tdwg3dSolid = class(TdwgACISEntity)
  end;

  TdwgBody = class(TdwgACISEntity)
  end;

  TdwgDimAligned = class(TdwgDimension)
  protected
    procedure ReadEntData(var APBit: TsgInt64); override;
  end;

  TdwgDimAngular2L = class(TdwgDimension)
  protected
    procedure ReadEntData(var APBit: TsgInt64); override;
  end;

  TdwgDimAngular3P = class(TdwgDimension)
  protected
    procedure ReadEntData(var APBit: TsgInt64); override;
  end;

  TdwgDimLinear = class(TdwgDimension)
  protected
    procedure ReadEntData(var APBit: TsgInt64); override;
  end;

  TdwgDimOrdinate = class(TdwgDimension)
  protected
    procedure ReadEntData(var APBit: TsgInt64); override;
  end;

  TdwgDimRadius = class(TdwgDimension)
  protected
    procedure ReadEntData(var APBit: TsgInt64); override;
    procedure SetFlags; virtual;
  end;

  TdwgDimDiameter = class(TdwgDimRadius)
  protected
    procedure SetFlags; override;
  end;

  TdwgRegion = class(TdwgACISEntity)
  end;

  TdwgDictionaryVar = class(TdwgObject)
  protected
    procedure ReadData(var APBit: TsgInt64); override;
  end;

  TdwgMaterial = class(TdwgObject)
  private
    FOwnerDictionary: TdwgDictionary;
    procedure ReadMaterialColor(var APBit: TsgInt64;
      AMaterialColor: TsgCustomMaterialColor);
    procedure ReadTexMatrix(var APBit: TsgInt64; AMaterialMap: TsgMaterialMap);
    function ReadMapTail(var APBit: TsgInt64;
      AMaterialMap: TsgMaterialMap): Boolean;
  protected
    procedure ReadData(var APBit: TsgInt64); override;
    procedure ReadOwner(AReader: TdwgReader); override;
  end;

  TdwgScale = class(TdwgObject)
  protected
    procedure ReadData(var APBit: TsgInt64); override;
    procedure References(AReader: TdwgReader); override;
  end;

  TdwgObjectContextData = class(TdwgObject)
  private
    FScale: UInt64;
    FBitSize: Integer;
    FObjectBeginning: TsgInt64;
  protected
    function GetBitSize: Integer; override;
    function GetObjectBeginning: TsgInt64; override;
    procedure SetBitSize(const AValue: Integer); override;
    procedure SetObjectBeginning(const AValue: TsgInt64); override;
    procedure ReadData(var APBit: TsgInt64); override;
    procedure References(AReader: TdwgReader); override;
  end;

const
  cnstLimit = {$IFDEF DATA_LINK}98{$ELSE}97{$ENDIF};
  cnstDwgClassTosgDwgClass: array[0..cnstLimit] of record
    Objs: TdwgClass;
    Ents: TsgDXFEntityClass;
  end = (( Objs: nil; Ents: nil),
         ( Objs: TdwgText; Ents: TsgDXFText),
         ( Objs: TdwgAttrib; Ents: TsgDXFAttrib),
         ( Objs: TdwgAttdef; Ents: TsgDXFAttdef),
         ( Objs: TdwgBlock; Ents: TsgDXFBlock),
         ( Objs: nil; Ents: TsgDXFSeqend),
         ( Objs: nil; Ents: TsgDXFSeqend),
         ( Objs: TdwgInsert; Ents: TsgDXFInsert),
         ( Objs: TdwgMInsert; Ents: TsgCADMInsert),
         ( Objs: nil; Ents: nil),
         ( Objs: TdwgVertex2D; Ents: TsgDXFVertex),//VERTEX (2D)
         ( Objs: TdwgVertex; Ents: TsgDXFVertex), //VERTEX (3D)
         ( Objs: TdwgVertex; Ents: TsgDXFVertex), //VERTEX (MESH)
         ( Objs: TdwgVertex; Ents: TsgDXFVertex), //VERTEX (PFACE)
         ( Objs: TdwgVertexFace; Ents: TsgDXFVertex), //VERTEX (PFACE FACE)
         ( Objs: TdwgPolyline; Ents: TsgDXFPolyline),
         ( Objs: TdwgPolyline3D; Ents: TsgDXFPolyline),
         ( Objs: TdwgArc; Ents: TsgDXFArc),
         ( Objs: TdwgCircle; Ents: TsgDXFCircle),
         ( Objs: TdwgLine; Ents: TsgDXFLine),
         ( Objs: TdwgDimOrdinate; Ents: TsgDXFDimension), //20
         ( Objs: TdwgDimLinear; Ents: TsgDXFDimension),
         ( Objs: TdwgDimAligned; Ents: TsgDXFDimension),
         ( Objs: TdwgDimAngular3P; Ents: TsgDXFDimension),
         ( Objs: TdwgDimAngular2L; Ents: TsgDXFDimension),
         ( Objs: TdwgDimRadius; Ents: TsgDXFDimension),
         ( Objs: TdwgDimDiameter; Ents: TsgDXFDimension),
         ( Objs: TdwgPoint; Ents: TsgDXFPoint),
         ( Objs: Tdwg3DFace; Ents: TsgDXF3dFace),
         ( Objs: TdwgPFace; Ents: TsgDXFPolyline),
         ( Objs: TdwgPolyMesh; Ents: TsgDXFPolyline), //30
         ( Objs: TdwgSolid; Ents: TsgDXFSolid),
         ( Objs: TdwgTrace; Ents: TsgDXFTrace),
         ( Objs: TdwgShape; Ents: TsgDXFShape),
         ( Objs: TdwgViewport; Ents: TsgDXFViewport),
         ( Objs: TdwgEllipse; Ents: TsgDXFEllipse),
         ( Objs: TdwgSpline; Ents: TsgDXFSpline),
         ( Objs: TdwgRegion; Ents: TsgDXFRegion),
         ( Objs: Tdwg3dSolid; Ents: TsgDXF3dSolid),
         ( Objs: TdwgBody; Ents: TsgDXFBody),
         ( Objs: nil; Ents: nil),   //40
         ( Objs: nil; Ents: nil),
         ( Objs: TdwgDictionary; Ents: TsgDXFDictionary), //( Objs: nil; Ents: nil), //42
         ( Objs: nil; Ents: nil), //43
         ( Objs: TdwgMText; Ents: TsgDXFMText),
         ( Objs: TdwgLeader; Ents: TsgDXFLeader),
         ( Objs: TdwgTolerance; Ents: TsgDXFTolerance),
         ( Objs: TdwgMLine; Ents: TsgCADMLine), //47
         ( Objs: TdwgBlockControl; Ents: TsgDXFBlockRecords),
         ( Objs: TdwgBlockRecord; Ents: TsgDXFBlockRecord), //49
         ( Objs: TdwgLayerControl; Ents: TsgDXFTable),
         ( Objs: TdwgLayer; Ents: TsgDXFLayer),
         ( Objs: TdwgStyleControl; Ents: TsgDXFTable),
         ( Objs: TdwgStyle; Ents: TsgDXFStyle),
         ( Objs: TdwgImageEnt; Ents: TsgDXFImageEnt),
         ( Objs: TdwgImageDef; Ents: TsgDXFImageDef),
         ( Objs: TdwgLTControl; Ents: TsgDXFTable),
         ( Objs: TdwgLType; Ents: TsgDXFLineType),
         ( Objs: TdwgSortEntsTable; Ents: TsgDXFSortEntsTable),
         ( Objs: nil; Ents: nil),
         ( Objs: nil; Ents: nil), //60
         ( Objs: nil; Ents: nil),
         ( Objs: nil; Ents: nil),
         ( Objs: nil; Ents: nil),
         ( Objs: TdwgVPortControl; Ents: TsgDXFTable),
         ( Objs: TdwgVPort; Ents: TsgDXFVPort),
         ( Objs: TdwgAppIDControl; Ents: TsgDXFTable),
         ( Objs: TdwgAppID; Ents: TsgDXFPenTableItem), //67 - APPID
         ( Objs: TdwgDimStyleControl; Ents: TsgDXFTable),
         ( Objs: TdwgDimStyle; Ents: TsgDXFDimensionStyle),
         ( Objs: nil; Ents: nil),  //70
         ( Objs: nil{TdwgViewportEntHeader}; Ents: nil),
         ( Objs: nil; Ents: nil),
         ( Objs: TdwgMLStyle; Ents: TsgMLineStyle),
         ( Objs: TdwgOLE2Frame; Ents: TsgDXFOLE2Frame),
         ( Objs: nil; Ents: nil),
         ( Objs: nil; Ents: nil),
         ( Objs: TdwgLWPline; Ents: TsgDXFLWPolyline),
         ( Objs: TdwgHatch; Ents: TsgCADHatch),
         ( Objs: TdwgXRecord; Ents: TsgDXFXRecord),
         ( Objs: nil; Ents: nil),
         ( Objs: nil; Ents: nil),
         ( Objs: TdwgLayout; Ents: TsgDXFLayout),
         ( Objs: TdwgProxy; Ents: TsgDXFProxy),
{$IFDEF SG_DWG_IMPORT_ACAD_TABLE}
         ( Objs: TdwgAcadTable; Ents: TsgDXFAcadTable),
{$ELSE}
         ( Objs: TdwgAcadTable; Ents: TsgDXFInsert),
{$ENDIF}
         ( Objs: TdwgWipeout; Ents: TsgCADWipeout),
         ( Objs: TdwgWipeoutVar; Ents: TsgCADWipeoutVariables),
         ( Objs: TdwgMPolygon; Ents: TsgCADMPolygon), //this position undefined
         ( Objs: TdwgProxy; Ents: TsgDXFSurface),
         ( Objs: TdwgDbColor; Ents: TsgDXFCustomColor),
         ( Objs: TdwgAcadTableStyle; Ents: TsgDXFAcadTableStyle),
         ( Objs: TdwgRasterVariables; Ents: TsgCADRasterVariables),
         ( Objs: TdwgPlotSettings; Ents: TsgDXFPlotSettings),
         ( Objs: TdwgDictionaryVar; Ents: TsgDXFDictionaryVar),
         ( Objs: TdwgMesh; Ents: TsgDXFProxy),
         ( Objs: TdwgScale; Ents: TsgDXFScale),
         ( Objs: TdwgMaterial; Ents: TsgDXFMaterial),
         ( Objs: TdwgObjectContextData; Ents: TsgDXFObjectContextData)
{$IFDEF DATA_LINK}
        ,( Objs: TdwgDataLink; Ents: TsgCADDataLink)
{$ENDIF}
         );

var
  FiderCodeFromName :TStringList = nil;

{Fuctions}

procedure InitFiderCodeFromName;
var
  I: Integer;
begin
  if FiderCodeFromName <> nil then
    Exit;
  FiderCodeFromName := TStringList.Create;
  FiderCodeFromName.Capacity := High(cnstNameToCode);
  FiderCodeFromName.Sorted := True;
  FiderCodeFromName.Duplicates := dupIgnore;
{$IFDEF SG_DEL6}
  FiderCodeFromName.CaseSensitive := False;
{$ENDIF}
  for I := Low(cnstNameToCode) to High(cnstNameToCode) do
    FiderCodeFromName.AddObject(cnstNameToCode[I].Name,
      Pointer(cnstNameToCode[I].Code));
end;

function CodeFromName(const AKey: string): Byte;
var
  vIndex: Integer;
begin
  if FiderCodeFromName = nil then
    InitFiderCodeFromName;
  vIndex := FiderCodeFromName.IndexOf(AKey);
  if vIndex > -1 then
    Result := Byte(FiderCodeFromName.Objects[vIndex])
  else
    Result := 0;
end;

{ DWG 2004 support }

function CreateDWGStream(ACADVer: array of AnsiChar; ALocCount,
  AStreamCapacity: Integer): TMemoryStream;
var
  I, vSize, vCountCharInVersion: Integer;
begin
  vSize := SizeOf(Tdwg2004FileHeader);
  Result := TMemoryStream.Create;
  TdwgStream(Result).Capacity := vSize + AStreamCapacity;
  Result.Size := vSize;
  Result.Position := vSize;
  Tdwg2004FileHeader(Result.Memory^).LocCount := ALocCount;
  vCountCharInVersion := High(ACADVer);
  FillChar(Result.Memory^, vSize, 0);
  if High(Tdwg2004FileHeader(Result.Memory^).VersionID) < vCountCharInVersion then
    vCountCharInVersion := High(Tdwg2004FileHeader(Result.Memory^).VersionID);
  for I := 0 to vCountCharInVersion do
    Tdwg2004FileHeader(Result.Memory^).VersionID[I] := ACADVer[I];
end;

procedure GetCount(const AValue: TsgNativeUInt; var ASrc: PByte; var ACount: TsgNativeInt);
begin
  ACount := AValue;
  while ASrc^ = 0 do
  begin
    Inc(ACount, 255);
    Inc(ASrc);
  end;
  Inc(ACount, ASrc^);
  Inc(ASrc);
end;

//procedure DoMove(var ASrc, ADst: PByte; ACount, ATail: TsgNativeUInt;
//  AOffset: TsgNativeInt); register;
//var
//  vSrcTemp: PByte;
//begin
//  if AOffset >= 0 then
//  begin
//    vSrcTemp := ASrc;
//    ASrc := ADst;
//    Dec(ASrc, AOffset);
//    if AOffset < ACount then
//    begin
//      while ACount > 0 do
//      begin
//        ADst^ := ASrc^;
//        Inc(ASrc);
//        Inc(ADst);
//        Dec(ACount);
//      end;
//    end
//    else
//    begin
//      Move(ASrc^, ADst^, ACount);
//      Inc(ADst, ACount);
//    end;
//    ASrc := vSrcTemp;
//  end
//  else
//  begin
//    Move(ASrc^, ADst^, ACount);
//    Inc(ASrc, ACount);
//    Inc(ADst, ACount);
//  end;
//  Move(ASrc^, ADst^, ATail);
//  Inc(ASrc, ATail);
//  Inc(ADst, ATail);
//end;
procedure DoMove(var ASrc, ADst: PByte; ACount, ATail: TsgNativeUInt;
  AOffset: TsgNativeInt); register;
{$IFDEF SG_CPUX64}
asm
    PUSH      RSI
    PUSH      RDI
    MOV       RSI,[RCX]     // ASrc
    XCHG      RCX,R8        // R8=ASrc, RCX=ACount
    MOV       RDI,[RDX]     // ADst
    MOV       RAX,AOffset
    OR        RAX,RAX
    JS        @@1
    MOV       RSI,RDI
    SUB       RSI,RAX
@@1: REP       MOVSB
    OR        RAX,RAX
    JNS       @@2
    MOV       [R8],RSI
@@2: MOV       RSI,[R8]
    MOV       RCX,R9        // ATail
    REP       MOVSB
    MOV       [R8],RSI
    MOV       [RDX],RDI
    POP       RDI
    POP       RSI
end;
{$ELSE}
// EAX = ASrc
// EDX = ADst
// ECX = ACount
asm
    PUSH      ESI
    PUSH      EDI
    PUSH      EBX
    MOV       EBX,EAX
    MOV       ESI,[EAX]
    MOV       EDI,[EDX]
    MOV       EAX,AOffset
    OR        EAX,EAX
    JS        @@1
    MOV       ESI,EDI
    SUB       ESI,EAX
@@1: REP       MOVSB
    OR        EAX,EAX
    JNS       @@2
    MOV       [EBX],ESI
@@2: MOV       ESI,[EBX]
    MOV       ECX,ATail
    REP       MOVSB
    MOV       [EBX],ESI
    MOV       [EDX],EDI
    POP       EBX
    POP       EDI
    POP       ESI
end;
{$ENDIF}
procedure DoDecode2004(AStream: TMemoryStream; ASrc: PByte;
  APSize, AUSize: Integer);
var
  vDst, vLimit, vLimit2: PByte;
  vCount: TsgNativeInt;
  vCount1, vTail: TsgNativeUInt;
  vOffset: TsgNativeInt;
  vCode: Byte;
begin
  vCount := AStream.Position + AUSize;
//  if USize > $7400 then
//    USize := $7400;
  if AStream.Size < vCount then
    AStream.Size := vCount;
  vDst := AStream.Memory;
  Inc(vDst, AStream.Position);
  AStream.Position := AStream.Position + AUSize;
  vLimit := vDst;
  Inc(vLimit, AUSize);
  vLimit2 := ASrc;
  Inc(vLimit2,APSize);
  while (PAnsiChar(vDst) < PAnsiChar(vLimit)) and
        (PAnsiChar(ASrc) < PAnsiChar(vLimit2)) do
  begin
    vCode := ASrc^;
    Inc(ASrc);
    case vCode of
      $00..$0F:
        begin
          if vCode=0 then
            GetCount(18, ASrc, vCount)
          else
            vCount := vCode + 3;
          vOffset := TsgNativeInt(1) shl (SizeOf(TsgNativeInt) shl 3 - 1);
        end;
      $10..$1F:
        begin
          if vCode=$10 then
            GetCount(9, ASrc, vCount)
          else
            vCount := vCode and $F + 2;
          vOffset := PWord(ASrc)^ + $10000 - 4; Inc(ASrc,2);
        end;
      $20..$3F:
        begin
          if vCode=$20 then
            GetCount(33, ASrc, vCount)
          else
            vCount := vCode and $1F + 2;
          vOffset := PWord(ASrc)^; Inc(ASrc,2);
        end;
      else
        begin
          vCount := vCode shr 4 - 1;
          vOffset := ASrc^ shl 4 + vCode and $F;
          Inc(ASrc);
        end;
    end;
    vTail := vOffset and 3;
    if vOffset >= 0 then
      vOffset := vOffset shr 2 + 1;
    vCount1 := TsgNativeUInt(vLimit) - TsgNativeUInt(vDst) - vTail;
    if vCount > TsgNativeInt(vCount1) then
    begin
      vCount := vCount1;
      if vCount < 0 then
      begin
        vCount := TsgNativeUInt(vLimit) - TsgNativeUInt(vDst);
        vTail := 0;
      end;
    end;
    DoMove(ASrc, vDst, vCount, vTail, vOffset);
  end;
end;

procedure Decode2004(const APointer: Pointer; AStream: TMemoryStream);
var
  vSrc, vDst: PByte;
  vPSize, vUSize: Integer;
  vPHead: PInteger;
begin
  vSrc := APointer;
  Inc(vSrc,$14);
  Move(APointer, vPHead, SizeOf(vPHead));
//  vPHead := P;
  Inc(vPHead);
  vUSize := PInteger(vPHead)^ + 4;
  Inc(vPHead);
  vPSize := vPHead^ - 3;
  AStream.Size := 0;
  DoDecode2004(AStream, vSrc, vPSize, vUSize);
  vDst := AStream.Memory;
  Inc(vDst, AStream.Size-4);
  PInteger(vDst)^ := 0;
end;

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

procedure ScanHeader2004(AStream: TMemoryStream; var ADst: array of PHead2004Rec);
var
  vPHead2004,vLimit: PHead2004Rec;
  I: Integer;
  vName: AnsiString;
begin
  for I := 0 to High(ADst) do
    ADst[I] := nil;
  vPHead2004 := AStream.Memory;
  vLimit := vPHead2004;
  Inc(PByte(vPHead2004), $74);
  Inc(PByte(vLimit), AStream.Size-$60);
  while PAnsiChar(vPHead2004) < PAnsiChar(vLimit) do
  begin
    vName := vPHead2004.Name;
    if vName = '' then
      Exit;
    if vName = 'Header' then
      I := cntDWGSectHeaderIndex
    else
      if vName = 'Classes' then
        I := cntDWGSectClassesIndex
    else
      if vName = 'Handles' then
        I := cntDWGSectHandlesIndex
    else
      if vName = 'AcDbObjects' then
        I := cntDWGSectObjectsIndex
    else
      if vName = 'SummaryInfo' then
        I := cntDWGSectSummaryInfoIndex
    else
      I := -1;
    if (I >= 0) and (vPHead2004.Extra > 0) then
    begin
      ADst[I] := vPHead2004;
      if I=1 then Dec(vPHead2004.UnpackSize, 8);
    end;
    Inc(PByte(vPHead2004), vPHead2004.Extra shl 4 + $60);
  end;
end;

function SecSize(ANumber: array of Integer;
  ASections: array of PHead2004Rec): Integer;
var
  I : Integer;
begin
  Result := 0;
  for I := Low(ANumber) to High(ANumber) do
  begin
    if ASections[ANumber[I]] <> nil then
      Inc(Result,ASections[ANumber[I]].UnpackSize);
  end;
end;

procedure DoSection2004(AStream: TCustomMemoryStream; ANumber: array of Integer;
  ADwgSteram: TMemoryStream; ASections: TsgSectionsArray;
  vTable: TsgTableArray);
var
  vPFileHeader2004: Pdwg2004FileHeader;
  vPHead: PHead2004Rec;
  vSrc: PByte;
  I, U,V,E: Integer;
begin
  for I := Low(ANumber) to High(ANumber) do
  begin
    vPFileHeader2004 := ADwgSteram.Memory;
    vPHead := ASections[ANumber[I]];
    if vPHead <>nil then
    begin
      U := vPHead.UnpackSize;
      E := vPHead.Extra;
      vPFileHeader2004.Locators[ANumber[I]].RecNumber := ANumber[I];
      vPFileHeader2004.Locators[ANumber[I]].Seeker := ADwgSteram.Size;
      vPFileHeader2004.Locators[ANumber[I]].Size := vPHead.UnpackSize;
      while E > 0 do
      begin
        if vPHead.Index and not 4095 <> 0 then
          Break;
        vSrc := AStream.Memory;
        Inc(vSrc, vTable[vPHead.Index]);
        V := U;
        if V > $7400 then
          V := $7400;
        DoDecode2004(ADwgSteram, vSrc, vPHead.PackSize, V);
        Inc(PAnsiChar(vPHead),$10);
        Dec(U,$7400);
        Dec(E);
      end;
    end;
  end;
end;

function Unpack2004(AVesrsion: TsgDWGVersion; AStream: TCustomMemoryStream;
  var ASecCount: Integer): TMemoryStream;
var
  vOutStream: TMemoryStream;
  vDwgSteram: TMemoryStream;
  vPByte: PByte;
  vPInteger: PInteger;
  I,N,RS: Integer;
  vRoot: array[0..127] of Byte;
  vTable: TsgTableArray;
  vSections: TsgSectionsArray;
begin
  vOutStream := TMemoryStream.Create;
  try
    ASecCount := 5;
    Result := nil;
    vPByte := PByte(AStream.Memory);
    Inc(vPByte,$80);
    RS := 1;
    for I := 0 to $7F do begin
      RS := RS * $343FD + $269EC3;
      vRoot[I] := vPByte^ xor (RS shr 16);
      Inc(vPByte);
    end;
    vPByte := @vRoot[$54];
    I := PInteger(vPByte)^ + $100;
    vPByte := PByte(AStream.Memory);
    Inc(vPByte,I);
    Decode2004(vPByte,vOutStream);
    FillChar(vTable[0], SizeOf(vTable), 0);
    vPInteger := Pinteger(vOutStream.Memory);
    RS := $120;
    N := vOutStream.Size shr 3;
    while N > 0 do
    begin
      I := vPInteger^; Inc(vPInteger);
      if I and not 4095 = 0 then vTable[I] := RS;
      I := vPInteger^; Inc(vPInteger);
      if (I >= 0) and (I < AStream.Size) then Inc(RS,I);
      Dec(N);
    end;
    vPByte := @vRoot[$5C];
    I := vTable[PInteger(vPByte)^] - $20;
    vPByte := PByte(AStream.Memory);
    Inc(vPByte,I);
    Decode2004(vPByte,vOutStream);
    ScanHeader2004(vOutStream,vSections);
    vDwgSteram := CreateDWGStream(['A', 'C', '1', '0', '1', '8'], ASecCount,
      SecSize([0, 1, 2, 3, 4], vSections));
    DoSection2004(AStream,[0, 1, 2, 3, 4],vDwgSteram,vSections,vTable);
    Result := vDwgSteram;
  finally
    vOutStream.Free;
  end;
end;


{ DWG 2007 support }

{$IFNDEF SGDEL_4}
function UnpackR18Plus(AStream: TCustomMemoryStream): TMemoryStream;
begin
  Result := nil;
  raise EdwgError.CreateFmt(sDWGCompilerError, ['2007']);
end;

function UnpackR24(AStream: TCustomMemoryStream): TMemoryStream;
begin
  Result := nil;
  raise EdwgError.CreateFmt(sDWGCompilerError, ['2010']);
end;

{$ELSE}

const
  cDWGSectCount = 5;


function Page2007Decode(Dest, Source: PAnsiChar; DstSize, SrcSize, Factor: Cardinal;
  const ACoder: TsgRSCoder): Boolean;
var
  vBuf: array[0..$FF + 1] of Byte;
  I, vDataSize, vCopySize: Cardinal;
  vLen: Integer;
  vCurDst, vCurSrc, vDstEnd, vSrcEnd: PAnsiChar;
begin
  Result := True;
  vDataSize := DstSize;
  vDstEnd := Dest;
  Inc(vDstEnd, DstSize);
  vSrcEnd := Source;
  Inc(vSrcEnd, SrcSize);
  I := 0;
  while I < Factor do
  begin
    if Dest > vDstEnd then Exit;
    if Source > vSrcEnd then Exit;
    vCurDst := @vBuf;
    vCurSrc := Source;
    vLen := $FF - 1;
    while vLen >= 0 do
    begin
      if vCurSrc > vSrcEnd then Exit;
      vCurDst^ := vCurSrc^;
      Inc(vCurSrc, Factor);
      Inc(vCurDst);
      Dec(vLen);
    end;
    if ACoder.Decode(PAnsiChar(@vBuf)) < 0 then
      raise EsgRSCoderError.Create(sRSDecoderError);
    vCopySize := Math.Min(vDataSize, ACoder.DSize);
    Dec(vDataSize, vCopySize);
    Move(vBuf, Dest^, vCopySize);
    Inc(Dest, vCopySize);
    Inc(Source);
    Inc(I);
  end;
end;

function LoadPage(FileOffset: Cardinal; SizeCompr, SizeSrc, Factor: Int64;
  AStream: TCustomMemoryStream; ACoder: TsgRSCoder;
  ADecomp: TsgDWG2007Decompressor; var Data: PByte; var DataSize: Int64): Integer;
var
  vSizeSrc, vSizeCompr, vAlignedSize, vDstSize: Int64;
  vFactor, vFilePageSize: Cardinal;
  vPageData, vCmprData: PByte;
begin
  Result := 0;
  vSizeCompr := SizeCompr;
  vSizeSrc := SizeSrc;
  vAlignedSize := (vSizeCompr + 7) and $FFFFFFF8;
  vDstSize := vAlignedSize * Factor;
  vFactor := (ACoder.DSize + vDstSize - 1) div ACoder.DSize;
  vFilePageSize := (vFactor * $FF + $FF) and $FFFFFF00;
  GetMem(vPageData, vFilePageSize);
  vCmprData := nil;
  try
    AStream.Position := $80 + $400 + FileOffset;
    AStream.Read(vPageData^, vFilePageSize);
    GetMem(vCmprData, vDstSize);
    Page2007Decode(PAnsiChar(vCmprData), PAnsiChar(vPageData), vDstSize, vFilePageSize,
      vFactor, ACoder);
    ADecomp.Decompress(PAnsiChar(vCmprData), vSizeCompr, PAnsiChar(vPageData), vSizeSrc);
    GetMem(Data, vSizeSrc);
    Move(vPageData^, Data^, vSizeSrc);
    DataSize := vSizeSrc;
  finally
    if Assigned(vCmprData) then
      FreeMem(vCmprData);
    FreeMem(vPageData);
  end;
end;

procedure CreateDWG2007PgsLst(var APages: TList; const APagesMaxId: UInt64);
var
  I: Integer;
  PPage: PsgDWG2007Page;
begin
  if APages = nil then
    APages := TList.Create;
  for I := 0 to APagesMaxId + 1 do
  begin
    New(PPage);
    FillChar(PPage^, SizeOf(TsgDWG2007Page), 0);
    APages.Add(PPage);
  end;
end;

procedure ClearDWG2007PgsLst(var APages: TList);
begin
  ClearRecordList(APages);
  APages.Free;
end;

function IsSectonAllowed(const ASectName: WideString; AddSections: array of string): Boolean;
const
  cSection: array[0..cDWGSectCount] of WideString = (sAcadSectHeader, sAcadSectClasses,
    sAcadSectHandles, sAcadSectObjects, sAcadSectSummaryInfo, sAcadSectTemplate);
var
  I: Integer;
  S: WideString;
begin
  S := WideUpperCase(ASectName);
  for I := 0 to High(cSection) do
  begin
    Result := WideUpperCase(cSection[I]) = S;
    if Result then Break;
  end;
  if not Result then
    for I := Low(AddSections) to High(AddSections) do
    begin
      Result := WideUpperCase(AddSections[I]) = S;
      if Result then Break;
    end;
end;

function GetSecIndByName(const ASectionName: WideString): Integer;
begin
  Result := -1;
  if ASectionName = sAcadSectHeader then
    Result := cntDWGSectHeaderIndex;
  if ASectionName = sAcadSectClasses then
    Result := cntDWGSectClassesIndex;
  if ASectionName = sAcadSectHandles then
    Result := cntDWGSectHandlesIndex;
  if ASectionName = sAcadSectObjects then
    Result := cntDWGSectObjectsIndex;
  if ASectionName = sAcadSectSummaryInfo then
    Result := cntDWGSectSummaryInfoIndex;
  if ASectionName = sAcadSectTemplate then
    Result := cntDWGSectTemplateIndex;
end;

procedure DoSection(PHead: Pdwg2004FileHeader; ANumber: Integer;
  const ASecStream, AStream: TStream);
begin
  PHead^.Locators[ANumber].RecNumber := ANumber;
  PHead^.Locators[ANumber].Seeker := AStream.Size;
  PHead^.Locators[ANumber].Size := ASecStream.Size;
  AStream.CopyFrom(ASecStream, 0);
end;

function UnpackR18Plus(AVersion: TsgDWGVersion; AStream: TCustomMemoryStream;
  var ASecCount: Integer): TMemoryStream;
const
  cFactor = 3;
  cPoly0: array[0..7] of Byte = (1, 0, 1, 1, 1, 0, 0, 0);
  cPoly1: array[0..7] of Byte = (1, 0, 0, 1, 0, 1, 1, 0);
  cFileHeaderSize = $110;
  cInt64SysSize = SizeOf(Int64);
var
  vChData: TsgDWG2007ChData;
  vSize, vId, vOffset: Int64;
  vStream: TMemoryStream;
  vDstSize, vVal, vLen1, vLen2: Cardinal;
  vRSSys, vRSSec: TsgRSCoder;
  vCmprData, vData: PByte;
  vDecomp: TsgDWG2007Decompressor;
  vHeader: TsgDwg2007FileHeader;
  vPages: TList;
  I, J: Integer;
  vPage: TsgDWG2007Page;
  PPage: PsgDWG2007Page;
  vSection: TsgDwg2007Section;
  vSections: array[0..cDWGSectCount] of TsgDwg2007Section;
  PSrmPage: PsgDwg2007StreamPage;
  PHead: Pdwg2004FileHeader;

  procedure StreamPageDecode(var ASection: TsgDwg2007Section;
    const APage: TsgDWG2007StreamPage);
  var
    vId, vPos, vOffset, vPageDstSize, vFactor, vAlignedSize: Int64;
    vSecData, P: PByte;
    PPage: PsgDwg2007Page;
  begin
    vId := APage.PageId;
    if vId < 0 then
      PPage := vPages[0 - vId]
    else
      PPage := vPages[vId];
    vOffset := $80 + $400 + PPage^.Offset;

    GetMem(vSecData, PPage^.Size);
    try
      AStream.Position := vOffset;
      AStream.Read(vSecData^, PPage^.Size);

      vAlignedSize := ((APage.ComprSize + 8) - 1) and $FFFFFFF8;
      if ASection.Encoded = 4 then
      begin
        vFactor := (vRSSec.DSize + vAlignedSize - 1) div vRSSec.DSize;
        vPageDstSize := vFactor * vRSSec.DSize;
        GetMem(P, vPageDstSize);
        try
          Page2007Decode(PAnsiChar(P), PAnsiChar(vSecData), vPageDstSize, PPage^.Size,
            vFactor, vRSSec);
          FreeMem(vSecData);
          GetMem(vSecData, vPageDstSize);
          Move(P^, vSecData^, vPageDstSize);
        finally
          FreeMem(P);
        end;
      end;
      if ASection.Data = nil then
        ASection.Data := TMemoryStream.Create;
      ASection.Data.Position := ASection.Data.Size;
      vPos := ASection.Data.Position;
      ASection.Data.Size := ASection.Data.Size + APage.DataSize;
      P := ASection.Data.Memory;
      Inc(P, vPos);
      FillChar(P^, APage.DataSize, 0);
      if APage.DataSize <> APage.ComprSize then
        vDecomp.Decompress(PAnsiChar(vSecData), APage.ComprSize, PAnsiChar(P), APage.DataSize)
      else
        Move(vSecData^, P^, APage.DataSize);
    finally
      FreeMem(vSecData);
    end;
  end;

  function GetSectionsSummmary: Integer;
  var
    I: Integer;
  begin
    Result := 0;
    for I := 0 to High(vSections) do
      if (vSections[I].Data <> nil) then
        Result := Result + vSections[I].Data.Size;
  end;

  procedure ClearSection(var ASection: TsgDwg2007Section);
  begin
    FillChar(ASection, cInt64SysSize * 8, 0);
    ASection.SecName := '';
    ASection.Pages := nil;
    ASection.Data := nil;
  end;

begin
  FillChar(vChData, SizeOf(TsgDWG2007ChData), 0);
  vStream := TMemoryStream.Create;
  Result := nil;
  vCmprData := nil;
  vData := nil;
  vDecomp := nil;
  vRSSys := nil;
  vRSSec := nil;
  vPages := nil;
  ASecCount := 6;
  try
    AStream.Position := $80;
    vStream.CopyFrom(AStream, $400);
    GetMem(vData, vStream.Size);
    vStream.Position := 0;
    vStream.Read(vData^, vStream.Size);

    vStream.Position := $3D8;
    vStream.Read(vChData, SizeOf(TsgDWG2007ChData));

    vRSSec := TsgRSCoder.Create;
    vRSSec.Generate(cPoly0, 8, 2);

    vRSSys := TsgRSCoder.Create;
    vRSSys.Generate(cPoly1, 8, 8);

    vDstSize := vRSSys.DSize + 2 * vRSSys.DSize;

    GetMem(vCmprData, vDstSize);
    Page2007Decode(PAnsiChar(vCmprData), PAnsiChar(vData), vDstSize, $400, cFactor, vRSSys);

    vStream.Clear;
    vStream.Write(vCmprData^, vDstSize);
    (*
      vCmprData is Header page info
      The first 16 bytes are CRC of Header page (two Int64 values CheckCrc and CheckVal), we skip this information.
      Next is CRC of compressed data, we skip it also
    *)
    vStream.Position := 24;
    vStream.Read(vLen1, SizeOf(vLen1));
    vStream.Read(vLen2, SizeOf(vLen2));
    if vLen1 > cFileHeaderSize then
      raise EdwgError.Create(sDWG2007HeaderError);

    vVal := vDstSize - vStream.Position;
    FreeMem(vData);
    GetMem(vData, cFileHeaderSize);

    vStream.Read(vCmprData^, vVal);
    vDecomp := TsgDWG2007Decompressor.Create;
    vDecomp.Decompress(PAnsiChar(vCmprData), vLen1, PAnsiChar(vData), cFileHeaderSize);
    vStream.Clear;
    vStream.Write(vData^, cFileHeaderSize);
    vStream.Position := 0;
    vStream.Read(vHeader, SizeOf(TsgDwg2007FileHeader));

    FreeMem(vData);//PagesMap load begin
    LoadPage(vHeader.PagesMapOffset, vHeader.PagesMapSizeCompr,
      vHeader.PagesMapSizeSrc, vHeader.PagesMapFactor,
      AStream, vRSSys, vDecomp, vData, vSize);

    vStream.Clear;
    vStream.Write(vData^, vSize);
    vStream.Position := 0;

    CreateDWG2007PgsLst(vPages, vHeader.PagesMaxId);

    vOffset := 0;
    while True do
    begin
      if vStream.Read(vSize, cInt64SysSize) = 0 then Break;
      if vStream.Read(vId, cInt64SysSize) = 0 then Break;
      if Abs(vId) > vHeader.PagesMaxId then Continue;
      if vId < 0 then
        PPage := vPages[0 - vId]
      else
        PPage := vPages[vId];
      PPage^.Id := vId;
      PPage^.Size := vSize;
      PPage^.Offset := vOffset;
      Inc(vOffset, vSize);
    end;//PagesMap is loaded

    vPage := PsgDwg2007Page(vPages[vHeader.SectionsMapId])^;
    FreeMem(vData);

    LoadPage(vPage.Offset, vHeader.SectionsMapSizeCompr,
      vHeader.SectionsMapSizeSrc, vHeader.SectionsMapFactor,
      AStream, vRSSys, vDecomp, vData, vSize);

    vStream.Clear;
    vStream.Write(vData^, vSize);
    vStream.Position := 0;
    for I := 0 to High(vSections) do
      ClearSection(vSections[I]);
    while True do
    begin
      ClearSection(vSection);
      if vStream.Position = vStream.Size then Break;

      if vStream.Read(vSection, cInt64SysSize * 8) <> cInt64SysSize * 8 then Break;
      if (vSection.SecNameLen = 0) and (vSection.PagesAmount = 0) then Continue;

      if vSection.SecNameLen > 0 then
      begin
        SetLength(vSection.SecName, vSection.SecNameLen shr 1);
        if vStream.Read(vSection.SecName[1], vSection.SecNameLen) <> vSection.SecNameLen then Break;
        if vSection.SecName[Length(vSection.SecName)] = #0 then
            vSection.SecName := Copy(vSection.SecName, 1, Length(vSection.SecName) - 1);
      end;

      if vStream.Position = vStream.Size then Break;

      if (vSection.PagesAmount = 0) or (vSection.PagesAmount < 0) or
        (vSection.PagesAmount > vHeader.PagesMaxId + 1) then Continue;

      if not IsSectonAllowed(vSection.SecName, []) then
      begin
        vStream.Position := vStream.Position + vSection.PagesAmount * SizeOf(TsgDWG2007StreamPage);
        Continue;
      end;

      vSection.Pages := TList.Create;
      for I := 0 to vSection.PagesAmount - 1 do
      begin
        New(PSrmPage);
        vStream.Read(PSrmPage^, SizeOf(TsgDWG2007StreamPage));
        vSection.Pages.Add(PSrmPage);
      end;

      for I := 0 to vSection.Pages.Count - 1 do
      begin
        try
          StreamPageDecode(vSection, PsgDwg2007StreamPage(vSection.Pages[I])^);
        except
          Continue;
        end;
      end;
      vSections[GetSecIndByName(vSection.SecName)] := vSection;
    end;
    Result := CreateDWGStream(['A', 'C', '1', '0', '2', '1'], ASecCount,
      GetSectionsSummmary);
    for I := 0 to High(vSections) do
    begin
      if vSections[I].Data = nil then
        Continue;
      PHead := Result.Memory;
      DoSection(PHead, I, vSections[I].Data, Result);
      vSections[I].Data.Free;
      for J := 0 to vSections[I].Pages.Count - 1 do
        Dispose(vSections[I].Pages[J]);
      vSections[I].Pages.Free;
      vSections[I].SecName := '';
    end;
  finally
    if vCmprData <> nil then
      FreeMem(vCmprData);
    if vData <> nil then
      FreeMem(vData);
    vDecomp.Free;
    vStream.Free;
    vRSSec.Free;
    vRSSys.Free;
    ClearDWG2007PgsLst(vPages);
  end;
end;

{ TsgDWG2007Decompressor }

{private}

procedure TsgDWG2007Decompressor.GetCmpData(ADest: PAnsiChar; ALength,
  AOffset: Integer);
var
  vDstPrev: PAnsiChar;
begin
  vDstPrev := ADest;
  Dec(vDstPrev, AOffset);
  if ADest > FDstEnd then
    Exit;
  if ALength < AOffset then
  begin
    if ADest + ALength <= FDstEnd then
      Move(vDstPrev^, ADest^, ALength)
  end
  else
    while ALength > 0 do
    begin
      Dec(ALength);
      ADest^ := vDstPrev^;
      Inc(ADest);
      if ADest > FDstEnd then Break;
      Inc(vDstPrev);
    end;
end;

procedure TsgDWG2007Decompressor.GetCmpOpcode;
var
  vVal: Cardinal;
begin
  vVal := FOpCode shr 4;
  case vVal of
    0:
      begin
        FLength := (FOpCode and $0F) + $13;
        FOffset := Byte(FSrc^);
        Inc(FSrc);
        if FSrc > FSrcEnd then
          Exit;
        FOpCode := Byte(FSrc^);
        Inc(FSrc);
        if FSrc > FSrcEnd then
          Exit;
        FLength := ((FOpCode shr 3) and $10) + FLength;
        FOffset := ((FOpCode and $78) shl 5) + 1 + FOffset;
      end;
    1:
      begin
        FLength := (FOpCode and $0F) + 3;
        FOffset := Byte(FSrc^);
        Inc(FSrc);
        if FSrc > FSrcEnd then
          Exit;
        FOpCode := Byte(FSrc^);
        Inc(FSrc);
        if FSrc > FSrcEnd then
          Exit;
        FOffset := ((FOpCode and $F8) shl 5) + FOffset + 1;
      end;
    2:
      begin
        FOffset := Byte(FSrc^);
        Inc(FSrc);
        if FSrc > FSrcEnd then
          Exit;
        FOffset := ((Byte(FSrc^) shl 8) and $0FF00) or FOffset;
        Inc(FSrc);
        if FSrc > FSrcEnd then
          Exit;
        FLength := FOpCode and 7;
        if (FOpCode and 8) = 0 then
        begin
          FOpCode := Byte(FSrc^);
          Inc(FSrc);
          if FSrc > FSrcEnd then Exit;
          FLength := (FOpCode and $0F8) + FLength;
        end
        else
        begin
          Inc(FOffset);
          FLength := Byte(FSrc^) * 8 + FLength;
          Inc(FSrc);
          if FSrc > FSrcEnd then Exit;
          FOpCode := Byte(FSrc^);
          Inc(FSrc);
          if FSrc > FSrcEnd then Exit;
          FLength := ((FOpCode and $0F8) shl 8) + FLength + $100;
        end;
      end;
  else
    begin
      FLength := FOpCode shr 4;
      FOffset := FOpCode and $0F;
      FOpCode := Byte(FSrc^);
      Inc(FSrc);
      if FSrc > FSrcEnd then Exit;
      FOffset := (FOpCode and $0F8) * 2 + FOffset + 1;
    end;
  end;
end;


type
  TsgMover = (mv0, mv1, mv2, mv3, mv4, mv5, mv6, mv7, mv8, mv9, mvA, mvB, mvC,
    mvD, mvE, mvF, mv10, mv11, mv12, mv13, mv14, mv15, mv16, mv17, mv18, mv19,
    mv1A, mv1B, mv1C, mv1D, mv1E, mv1F, mvO1, mvO2, mvO3, mvO4, mvO8, mvO16);

procedure MassOperation(ADest, ASource: PAnsiChar; AMassOper: array of TsgMover);
var
  I: Integer;
  vDest, vSource: PAnsiChar;
begin
  for I := Low(AMassOper) to (High(AMassOper) div 3) do
  begin
    vDest := ADest+Ord(AMassOper[I*3+1]);
    vSource := ASource+Ord(AMassOper[I*3+2]);
    case TsgMover(AMassOper[I*3]) of
      mvO1: vDest^ := vSource^;
      mvO2: begin
               vDest[0] := vSource[1];
               vDest[1] := vSource[0];
             end;
      mvO3: begin
               vDest[0] := vSource[2];
               vDest[1] := vSource[1];
               vDest[2] := vSource[0];
             end;
      mvO4: PCardinal(vDest)^ := PCardinal(vSource)^;
      mvO8: begin
               PCardinal(vDest)^ := PCardinal(vSource)^;
               PCardinal(vDest+4)^ := PCardinal(vSource+4)^;
             end;
      mvO16: begin
                PCardinal(vDest)^ := PCardinal(vSource+8)^;
                PCardinal(vDest+4)^ := PCardinal(vSource+8+4)^;
                PCardinal(vDest+8)^ := PCardinal(vSource)^;
                PCardinal(vDest+8+4)^ := PCardinal(vSource+4)^;
             end;
    end;
  end;
end;

procedure TsgDWG2007Decompressor.GetLiteralData(ADest, ASource: PAnsiChar; ALength: Integer);
var
  vLen: Integer;
begin
  while ALength >= $20 do
  begin
    MassOperation(ADest, ASource,[mvO4, mv0, mv18, mvO4, mv4, mv1C,
      mvO4, mv8, mv10, mvO4, mvC, mv14, mvO4, mv10, mv8, mvO4, mv14, mvC,
      mvO4, mv14, mvC, mvO4, mv18, mv0, mvO4, mv1C, mv4]);
    Inc(ASource, $20);
    Inc(ADest, $20);
    Dec(ALength, $20);
  end;
  vLen := ALength - 1;

  if vLen > $1E then
    Exit;

  case vLen of
    0: MassOperation(ADest, ASource,[mvO1,mv0,mv0]);
    1: MassOperation(ADest, ASource,[mvO2,mv0,mv0]);
    2: MassOperation(ADest, ASource,[mvO3,mv0,mv0]);
    3: MassOperation(ADest, ASource,[mvO4,mv0,mv0]);
    4: MassOperation(ADest, ASource,[mvO1,mv0,mv4,mvO4,mv1,mv0]);
    5: MassOperation(ADest, ASource,[mvO1,mv0,mv5,mvO4,mv1,mv1,mvO1,mv5,mv0]);
    6: MassOperation(ADest, ASource,[mvO2,mv0,mv5,mvO4,mv2,mv1,mvO1,mv6,mv0]);
    7: MassOperation(ADest, ASource,[mvO8,mv0,mv0]);
    8: MassOperation(ADest, ASource,[mvO1,mv0,mv8,mvO8,mv1,mv0]);
    9: MassOperation(ADest, ASource,[mvO1,mv0,mv9,mvO8,mv1,mv1,mvO1,mv9,mv0]);
    10: MassOperation(ADest, ASource,[mvO2,mv0,mv9,mvO8,mv2,mv1,mvO1,mvA,mv0]);
    11: MassOperation(ADest, ASource,[mvO4,mv0,mv8,mvO8,mv4,mv0]);
    12: MassOperation(ADest, ASource,[mvO1,mv0,mvC,mvO4,mv1,mv8,mvO8,mv5,mv0]);
    13: MassOperation(ADest, ASource,[mvO1,mv0,mvD,mvO4,mv1,mv9,
          mvO8,mv5,mv1,mvO1,mvD,mv0]);
    14: MassOperation(ADest, ASource,[mvO2,mv0,mvD,mvO4,mv2,mv9,
          mvO8,mv6,mv1,mvO1,mvE,mv0]);
    15: MassOperation(ADest, ASource,[mvO16,mv0,mv0]);
    16: MassOperation(ADest, ASource,[mvO8,mv0,mv9,mvO1,mv8,mv8,mvO8,mv9,mv0]);
    17: MassOperation(ADest, ASource,[mvO1,mv0,mv11,mvO16,mv1,mv1,
          mvO1,mv11,mv0]);
    18: MassOperation(ADest, ASource,[mvO3,mv0,mv10,mvO16,mv3,mv0]);
    19: MassOperation(ADest, ASource,[mvO4,mv0,mv10,mvO8,mv4,mv8,mvO8,mvC,mv0]);
    20: MassOperation(ADest, ASource,[mvO1,mv0,mv14,mvO4,mv1,mv10,
          mvO8,mv5,mv8,mvO8,mvD,mv0]);
    21: MassOperation(ADest, ASource,[mvO2,mv0,mv14,mvO4,mv2,mv10,
          mvO8,mv6,mv8,mvO8,mvE,mv0]);
    22: MassOperation(ADest, ASource,[mvO3,mv0,mv14,mvO4,mv3,mv10,
          mvO8,mv7,mv8,mvO8,mvF,mv0]);
    23: MassOperation(ADest, ASource,[mvO8,mv0,mv10,mvO16,mv8,mv0]);
    24: MassOperation(ADest, ASource,[mvO8,mv0,mv11,mvO1,mv8,mv10,
          mvO16,mv9,mv0]);
    25: MassOperation(ADest, ASource,[mvO1,mv0,mv19,mvO8,mv1,mv11,
          mvO1,mv9,mv10,mvO16,mvA,mv0]);
    26: MassOperation(ADest, ASource,[mvO2,mv0,mv19,mvO8,mv2,mv11,
          mvO1,mvA,mv10,mvO16,mvB,mv0]);
    27: MassOperation(ADest, ASource,[mvO4,mv0,mv18,mvO8,mv4,mv10,
          mvO8,mvC,mv8,mvO8,mv14,mv0]);
    28: MassOperation(ADest, ASource,[mvO1,mv0,mv1C,mvO4,mv1,mv18,
          mvO8,mv5,mv10,mvO8,mvD,mv8,mvO8,mv15,mv0]);
    29: MassOperation(ADest, ASource,[mvO2,mv0,mv1C,mvO4,mv2,mv18,
          mvO8,mv6,mv10,mvO8,mvE,mv8,mvO8,mv16,mv0]);
    30: MassOperation(ADest, ASource,[mvO1,mv0,mv1E,mvO4,mv1,mv1A,
          mvO8,mv5,mv12,mvO8,mvD,mvA,mvO8,mv15,mv2,mvO2,mv1D,mv0]);
  end;
end;

procedure TsgDWG2007Decompressor.GetLiteralOpcode;
var
  vVal1, vVal2: Cardinal;
begin
  Inc(FLength, 8);
  if FLength <> $17 then
    Exit;

  vVal1 := Byte(FSrc^);
  Inc(FSrc);
  if FSrc > FSrcEnd then
    Exit;
  Inc(FLength, vVal1);

  if vVal1 <> $FF then
    Exit;
  repeat
    vVal1 := Byte(FSrc^);
    Inc(FSrc);
    if FSrc > FSrcEnd then
      Exit;
    vVal2 := Byte(FSrc^);
    vVal1 := (vVal2 shl 8) or vVal1;
    Inc(FSrc);
    Inc(FLength, vVal1);
    if FSrc > FSrcEnd then
      Break;
  until vVal1 <> $FFFF;
end;

{public}

constructor TsgDWG2007Decompressor.Create;
begin
  Clear;
end;

procedure TsgDWG2007Decompressor.Clear;
begin
  FOpCode := 0;
  FOffset := 0;
  FLength := 0;
end;

procedure TsgDWG2007Decompressor.Decompress(ASource: PAnsiChar; ASrcSize: Cardinal;
  ADest: PAnsiChar; ADstSize: Cardinal);
var
  vDst: PAnsiChar;
begin
  FSrc := ASource;
  vDst := ADest;
  FDstEnd := vDst;
  Inc(FDstEnd, ADstSize);
  FSrcEnd := FSrc;
  Inc(FSrcEnd, ASrcSize);
  FOffset := 0;
  FLength := 0;
  FOpCode := Byte(FSrc^);
  Inc(FSrc, 1);
  if FSrc > FSrcEnd then Exit;
  if (FOpCode and $F0) = $20 then
  begin
    Inc(FSrc, 3);
    FLength := PByte(TsgNativeUInt(FSrc) - 1)^;
    FLength := FLength and 7;
  end;

  while True do
  begin
    if FSrc >= FSrcEnd then Exit;
    if FLength = 0 then
    begin
      FLength := FOpCode;
      GetLiteralOpcode;
    end;
    if vDst + FLength <= FDstEnd then
      GetLiteralData(vDst, FSrc, FLength);
    Inc(vDst, FLength);
    if vDst > FDstEnd then Exit;
    Inc(FSrc, FLength);
    FLength := 0;
    if FSrc >= FSrcEnd then Exit;

    FOpCode := Byte(FSrc^);
    Inc(FSrc);
    GetCmpOpcode;

    while True do
    begin
      GetCmpData(vDst, FLength, FOffset);
      Inc(vDst, FLength);
      if vDst > FDstEnd then Exit;
      FLength := FOpCode and 7;
      if FLength <> 0 then Break;
      if FSrc >= FSrcEnd then Break;
      FOpCode := Byte(FSrc^);
      Inc(FSrc);
      if FSrc > FSrcEnd then Break;
      if (FOpCode shr 4) = 0 then Break;
      if (FOpCode shr 4) = $0F then
        FOpCode := FOpCode and $0F;
      GetCmpOpcode;
    end;
  end;
end;

{ TsgRSCoder }

{private}

procedure TsgRSCoder.Generate(const APoly: array of Byte; AM, AErrors: Cardinal);
const
  cntMaxErrors = 8;
var
  I, vPBSize, vMask: Cardinal;
  PBCur, PBEnd: PAnsiChar;
begin
  FBlockSize := (1 shl AM) - 1;
  if FBlockSize <> $FF then
    raise EsgRSCoderError.Create(sRSBlockSizeError);
  if AErrors > cntMaxErrors then
    raise EsgRSCoderError.CreateFmt(sRSMaxErrors, [cntMaxErrors]);
  FErr := AErrors;
  FPSize := FErr shl 1;
  FDSize := Integer(FBlockSize) - FPSize;
  vPBSize := (FPSize + 1) shl 8;
  GetMem(FMod255, vPBSize);
  FillChar(FMod255^, vPBSize, #0);
  PBCur := FMod255;
  PBEnd := PBCur;
  Inc(PBEnd, vPBSize);
  I := 0;
  while PBCur < PBEnd do
  begin
    PBCur^ := AnsiChar(I);
    Inc(I);
    if I = FBlockSize then
      I := 0;
    Inc(PBCur);
  end;
  vMask := 1;
  FAlfaTo[AM] := 0;
  for I := 0 to AM - 1 do
  begin
    FAlfaTo[I] := vMask;
    FIndexOf[FAlfaTo[I]] := I;
    if APoly[I] <> 0 then
      FAlfaTo[AM] := FAlfaTo[AM] xor vMask;
    vMask := vMask shl 1 ;
  end;
  FIndexOf[FAlfaTo[AM]] := AM;
  vMask := vMask shr 1;
  for I := AM + 1 to $FF - 1 do
  begin
    if FAlfaTo[I - 1] >= vMask then
      FAlfaTo[I] := FAlfaTo[AM] xor ((FAlfaTo[I - 1] xor vMask) shl 1)
    else
      FAlfaTo[I] := FAlfaTo[I - 1] shl 1;
    FIndexOf[FAlfaTo[I]] := I;
  end;
  FIndexOf[0] := $FFFFFFFF;
  if vPBSize = $500 then
    InitRSCoder500;
  if vPBSize = $1100 then
    InitRSCoder1100;
end;

function TsgRSCoder.GetDSize: Integer;
begin
  Result := FDSize;
end;

procedure TsgRSCoder.InitRSCoder1100;
begin
  FGPoly[0] := 136; FGPoly[1] := 105; FGPoly[2] := 57; FGPoly[3] := 25;
  FGPoly[4] := 160; FGPoly[5] := 222; FGPoly[6] := 95; FGPoly[7] := 66;
  FGPoly[8] := 119; FGPoly[9] := 49; FGPoly[10] := 61; FGPoly[11] := 171;
  FGPoly[12] := 92; FGPoly[13] := 195; FGPoly[14] := 210; FGPoly[15] := 241;
  FGPoly[16] := 0;
end;

procedure TsgRSCoder.InitRSCoder500;
//var
//  _FGPoly: array[0..16] of Cardinal;
//   I, J, vBlockSize: Integer;
begin
  FGPoly[0] := 10; FGPoly[1] := 81; FGPoly[2] := 251; FGPoly[3] := 76;
  FGPoly[4] := 0;
//  FillChar(_FGPoly, SizeOf(_FGPoly), 0);
//  _FGPoly[0] := 2;
//  _FGPoly[1] := 1;
//  vBlockSize := Integer(FBlockSize);
//
//  for I := 2 to vBlockSize - (vBlockSize - 2 * FErr) do
//  begin
//   _FGPoly[I] := 1;
//
//   for J := I - 1 downto 1 do
//   begin
//     if _FGPoly[J] <> 0 then
//       _FGPoly[J] := _FGPoly[J - 1] xor FAlfaTo[(FIndexOf[_FGPoly[J]] + Cardinal(I)) mod FBlockSize]
//     else
//       _FGPoly[J] := _FGPoly[J - 1];
//   end;
//  end;
//  for I := 0 to 2 * FErr do
//   _FGPoly[I] := FIndexOf[_FGPoly[I]] ;
end;

{public}

constructor TsgRSCoder.Create;
begin
  inherited Create;
  FillChar(FGPoly, SizeOf(FGPoly), 0);
  FillChar(FIndexOf, SizeOf(FIndexOf), 0);
  FillChar(FAlfaTo, SizeOf(FAlfaTo), 0);
  FMod255 := nil;
end;

destructor TsgRSCoder.Destroy;
begin
  if FMod255 <> nil then
    FreeMem(FMod255);
end;

//RS(255, 239) n = 255, k = 239
function TsgRSCoder.Decode(AData: PAnsiChar): Integer;
const
  cntN = 255;
  cntK = 239;
  cntNminK = cntN - cntK; //n - k = 255 - 239 = 16
  cntMaxCardinal = $FFFFFFFF;

var
  vData: Cardinal;
  I, J, U, Q, vCount: Integer;
  vIndex: array[Byte] of Cardinal;
  vSyn: array[0..cntNminK] of Cardinal;
  vErr: Boolean;
  vElp: array[0..cntNminK + 2, 0..cntNminK] of Integer;
  D: array[0..cntNminK + 2] of Integer;
  L: array[0..cntNminK + 2] of Integer;
  vUL: array[0..cntNminK + 2] of Integer;
  vErrs, vRoot, vLoc, Z, vReg: array of Integer;

begin
  vCount := 0;
  FillChar(vSyn, SizeOf(vSyn), $FF);
  FillChar(vIndex, SizeOf(vIndex), $FF);

  for I := 0 to $FF - 1 do
    vIndex[I] := FIndexOf[Byte(AData[I])];
  vErr := False;
  I := 1;
  while I <= FPSize do
  begin
    vSyn[I] := 0;
    for J := 0 to $FF - 1 do
    begin
      vData := vIndex[J];
      if vData <> cntMaxCardinal then
      begin
        vData := Byte(FMod255[vData + Cardinal(I * J)]);
        vData := FAlfaTo[vData];
        vSyn[I] := vData xor vSyn[I];
      end
      else
        Continue;
    end;
    if vSyn[I] <> 0 then
      vErr := True;
    vSyn[I] := FIndexOf[vSyn[I]];
    Inc(I);
  end;
  Result := I;
  if vErr then
  begin
    Result := 0;
    SetLength(vErrs, cntN);
    SetLength(vRoot, FErr);
    SetLength(vLoc, FErr);
    SetLength(Z, FErr + 1);
    SetLength(vReg, FErr + 1);

    D[0] := 0;
    D[1] := vSyn[1];
    vElp[0][0] := 0;
    vElp[1][0] := 1;

    I := 1;
    while I < cntNminK do
    begin
      vElp[0][I] := -1;
      vElp[1][I] := 0;
      Inc(I);
    end;

    L[0] := 0;
    L[1] := 0;
    vUL[0] := -1;
    vUL[1] := 0;
    U := 0;

    while (U < FPSize) and (L[U + 1] <= FErr) do
    begin
      Inc(U);
      if D[U] = -1 then
      begin
        L[U + 1] := L[U];
        for I := 0 to L[U] do
        begin
          vElp[U + 1][I] := vElp[U][I];
          vElp[U][I]   := FIndexOf[vElp[U][I]];
        end;
      end
      else
      begin
        Q := U - 1;
        while (D[Q] = -1) and (Q > 0) do
          Dec(Q);
        if Q > 0 then
        begin
          J := Q;
          while J > 0 do
          begin
            Dec(J);
            if (D[J] <> -1) and (vUL[Q] < vUL[J]) then
              Q := J;
          end;
        end;
        if L[U] > L[Q] + U - Q then
          L[U + 1] := L[U]
        else
          L[U + 1] := L[Q] + U - Q;
        for I := 0 to FPSize - 1 do
          vElp[U + 1][I] := 0;

        for I := 0 to L[Q] do
          if (vElp[Q][I] <> -1) then
            vElp[U + 1][I+U-Q] := FAlfaTo[(D[U] + cntN - D[Q] + vElp[Q][I]) mod cntN];

        for I := 0 to L[U] do
        begin
          vElp[U + 1][I] := vElp[U + 1][I] xor vElp[U][I];
          vElp[U][I] := FIndexOf[vElp[U][I]];
        end;
      end;

      vUL[U + 1] := U - L[U + 1];

      if U < FPSize then
      begin
        if vSyn[U + 1] <> cntMaxCardinal then
          D[U + 1] := FAlfaTo[vSyn[U + 1]]
        else
          D[U + 1] := 0;
        for I := 1 to L[U + 1] do
          if (vSyn[U + 1 - I] <> cntMaxCardinal) and (vElp[U + 1][I] <> 0) then
            D[U + 1] := D[U + 1] xor Integer(FAlfaTo[(vSyn[U + 1 - I] + FIndexOf[vElp[U + 1][I]]) mod cntN]);
        D[U + 1] := FIndexOf[D[U + 1]];
      end;
    end;

    Inc(U);
    if L[U] <= FErr then
    begin
      for I := 0 to L[U]do
        vElp[U][I] := FIndexOf[vElp[U][I]];

      for I := 1 to L[U] do
        vReg[I] := vElp[U][I];

      for I := 1 to cntN do
      begin
        Q := 1;
        for J := 1 to L[U] do
          if vReg[J] <> -1 then
          begin
            vReg[J] := (vReg[J] + J) mod cntN;
            Q := Q xor Integer(FAlfaTo[vReg[J]]);
          end;

        if Q = 0 then
        begin
          vRoot[vCount] := I;
          vLoc[vCount] := cntN - I;
          Inc(vCount);
        end;
      end;

      if vCount = L[U] then
      begin
        Result := vCount;
        for I := 1 to L[U] do
        begin
          if (vSyn[I]<> cntMaxCardinal) and (vElp[U][I] <> -1) then
            Z[I] := FAlfaTo[vSyn[I]] xor FAlfaTo[vElp[U][I]]
          else
            if (vSyn[I] <> cntMaxCardinal) and (vElp[U][I] = -1) then
              Z[I] := FAlfaTo[vSyn[I]]
            else
              if (vSyn[I] = cntMaxCardinal) and (vElp[U][I] <> -1) then
                Z[I] := FAlfaTo[vElp[U][I]]
              else
                Z[I] := 0;

          for J := 1 to I - 1 do
            if (vSyn[J] <> cntMaxCardinal) and (vElp[U][I - J] <> -1) then
              Z[I] := Z[I] xor Integer(FAlfaTo[(Cardinal(vElp[U][I - J]) + vSyn[J]) mod cntN]);
          Z[I] := FIndexOf[Z[I]];
        end;
        for I := 0 to cntN - 1 do
        begin
          vErrs[I] := 0;
          if vIndex[I] <> cntMaxCardinal then
             vIndex[I] := FAlfaTo[vIndex[I]]
          else
            vIndex[I] := 0;
        end;
        for I := 0 to L[U] - 1 do
        begin
          vErrs[vLoc[I]] := 1;
          for J := 1 to L[U] do
            if Z[J] <> -1 then
              vErrs[vLoc[I]] := vErrs[vLoc[I]] xor Integer(FAlfaTo[(Z[J] + J * vRoot[I]) mod cntN]);
          if vErrs[vLoc[I]] <> 0 then
          begin
            vErrs[vLoc[I]] := FIndexOf[vErrs[vLoc[I]]];
            Q := 0;
            for J := 0 to L[U] - 1 do
              if J <> I then
                Q := Q + Integer(FIndexOf[1 xor FAlfaTo[(vLoc[J] + vRoot[I]) mod cntN]]);
            Q := Q mod cntN;
            vErrs[vLoc[I]] := Integer(FAlfaTo[(vErrs[vLoc[I]] - Q + cntN) mod cntN]);
            vIndex[vLoc[I]] := vIndex[vLoc[I]] xor Cardinal(vErrs[vLoc[I]]);
          end;
        end;
      end
      else
      begin
        Result := -1;
        for I := 0 to cntN do
          if vIndex[I] <> cntMaxCardinal then
            vIndex[I] := FAlfaTo[vIndex[I]]
          else
            vIndex[I] := 0;
      end;
    end
    else
      for I := 0 to cntN do
      begin
        if vIndex[I] <> cntMaxCardinal then
          vIndex[I] := FAlfaTo[vIndex[I]]
        else
          vIndex[I] := 0;
      end;
    for I := 0 to $FF - 1 do
      if vIndex[I] <> cntMaxCardinal then
        AData[I] := AnsiChar(vIndex[I])
      else
        AData[I] := #0;
  end;
end;

{ DWG 2010 support }

{ TsgDWG2010Decompressor }

function SAR(AValue: Integer; const ACount: Byte): Integer;
asm
{$IFDEF SG_CPUX64}
  MOV EAX,ECX               // value to result
{$ENDIF}
  MOV CL,DL                 // cl - shift count
  SAR EAX,CL                // do shift
end;

procedure TsgDWG2010Decompressor.Clear;
begin
  inherited Clear;
  FHashTable := nil;
  FSrcStart := nil;
  FSrcCurr := nil;
  FSrcPrev := nil;
  FSrcEnd := nil;
  FDstCurr := nil;
  FTarget := nil;
end;

constructor TsgDWG2010Decompressor.Create;
begin
  inherited Create;
end;

procedure TsgDWG2010Decompressor.Decompress(ASource: PAnsiChar;
  ASrcSize: Cardinal; ADest: PAnsiChar; ADstSize: Cardinal);
var
  vOffset, vOpCode1, vLength, vOpCode2, vVal: Integer;
  vDstEnd: PAnsiChar;

  procedure CheckError;
  begin
    vVal := Byte(FSrcCurr^);
    Inc(FSrcCurr);
    if vVal <> 0 then
      raise EdwgError.Create(sDecompressDWGError);
  end;

begin
  Clear;
  if (ASource = nil) or (ADest = nil) then
    raise EdwgError.Create(sCorruptedDWGFileHeader);
  if (ASrcSize = 0) or (ADstSize = 0) then
    raise EdwgError.Create(sCorruptedDWGFileHeader);
  FDstCurr := ADest;
  vDstEnd := ADest;
  Inc(vDstEnd, ADstSize);
  FSrcStart := ASource;
  FSrcCurr := ASource;
  FSrcEnd := ASource;
  Inc(FSrcEnd, ASrcSize);
  vOpCode1 := 0;
  vOpCode2 := 0;

  while FSrcCurr < FSrcEnd do
  begin
    vOffset := 0;
    vLength := 0;
    GetLiteral(vOpCode1);
    vOpCode1 := Byte(FSrcCurr^);
    Inc(FSrcCurr);
    while True do
    begin
      if vOpCode1 <> $11 then Break;
      CheckError;
      CheckError;
      Exit;
    end;
    if FDstCurr > vDstEnd then
      raise EdwgError.Create(sCorruptedDWGFileHeader);
    if (vOpCode1 < $10) or (vOpCode1 >= $40) then
    begin
      vOpCode2 := Byte(FSrcCurr^);
      Inc(FSrcCurr);
      vOffset := (SAR(vOpCode1, 2) and 3) or (vOpCode2 shl 2);
      vLength := SAR(vOpCode1, 4);
      Dec(vLength);
      Inc(vOffset);
    end
    else
    begin
      if vOpCode1 < $20 then
      begin
        GetLength(vLength, vOpCode1, 7);
        vOffset := (vOpCode1 and 8) shl $B;
        GetOffset(vOpCode1, vOpCode2, vOffset);
        Inc(vOffset, $4000);
      end
      else
      begin
        GetLength(vLength, vOpCode1, $1F);
        GetOffset(vOpCode1, vOpCode2, vOffset);
        Inc(vOffset);
      end;
    end;
    GetCompressed(vLength, vOffset);
  end;
end;

procedure TsgDWG2010Decompressor.GetCompressed(ALength, AOffset: Integer);
var
  vDstPrev: PAnsiChar;
begin
  vDstPrev := FDstCurr;
  Dec(vDstPrev, AOffset);
  if ALength < AOffset then
  begin
    Move(vDstPrev^, FDstCurr^, ALength);
    Inc(FDstCurr, ALength);
  end
  else
  begin
    while True do
    begin
      Dec(ALength);
      if ALength < 0 then Exit;
      FDstCurr^ := vDstPrev^;
      Inc(FDstCurr);
      Inc(vDstPrev);
    end;
  end;
end;

procedure TsgDWG2010Decompressor.GetLength(var ALength: Integer; AOpCode,
  AMask: Integer);
begin
   ALength := AOpCode and AMask;
   if ALength = 0 then
   begin
     ALength := AMask;
     GetLongLength(ALength);
   end;
   Inc(ALength, 2);
end;

procedure TsgDWG2010Decompressor.GetLiteral(AOpCode: Integer);
var
  vLitLength: Integer;
  vByte: Byte;
begin
  vLitLength := AOpCode and 3;
  if vLitLength = 0 then
  begin
    if Byte(FSrcCurr^) and $0F0 = 0 then
    begin
      vByte := Byte(FSrcCurr^);
      Inc(FSrcCurr);
      GetLength(vLitLength, vByte, $F);
      Inc(vLitLength);
    end;
  end;
  if vLitLength = 0 then Exit;
  Move(FSrcCurr^, FDstCurr^, vLitLength);
  Inc(FSrcCurr, vLitLength);
  Inc(FDstCurr, vLitLength);
end;

procedure TsgDWG2010Decompressor.GetLongLength(var ALength: Integer);
var
  vChar: AnsiChar;
begin
  vChar := FSrcCurr^;
  Inc(FSrcCurr);
  while vChar = #0 do
  begin
    Inc(ALength, $FF);
    vChar := FSrcCurr^;
    Inc(FSrcCurr);
  end;
  Inc(ALength, Byte(vChar));
end;

type
  TsgDWG2010Section = packed record
    DataSize: UInt64;
    PagesAmount: Cardinal;
    PageSize: Cardinal;
    Unknown: Cardinal;
    Compressed: Cardinal;
    SectID: Cardinal;
    Encrypted: Cardinal;
    SecNameLen: Integer;
    SecName: AnsiString;
    Pages: TList;
    Data: TMemoryStream;
  end;

  PsgDWG2010StreamPage = ^TsgDWG2010StreamPage;
  TsgDWG2010StreamPage = packed record
    PageId: Cardinal;
    ComprSize: Cardinal;
    DataOffset: UInt64;
  end;

  TsgDWG2010PageHeader = packed record
    PageType: Cardinal;
    SectionId: Cardinal;
    DataSize: Cardinal;
    PageSize: Cardinal;
    StartOffset: UInt64;
    CRC1: Cardinal;
    CRC2: Cardinal;
  end;

procedure TsgDWG2010Decompressor.GetOffset(var AOpCode1, AOpCode2,
  AOffset: Integer);
begin
  AOpCode1 := Byte(FSrcCurr[0]);
  AOpCode2 := Byte(FSrcCurr[1]);
  Inc(FSrcCurr, 2);
  AOffset := SAR(AOpCode1, 2) or AOffset;
  AOffset := (AOpCode2 shl 6) or AOffset;
end;

{UnpackR24}

const
  cntDWGId: array[0..11] of AnsiChar = ('A', 'c', 'F', 's', 's', 'F', 'c', 'A',
    'J', 'M', 'B', #0);
  cntSecSize = SizeOf(Cardinal) * 6 + SizeOf(UInt64);

type
  TRndArray = array of Byte;

procedure SetRndArray(var ARandom: TRndArray; const ARndSize: Integer);
var
  I, vRndSeed: Integer;
begin
  SetLength(ARandom, ARndSize);
  vRndSeed := 1;
  for I := 0 to ARndSize - 1 do
  begin
    vRndSeed := $343FD * vRndSeed + $269EC3;
    ARandom[I] := SAR(vRndSeed, $10);
  end;
end;

procedure CheckErrors(AStreamInternal: TMemoryStream; AErrs: array of Cardinal);
var
  I, vVal: Cardinal;
begin
  for I := Low(AErrs) to High(AErrs) do
  begin
    AStreamInternal.Read(vVal, SizeOf(vVal));
    if AErrs[I] <> vVal then
      raise EdwgError.Create(sCorruptedDWGFileHeader);
  end;
end;

procedure LoadSysPage(AStreamInternal: TMemoryStream;
  AStream: TCustomMemoryStream ;ASecType, ASecSize: Cardinal;
  ASecOffset: Integer;
  ANeedCopy: Boolean = True);
var
  vSysPage: TsgDWG2010SysPage;
  vData: Pointer;
  vDecomp: TsgDWG2010Decompressor;
begin
  AStreamInternal.Clear;
  FillChar(vSysPage, SizeOf(vSysPage), 0);
  vSysPage.PageType := ASecType;
  vSysPage.CompType := 2;
  AStream.Position := ASecOffset;
  AStreamInternal.CopyFrom(AStream, ASecSize);
  AStreamInternal.Position := 0;
  CheckErrors(AStreamInternal,[vSysPage.PageType]);
  AStreamInternal.Read(vSysPage.DecompSize, SizeOf(vSysPage.DecompSize));
  AStreamInternal.Read(vSysPage.CompSize, SizeOf(vSysPage.CompSize));
  CheckErrors(AStreamInternal,[vSysPage.CompType]);
  AStreamInternal.Read(vSysPage.CRC, SizeOf(vSysPage.CRC));
  if ANeedCopy then
  begin
    AStreamInternal.Clear;
    AStreamInternal.CopyFrom(AStream, vSysPage.CompSize);
    AStreamInternal.Position := 0;
  end
  else
  begin
    GetMem(vData, vSysPage.CompSize);
    try
      AStreamInternal.Read(vData^, vSysPage.CompSize);
      AStreamInternal.Clear;
      AStreamInternal.Write(vData^, vSysPage.CompSize);
    finally
      FreeMem(vData);
    end;
  end;
  vDecomp := nil;
  GetMem(vData, vSysPage.DecompSize);
  try
    vDecomp := TsgDWG2010Decompressor.Create;
    vDecomp.Decompress(AStreamInternal.Memory, AStreamInternal.Size, vData, vSysPage.DecompSize);
    AStreamInternal.Clear;
    AStreamInternal.Write(vData^, vSysPage.DecompSize);
    AStreamInternal.Position := 0;
  finally
    vDecomp.Free;
    FreeMem(vData);
  end;
end;

procedure ClearSection(var ASection: TsgDWG2010Section);
begin
  ASection.DataSize := 0;
  FillChar(ASection, cntSecSize, 0);
  ASection.SecNameLen := 0;
  ASection.SecName := '';
  ASection.Pages := nil;
  ASection.Data := nil;
end;

procedure ClearPage(var APage: TsgDWG2010StreamPage);
begin
  APage.PageId := 0;
  APage.ComprSize := 0;
  APage.DataOffset := 0;
end;

function GetSectionsSummmary(
  const ASections: array of TsgDWG2010Section): Integer;
var
  I: Integer;
begin
  Result := 0;
  for I := 0 to High(ASections) do
    if (ASections[I].Data <> nil) then
      Result := Result + ASections[I].Data.Size;
end;

procedure ClearPages(var ASection: TsgDWG2010Section);
var
  I: Integer;
begin
  ASection.SecName := '';
  ASection.Data.Free;
  ASection.Data := nil;
  if ASection.Pages <> nil then
    for I := 0 to ASection.Pages.Count - 1 do
      Dispose(ASection.Pages[I]);
  ASection.Pages.Free;
  ASection.Pages := nil;
end;

procedure EncodeR24(const AData, ARandom: Pointer; const ADataSize, ARndSize: Cardinal);
var
  I, vDataSize, vMgcSize: Integer;
  PData, PMgc: PCardinal;

begin
  vDataSize := ADataSize shr 2;
  vMgcSize := ARndSize shr 2;
  if vDataSize > vMgcSize then
    raise EdwgError.Create(sCorruptedDWGFileHeader);
  PData := AData;
  PMgc := ARandom;
  for I := 0 to vDataSize do
  begin
    PData^ := PData^ xor PMgc^;
    Inc(PData);
    Inc(PMgc);
  end;
end;


function UnpackR24Up(AVersion: TsgDWGVersion; AStream: TCustomMemoryStream;
  var ASecCount: Integer): TMemoryStream;
var
  vStream: TMemoryStream;
  vRandom: TRndArray;
  vCardinal, vPageSize, vFileOffset: Cardinal;
  vFileHeader: TsgDWG2010FileHeader;
  vPages: TList;
  I, vPageId, vSecAmount, vUnknown, vGetSecIndByName: Integer;
  vPage: TsgDWG2007Page;
  vSections: array of TsgDWG2010Section;
  vSection: TsgDWG2010Section;
  PStreamPage: PsgDWG2010StreamPage;
  PHead: Pdwg2004FileHeader;
  vIsSectonAllowed: Boolean;


  procedure PageR24HeaderDecode(P: Pointer; AOffset: Cardinal);
  var
    vSecMask: Cardinal;
    vBegin, vStop: PByte;
  begin
    vSecMask := AOffset xor $4164536B;
    vBegin := P;
    vStop := vBegin;
    Inc(vStop, 32);
{$IFDEF SGDEL_XE2}
    while NativeUInt(vBegin) <= NativeUInt(vStop) do
{$ELSE}
    while Cardinal(vBegin) <= Cardinal(vStop) do
{$ENDIF}
    begin
      PCardinal(vBegin)^ := PCardinal(vBegin)^ xor vSecMask;
      Inc(vBegin, 4);
    end;
  end;

  procedure LoadSection(var ASection: TsgDWG2010Section);
  var
    vPageID, I: Integer;
    vPage: TsgDWG2007Page;
    vBuf: array[0..31] of Byte;
    vDst: Pointer;
    vPageHeader: TsgDWG2010PageHeader;
    vDecom: TsgDWG2010Decompressor;
    vData: TMemoryStream;
    vDataSize: Int64;
  begin
    vDecom := TsgDWG2010Decompressor.Create;
    vData := TMemoryStream.Create;
    try
      for I := 0 to ASection.Pages.Count - 1 do
      begin
        vPageID := PsgDWG2010StreamPage(ASection.Pages[I]).PageId;
        if (vPageID < 0) or (vPageID > vPages.Count - 1) then Continue;
        vPage := PsgDWG2007Page(vPages[vPageID])^;
        if (vPage.Offset = 0) or (vPage.Size = 0) then Continue;
        if ASection.Data = nil then ASection.Data := TMemoryStream.Create;
        vDataSize := ASection.Data.Size;
        ASection.Data.Size := vDataSize + ASection.PageSize;
        vDst := Pointer(TsgNativeUInt(ASection.Data.Memory) + vDataSize);

        AStream.Position := vPage.Offset;
        FillChar(vBuf, SizeOf(vBuf), 0);
        AStream.Read(vBuf[0], SizeOf(vBuf));
        PageR24HeaderDecode(@vBuf[0], vPage.Offset);
        vData.Clear;
        vData.Write(vBuf, SizeOf(vBuf));
        vData.Position := 0;
        FillChar(vPageHeader, SizeOf(vPageHeader), 0);
        vData.Read(vPageHeader, SizeOf(TsgDWG2010PageHeader));
        if vPageHeader.PageType <> $4163043B then
          raise EdwgError.Create(sCorruptedDWGFileHeader);
        vData.Clear;
        vData.CopyFrom(AStream, vPageHeader.DataSize);
        vData.Position := 0;
        if ASection.Compressed = 2 then
          vDecom.Decompress(vData.Memory, vData.Size, vDst, ASection.PageSize)
        else
          ASection.Data.Write(vData.Memory^, vData.Size);
    end;
    finally
      vDecom.Free;
      vData.Free;
    end;
  end;

begin
  Result := nil;
  vPages := nil;
  SetLength(vSections, cDWGSectCount + 1);
  for I := Low(vSections) to High(vSections) do
    ClearSection(vSections[I]);

  vStream := TMemoryStream.Create;
  try
    AStream.Position := $80;
    vStream.CopyFrom(AStream, 108);
    SetRndArray(vRandom, 256);
    EncodeR24(vStream.Memory, vRandom, 108, 256);
    if not CompareMem(vStream.Memory, @cntDWGId[0], {$IFDEF SGDEL_XE4}AnsiStrings.{$ENDIF}StrLen(cntDWGId)) then
      raise EdwgError.Create(sCorruptedDWGFileHeader);
    //last 4 bytes are CRC, ignore
    vStream.Position := vStream.Size - 4;
    vCardinal := 0;
    vStream.Write(vCardinal, SizeOf(vCardinal));
    vStream.Position := 12;
    CheckErrors(vStream, [0, $6C, 4]);

    FillChar(vFileHeader, SizeOf(vFileHeader), 0);
//    //reading first 9 fields of the TsgDWG2010FileHeader structure
//    vSize := 11 * SizeOf(Cardinal);
//    vStream.Read(vFileHeader, vSize);
//    CheckErrors([$20, $80, $40]);
//
//    //reading next fields of the TsgDWG2010FileHeader structure
//    P := Pointer(Cardinal(@vFileHeader) + vSize);
//    vStream.Read(P^, SizeOf(TsgDWG2010FileHeader) - vSize);
//    Inc(vFileHeader.PagesMapOffset, $100);
//    CheckErrors([0]);

    vStream.Read(vFileHeader.GpsRtId, SizeOf(vFileHeader.GpsRtId));
    vStream.Read(vFileHeader.GpsLeftId, SizeOf(vFileHeader.GpsLeftId));
    vStream.Read(vFileHeader.GpsRightId, SizeOf(vFileHeader.GpsRightId));
    vStream.Read(vFileHeader.GpsUnknown, SizeOf(vFileHeader.GpsUnknown));
    vStream.Read(vFileHeader.LastPageId, SizeOf(vFileHeader.LastPageId));
    vStream.Read(vFileHeader.LastPageEndOffset, SizeOf(vFileHeader.LastPageEndOffset));
    vStream.Read(vFileHeader.Hdr2Offset, SizeOf(vFileHeader.Hdr2Offset));
    vStream.Read(vFileHeader.GapsAmount, SizeOf(vFileHeader.GapsAmount));
    vStream.Read(vFileHeader.PagesAmount, SizeOf(vFileHeader.PagesAmount));
    CheckErrors(vStream,[$20, $80, $40]);

    vStream.Read(vFileHeader.PagesMapId, SizeOf(vFileHeader.PagesMapId));
    vStream.Read(vFileHeader.PagesMapOffset, SizeOf(vFileHeader.PagesMapOffset));
    Inc(vFileHeader.PagesMapOffset, $100);
    vStream.Read(vFileHeader.SectionsMapId, SizeOf(vFileHeader.SectionsMapId));
    vStream.Read(vFileHeader.PagesMaxId, SizeOf(vFileHeader.PagesMaxId));
    vStream.Read(vFileHeader.GapsMaxId, SizeOf(vFileHeader.GapsMaxId));
    CheckErrors(vStream,[0]);


    CreateDWG2007PgsLst(vPages, vFileHeader.PagesMaxId);
    LoadSysPage(vStream, AStream, $41630E3B, 20, vFileHeader.PagesMapOffset);
    vFileOffset := $100;
    while vStream.Position < vStream.Size do
    begin
      vStream.Read(vPageId, SizeOf(vPageId));
      vStream.Read(vPageSize, SizeOf(vPageSize));
      if vPageId >= 0 then
      begin
        if vPageId > Integer(vFileHeader.PagesMaxId) then
          raise EdwgError.Create(sCorruptedDWGFileHeader);
        PsgDWG2007Page(vPages[vPageId])^.Id := vPageId;
        PsgDWG2007Page(vPages[vPageId])^.Size := vPageSize;
        PsgDWG2007Page(vPages[vPageId])^.Offset := vFileOffset;
      end
      else
        vStream.Position := vStream.Position + SizeOf(vPageSize) * 4;
      Inc(vFileOffset, vPageSize);
    end;
    if (vFileHeader.LastPageId <> vPageId) or (vFileHeader.LastPageEndOffset <> (vFileOffset - $100)) then
      raise EdwgError.Create(sCorruptedDWGFileHeader);
    if vFileHeader.SectionsMapId > Cardinal(vPages.Count) then
      raise EdwgError.Create(sCorruptedDWGFileHeader);
    vPage := PsgDWG2007Page(vPages[vFileHeader.SectionsMapId])^;
    LoadSysPage(vStream, AStream, $4163003B, vPage.Size, vPage.Offset, False);
    vStream.Read(vSecAmount, SizeOf(vSecAmount));
    CheckErrors(vStream, [2, $7400, 0]);
    vStream.Read(vUnknown, SizeOf(vUnknown));

    while True do
    begin
      ClearSection(vSection);
      if vStream.Position = vStream.Size then Break;
      if vStream.Read(vSection, cntSecSize) <> cntSecSize then Break;
      SetLength(vSection.SecName, 64);
      if vStream.Read(Pointer(vSection.SecName)^, 64) <> 64 then
        Break;
      vSection.SecNameLen := Max(Pos(AnsiString(#0), vSection.SecName) - 1, 0);
      if (vSection.SecNameLen = 0) or (vSection.PagesAmount = 0) or
        (vSection.PagesAmount > vFileHeader.PagesMaxId + 1) then
        Continue;
      if vStream.Position = vStream.Size then Break;
      vSection.SecName := Copy(vSection.SecName, 1, vSection.SecNameLen);

      vSection.Pages := TList.Create;
      for I := 0 to vSection.PagesAmount - 1 do
      begin
        New(PStreamPage);
        ClearPage(PStreamPage^);
        vStream.Read(PStreamPage^, SizeOf(TsgDWG2010StreamPage));
        vSection.Pages.Add(PStreamPage);
      end;

      if AVersion < acR2013 then
        vIsSectonAllowed := IsSectonAllowed(WideString(vSection.SecName), [])
      else
        vIsSectonAllowed := IsSectonAllowed(WideString(vSection.SecName), [sAcadSectPrototype]);
      if not vIsSectonAllowed then
      begin
        ClearPages(vSection);
        Continue;
      end;
      try
        LoadSection(vSection);
      except
        ClearPages(vSection);
        Continue;
      end;
      vGetSecIndByName := GetSecIndByName(WideString(vSection.SecName));
      if vGetSecIndByName < 0 then
      begin
        SetLength(vSections, Length(vSections) + 1);
        vGetSecIndByName := High(vSections);
      end;
      vSections[vGetSecIndByName] := vSection;
    end;
    ASecCount := High(vSections) + 1;
    Result := CreateDWGStream(['A', 'C', '1', '0', '2', '4'], ASecCount,
      GetSectionsSummmary(vSections));
    for I := 0 to High(vSections) do
    begin
      if vSections[I].Data = nil then
      begin
        ClearPages(vSections[I]);
        Continue;
      end;
      PHead := Result.Memory;
      DoSection(PHead, I, vSections[I].Data, Result);
      ClearPages(vSections[I]);
    end;
  finally
    vStream.Free;
    for I := Low(vSections) to High(vSections) do
      ClearPages(vSections[I]);
    ClearDWG2007PgsLst(vPages);
  end;
end;

{$ENDIF}

function ReadMC(var P: Pointer): UInt64; register;
{$IFDEF SGFPC}
var
  vDWGBits: TsgDWGBits;
begin
  vDWGBits := TsgDWGBits.CreateFromMemory(P, MaxInt);
  try
    Result := vDWGBits.ReadMCHandle;
    Inc(PByte(P), vDWGBits.CurByte);
  finally
    vDWGBits.Free;
  end;
end;

{$ELSE}
{$IFDEF SG_CPUX64}
asm
      PUSH    R8
      PUSH    R9
      MOV     R9,RCX
      MOV     R8,[R9]
      XOR     RAX,RAX
      XOR     RCX,RCX
@@1:  XOR     RDX,RDX
      MOV     DL,[R8]
      INC     R8
      OR      DL,DL
      JNS     @@2
      CMP     CL,63
      JA      @@3
      AND     DL,$7F
      SHL     RDX,CL
      OR      RAX,RDX
@@3:  ADD     CL,7
      JMP     @@1
@@2:  MOV     [R9],R8
      CMP     CL,63
      JA      @@4
      AND     DL,$7F
      SHL     RDX,CL
      OR      RAX,RDX
@@4:  POP     R9
      POP     R8
end;
{$ELSE}
var
  Next: UInt64;
  Shift: Byte;
begin
  Result := 0;
  Shift := 0;
  repeat
    Next := PByte(P)^;
    Inc(PByte(P));
    if Shift <= 63 then // 63 = 64 bit - 1
      Result := Result or (Next and $7F) shl Shift;
    Inc(Shift, 7);
  until Next and $80 = 0;
end;
{$ENDIF}
{$ENDIF}

function ReadMCSigned(var P: Pointer): Integer; register;
{var
  Next: Integer;
  Shift: Byte;
begin
  Result := 0;
  Shift := 0;
  while True do
  begin
    Next := PByte(P)^;
    Inc(PByte(P));
    if Next and $80 = 0 then Break;
    Result := Result or (Next and $7F) shl Shift;
    Inc(Shift,7);
  end;
  Result := Result or (Next and $3F) shl Shift;
  if Next and $40 <> 0 then
    Result := -Result;
end;
}
{$IFDEF SGFPC}
var
  vDWGBits: TsgDWGBits;
begin
  vDWGBits := TsgDWGBits.CreateFromMemory(P, MaxInt);
  try
    Result := vDWGBits.ReadMC;
    Inc(PByte(P), vDWGBits.CurByte);
  finally
    vDWGBits.Free;
  end;
end;
{$ELSE}
asm
{$IFDEF SG_CPUX64}
    PUSH    R8
    PUSH    R9
    MOV     R9,RCX
    MOV     R8,[R9]
    XOR     RAX,RAX
    XOR     RCX,RCX
@@1:
    XOR     RDX,RDX
    MOV     DL,[R8]
    INC     R8
    OR      DL,DL
    JNS     @@2
    AND     DL,$7F
    SHL     RDX,CL
    OR      RAX,RDX
    ADD     CL,7
    JMP     @@1
@@2:
    MOV     [R9],R8
    MOV     R8,RDX
    AND     DL,$3F
    SHL     RDX,CL
    OR      RAX,RDX
    TEST    R8,$40
    JZ      @@3
    NEG     RAX
@@3:
    POP     R9
    POP     R8
{$ELSE}
    PUSH    EBX
    PUSH    EBP
    MOV     EBP,EAX
    MOV     EBX,[EBP]
    XOR     EAX,EAX
    XOR     ECX,ECX
@@1:        XOR     EDX,EDX
    MOV     DL,[EBX]
    INC     EBX
    OR      DL,DL
    JNS     @@2
    AND     DL,$7F
    SHL     EDX,CL
    OR      EAX,EDX
    ADD     CL,7
    JMP     @@1
@@2:        MOV     [EBP],EBX
    MOV     BL,DL
    AND     DL,$3F
    SHL     EDX,CL
    OR      EAX,EDX
    TEST    BL,$40
    JZ      @@3
    NEG     EAX
@@3:        POP     EBP
    POP     EBX
{$ENDIF}
end;
{$ENDIF}

function ReadMS(var P: Pointer): Integer; register;
{var
  vFirstByte, vSecondByte: Byte;
  vResult: UInt64;
  I, J: Integer;
  vP: PByte;
begin
  vP := P;
  I := 0; J := 0;
  vResult := 0;
  repeat
    vFirstByte := vP^;
    Inc(vP);
    vSecondByte := vP^;
    Inc(vP);
    Inc(J,2);
    vResult := vResult +
      ( (((vSecondByte shl 8) + vFirstByte) and 32767) shl  (15 * I) );
    Inc(I);
  until vSecondByte <= 127;
  P := vP;
  Result := vResult;
end;}
{$IFDEF SG_CPUX64}
asm
        PUSH    R8
        PUSH    R9
        MOV     R8,RCX
        MOV     R9,[R8]
        XOR     RAX,RAX
        XOR     RCX,RCX
@@1:    XOR     RDX,RDX
        MOV     DX,[R9]
        INC     R9
        INC     R9
        OR      DX,DX
        JNS     @@2
        CMP     CL,31
        JA      @@3
        AND     DX,$7FFF
        SHL     RDX,CL
        OR      RAX,RDX
@@3:    ADD     CL,15
        JMP     @@1
@@2:    MOV     [R8],R9
        CMP     CL,31
        JA      @@4
        AND     DX,$7FFF
        SHL     RDX,CL
        OR      RAX,RDX
@@4:
        POP     R9
        POP     R8
end;
{$ELSE}
asm
        PUSH    EBX
        PUSH    EBP
        MOV     EBP,EAX
        MOV     EBX,[EBP]
        XOR     EAX,EAX
        XOR     ECX,ECX
@@1:    XOR     EDX,EDX
        MOV     DX,[EBX]
        INC     EBX
        INC     EBX
        OR      DX,DX
        JNS     @@2
        CMP     CL,31
        JA      @@3
        AND     DX,$7FFF
        SHL     EDX,CL
        OR      EAX,EDX
@@3:    ADD     CL,15
        JMP     @@1
@@2:    MOV     [EBP],EBX
        CMP     CL,31
        JA      @@4
        AND     DX,$7FFF
        SHL     EDX,CL
        OR      EAX,EDX
@@4:    POP     EBP
        POP     EBX
end;
{$ENDIF}


procedure Inc2(var APBit: TsgInt64; Value: TsgNativeInt);
asm
{$IFDEF SG_CPUX64}
        ADD     [RCX],RDX
        ADC     DWORD PTR 8[rcx],0
{$ELSE}
        ADD     [EAX],EDX
        ADC     DWORD PTR 4[EAX],0
{$ENDIF}
end;

procedure Dec2(var APBit: TsgInt64; Value: TsgNativeInt);
asm
{$IFDEF SG_CPUX64}
        SUB     [RCX],RDX
        SBB     DWORD PTR 8[RCX],0
{$ELSE}
        SUB     [EAX],EDX
        SBB     DWORD PTR 4[EAX],0
{$ENDIF}
end;

function Comp2(var A,B: TsgInt64): Boolean;
asm
{$IFDEF SG_CPUX64}
        MOV     EAX,8[RCX]
        CMP     EAX,8[RDX]
        JNZ     @@1
        MOV     RAX,[RCX]
        CMP     RAX,[RDX]
{$ELSE}
        MOV     ECX,[4 +EAX]
        CMP     ECX,[4 + EDX]
        JNZ     @@1
        MOV     ECX,[EAX]
        CMP     ECX,[EDX]
{$ENDIF}
@@1:    SETB    AL
        AND     EAX,1
end;

function Comp2WithAccuracy(const A, B: TsgInt64; Accuracy: Integer): Boolean;
begin
  Result := (B.Hi = A.Hi) and (B.Lo > A.Lo) and ((B.Lo - A.Lo) > Accuracy);
end;

procedure ReadBytes(var APBit: TsgInt64; var Dest; Count: Integer); register;
{var
  Src: PByte;
  Next: WordRec;
  Shift: Byte;
  P: PByte;
begin
  PByte(Src) := PByte(APBit.Lo shr cnstAddressBit or APBit.Hi shl cnstAddressHi);
  Shift := APBit.Lo and 7;
  Inc2(APBit, Count shl 3);
  P := @Dest;
  while Count > 0 do
  begin
    Next.Hi := Src^;
    Inc(Src);
    Next.Lo := Src^;
    Word(Next) := Word(Next) shl Shift;
    P^ := Next.Hi;
    Inc(P);
    Dec(Count);
  end;
end;}
{$IFDEF SG_CPUX64}
asm
    PUSH    R9
    PUSH    RDX
    MOV     RDX,RCX
    MOV     RCX,[RDX]
    MOVSX   RAX,8[RDX]
    MOV     R9,RCX
    SHRD    R9,RAX,3
    AND     CL,7
    MOV     RAX,R8
    SHL     RAX,3
    ADD     [RDX],RAX
    ADC	    DWORD PTR 8[RDX],0
    POP     RDX
@@1:
    MOV     AX,[R9]
    XCHG    AL,AH
    SHL     AX,CL
    MOV     AL,AH
    MOV     [RDX],AL
    INC     R9
    INC     RDX
    DEC     R8
    JNZ     @@1
    POP     R9
end;
{$ELSE}
asm
    PUSH    EBX
    PUSH    ESI
    PUSH    EDX
    MOV     EDX,EAX
    MOV     EBX,ECX
    MOV     ECX,[EDX]
    MOV	    EAX,[4 + EDX]
    MOV     ESI,ECX
    SHRD    ESI,EAX,3
    AND     CL,7
    MOV     EAX,EBX             // Count
    SHL     EAX,3
    ADD     [EDX],EAX
    ADC	    DWORD PTR 4[EDX],0
    POP     EDX
@@1:MOV     AX,[ESI]
    XCHG    AL,AH
    SHL     AX,CL
    MOV     [EDX],AH
    INC     ESI
    INC     EDX
    DEC     EBX
    JNZ     @@1
    POP     ESI
    POP     EBX
end;
{$ENDIF}

procedure ReadBytesPair(var APBit: TsgInt64; var Dest; Count: Integer); register;
asm
{$IFDEF SG_CPUX64}
    PUSH    R9
    PUSH    RDX
    MOV     RDX,RCX
    MOV     RCX,[RDX]
    MOVSX   RAX,8[RDX]
    MOV     R9,RCX
    SHRD    R9,RAX,3
    AND     CL,7
    MOV     RAX,R8
    SHL     RAX,4
    ADD     [RDX],RAX
    ADC	    DWORD PTR 8[RDX],0
    POP     RDX
@@1:
    MOV     EAX,[R9]
    BSWAP   EAX
    SHL     EAX,CL
    BSWAP   EAX
    MOV     [RDX],AX
    ADD     R9,2
    ADD     RDX,2
    DEC     R8
    JNZ     @@1
    POP     R9
{$ELSE}
    PUSH    EBX
    PUSH    ESI
    PUSH    EDX
    MOV     EDX,EAX
    MOV     EBX,ECX
    MOV     ECX,[EDX]
    MOV	    EAX,[4 + EDX]
    MOV     ESI,ECX
    SHRD    ESI,EAX,3
    AND     CL,7
    MOV     EAX,EBX
    SHL     EAX,4
    ADD     [EDX],EAX
    ADC	    DWORD PTR 4[EDX],0
    POP     EDX
@@1:MOV     EAX,[ESI]
    BSWAP   EAX
    SHL     EAX,CL
    BSWAP   EAX
    MOV     [EDX],AX
    ADD     ESI,2
    ADD     EDX,2
    DEC     EBX
    JNZ     @@1
    POP     ESI
    POP     EBX
{$ENDIF}
end;

procedure ReadBytesDoublePair(var APBit: TsgInt64; var Dest; Count: Integer); register;
asm
{$IFDEF SG_CPUX64}
    PUSH    R9
    PUSH    RDX
    MOV     RDX,RCX
    MOV     RCX,[RDX]
    MOVSX   RAX,8[RDX]
    MOV     R9,RCX
    SHRD    R9,RAX,3
    AND     CL,7
    MOV     RAX,R8
    SHL     RAX,5
    ADD     [RDX],RAX
    ADC	    DWORD PTR 8[RDX],0
    POP     RDX
@@1:
    MOV     RAX,[R9]
    BSWAP   RAX
    SHL     RAX,CL
    BSWAP   RAX
    MOV     [RDX],EAX
    ADD     R9,4
    ADD     RDX,4
    DEC     R8
    JNZ     @@1
    POP     R9
{$ELSE}
    PUSH    EBX
    PUSH    ESI
    PUSH    EDX
    MOV     EDX,EAX
    MOV     EBX,ECX
    SHL     EBX,1
    MOV     ECX,[EDX]
    MOV	    EAX,[4 + EDX]
    MOV     ESI,ECX
    SHRD    ESI,EAX,3
    AND     CL,7
    MOV     EAX,EBX
    SHL     EAX,4
    ADD     [EDX],EAX
    ADC	    DWORD PTR 4[EDX],0
    POP     EDX
@@1:MOV     EAX,[ESI]
    BSWAP   EAX
    SHL     EAX,CL
    BSWAP   EAX
    MOV     [EDX],AX
    ADD     ESI,2
    ADD     EDX,2
    DEC     EBX
    JNZ     @@1
    POP     ESI
    POP     EBX
{$ENDIF}
end;

{$IFNDEF SGDEL_6}
procedure DivMod(AValue, ADivide: Integer; var ADiv, AMod: Word);
begin
  ADiv := AValue div ADivide;
  AMod := AValue mod ADivide;
end;
{$ENDIF}

procedure ReadBytesCustom(var APBit: TsgInt64; var Dest; Count: Integer); register;
var
  vDest: Pointer;
  vDiv, vMod: Word;
begin
  DivMod(Count, 4, vDiv, vMod);
  if vDiv > 0 then
  begin
    ReadBytesDoublePair(APBit, Dest, vDiv);
    if vMod > 0 then
    begin
      vDest := Pointer(TsgNativeUInt(Pointer(@Dest)) + vDiv shl 2);
      ReadBytesCustom(APBit, vDest^, vMod);
    end;
  end
  else
  begin
    DivMod(Count, 2, vDiv, vMod);
    if vDiv > 0 then
    begin
      ReadBytesPair(APBit, Dest, vDiv);
      if vMod > 0 then
      begin
        vDest := Pointer(TsgNativeUInt(Pointer(@Dest)) + vDiv shl 1);
        ReadBytesCustom(APBit, vDest^, vMod);
      end;
    end
    else
      ReadBytes(APBit, Dest, Count);
  end;
end;

function ReadBit(var APBit: TsgInt64): Integer; register;
{$IFDEF SG_CPUX64}
{var
  Src: PByte;
  Mask: Byte;
begin
  NativeUInt(Src) := APBit.Lo shr cnstAddressBit or APBit.Hi shl cnstAddressHi;
  Mask := $80 shr (APBit.Lo and 7);
  Inc2(APBit,1);
  Result := 0;
  if Src^ and Mask <> 0
  then Result := 1;
end;}
asm
    MOV     RAX,RCX
    MOV     RDX,[RAX]
    MOV     CL,DL
    AND     CL,7
    MOV     CH,$80
    SHR     CH,CL
    MOV	    CL,8[RAX]
    SHRD    RDX,RCX,3
    ADD     QWORD PTR [RAX],1
    ADC     DWORD PTR 8[RAX],0
    TEST    [RDX],CH
    SETNZ   AL
    AND	    RAX,1
end;
{$ELSE}
asm
    MOV     EDX,[EAX]
    MOV     CL,DL
    AND     CL,7
    MOV     CH,$80
    SHR     CH,CL
    MOV	    CL,[4 + EAX]
    SHRD    EDX,ECX,3
    ADD     DWORD PTR [EAX],1
    ADC     DWORD PTR 4[EAX],0
    TEST    [EDX],CH
    SETNZ   AL
    AND	    EAX,1
end;
{$ENDIF}

function ReadBB(var APBit: TsgInt64): Integer;
//begin
//  Result := ReadBit(APBit);
//  Result := Result + Result;
//  Result := Result + ReadBit(APBit);
//end;
asm
{$IFDEF SG_CPUX64}
    MOV     RDX,RCX
    MOV     RCX,[RDX]
    MOVSX   RAX,8[RDX]
    ADD     QWORD PTR [RDX],2
    ADC	    DWORD PTR 8[RDX],0
    MOV     RDX,RCX
    SHRD    RDX,RAX,3
    AND     CL,7
    INC     CL
    MOV     AX,[RDX]
    XCHG    AL,AH
    SHL     AX,CL
    RCL     AL,1
    SHL     AH,1
    RCL     AL,1
    AND     RAX,3
{$ELSE}
    MOV     EDX, EAX
    MOV     ECX, [EDX]
    MOV	    EAX, [4 + EDX]
    ADD     DWORD PTR [EDX],2
    ADC	    DWORD PTR 4[EDX],0
    MOV     EDX,ECX
    SHRD    EDX,EAX,3
    AND     CL,7
    INC     CL
    MOV     AX,[EDX]
    XCHG    AL,AH
    SHL     AX,CL
    RCL     AL,1
    SHL     AH,1
    RCL     AL,1
    AND     EAX,3
{$ENDIF}
end;

function Read3Bit(var APBit: TsgInt64): Integer;
begin
  Result := ReadBB(APBit);
  Result := Result + Result;
  Result := Result + ReadBit(APBit);
end;


function ReadRC(var APBit: TsgInt64): Integer;
begin
  Result := 0;
  ReadBytes(APBit, Result, 1);
end;

function ReadRS(var APBit: TsgInt64): Integer;
var
  S: Smallint;
begin
  //ReadBytes(APBit, S, 2);
  ReadBytesPair(APBit, S, 1);
  Result := S;
end;

function ReadRL(var APBit: TsgInt64): Integer;
begin
  //ReadBytes(APBit, Result, 4);
  //ReadBytesPair(APBit, Result, 2);
  ReadBytesDoublePair(APBit, Result, 1);
end;

function ReadRD(var APBit: TsgInt64): Double;
begin
  //ReadBytes(APBit, Result, 8);
  //ReadBytesPair(APBit, Result, 4);
  ReadBytesDoublePair(APBit, Result, 2);
  if IsNan(Result) or (Abs(Result) > 1E+101) then
    Result := 0;
end;

function ReadBS(var APBit: TsgInt64): Integer;
begin
  case ReadBB(APBit) of
    0: Result := ReadRS(APBit);
    1: Result := ReadRC(APBit);
    2: Result := 0;
    else Result := 256;
  end;
end;

function ReadBL(var APBit: TsgInt64): Integer;
begin
  case ReadBB(APBit) of
    0: Result := ReadRL(APBit);
    1: Result := ReadRC(APBit);
    else Result := 0;
  end;
end;

function ReadBUL(var APBit: TsgInt64): Int64;
var
  vBytesCount: Byte;
begin
  Result := 0;
  vBytesCount := Read3Bit(APBit);
  if vBytesCount > 0 then
    ReadBytesCustom(APBit, Result, vBytesCount);
end;

function ReadBD(var APBit: TsgInt64): Double;
begin
  case ReadBB(APBit) of
    0: Result := ReadRD(APBit);
    1: Result := 1.0;
    else Result := 0.0;
  end;
end;

function Read2RD(var APBit: TsgInt64): TFPoint;
begin
  Result.X := ReadRD(APBit);
  Result.Y := ReadRD(APBit);
  Result.Z := 0.0;
end;

function Read2RDElevation(var APBit: TsgInt64; const AElevation: Double): TFPoint;
begin
  Result.X := ReadRD(APBit);
  Result.Y := ReadRD(APBit);
  Result.Z := AElevation;
end;

function ReadF2DPoint(var APBit: TsgInt64): TF2DPoint;
begin
  Result.X := ReadRD(APBit);
  Result.Y := ReadRD(APBit);
end;

function Read3RD(var APBit: TsgInt64): TFPoint;
begin
  Result.X := ReadRD(APBit);
  Result.Y := ReadRD(APBit);
  Result.Z := ReadRD(APBit);
end;

function Read2D(var APBit: TsgInt64): TFPoint;
begin
  Result.X := ReadBD(APBit);
  Result.Y := ReadBD(APBit);
  Result.Z := 0.0;
end;

function Read3D(var APBit: TsgInt64): TFPoint;
begin
  Result.X := ReadBD(APBit);
  Result.Y := ReadBD(APBit);
  Result.Z := ReadBD(APBit);
end;

function Read3Bits(var APBit: TsgInt64): Byte;
begin
  Result := (((ReadBit(APBit) shl 1) or ReadBit(APBit)) shl 1) or ReadBit(APBit);
end;

procedure AddBinaryChunk(var APBit: TsgInt64; const ACode: Integer;
  AExtData: TsgCADExtendedData);
var
  vBytesCount: Integer;
  vPBytes: PByte;
begin
  vBytesCount := ReadRC(APBit);
  if vBytesCount > 0 then
  begin
    GetMem(vPBytes, vBytesCount);
    try
      ReadBytesCustom(APBit, vPBytes^, vBytesCount);
      AExtData.AddBinary(ACode, vBytesCount, vPBytes);
    finally
      FreeMem(vPBytes);
    end;
  end
  else
    AExtData.AddBinary(ACode, 0, nil);
end;

{optimization}
// <--
type
  TsgSeekDWG = (seB,seBB,seBS,seBL,seBD,se2RD,se3RD,se2D,se3D,seRS,seRC,seRL,seRGB,seUInt64);

procedure SeekGeneral(var APBit: TsgInt64; const AParam: array of TsgSeekDWG);
var
  I,J: Integer;
  vMasSeek: Integer;
begin
  vMasSeek :=0;
  for I := Low(AParam) to High(AParam) do
  begin
    if AParam[I] in [seBS,seBL,seBD,se2D,se3D,seRGB,seUInt64] then
      if vMasSeek <> 0 then
      begin
        Inc2(APBit,vMasSeek);
        vMasSeek :=0;
      end;
    case AParam[I] of
      seB: Inc(vMasSeek,1);
      seBB: Inc(vMasSeek,2);
      seBS: case ReadBB(APBit) of
              0: Inc(vMasSeek,16);// seek 2 bytes
              1: Inc(vMasSeek,8);// seek 1 bytes
            end;
      seBL: case ReadBB(APBit) of
              0: Inc(vMasSeek,32);// seek 4 bytes
              1: Inc(vMasSeek,8);// seek 1 bytes
            end;
      seBD: case ReadBB(APBit) of
              0: Inc(vMasSeek,64);// seek 8 bytes
            end;
      se2RD: Inc(vMasSeek,128);// seek 16 bytes
      se3RD: Inc(vMasSeek,192);// seek 8 bytes
      se2D,se3D: for J := 0 to 1+ Byte(AParam[I] = se3D) do
                 case ReadBB(APBit) of
                   0: Inc2(APBit, 64); // seek 8 bytes
                 end;
      seRS: Inc(vMasSeek,16);// seek 2 bytes
      seRC: Inc(vMasSeek,8);// seek 1 bytes
      seRL: Inc(vMasSeek,32);// seek 4 bytes
      seRGB: begin
               case ReadBB(APBit) of
                 0: Inc2(APBit,16); // seek 2 bytes
                 1: Inc2(APBit,8); // seek 1 bytes
               end;
               case ReadBB(APBit) of
                 0: Inc(vMasSeek,32);// seek 4 bytes
                 1: Inc(vMasSeek,8);// seek 1 bytes
               end;
               Inc(vMasSeek,8);// seek 1 bytes
             end;
      seUInt64: Inc(vMasSeek,8*Read3Bits(APBit));// seek 1*Read3Bits(APBit) bytes
    end;
  end;
  if vMasSeek <> 0 then
    Inc2(APBit,vMasSeek);
end;
//<----

function ReadR21Text(var APBit: TsgInt64): WideString;
var
  Len: Integer;
begin
  Result := '';
  Len := ReadBS(APBit);
  if Len > 0 then
  begin
    SetLength(Result, Len);
    ReadBytesCustom(APBit, Result[1], Len shl 1);
  end;
end;

(*procedure DoTextRead(ALen: Integer; ACodepage: Word;
  var APBit: TsgInt64; var AStr: string);
var
  vAnsi: sgRawByteString;
begin
  AStr := '';
  if ALen > 0 then
  begin
    SetLength(vAnsi, ALen);
{$IFDEF SGDEL_2009}
    SetCodePage(vAnsi, $FFFF, False);
{$ENDIF}
    ReadBytesCustom(APBit, vAnsi[1], ALen); // ReadBytes(APBit, vAnsi[1], Len);
{$IFDEF SGDEL_2009}
    SetCodePage(vAnsi, ACodePage, False);
{$ENDIF}
    AStr := string(vAnsi);
    ALen := Length(AStr);
    if AStr[ALen] = #0 then
      SetLength(AStr, ALen - 1);
  end;
end;

function _ReadText(Obj: TdwgObject; var APBit: TsgInt64; AParseUnicode: Boolean = True;
  CodePage: Word = CP_ACP; AXRecordText: Boolean = False): string;

  procedure RdText;
  var
    vLen: Integer;
    vCodePage: Word;
  begin
    Result := '';
    if Obj <> nil then
      vCodePage := Obj.Reader.FConverter.CodePage
    else
      vCodePage := CodePage;
    if AXRecordText then
    begin
      vLen := ReadRS(APBit);
      vCodePage := sgCodePageFromDWG(ReadRC(APBit));
    end
    else
      vLen := ReadBS(APBit);
    DoTextRead(vLen, vCodePage, APBit, Result);
  end;

begin
  if (Obj = nil) or (Obj.Reader.Version < acR2007) then
    RdText
  else
    Result := ReadR21Text(Obj.FStrsStart);
{$IFDEF SGDEL_2009}
  if AParseUnicode then
    Result := ParseUnicode(Result, [puU, puM]);
{$ENDIF}
end;*)

function ReadMText(Obj: TdwgObject): string;
var
  L: Integer;
begin
  Result := Obj.FStringReader.ReadText;
  // Replacement of tabulations accordingly DXF
  ReplaceAnsi(Result, #09, '^I');
  ReplaceAnsi(Result, #$0A, '^J');
  L := Length(Result);
  if (L > 0) and (Result[L] = #0) then
    SetLength(Result, L-1);
end;

function ReadR21TextWithCheck(var APBit, PEnd: TsgInt64; Accuracy: Integer): WideString;
var
  Len: Integer;
begin
  Result := '';
  if not Comp2WithAccuracy(APBit, PEnd, Accuracy) then Exit;
  Len := ReadBS(APBit);
  if not Comp2WithAccuracy(APBit, PEnd, Accuracy) then Exit;
  if Len <= 0 then
    Exit;
  SetLength(Result,Len);
  ReadBytesCustom(APBit,Result[1],Len shl 1); // ReadBytes(APBit,Result[1],Len shl 1);
end;

function ReadDD(var APBit: TsgInt64; DefValue: Double): Double;

  procedure Read6;
  var
    P: PAnsiChar;
  begin
    P := PAnsiChar(@Result) + 4;
    ReadBytesPair(APBit,P^,1); //ReadBytes(APBit,P^,2);
    ReadBytesDoublePair(APBit,Result,1); //ReadBytes(APBit,Result,4);
  end;

begin
  Result := DefValue;
  case ReadBB(APBit) of
    1: ReadBytesDoublePair(APBit,Result,1); //ReadBytes(APBit,Result,4);
    2: Read6;
    3: ReadBytesDoublePair(APBit,Result,2); //ReadBytes(APBit,Result,8);
  end;
  if IsNan(Result) or (Abs(Result) > 1E+101) then
    Result := 0;
end;

function ReadBT(var APBit: TsgInt64; Ver: TsgDWGVersion): Double;
begin
  if (Ver >= acR2000) and (ReadBit(APBit) <> 0) then
    Result := 0.0
  else
    Result := ReadBD(APBit);
end;

function ReadBE(var APBit: TsgInt64; AVer: TsgDWGVersion): TFPoint;
begin
  if (AVer >= acR2000) and (ReadBit(APBit) <> 0) then
    Result := MakeFPoint(0,0,1)
  else
    Result := Read3D(APBit);
end;

function ReadBytesHandle(var APBit: TsgInt64; const ABytesCount: Byte): UInt64;
var
  I: Integer;
begin
  Result := 0;
  for I := 0 to ABytesCount - 1 do
    Result := Result shl 8 + ReadRC(APBit);
end;

function Read8BytesHandle(var APBit: TsgInt64): UInt64;
begin
  Result := ReadBytesHandle(APBit, 8);
end;

procedure MakeHandle(ARef: UInt64; var ACode: Byte; var AResult: UInt64);{$IFDEF SG_INLINE} inline;{$ENDIF}
begin
  ACode := ACode shr 4;
  case ACode of
    6:      AResult := ARef + 1;
    8:      AResult := ARef - 1;
    $A:     AResult := ARef + AResult;
    $C:     AResult := ARef - AResult;
  end;
end;

function ReadHandle(var APBit: TsgInt64; var ACode: Byte; ARef: UInt64): UInt64;{$IFDEF SG_INLINE} inline;{$ENDIF}
begin
  ACode := ReadRC(APBit);
  Result := ReadBytesHandle(APBit, ACode and $F);
  MakeHandle(ARef, ACode, Result);
end;

{function ReadObjName(const Obj: TdwgObject; var APBit: TsgInt64;
  var Flags: Integer; Ver: TsgDWGVersion): string;
begin
  if Obj <> nil then
    Obj.ReadObjHeader(APBit);
  Result := _ReadText(Obj, APBit);
  if Ver > acR2004 then
    Flags := ReadBS(APBit)
  else
  begin
    Flags := ReadBit(APBit) shl 6;
    SeekGeneral(APBit, [seBS]);
    Flags := Flags or ReadBit(APBit) shl 4;
  end;
end;

procedure ReadLimits(var APBit: TsgInt64; Obj: TdwgObject; const AFlags: Integer = 0);
var
  I: Integer;
  HC: Byte;
begin
  if Obj.Reader.Version < acR2004 then
  begin
    if AFlags and $C = 0 then
    begin
      Obj.FSrcStart := Obj.ReadID(APBit);
      Obj.FSrcEnd := Obj.ReadID(APBit);
    end;
    Exit;
  end;
  if Obj.FSubEnts = 0 then
    Exit;
  Obj.FChildren := TsgInt64List.Create;
  for I := 0 to Obj.FSubEnts - 1 do
    Obj.FChildren.Add(Obj.ReadID(APBit));
  Obj.FSrcStart := Obj.FChildren.First;
  Obj.FSrcEnd := Obj.FChildren.Last;
end;}

function ReadRGB(var APBit: TsgInt64): Integer;
begin
  SeekGeneral(APBit, [seBS]);
  Result := BGRToRGB(ReadBL(APBit));
  SeekGeneral(APBit, [seRC]);
end;

function CmEntityColorToColorCAD(ACmEntityColor: Cardinal): TsgColorCAD;
begin
  case Byte(ACmEntityColor shr 24) of
    $C1:  Result := MakeColorCAD(acIndexColor, clDXFByBlock);
    $C2:  Result := MakeColorCAD(acRGBColor, BGRToRGB(ACmEntityColor));
    $C3:  Result := MakeColorCAD(acIndexColor, ACmEntityColor and $FFFFFF);
    else  Result := MakeColorCAD(acIndexColor, clDXFByLayer);
  end;
end;

function ReadCmEntityColor(var APBit: TsgInt64): TsgColorCAD;
begin
  Result := CmEntityColorToColorCAD(ReadBL(APBit));
end;

function ReadCMCSection(Obj: TdwgObject; var APBit: TsgInt64): TsgColorCAD;
var
  vColor: Integer;
  vColorName, vColorBlockName: string;
begin
  Result := ReadCmEntityColor(APBit);
  vColor := ReadRC(APBit);// Color Byte
  if vColor and 1 <> 0 then
    vColorName := Obj.FStringReader.ReadText;// color name
  if vColor and 2 <> 0 then
    vColorBlockName := Obj.FStringReader.ReadText;// book name
  Result.AlbumString := vColorName;
//  if Assigned(Obj) then
//  begin
//    Obj.FColorName := vColorName;
//    Obj.FColorBlockName := vColorBlockName;
//  end;
end;

function ReadENCSection(AFlags: Integer; Obj: TdwgObject; var APBit: TsgInt64): TsgColorCAD;
var
  vUseColorIndex: Boolean;
begin
  Result.Active := acRGBColor;
  Result.Color := clEmpty;
  vUseColorIndex := True;
  if AFlags and $4000 <> 0 then
  begin
    //vHandle := Obj.ReadID(APBit);
    // The handle to the color is written in the handle stream.
  end
  else
    if AFlags and $8000 <> 0 then
    begin
      Result := MakeColorCAD(acRGBColor, BGRToRGB(ReadBL(APBit)));
      vUseColorIndex := False;
    end;
  if AFlags and $2000 <> 0 then
    ReadBL(APBit);
  if vUseColorIndex then
    Result := MakeColorCAD(acIndexColor, AFlags and $FFF);
end;

function ReadColorCAD(Obj: TdwgObject; var APBit: TsgInt64): TsgColorCAD;
var
  vTemp: Cardinal;
begin
  vTemp := ReadBS(APBit);
  if Obj.Reader.Version < acR2004 then
    Result := MakeColorCAD(acIndexColor, vTemp)
  else
    if vTemp = 0 then // CMC
      Result := ReadCMCSection(Obj, APBit)
    else
      if vTemp > $FFF then // ENC
        Result := ReadENCSection(vTemp, Obj, APBit)
      else
        Result := MakeColorCAD(acIndexColor, vTemp);
end;

function ReadCMC(Obj: TdwgObject; var APBit: TsgInt64): Cardinal;
var
  vColor: TsgColorCAD;
begin
  vColor := ReadColorCAD(Obj, APBit);
  Result := clNone;
  case vColor.Active of
    acIndexColor: Result := IntToColor(vColor.Color);
    acRGBColor: Result := vColor.Color;
  end;
end;

(*procedure ReadProxyData(AProxyEntList, ASubEntPropsList: TList;
  var APBit: TsgInt64; AConv: TsgDXFConverter);
var
  I, J, K, Count, vDataSize, vSubEntityType, vSubEntCount, vSymbolCounter,
    vFact, vRowsNumber, vColumnsNumber, vEntriesNumber: Integer;
  vRadius, vSweepAngle: Double;
  vPTransform: PsgCADIterate;
  pt1, pt2, pt3: TFPoint;
  vPF2DPoint: TF2DPoint;
  vPSubProps: PsgSubProxyProps;
  vTmpPBit: TsgInt64;
  vSymbol: Byte;
  vFill: Boolean;
  Str: string;
  vAStr: AnsiString;
  vTransforms: TList;
  vEntries: TsgIntegerList;
  vPolygon: TsgCADPolyPolygon;
  vPolyline: TsgDXFPolyLine;
  vVertex: TsgDXFVertex;
  vText: TsgDXFText;
  vLine: TsgDXFLine;
{ vAng1, vAng2, vAng3, vAng4: Double;
  eLayerID, fLayerID, meshEdgesNumber, meshFacesNumber, vertNumber, rrr, epf, fpf, vpf: Integer;
  vPt: PFPoint;
  pp: TList;   }

  function GetTextString(var APBit: TsgInt64): string;
  var
    WCh: Integer;
  begin
    Result := '';
    while True do // Reading text
    begin
      WCh := ReadRS(APBit);
      if WCh = 0 then
        Break;
      if (WCh shr 8 = 0) and CharInSet(Char(WCh), ['!'..'~', ' ']) then
        Result := Result + Char(WCh)
      else
        Result := Result + '\U+' + IntToHex(WCh shr 8, 2) + IntToHex(WCh and $00FF, 2);
    end;
    SetLength(Result, Length(Result));// to exclude special symbols
  end;

  function GetTransformPoint(const APoint: TFPoint): TFPoint;
  begin
    if vTransforms = nil then
      Result := APoint
    else
      Result := FPointXMat(APoint, PsgCADIterate(vTransforms.Last)^.Matrix);
  end;

  function GetTransformSize(const ASize: Double): Double;
  begin
    if vTransforms = nil then
      Result := ASize
    else
      Result := ASize*PsgCADIterate(vTransforms.Last)^.YScale;
  end;

  procedure InitSubProps;// first initialization
  begin
    New(vPSubProps);
    FillChar(vPSubProps^, SizeOf(vPSubProps^), 0);
	  vPSubProps^.LayerIndex := -1;
    vPSubProps^.LTypeIndex := -1;
  	vPSubProps^.ColorID := -1;
  end;

  procedure NewSubProps;
  var
    vTempPSubProps: PsgSubProxyProps;
  begin
    New(vTempPSubProps);
    CopyMemory(vTempPSubProps, vPSubProps, SizeOf(vTempPSubProps^));
    vPSubProps := vTempPSubProps;
  end;

  procedure AddEntityToProxy(AEntity: TsgDXFEntity);
  begin
    AProxyEntList.Add(AEntity);
    ASubEntPropsList.Add(vPSubProps);
    NewSubProps;
  end;

  function GetAngle(p, a: TFPoint): Single;
  var
    hip, leg: Double;
  begin
    Result := 0;
    if ((a.X > p.X) and (a.Y > p.Y)) then // quadrant 1
    begin
      hip := Sqrt(Sqr(a.X - p.X) + Sqr(a.Y - p.Y));
      leg := a.X - p.X;
      Result := (ArcCos(leg / hip) * f180DividedByPi);
      Exit;
    end
    else if ((a.X < p.X) and (a.Y > p.Y)) then// quadrant 2
    begin
      hip := Sqrt(Sqr(p.X - a.X) + Sqr(a.Y - p.Y));
      leg := p.X - a.X;
      Result := (180 - ArcCos(leg / hip) * f180DividedByPi);
      Exit;
    end
    else if ((a.X < p.X) and (a.Y < p.Y)) then// quadrant 3
    begin
      hip := Sqrt(Sqr(p.X - a.X) + Sqr(p.Y - a.Y));
      leg := p.X - a.X;
      Result := (180 + ArcCos(leg / hip) * f180DividedByPi);
      Exit;
    end
    else if ((a.X > p.X) and (a.Y < p.Y)) then// quadrant 4
    begin
      hip := Sqrt(Sqr(a.X - p.X) + Sqr(p.Y - a.Y));
      leg := a.X - p.X;
      Result := (360 - ArcCos(leg / hip) * f180DividedByPi);
      Exit;
    end
    else if((a.Y = p.Y) and (a.X > p.X)) then
      Exit// Result := 0;
    else if ((a.Y > p.Y) and (a.X = p.X)) then
    begin
      Result := 90;
      Exit;
    end
    else if((a.Y = p.Y) and (a.X < p.X)) then
    begin
      Result := 180;
      Exit;
    end
    else// if((a.Y < p.Y) and (a.X = p.X)) then
    begin
      Result := 270;
      Exit;
    end;
  end;

  procedure DoPolyline(const AClosed: Boolean);
  var
    N: Integer;
  begin
    Count := ReadRL(APBit);
    if Count = 2 then
    begin
      vLine := TsgDXFLine.Create;
      vLine.Point := GetTransformPoint(Read3RD(APBit));
      vLine.Point1 := GetTransformPoint(Read3RD(APBit));
      AddEntityToProxy(vLine);
    end
    else
    begin
      vPolyline := TsgDXFPolyLine.Create;
      vPolyline.Polyline3D := True; //3d Polyline
      for N := 0 to Count-1 do
      begin
        vVertex := TsgDXFVertex.Create;
        vVertex.Point := GetTransformPoint(Read3RD(APBit));
        vPolyline.AddEntity(vVertex);
      end;
      vPolyline.Closed := AClosed;
      AddEntityToProxy(vPolyline);
    end;
  end;

  procedure SetSHXFont(const AText: TsgDXFText; const ASHXFont: string);// to be changed in the future versions
  begin
    TsgDXFTextAccess(AText).SetFontName(ASHXFont);
  end;

  function GetString(const AStr: AnsiString): string;
  begin
    Result := ConvertToWideString(AStr, AConv.CodePage);
  end;

begin
  SeekGeneral(APBit,[seRL]);
  vSubEntCount := ReadRL(APBit);
  InitSubProps;
  vFill := False;
  vTransforms := nil;
  for I := 0 to vSubEntCount-1 do
  begin
    vDataSize := ReadRL(APBit);
    vSubEntityType := ReadRL(APBit);
    vTmpPBit := APBit;
    Inc2(vTmpPBit, (vDataSize - 8) shl 3);
    case vSubEntityType of
{      1:
        begin
          pt1 := Read3RD(APBit);
          pt2 := Read3RD(APBit);
        end;                       }
      2:// CIRCLE (normal circle)
        begin
          vPolyline := TsgDXFPolyline.Create;
          vPolyline.Polyline3D := True; //3d Polyline
          pt1 := GetTransformPoint(Read3RD(APBit));
          vRadius := ReadRD(APBit);
          pt2 := Read3RD(APBit);
          // Definition of the start vector direction
          if (pt2.X <= 1 + fAccuracy) and not IsEqual(Abs(pt2.Y), 1.0) then
            pt3 := Ort(Vector(pt2, cnstYOrtAxis))
          else
            pt3 := Ort(Vector(pt2, cnstXOrtAxis));
          if ArcFromTwoVectors(vPolyline, vRadius, 2*Pi, pt1, pt2, pt3, GetNumberOfCircleParts) then
            AddEntityToProxy(vPolyline)
          else
            vPolyline.Free;
        end;
      3:// CIRCLE3PT (3 point circle)
        begin
          vPolyline := TsgDXFPolyline.Create;
          vPolyline.Polyline3D := True; //3d Polyline
          pt1 := GetTransformPoint(Read3RD(APBit));
          pt2 := GetTransformPoint(Read3RD(APBit));
          pt3 := GetTransformPoint(Read3RD(APBit));
          if CircleFromThreePoints(vPolyline, pt1, pt2, pt3, GetNumberOfCircleParts, True) then
            AddEntityToProxy(vPolyline)
          else
            vPolyline.Free;
        end;
      4:// CIRCULARARC (normal and start vector arc)
        begin
          vPolyline := TsgDXFPolyline.Create;
          vPolyline.Polyline3D := True; //3d Polyline
          pt1 := GetTransformPoint(Read3RD(APBit));
          vRadius := ReadRD(APBit);
          pt2 := Read3RD(APBit);
          pt3 := Ort(Read3RD(APBit));// start vector direction
          vSweepAngle := ReadRD(APBit);
          SeekGeneral(APBit,[seRL]);
          if ArcFromTwoVectors(vPolyline, vRadius, vSweepAngle, pt1, pt2, pt3, GetNumberOfCircleParts) then
            AddEntityToProxy(vPolyline)
          else
            vPolyline.Free;
        end;
      5:// CIRCULARARC3PT (3 point arc)
        begin
          vPolyline := TsgDXFPolyline.Create;
          vPolyline.Polyline3D := True; //3d Polyline
          pt1 := GetTransformPoint(Read3RD(APBit));
          pt2 := GetTransformPoint(Read3RD(APBit));
          pt3 := GetTransformPoint(Read3RD(APBit));
          SeekGeneral(APBit,[seRL]);
          if CircleFromThreePoints(vPolyline, pt1, pt2, pt3, GetNumberOfCircleParts, False) then
            AddEntityToProxy(vPolyline)
          else
            vPolyline.Free;
        end;
      6:// POLYLINE
        DoPolyline(False);
      7:// POLYGON
        begin
          if vFill then
          begin
            vPolygon := TsgCADPolyPolygon.Create;
            vPolygon.Boundaries.Add(TF2DPointList.Create);
            Count := ReadRL(APBit);
            for J := 0 to Count-1 do
            begin
              pt1 := GetTransformPoint(Read3RD(APBit));
              vPF2DPoint.X := pt1.X;
              vPF2DPoint.Y := pt1.Y;
              TF2DPointList(vPolygon.Boundaries[0]).Add(vPF2DPoint);
            end;
            AddEntityToProxy(vPolygon);
          end
          else
            DoPolyline(True);
        end;
      8:// MESH
        begin
          vPolyline := TsgDXFPolyline.Create;
          vRowsNumber := ReadRL(APBit);
          vColumnsNumber := ReadRL(APBit);
          for J := 0 to vRowsNumber - 1 do
            for K := 0 to vColumnsNumber - 1 do
            begin
              vVertex := TsgDXFVertex.Create;
              vVertex.Point := GetTransformPoint(Read3RD(APBit));
              vPolyline.AddEntity(vVertex);
            end;
          vPolyline.MeshM := vRowsNumber;
          vPolyline.MeshN := vColumnsNumber;
          AddEntityToProxy(vPolyline);
          APBit := vTmpPBit;// if it is commented downwards
          { epf := ReadRL(APBit);
          if epf and $FFFF <> 0 then
          begin
            meshEdgesNumber := (vRowsNumber - 1) * vColumnsNumber +
              (vColumnsNumber - 1) * vRowsNumber;
            if epf and $00000001 <> 0 then
              for J := 0 to meshEdgesNumber - 1 do
                ReadRL(APBit);
            if epf and $00000002 <> 0 then
              for J := 0 to meshEdgesNumber - 1 do
                eLayerID := ReadRL(APBit);
            if epf and $00000004 <> 0 then
              for J := 0 to meshEdgesNumber - 1 do
                ReadRL(APBit);
            if epf and $00000020 <> 0 then
              for J := 0 to meshEdgesNumber - 1 do
                ReadRL(APBit);
            if epf and $00000040 <> 0 then
              for J := 0 to meshEdgesNumber - 1 do
                K := ReadRL(APBit);// visibility
          end;
          fpf := ReadRL(APBit);
          if fpf and $FFFF <> 0 then
          begin
            meshFacesNumber := (vRowsNumber - 1) * (vColumnsNumber - 1);
            if fpf and $00000001 <> 0 then
              for J := 0 to meshFacesNumber - 1 do
                ReadRL(APBit);
            if fpf and $00000002 <> 0 then
              for J := 0 to meshFacesNumber - 1 do
                fLayerID := ReadRL(APBit);
            if fpf and $00000020 <> 0 then
              for J := 0 to meshFacesNumber - 1 do
                ReadRL(APBit);
            if fpf and $00000080 <> 0 then
              for J := 0 to meshFacesNumber - 1 do
                pt1 := Read3RD(APBit);
            if fpf and $00000040 <> 0 then
              for J := 0 to meshFacesNumber - 1 do
                ReadRL(APBit);
            end;
            vpf := ReadRL(APBit);
            if vpf and $FFFF <> 0 then
            begin
              vertNumber := vRowsNumber * vColumnsNumber;
              if vpf and $00000080 <> 0 then
                for J := 0 to vertNumber - 1 do
                  pt1 := Read3RD(APBit);
              if vpf and $00000400 <> 0 then
                ReadRL(APBit);
          end;                                              }
        end;
      9:// SHELL
        begin
          vPolyline := TsgDXFPolyline.Create;
          vPolyline.Flags := 64;
          Count := ReadRL(APBit);
          for J := 0 to Count - 1 do
          begin
            vVertex := TsgDXFVertex.Create;
            vVertex.Point := GetTransformPoint(Read3RD(APBit));
            vPolyline.AddEntity(vVertex);
          end;
          vPolyline.MeshM := Count;
          vPolyline.MeshN := 1;// only for correct TsgDXFPolyline loading
          vEntriesNumber := ReadRL(APBit);
          vEntries := TsgIntegerList.Create;
          try
            for J := 0 to vEntriesNumber - 1 do
              vEntries.Add(ReadRL(APBit));
            J := 0;
            while J < vEntriesNumber do
            begin
              vVertex := TsgDXFVertex.Create;
              vVertex.Flags := 128;
              K := vEntries[J];
              for vFact := 1 to K do
                case vFact of
                  1: vVertex.PolyFaceVertexIndex1 := vEntries[J+vFact]+1;
                  2: vVertex.PolyFaceVertexIndex2 := vEntries[J+vFact]+1;
                  3: vVertex.PolyFaceVertexIndex3 := vEntries[J+vFact]+1;
                  4: vVertex.PolyFaceVertexIndex4 := vEntries[J+vFact]+1;
                else
                  // ERROR number
                end;
              Inc(J, K+1);
              vPolyline.AddEntity(vVertex);
            end;
          finally
            vEntries.Free;
          end;
          AddEntityToProxy(vPolyline);
          APBit := vTmpPBit;// if it is commented downwards
          { meshEdgesNumber := vEntriesNumber - 1;
          meshFacesNumber := Integer(vEntries[0]);
          epf := ReadRL(APBit);
          if epf and $0000FFFF <> 0 then
          begin
            if epf and $00000001 <> 0 then
              for J := 0 to meshEdgesNumber - 1 do
                rrr := ReadRL(APBit);
            if epf and $00000002 <> 0 then
              for J := 0 to meshEdgesNumber - 1 do
                eLayerID := ReadRL(APBit);
            if epf and $00000004 <> 0 then
              for J := 0 to meshEdgesNumber - 1 do
                rrr := ReadRL(APBit);
            if epf and $00000020 <> 0 then
              for J := 0 to meshEdgesNumber - 1 do
                rrr := ReadRL(APBit);
            if epf and $00000040 <> 0 then
              for J := 0 to meshEdgesNumber - 1 do
                rrr := ReadRL(APBit);
          end;
          fpf := ReadRL(APBit);
          if fpf and $0000FFFF <> 0 then
          begin
            if fpf and $00000001 <> 0 then
              for J := 0 to meshFacesNumber - 1 do
                rrr := ReadRL(APBit);
            if fpf and $00000002 <> 0 then
              for J := 0 to meshFacesNumber - 1 do
                fLayerID := ReadRL(APBit);
            if fpf and $00000020 <> 0 then
              for J := 0 to meshFacesNumber - 1 do
                rrr := ReadRL(APBit);
            if fpf and $00000080 <> 0 then
              for J := 0 to meshFacesNumber - 1 do
                pt1 := Read3RD(APBit);
            if fpf and $00000040 <> 0 then
              for J := 0 to meshFacesNumber - 1 do
                rrr := ReadRL(APBit);
          end;
          vpf := ReadRL(APBit);
          if vpf and $0000FFFF <> 0 then
          begin
            if vpf and $00000080 <> 0 then
              for J := 0 to Count - 1 do
                pt1 := Read3RD(APBit);
            if vpf and $00000400 <> 0 then
              rrr := ReadRL(APBit);
          end;                               }
        end;
      {10:
        begin
          vText := TsgDXFText.Create;
          vText.Point := GetTransformPoint(Read3RD(APBit));
          vText.Extrusion := Read3RD(APBit);
          vText.Rotation := GetAngle(cnstFPointZero, Read3RD(APBit));// Read3RD!
          vText.Height := ReadRD(APBit);
          vText.Scale := ReadRD(APBit);
          vText.ObliqueAngle := ReadRD(APBit);
          Str := '';
          vSymbolCounter := 0;
          while True do // Reading text
          begin
            vSymbol := ReadRC(APBit);
            if vSymbol = 0 then
              Break;
            Str := Str + Char(vSymbol);
          end;
          APBit := vTmpPBit;
          vText.Text := Str;
          AddEntityToProxy(vText);
        end;                                       }
      11:
        begin
          vText := TsgDXFText.Create;
          vText.Point := GetTransformPoint(Read3RD(APBit));
          vText.Extrusion := Read3RD(APBit);
          vText.Rotation := GetAngle(cnstFPointZero, Read3RD(APBit));// Read3RD!
          vAStr := '';
          vSymbol := ReadRC(APBit);
          vSymbolCounter := 1;
          while vSymbol <> 0 do // Reading text
          begin
            vAStr := vAStr + AnsiChar(vSymbol);
            vSymbol := ReadRC(APBit);
            Inc(vSymbolCounter);
          end;
          if (vSymbolCounter mod 4) <> 0 then
            Inc2(APBit, (4 - (vSymbolCounter mod 4)) * 8);
          Count := ReadRL(APBit); // Text length
          if Count = -1 then
            Count := Length(vAStr);
          SetLength(vAStr, Count);
          Str := GetString(vAStr);
          vText.Text := Str;
          SeekGeneral(APBit,[seRL]);
          vText.Height := GetTransformSize(ReadRD(APBit));
          vText.Scale := ReadRD(APBit);
          vText.ObliqueAngle := ReadRD(APBit) * f180DividedByPi;
          vText.Rotation := GetAngle(cnstFPointZero, Read3RD(APBit)) + vText.Rotation;// Read3RD!
          SeekGeneral(APBit,[seRL]);
          vAStr := '';
          vSymbol := ReadRC(APBit);
          {vSymbolCounter := 1;}
          while vSymbol <> 0 do // Reading text
          begin
            vAStr := vAStr + AnsiChar(vSymbol);
            vSymbol := ReadRC(APBit);
            {Inc(vSymbolCounter);}
          end;
          // For future versions (vSymbolCounter)
          {if ((vSymbolCounter mod 4) <> 0) then
            Inc2(APBit, (4 - (vSymbolCounter mod 4)) * 8);
          ReadRL(APBit);}
          Str := GetString(vAStr);
          SetSHXFont(vText, Str);// to be changed in the future versions
          APBit := vTmpPBit;
          AddEntityToProxy(vText);
        end;
{      12:
        begin
          pt1 := Read3RD(APBit);
          pt2 := Read3RD(APBit);
        end;
      13:
        begin
          pt1 := Read3RD(APBit);
          pt2 := Read3RD(APBit);
        end;                      }
      14:
        vPSubProps^.ColorID := ReadRL(APBit);
      16:
        vPSubProps^.LayerIndex := ReadRL(APBit);
      18:
        begin
          vPSubProps^.LTypeIndex := ReadRL(APBit);
          case vPSubProps^.LTypeIndex of
            $7FFF: vPSubProps^.LTypeIndex := -1;
            $7FFE: vPSubProps^.LTypeIndex := -2;
          end;
        end;
      19:
        vPSubProps^.Marker := ReadRL(APBit);
      20:// FILL (on/off)
        vFill := ReadRL(APBit) = 1;
      22:
        begin
          vPSubProps^.ColorID := ReadRC(APBit);
          SeekGeneral(APBit,[seRC,seRC]);
          Inc2(APBit, 8);
        end;
      23:
        vPSubProps^.LWeight := ReadRL(APBit);
      24:
        vPSubProps^.LTScale := ReadRD(APBit);
      26:
        begin
          vPSubProps^.ProxyType := ReadRL(APBit);
          vPSubProps^.PlotStyleIndex := ReadRL(APBit);
        end;
{      27:
        begin
          pt1 := Read3RD(APBit);
          pt2 := Read3RD(APBit);
          ReadRL(APBit);
          ReadRD(APBit);
          ReadRD(APBit);
          for J := 0 to 15 do
            ReadRD(APBit);
          for J := 0 to 15 do
            ReadRD(APBit);
          ReadRL(APBit);
          ReadRL(APBit);
          ReadRD(APBit);
          ReadRD(APBit);
          ReadRL(APBit);
        end;                       }
      29:// PUSH_MODELXFORM
        begin
          if vTransforms = nil then
            vTransforms := TList.Create;
          New(vPTransform);
          FillChar(vPTransform^, SizeOf(vPTransform^), 0);
          for J := 0 to 2 do
            for K := 0 to 3 do
              vPTransform^.Matrix.M[K, J] := ReadRD(APBit);
          if vTransforms.Count > 0 then
            vPTransform^.Matrix := FMatXMat(vPTransform^.Matrix, PsgCADIterate(vTransforms.Last)^.Matrix);
          DoScale2D(vPTransform^);
          vTransforms.Add(vPTransform);
          Inc2(APBit, 256);
        end;
{      30:
        for J := 0 to 15 do
          ReadRD(APBit);      }
      31:// POP_MODELXFORM
        if vTransforms <> nil then
        begin
          if vTransforms.Count > 0 then
          begin
            Dispose(vTransforms.Last);
            vTransforms.Delete(vTransforms.Count-1);
          end;
          if vTransforms.Count = 0 then
            FreeRecordList(vTransforms);
        end;
      32:// ACAD_TABLE line (not documented)
        begin
          DoPolyline(False);
          SeekGeneral(APBit, [se3RD]);
        end;
      {34:
        begin
          ReadRL(APBit);
          ReadRL(APBit);
        end;  }
      36:// AEC undocumented data
        begin
          vText := TsgDXFText.Create;
          vText.Point := GetTransformPoint(Read3RD(APBit));
          vText.Extrusion := Read3RD(APBit);
          vText.Rotation := GetAngle(cnstFPointZero, Read3RD(APBit));// Read3RD!
          vText.Height := GetTransformSize(ReadRD(APBit));
          vText.Scale := ReadRD(APBit);
          vText.ObliqueAngle := ReadRD(APBit) * f180DividedByPi;
          vText.Text := GetTextString(APBit);
          // ... unknow data ...
          APBit := vTmpPBit;
          AddEntityToProxy(vText);
        end;
      38:// ACAD_TABLE text (not documented)
        begin
          vText := TsgDXFText.Create;
          vText.Point := GetTransformPoint(Read3RD(APBit));
          vText.Extrusion := Read3RD(APBit);
          vText.Rotation := GetAngle(cnstFPointZero, Read3RD(APBit));// Read3RD!
          vText.Text := GetTextString(APBit);
          SeekGeneral(APBit,[seRL]);
          vFact := ReadRL(APBit);
          if vFact > 1 then
            SeekGeneral(APBit,[seRS]);
            //ReadRS(APBit);
          vText.Height := GetTransformSize(ReadRD(APBit));
          vText.Scale := ReadRD(APBit);
          vText.ObliqueAngle := ReadRD(APBit) * f180DividedByPi;
          vText.Rotation := GetAngle(cnstFPointZero, Read3RD(APBit)) + vText.Rotation;// Read3RD!
          SeekGeneral(APBit,[seRL,seRL,seRL,seRL,seRL,seRL]);
          Str := '';
          while True do // Reading font name
          begin
            vSymbol := ReadRS(APBit);
            if (vSymbol = 0) then
              Break;
            Str := Str + string(AnsiChar(vSymbol));
          end;
          SetSHXFont(vText, Str);// to be changed in the future versions
          APBit := vTmpPBit;
          AddEntityToProxy(vText);
        end;
      else
        Inc2(APBit, (vDataSize - 8) shl 3);
    end;
  end;
  FreeRecordList(vTransforms);
  Dispose(vPSubProps);
end; *)

function ObjStreamPos(const ABegin, ACurr: TsgInt64): TsgInt64;
begin
  Result.Hi := (ACurr.Lo - ABegin.Lo) div 8;
  Result.Lo := (ACurr.Lo - ABegin.Lo) mod 8;
end;

function ReadDWGType(var APBit: TsgInt64): Integer;
begin
  Result := 0;
  case ReadBB(APBit) of
    0:
      Result := ReadRC(APBit);
    1:
      Result := ReadRC(APBit) + $1F0;
    2:
      Result := ReadRS(APBit);
    3:
      Result := ReadRS(APBit);
  end;
end;

function ReadUInt64(var APBit: TsgInt64): UInt64;
var
  I, vCount: Byte;
begin
  Result := 0;
  vCount := Read3Bits(APBit);
  for I := 0 to vCount - 1 do
    Result := Result + ReadRC(APBit) shl (I shl 3);
end;

function GetLineWeight(AIndex: Integer): Double;
const
  LW: array[0..31] of Integer =
  (000, 005, 009, 013, 015, 018, 020, 025, 030, 035, 040, 050,
   053, 060, 070, 080, 090, 100, 106, 120, 140, 158, 200, 211,
   -1, -1, -1, -1, -1, -1, -2, -3);
begin
  if AIndex > 31 then
    Result := fLineWeightByLayer
  else
    Result := LW[AIndex];
  if Result > 0 then
    Result := 0.01*Result;
end;

{TdwgObject}

{protected}

function TdwgObject.GetBitSize: Integer;
begin
  Result := 0;
end;

function TdwgObject.GetChild(Handle: UInt64): TsgDXFEntity;
var
  I: Integer;

begin
  Result := nil;
  with Reader.FObjMap do
  begin
    I := IndexOfHandle(Handle);
    if I >= 0 then
      Result := GetChildEx(MapElement[I].Handle, I);
  end;
end;

function TdwgObject.GetChildEx(Handle: UInt64; MapIndex: Integer): TsgDXFEntity;
var
  vOwner: TsgDXFEntity;
  vObj: TdwgObject;
begin
  with Reader.FObjMap, MapElement[MapIndex] do
  begin
    Result := TsgDXFEntity(Obj);
    if not Assigned(Result) then
    begin
      vObj := ReadChild(Location, Handle, MapIndex);
      if Assigned(vObj) then
      try
        vObj.References(Reader);
        vOwner := vObj.GetOwner(Reader);
        if not Assigned(vOwner) or (vObj.OwnerAdd(vOwner) < 0) then
          FreeAndNil(vObj.FEntity);
        Result := vObj.FEntity;
        Objects[MapIndex] := Result;
      finally
        FreeAndNil(vObj);
      end;
    end;
  end;
end;

function TdwgObject.GetChildren(Index: Integer): UInt64;
begin
  Result := FChildren[Index];
end;

function TdwgObject.GetChildrenCount: Integer;
begin
  if Assigned(FChildren) then
    Result := FChildren.Count
  else
    Result := 0
end;

function TdwgObject.GetEEDataList: TsgExtendedDataList;
begin
  if not Assigned(FEEDataList) then
    FEEDataList := TsgExtendedDataList.Create;
  Result := FEEDataList;
end;

function TdwgObject.GetObjectBeginning: TsgInt64;
begin
  Result.Lo := 0;
  Result.Hi := 0;
end;

function TdwgObject.GetOwner(AReader: TdwgReader): TsgDXFEntity;
begin
  Result := FOwnerObject;
end;

function TdwgObject.IsEntity: Boolean;
begin
  Result := False;
end;

procedure TdwgObject.NewObject(ACode: Integer; AHandle: UInt64; var AObj: TdwgObject);
var
  vClass: TdwgClass;
begin
  AObj := nil;
  if (ACode=54) or (ACode=55) then
    Exit;
  if ACode >= 500 then
    ACode := Reader.VarCode(ACode);
  if ACode = 498 then
    ACode := cnstProxyObjectIndex;
  if ACode > cnstLimit then
    Exit;
  vClass := cnstDwgClassTosgDwgClass[ACode].Objs;
  if Assigned(vClass) then
  begin
    AObj := vClass.Create;
    AObj.Reader := Reader;
    AObj.FEntity := cnstDwgClassTosgDwgClass[ACode].Ents.Create;
    AObj.FHandle := AHandle;
    Reader.Conv.DoCreate(AObj.FEntity);
  end;
end;

function TdwgObject.OwnerAdd(AOwner: TsgDXFEntity): Integer;
begin
  Result := AOwner.AddEntity(FEntity);
end;

function TdwgObject.ReadID(var APBit: TsgInt64): UInt64;
var
  vCode: Byte;
begin
  Result := ReadHandle(FPHnds^, vCode, FHandle);
end;

function TdwgObject.ReadID(var APBit: TsgInt64; var ACode: Byte): UInt64;
begin
  Result := ReadHandle(FPHnds^, ACode, FHandle);
end;

function TdwgObject.ReadChild(ASeek: Integer;
  AHandle: UInt64; AIndex: Integer): TdwgObject;
var
  vSize, vBitSize, vCode: Integer;
  vBitSizeVal: Byte;
  vBitSizeShift: Cardinal;
  vIdsBitSize, vIdsPos: UInt64;
  vEndBit: Cardinal;
  vPBit, vPStart, vObjectBeginning: TsgInt64;
//  vOwner: TsgDXFEntity;
  vHCode: Byte;
  vStrsStart, vHndsStart, vIdsStrart: TsgInt64;
  //vMapElement: TdwgMapElementList;
begin
//  Result := nil;
  Reader.Read(ASeek, 256);
  {if Reader.FObjMap.ObjectLoadedCount[AIndex] > 2 then //Object can be loaded just two times
  begin
    vMapElement := Reader.FObjMap.MapElement[AIndex];
    if vMapElement.Handle = AHandle then
    begin
      Result := TsgDXFEntity(vMapElement.Obj);
      Exit;
    end;
  end;}
  vSize := ReadMS(Pointer(Reader.FMem));
  InitInt64(Reader.FMem, vPBit);
  vObjectBeginning := vPBit;
  Result := nil;
  if Reader.FVersion > acR2007 then
  begin
    vBitSizeShift := 0;
    vIdsBitSize := 0;
    while True do
    begin
      vBitSizeVal := Byte(ReadRC(vPBit));
      vIdsBitSize := UInt64(vBitSizeVal and $7F shl vBitSizeShift) or vIdsBitSize;
      Inc(vBitSizeShift, 7);
      if vBitSizeVal and $80 = 0 then
        Break;
    end;
    vBitSize := vSize shl 3;
    vIdsPos := vBitSize - vIdsBitSize;
    vIdsStrart := vPBit;
    Inc2(vIdsStrart, vIdsPos);
    Reader.Init2010ObjectData(vPBit, vStrsStart, vHndsStart, vIdsPos, vEndBit);
    vCode := ReadDWGType(vPBit);
  end
  else
  begin
    vCode := ReadBS(vPBit);
    if Reader.FVersion = acR2007 then
      vCode := Reader.Code2007ByClassName(vObjectBeginning, vPBit, vCode);
  end;
  NewObject(vCode, AHandle, Result);
  Reader.DoProgress(psRunning);
  if Assigned(Result) then
  begin
    case Reader.FVersion of
      acR2007..acR2013:
        begin
          if Reader.FVersion < acR2010 then
          begin
            Result.FStrsStart := vPBit;
            vPStart := vObjectBeginning;
            Reader.Init2007ObjectData(vPStart, Result.FStrsStart, Result.FHndsStart,
              vEndBit);
            vPBit := vPStart;
          end
          else
          begin
            Result.FStrsStart := vStrsStart;
            Result.FHndsStart := vHndsStart;
            Result.FIdsStrart := vIdsStrart;
          end;
          Result.FDataEnd := vObjectBeginning;
          Inc2(Result.FDataEnd, vSize shl 3);
          Result.FPHnds := @Result.FHndsStart;
        end;
      else
        Result.FPHnds := @vPBit;
    end;
    Result.FStringReader := Result.CreateStringReader(vPBit, Reader.Version);
    Reader.FObjMap.Objects[AIndex] := Result.FEntity;
    Result.ObjectBeginning := vObjectBeginning;
    case Reader.FVersion of
      acR2000..acR2004:
        Result.BitSize := ReadRL(vPBit);
    end;
    ReadHandle(vPBit, vHCode, AHandle);
    Result.FEntity.Handle := AHandle;
    Result.ReadEEDItems(vPBit);
    if not Reader.DoReadData(Result, vPBit) then
    begin
      Result.FEntity.Free;
      FreeAndNil(Result);
      Reader.FObjMap.Objects[AIndex] := nil;
    end;
  end;
end;

function TdwgObject.ReadEED(var APBit, APEnd: TsgInt64;
  const AAppID: UInt64): TsgCADExtendedData;
var
  vCode: Integer;
  vStringReader: TdwgStringReader;
begin
  Result := TsgCADExtendedData.Create;
  try
    vStringReader := Reader.GetStringReader(APBit);
    Result.AddInt64(1001, AAppID);
    while Comp2(APBit, APEnd) do
    begin
      vCode := ReadRC(APBit) + 1000;
      case vCode of
        1000: Result.AddString(vCode, vStringReader.ReadXrecordText);
        1002: Result.AddByte(vCode, ReadRC(APBit)); //Inc2(APBit, 8);
        1003: Result.AddInt64(vCode, Read8BytesHandle(APBit));
        1004: AddBinaryChunk(APBit, vCode, Result); //Inc2(APBit, ReadRC(APBit) shl 3);
        1005: Result.AddInt64(vCode, Read8BytesHandle(APBit));
        1040 .. 1042: Result.AddDouble(vCode, ReadRD(APBit)); //Inc2(APBit, 64);
        1010 .. 1013: Result.AddPoint(vCode, Read3RD(APBit)); //Inc2(APBit, 192);
        1060..1069, 1070: Result.AddInt16(vCode, ReadRS(APBit)); //Inc2(APBit, 16);
        1071: Result.AddInt(vCode, ReadRL(APBit)); //Inc2(APBit, 32);
      end;
    end;
  finally
    if Result.DataCount <= 1 then
      FreeAndNil(Result)
    else
      EEDataList.Add(Result);
  end;
end;

function TdwgObject.ReadEEDItems(var APBit: TsgInt64): TsgExtendedDataList;
var
  I: Integer;
  vHCode: Byte;
  vEEData: TsgCADExtendedData;
  vAppID: UInt64;
  vPEnd: TsgInt64;
begin
  // |Length|Application handle|Data items|
  I := ReadBS(APBit) shl 3;  // |Length|
  while I <> 0 do
  begin
    vAppID := ReadHandle(APBit, vHCode, FHandle); // |Application handle|

    vPEnd := APBit;
    Inc2(vPEnd, I);

    if CanEEDApply(vAppID) then
    begin
      vEEData := ReadEED(APBit, vPEnd, vAppID);   // |Data items|
      if Assigned(vEEData) then
        ApplyEED(vEEData, vAppID);
    end;
    APBit := vPEnd;

    I := ReadBS(APBit) shl 3;  // |Length|
  end;
  Result := FEEDataList;
end;

procedure TdwgObject.ReadError;
begin
  FCorrectData := False;
end;

procedure TdwgObject.ReadHandleRefs(var APBit: TsgInt64);
begin
  FOwner := ReadID(APBit);
  SkipHandles(APBit);
end;

function TdwgObject.ReadID: UInt64;
var
  vCode: Byte;
begin
  Result := ReadHandle(FPHnds^, vCode, FHandle);
end;

procedure TdwgObject.ReadLineWeight(AIndex: Integer);
begin
  FLineWeight := GetLineWeight(AIndex);
end;

procedure TdwgObject.ReadObjHeader(var APBit: TsgInt64);
begin
  if Reader.Version < acR2000 then
    SeekGeneral(APBit, [seRL]);
  FReactorsCount := ReadBL(APBit);
  if Reader.Version >= acR2004 then
  begin
    FXDicHandlePresent := ReadBit(APBit) <> 1;
    if Reader.Version >= acR2013 then
      Inc2(APBit, 1);
  end;
end;

function TdwgObject.ReadObjName(var APBit: TsgInt64; var Flags: Integer): string;
begin
  ReadObjHeader(APBit);
  Result := FStringReader.ReadText;
  if Reader.Version > acR2004 then
    Flags := ReadBS(APBit)
  else
  begin
    Flags := ReadBit(APBit) shl 6;
    SeekGeneral(APBit, [seBS]);
    Flags := Flags or ReadBit(APBit) shl 4;
  end;
end;

procedure TdwgObject.ReadOwner(AReader: TdwgReader);
begin
  FOwnerObject := AReader.ObjByHandle(FOwner, nil);
end;

procedure TdwgObject.ReadPredefined(ASeek: Integer; AObj: TdwgObject;
  AIndex: Integer);
var
  vSize, vBitSize, vCode: Integer;
  vBitSizeVal: Byte;
  vBitSizeShift: Cardinal;
  vIdsBitSize, vIdsPos: UInt64;
  vEndBit: Cardinal;
  vPBit, vPStart, vObjectBeginning: TsgInt64;
  vHCode: Byte;
  vStrsStart, vHndsStart, vIdsStrart: TsgInt64;
begin
  Reader.Read(ASeek, 256);
  vSize := ReadMS(Pointer(Reader.FMem));
  InitInt64(Reader.FMem, vPBit);
  vObjectBeginning := vPBit;
  if Reader.FVersion > acR2007 then
  begin
    vBitSizeShift := 0;
    vIdsBitSize := 0;
    while True do
    begin
      vBitSizeVal := Byte(ReadRC(vPBit));
      vIdsBitSize := UInt64(vBitSizeVal and $7F shl vBitSizeShift) or vIdsBitSize;
      Inc(vBitSizeShift, 7);
      if vBitSizeVal and $80 = 0 then
        Break;
    end;
    vBitSize := vSize shl 3;
    vIdsPos := vBitSize - vIdsBitSize;
    vIdsStrart := vPBit;
    Inc2(vIdsStrart, vIdsPos);
    Reader.Init2010ObjectData(vPBit, vStrsStart, vHndsStart, vIdsPos, vEndBit);
    {vCode := }ReadDWGType(vPBit);
  end
  else
  begin
    vCode := ReadBS(vPBit);
    if Reader.FVersion = acR2007 then
      {vCode := }Reader.Code2007ByClassName(vObjectBeginning, vPBit, vCode);
  end;
  Reader.DoProgress(psRunning);
  case Reader.FVersion of
    acR2007..acR2013:
      begin
        if Reader.FVersion < acR2010 then
        begin
          AObj.FStrsStart := vPBit;
          vPStart := vObjectBeginning;
          Reader.Init2007ObjectData(vPStart, AObj.FStrsStart, AObj.FHndsStart,
            vEndBit);
          vPBit := vPStart;
        end
        else
        begin
          AObj.FStrsStart := vStrsStart;
          AObj.FHndsStart := vHndsStart;
          AObj.FIdsStrart := vIdsStrart;
        end;
        AObj.FDataEnd := vObjectBeginning;
        Inc2(AObj.FDataEnd, vSize shl 3);
        AObj.FPHnds := @AObj.FHndsStart;
      end;
    else
      AObj.FPHnds := @vPBit;
  end;
  Reader.FObjMap.Objects[AIndex] := AObj.FEntity;
  AObj.ObjectBeginning := vObjectBeginning;
  AObj.FStringReader := AObj.CreateStringReader(vPBit, Reader.Version);
  case Reader.FVersion of
    acR2000..acR2004:
      AObj.BitSize := ReadRL(vPBit);
  end;
  ReadHandle(vPBit, vHCode, AObj.FHandle);
  AObj.FEntity.Handle := AObj.FHandle;
  AObj.ReadEEDItems(vPBit);
  Reader.DoReadData(AObj, vPBit);
end;

procedure TdwgObject.ReadSubEntIDs(var APBit: TsgInt64; const AFlags: Integer);
var
  I{, J, K}: Integer;
begin
  if Reader.Version < acR2004 then
  begin
    if AFlags and $C = 0 then
    begin
      FFirstChildHandle := ReadID(APBit);
      FLastChildHandle := ReadID(APBit);
//      J := FObjMap.IndexOfHandle(FFirstChildHandle);
//      K := FObjMap.IndexOfHandle(FLastChildHandle);
//      if J > K then
//      begin
//        SwapInts(J, K);
//        SwapUInt64(FLastChildHandle, FFirstChildHandle);
//        FSwapped := True;
//      end;
//      FSubEnts := K - J + 1;
//      if (J >= 0) and (K >= 0) then
//      begin
//        FChildren := TsgInt64List.Create(0, FSubEnts);
//        for I := J to K do
//          FChildren.Add(Reader.FObjMap.MapElement[I].Handle);
//      end;
    end;
  end
  else
    if FSubEnts > 0 then
    begin
      FChildren := TsgInt64List.Create(0, FSubEnts);
      for I := 0 to FSubEnts - 1 do
        FChildren.Add(ReadID(APBit));
      FFirstChildHandle := FChildren.First;
    end;
end;

procedure TdwgObject.ReadSubEnts(AReader: TdwgReader);
begin
  if AReader.Version >= acR2004 then
    ReadSubEntsR2004(AReader)
  else
    ReadSubEntsR2000(AReader)
end;

procedure TdwgObject.ReadSubEntsR2000(AReader: TdwgReader);
var
  I: Integer;
  vOwner: TsgDXFEntity;
  vNext: UInt64;
  vObj: TdwgObject;

  procedure Next;
  begin
    repeat
      Inc(I);
    until (I > Reader.FObjMap.Count) or (Reader.FObjMap.MapElement[I].Obj = nil);
    if I <= Reader.FObjMap.Count  then
      vNext := Reader.FObjMap.MapElement[I].Handle
    else
      vNext := cnstBadHandle;
  end;

begin
//  if FSwapped then
//    vNext := FLastChildHandle
//  else
    vNext := FFirstChildHandle;
  with Reader.FObjMap do
    repeat
      I := IndexOfHandle(vNext);
      if I >= 0 then
      begin
        with MapElement[I] do
          if not Assigned(Obj) then
          begin
            vObj := ReadChild(Location, vNext, I);
            if Assigned(vObj) then
            try
              vNext := vObj.FSibling;
              vObj.References(AReader);
              vOwner := vObj.GetOwner(AReader);
              if not Assigned(vOwner) or (vObj.OwnerAdd(vOwner) < 0) then
                FreeAndNil(vObj.FEntity);
              Objects[I] := vObj.FEntity;
            finally
              FreeAndNil(vObj);
            end
            else
              Next;
          end
          else
            Next;
      end;
    until (vNext = cnstBadHandle) or (I < 0);
end;

procedure TdwgObject.ReadSubEntsR2004(AReader: TdwgReader);
var
  C: Integer;
begin
  C := GetChildrenCount;
  FChildIndex := 0;
  while (FChildIndex < C) and not AReader.Stopped do
  begin
    Child[Children[FChildIndex]];
    Inc(FChildIndex);
  end;
end;

procedure TdwgObject.References(AReader: TdwgReader);
begin
  ReadOwner(AReader);
  FReactors.Remove(FOwner);
  ReadSubEnts(AReader);
end;

procedure TdwgObject.SetBitSize(const AValue: Integer);
begin
end;

procedure TdwgObject.SetObjectBeginning(const APosition: TsgInt64);
begin
end;

procedure TdwgObject.SkipHandles(var APBit: TsgInt64);
var
  I: Integer;
  vHCode: Byte;
  vHandle: UInt64;
begin
  if Reader.Version >= acR2004 then
  begin
    for I := 0 to FReactorsCount - 1 do
      FReactors.Add(ReadID(APBit));
    if FXDicHandlePresent then
      FXDict := ReadID(APBit); //xdicobjhandle (hard owner)
  end
  else
    repeat
      vHandle := ReadID(APBit, vHCode);
      case vHCode of
        cntDWGObjHandleSoftPointer: FReactors.Add(vHandle);
        cntDWGObjHandleHardOwner: FXDict := vHandle;
      end;
    until vHCode = cntDWGObjHandleHardOwner;
end;

{public}

procedure TdwgObject.ApplyAnnotativeData(const AEEData: TsgCADExtendedData);
var
  I: Integer;
begin
  FAnnotativeFlags := 0;
  I := 1;
  while I < AEEData.DataCount do
  begin
    if (AEEData.DataType[I] = edtInt16) and (AEEData.DataCode[I] = 1070) then
      FAnnotativeFlags := FAnnotativeFlags shl 16 or AEEData.DataInt16[I];
    Inc(I);
  end;
end;

function TdwgObject.ApplyEED(const AEEData: TsgCADExtendedData;
  const AAppID: UInt64): Boolean;
begin
  if AAppID = Reader.FAnnotativeAppID then
  begin
    ApplyAnnotativeData(AEEData);
    Result := True;
  end
  else
    Result := False;
end;

function TdwgObject.CanEEDApply(const AAppID: UInt64): Boolean;
begin
  Result := AAppID = Reader.FAnnotativeAppID;
end;

constructor TdwgObject.Create;
begin
  inherited Create;
  FCorrectData := True;
  FReactors := TsgInt64List.Create;
  FLineWeight := fLineWeightByLayer;
end;

function TdwgObject.CreateStringReader(var APBit: TsgInt64;
  AVersion: TsgDWGVersion): TdwgStringReader;
begin
  case AVersion of
    acR2007..acR2013:
      Result := TdwgWideStringReaderParse.Create(@FStrsStart, Reader.Conv.CodePage);
  else
    Result := TdwgAnsiStringReaderParse.Create(@APBit, Reader.Conv.CodePage);
  end;
end;

destructor TdwgObject.Destroy;
begin
  FChildren.Free;
  FReactors.Free;
  FreeList(TList(FEEDataList));
  FStringReader.Free;
  inherited Destroy;
end;

function TdwgObject.Find(AHandle: UInt64; var I: Integer): Boolean;
begin
  if Assigned(FChildren) then
    I := FChildren.IndexOf(AHandle)
  else
    I := -1;
  Result := I >= 0;
end;

{ TdwgReader }

function TdwgReader.CheckSentinel(P: Pointer; const ASentinel: TsgDWGSentinel): Boolean;
begin
  Result := CompareMem(P, @ASentinel, SizeOf(TsgDWGSentinel));
end;

function TdwgReader.Code2007ByClassName(const AObjectBeginning, APBit: TsgInt64;
  AReadedCode: Integer): Integer;
var
  I: Integer;
  vAcDbName: string;
  vPStart, vPBit, vPHndStart: TsgInt64;
  vEndBit: Cardinal;
begin
  case AReadedCode of
    498 .. 499: // entity or object
      begin
        vPBit := APBit;
        vPStart := AObjectBeginning;
        Init2007ObjectData(vPStart, vPBit, vPHndStart, vEndBit);
        ReadR21Text(vPBit);
        vAcDbName := ReadR21Text(vPBit);
        I := FAcDbClasses.IndexOf(vAcDbName);
        if I >= 0 then
          Result := Integer(FAcDbClasses.Objects[I])
        else
          Result := AReadedCode;
      end;
  else
    Result := AReadedCode;
  end;
end;

procedure TdwgReader.CRead(ASeek, ASize: Integer);
var
  vStream: TStream;
begin
  vStream := FSource;
  if vStream = nil then
    vStream := FStream;
  if (ASeek < 0) or (ASize < 0) or (ASeek + ASize > vStream.Size) then
    raise EReadError.Create(sCorruptedDWGFileHeader);
  Read(ASeek, ASize);
end;

procedure TdwgReader.DoException;
var
  vMessage: string;
begin
  if Assigned(FExceptionClass) then
  begin
    TsgDXFConverterAccess(FConverter).ClearBlocks;
    vMessage := FExceptionClass.ClassName;
    if FExceptionEntityHandle > 0 then
      vMessage := vMessage + cnstEntityHandle + IntToHex(FExceptionEntityHandle, 0);
    vMessage := vMessage + '.';
    raise FExceptionClass.Create(vMessage);
  end;
end;

procedure TdwgReader.DoProgress(AStage: TProgressStage);
begin
  if Assigned(FOnProgress) then
    FOnProgress(AStage, FObjMap.ObjectsLoaded, FObjMap.Count + 1);
end;

function TdwgReader.DoReadData(AObj: TdwgObject;
  var APBit: TsgInt64): Boolean;
begin
  Result := False;
  try
    AObj.ReadData(APBit);
    Result := AObj.FCorrectData;
  except
    on E: Exception do
    begin
      if not Assigned(FExceptionClass) then
      begin
        FExceptionClass := ExceptClass(E.ClassType);
        FExceptionEntityHandle := AObj.FHandle;
      end;
    end;
  end;
end;

function TdwgReader.EntAddRef(AEnt: TsgDXFEntity): Integer;
var
  Item: TsgOwneredItem;
begin
  Item := TsgOwneredItem(TsgDXFEntityAccess(AEnt).GetNamedItem);
  if Assigned(Item) then
    Result := Item.ObjAddRef
  else
    Result := -1;
end;

function TdwgReader.EntRelease(AEnt: TsgDXFEntity): Integer;
var
  Item: TsgOwneredItem;
begin
  Item := TsgOwneredItem(TsgDXFEntityAccess(AEnt).GetNamedItem);
  if Assigned(Item) then
    Result := Item.ObjRelease
  else
    Result := -1;
end;

{function TdwgReader.FindLocation(const AHandle: UInt64;
  var AIndex: Integer): Integer;
begin
   AIndex := FObjMap.IndexOfHandle(AHandle);
   if AIndex > -1 then
     Result := FObjMap.MapElement[AIndex].Location
   else
     Result := 0;
end;}

{function TdwgReader.FinishObject(AObj: TdwgObject;
  AOwner: TsgDXFEntity; AIndex: Integer): TsgDXFEntity;
begin
  Result := nil;
  if Assigned(AOwner) and (AObj.OwnerAdd(AOwner) >= 0) then
  begin
    Result := AObj.FEntity;
    FObjMap.Objects[AIndex] := Result;
  end
  else
    FreeAndNil(AObj.FEntity)
end;}

function TdwgReader.ForceDictionarySection(const ADictName: string;
  const ASection: TsgDXFEntity; const ASectionName: string): TsgDXFEntity;
var
  vNamedObjects: TsgDXFEntity;
begin
  Result := ASection;
  if not Assigned(Result) then
  begin
    if Conv.Counts[csObjects] > 0 then
    begin
      vNamedObjects := Conv.Sections[csObjects].FindEntByHandle(FNamedObjects);
      if Assigned(vNamedObjects) then
      begin
        Result := vNamedObjects.FindEntByName(ADictName);
        if Assigned(Result) then
          vNamedObjects.RemoveEntity(Result)
        else
          Result := TsgDXFDictionary.Create;
        Result.Name := ASectionName;
        Conv.Sections[csObjects].AddEntity(Result);
      end;
    end
    else
    begin
      Result := TsgDXFDictionary.Create;
      Result.Name := ASectionName;
      Conv.Sections[csObjects].AddEntity(Result);
    end;
  end;
end;

function TdwgReader.GetArrowTypeByHandle(const ABlockRecordHandle: UInt64): TsgDimArrowType;
var
  vBlockRecord: TsgDXFBlockRecord;
begin
  if ABlockRecordHandle <> cnstBadHandle then
  begin
    vBlockRecord := TsgDXFBlockRecord(ObjByHandle(ABlockRecordHandle, TsgDXFBlockRecord));
    Result := GetArrowTypeByName(vBlockRecord.Name, datUndefined);
  end
  else
    Result := datClosedfilled;
end;

function TdwgReader.GetDictionary(Name: string): TsgDXFDictionary;
begin
  Result := TsgDXFDictionary(Conv.Sections[csObjects].FindEntByName(Name));
  if not Assigned(Result) then
  begin
    Result := TsgDXFDictionary.Create;
    Result.Name := Name;
    Conv.Sections[csObjects].AddEntity(Result);
  end;
end;

function TdwgReader.GetPHeadVarStruct: PsgHeadVarStruct;
begin
  Result := TsgDWGConverter(FConverter).PHeadVarStruct;
end;

function TdwgReader.GetTableNameByHandle(const AHandle: UInt64;
  AClass: TsgDXFEntityClass): string;
var
  vEntity: TsgDXFEntity;
begin
  vEntity := ObjByHandle(AHandle, AClass);
  if Assigned(vEntity) then
    Result := vEntity.Name
  else
    Result := '';
end;

procedure TdwgReader.Init2007ObjectData(var AStartBit, APStrStart, APHndStart: TsgInt64;
  var AEndBit: Cardinal; ANeedReadEndBit: Boolean = True);
var
  vPBit: TsgInt64;
  vStrsSize: Cardinal;
begin
  vPBit := APStrStart;
  APHndStart := AStartBit;
  if ANeedReadEndBit then
    AEndBit := Cardinal(ReadRL(vPBit));
  Inc2(APHndStart, AEndBit);
  vStrsSize := 0;
  Read2007StrDataLength(AStartBit, AEndBit, vStrsSize);
  Dec(AEndBit, vStrsSize);
  APStrStart := AStartBit;
  AStartBit := vPBit;
  Inc2(APStrStart, AEndBit);
end;

procedure TdwgReader.Init2010ObjectData(var AStartBit, APStrStart,
  APHndStart: TsgInt64; const AIdsPos: Cardinal; var AEndBit: Cardinal);
begin
  AEndBit := AIdsPos;
  APStrStart := AStartBit;
  Init2007ObjectData(AStartBit, APStrStart, APHndStart, AEndBit, False);
end;

procedure TdwgReader.InitLayouts;
var
  vLayout: TsgDXFEntity;
  vPaper, vModel: TsgDXFBlock;
  vLayouts: TsgDXFEntity;

  // ALayouts - section
  // ACurrentLayout - in/out
  procedure _CleaningLayouts(ALayouts: TsgDXFEntity;
    var ACurrentLayout: TsgDXFLayout);
  var
    I: Integer;
    vTmpLayout: TsgDXFLayoutAccess;
    vTmpBlock: TsgDXFEntity;
  begin
    I := ALayouts.Count - 1;
    while I >= 1 do
    begin
      vTmpLayout := TsgDXFLayoutAccess(ALayouts[I]);
      if vTmpLayout.IsEmpty then
      begin
        vTmpBlock := nil;
        if Assigned(vTmpLayout.BlockRecord) then
          vTmpBlock := TsgDXFBlockRecordAccess(vTmpLayout.BlockRecord).Block;
        vTmpLayout.ClearReferences;
        if vTmpLayout = ACurrentLayout then
          ACurrentLayout := nil;
        ALayouts.DeleteEntity(I);
        vTmpLayout.Free;
        if I >= 2 then // do not delete model and paper blocks
          if Assigned(vTmpBlock) then
          begin
            if Assigned(vTmpBlock.Owner) then
              vTmpBlock.Owner.RemoveEntity(vTmpBlock);
            vTmpBlock.Free;
          end;
      end;
      Dec(I);
    end;
  end;

begin
  vLayouts := Conv.Sections[csLayouts];
  vModel := Model;
  if not Assigned(vModel.Layout) then
  begin
    vLayout := TsgDXFLayout.Create;
    vLayouts.AddEntity(vLayout);
    TsgDXFLayout(vLayout).PaperSpaceBlock := vModel;
  end;
  vPaper := Paper;
  if not Assigned(vPaper.Layout) then
  begin
    vLayout := TsgDXFLayout.Create;
    vLayout.Name := sLayout + '1';
    vLayouts.AddEntity(vLayout);
    TsgDXFLayout(vLayout).PaperSpaceBlock := vPaper;
  end;
  vLayouts.RemoveEntity(vModel.Layout);
  TsgDXFGroupAccess(vLayouts).SortEntByHandle;
  vLayouts.InsertEntity(0, vModel.Layout);
  if Conv.HeadVarStruct.TileMode = 0 then
  begin
    vLayout := nil;
    vPaper := Paper;
    if Assigned(vPaper) then
      vLayout := vPaper.Layout;
  end
  else
    vLayout := vModel.Layout;
  _CleaningLayouts(vLayouts, TsgDXFLayout(vLayout));
  if Assigned(vLayout) then
    Conv.DefaultLayoutIndex := vLayouts.IndexOfEntity(vLayout);
end;

procedure TdwgReader.InitViewportsByList;
var
  I, J, K: Integer;
  vList: TsgInt64List;
  vHashItem: TsgHashItem;
  vPaperSpaceBlockRecordHandle: UInt64;
  vBlockRecord: TsgDXFBlockRecordAccess;
  vBlock: TsgDXFBlockAccess;
  vViewport: TsgDXFViewport;
begin
  for I := 0 to FViewports.Count - 1 do
  begin
    vHashItem := FViewports[I];
    vPaperSpaceBlockRecordHandle := vHashItem.HashCode;
    J := FObjMap.IndexOfHandle(vPaperSpaceBlockRecordHandle);
    if J >= 0 then
    begin
      vBlockRecord := TsgDXFBlockRecordAccess(FObjMap.MapElement[J].Obj);
      vBlock := TsgDXFBlockAccess(vBlockRecord.Block);
      vBlock.FViewPortOrdIndex := -1;
      vBlock.FViewPortWithMinIndex := nil;
      vList := TsgInt64List(vHashItem.Data);
      for K := 0 to vList.Count - 1 do
      begin
        J := FObjMap.IndexOfHandle(vList[K]);
        if J >= 0 then
        begin
          vViewport := TsgDXFViewport(FObjMap.MapElement[J].Obj);
          Inc(vBlock.FViewPortOrdIndex);
          vViewport.OrdIndex := vBlock.FViewPortOrdIndex;
          vViewport.ThisID := vBlock.FViewPortOrdIndex + 1;
          if vBlock.FViewPortWithMinIndex = nil then
            vBlock.FViewPortWithMinIndex := vViewport;
        end;
      end;
    end;
  end;
end;

function TdwgReader.IsFamiliarApplication(const AAppID,
  AHandle: UInt64): Boolean;
begin
  Result := AAppID = FACADAppID;
end;

{function TdwgReader.LoadEntity(const AObject: TdwgObject): Boolean;
begin
  Result := False;
  try
    AObject.Loads(Self);
    Result := True;
  except
    on E: Exception do
      if not Assigned(FExceptionClass) then
      begin
        FExceptionClass := ExceptClass(E.ClassType);
        FExceptionEntityHandle := AObject.FEntity.Handle;
      end;
  end;
end;}

procedure TdwgReader.LoadHeaderHandles;
var
  I, J: Integer;
  vPHeadVS: PsgHeadVarStruct;
  vDimStyle: TsgDXFDimensionStyleAccess;
begin
  vPHeadVS := GetPHeadVarStruct;
  vPHeadVS.CLayer := GetTableNameByHandle(FHeaderHandles.CLAYER, TsgDXFLayer);
  vPHeadVS.CELType := GetTableNameByHandle(FHeaderHandles.CELTYPE, TsgDXFLineType);
  vPHeadVS.TextStyle := GetTableNameByHandle(FHeaderHandles.TEXTSTYLE,
    TsgDXFStyle);
  vPHeadVS.DimStyle := GetTableNameByHandle(FHeaderHandles.DIMSTYLE,
    TsgDXFDimensionStyle);
  if FVersion >= acR2000 then
  begin
    vPHeadVS.DimProps.Arrows.Blk := GetArrowTypeByHandle(FHeaderHandles.DIMBLK);
    vPHeadVS.DimProps.Arrows.Blk1 := GetArrowTypeByHandle(FHeaderHandles.DIMBLK1);
    vPHeadVS.DimProps.Arrows.Blk2 := GetArrowTypeByHandle(FHeaderHandles.DIMBLK2);
    vPHeadVS.DimProps.Arrows.LrBlk := GetArrowTypeByHandle(FHeaderHandles.DIMLDRBLK);
  end;
  if FArrows.Count > 0 then
  begin
    vDimStyle := TsgDXFDimensionStyleAccess(TsgDXFDimensionStyle.Create);
    try
      J := FDummy.AddEntity(vDimStyle);
      try
        for I := 0 to FArrows.Count - 1 do
          if TsgLinkObject(FArrows.Objects[I]).GetObject(Conv.Sections[csBlocks]) = nil then
            vDimStyle.DIMBLKT := GetArrowTypeByName(FArrows[I], datUndefined);
      finally
        FDummy.DeleteEntity(J);
      end;
    finally
      vDimStyle.Free;
    end;
  end;
end;

procedure TdwgReader.ReadPlotSettings(Obj: TdwgObject; const APlotSettings: PsgPlotSettingsData;
  var APBit: TsgInt64);
begin
  APlotSettings^.PageSetupName := Obj.FStringReader.ReadText;
  APlotSettings^.PrintOrConfigName := Obj.FStringReader.ReadText;
  APlotSettings^.PlotLayoutFlags := ConvertIntegerToPlotLayoutFlags(ReadBS(APBit));
  APlotSettings^.UnprintableMargin.Left := ReadBD(APBit);
  APlotSettings^.UnprintableMargin.Bottom := ReadBD(APBit);
  APlotSettings^.UnprintableMargin.Right := ReadBD(APBit);
  APlotSettings^.UnprintableMargin.Top := ReadBD(APBit);
  APlotSettings^.PlotPaperSize.X := ReadBD(APBit);
  APlotSettings^.PlotPaperSize.Y := ReadBD(APBit);
  APlotSettings^.PaperSize := Obj.FStringReader.ReadText;
  APlotSettings^.PlotOrigin.X := ReadBD(APBit);
  APlotSettings^.PlotOrigin.Y := ReadBD(APBit);
  APlotSettings^.PlotPaperUnits := TsgPlotPaperUnits(ReadBS(APBit));
  APlotSettings^.PlotRotation := GetPlotRotation(ReadBS(APBit));
  APlotSettings^.PlotType := TsgPlotType(ReadBS(APBit));
  APlotSettings^.PlotWindowAreaMin.X := ReadBD(APBit);
  APlotSettings^.PlotWindowAreaMin.Y := ReadBD(APBit);
  APlotSettings^.PlotWindowAreaMax.X := ReadBD(APBit);
  APlotSettings^.PlotWindowAreaMax.Y := ReadBD(APBit);
  if Version < acR2004 then
    APlotSettings^.PlotViewName := Obj.FStringReader.ReadText;
  APlotSettings^.NumeratorOfCustomPrintScale := ReadBD(APBit);
  APlotSettings^.DenominatorOfCustomPrintScale := ReadBD(APBit);
  APlotSettings^.CurrentStyleSheet := Obj.FStringReader.ReadText;
  APlotSettings^.StandardScaleType := ReadBS(APBit);
  APlotSettings^.FloatingPointScaleFactor := ReadBD(APBit);
  APlotSettings^.PaperImageOrigin.X := ReadBD(APBit);
  APlotSettings^.PaperImageOrigin.Y := ReadBD(APBit);
  if Version >= acR2004 then
  begin
    APlotSettings^.ShadePlotMode := ReadBS(APBit);
    APlotSettings^.ShadePlotResolutionLevel := ReadBS(APBit);
    APlotSettings^.ShadePlotCustomDPI := ReadBS(APBit);
  end;
end;

procedure TdwgReader.ReadPrototype(ASeek, ASize: Integer);
begin
  CRead(ASeek, ASize);
  FSegmentedFile := TsgSegmentedFile.CreateFromMemory(FConverter, FMem, ASize);
  FSegmentedFile.ReadFile;
end;

function TdwgReader.LTypeByIndex(AIndex: Integer): TsgDXFLineType;
begin
  Result := Conv.LTypes[AIndex + 2];
end;

{procedure TdwgReader.NewObject(ACode: Integer; var AObj: TdwgObject);
var
  vClass: TdwgClass;
begin
  if (ACode=54) or (ACode=55) then
    Exit;
  if ACode >= 500 then
    ACode := VarCode(ACode);
  if ACode = 498 then
    ACode := cnstProxyObjectIndex;
  if ACode > cnstLimit then
    Exit;
  vClass := cnstDwgClassTosgDwgClass[ACode].Objs;
  if vClass=nil then
    Exit;
  AObj := vClass.Create;
  AObj.Reader := Self;
  AObj.FEntity := cnstDwgClassTosgDwgClass[ACode].Ents.Create;
  FConverter.DoCreate(AObj.FEntity);
end;}

function TdwgReader.ObjByHandle(AHandle: UInt64;
  AClass: TsgDXFEntityClass): TsgDXFEntity;
begin
  Result := FDataBase.Child[AHandle];
  if (AClass <> nil) and not (Result is AClass) then
    Result := nil;
end;

function TdwgReader.PMSpace(var APBit: TsgInt64; AObj: TdwgObject;
  var APHeadVar: PsgHeadVarStruct): TFRect;
var
  I: Integer;
begin
  APHeadVar^.InsBase := Read3D(APBit);
  Result.TopLeft := Read3D(APBit);
  Result.BottomRight := Read3D(APBit);
  SeekGeneral(APBit,[se2RD,se2RD,seBD]);
  APHeadVar.UCSORG := Read3D(APBit);
  APHeadVar.UCSXDir := Read3D(APBit);
  APHeadVar.UCSYDir := Read3D(APBit);
  AObj.ReadID(APBit);
  if FVersion >= acR2000 then
  begin
    AObj.ReadID(APBit);
    SeekGeneral(APBit, [seBS]);
    AObj.ReadID(APBit);
    for I := 0 to 5 do
      SeekGeneral(APBit,[se3D]);
  end;
end;

procedure TdwgReader.Read(ASeek,ASize: Integer);
begin
  if FSource <> nil then
  begin
    FMem := FSource.Memory;
    Inc(FMem,ASeek);
    Exit;
  end;
  if ASeek >= 0 then
    FStream.Seek(ASeek,soFromBeginning);
  if ASize > FSize then
  begin
    ReallocMem(FMem,ASize);
    FSize := ASize;
  end;
  FStream.ReadBuffer(FMem^,ASize);
end;

procedure TdwgReader.Read2007StrDataLength(const APStart: TsgInt64;
  var AEndBit, AStrSize: Cardinal);
var
  vPBit: TsgInt64;
begin
  Dec(AEndBit);
  vPBit := APStart;
  Inc2(vPBit, AEndBit);
  if ReadBit(vPBit) = 1 then
  begin
    Dec(AEndBit, $10);
    vPBit := APStart;
    Inc2(vPBit, AEndBit);
    AStrSize := Word(ReadRS(vPBit));
    if AStrSize and $8000 <> 0 then
    begin
      Dec(AEndBit, $10);
      vPBit := APStart;
      Inc2(vPBit, AEndBit);
      AStrSize := AStrSize and $7FFF;
      AStrSize := (Word(ReadRS(vPBit)) shl $F) or AStrSize;
    end;
  end;
end;

procedure TdwgReader.ReadClasses(ASeek, ASize: Integer);
var
  vN, vC, vClassID: Integer;
  vEndBit: Cardinal;
  vPStart, vPEnd, vPR21Strs, vPR21StrsEnd, vPHndsStart: TsgInt64;
  vString, vAcDbClass: string;
begin
  CRead(ASeek, ASize);
  if not CheckSentinel(FMem, cnstClassesSectionBeginSentinel) then
    Exit;
  InitInt64(FMem, vPStart);
  Inc2(vPStart,128);
  //Inc2(vPStart,64);
  vN := ReadRL(vPStart);
  if (vN < 20) or (vN > ASize-20) then
    Exit;
  if (FVersion > acR2007) and (FMetadata.ReleaseVersion > 3) then
  begin
    if ReadRL(vPStart) <> 0 then
      raise EdwgError.Create(sDecompressDWGError);
  end;
  vPR21Strs := vPStart;
  vPEnd := vPStart;
  Inc2(vPEnd, vN shl 3 - 20);
  case FVersion of
    acR2004:
      Inc2(vPStart,35);
    acR2007..acR2013:
      begin
        //ReadRL(vPStart);
        vPR21Strs := vPStart;
        Init2007ObjectData(vPStart, vPR21Strs, vPHndsStart, vEndBit);
        vPEnd := vPStart;
        Inc2(vPEnd, vEndBit);
        vPR21StrsEnd := vPR21Strs;
        Inc2(vPR21StrsEnd, Cardinal(vN) shl 3 - vEndBit - 20);
        SeekGeneral(vPStart,[seBS,seRC,seRC,seB]);
      end;
  end;
  if FClasses=nil then
    FClasses := TsgIntegerList.Create;
  FStringReader.Create(@vPStart, Conv.CodePage);
  while Comp2(vPStart, vPEnd) do
  begin
    vN := ReadBS(vPStart);
    SeekGeneral(vPStart, [seBS]);
    case FVersion of
      acR2007..acR2013:
        begin
          ReadR21TextWithCheck(vPR21Strs, vPR21StrsEnd, 8);
          vAcDbClass := ReadR21TextWithCheck(vPR21Strs, vPR21StrsEnd, 8);
          vString := ReadR21TextWithCheck(vPR21Strs, vPR21StrsEnd, 8);
        end;
    else
      FStringReader.ReadText;
      vAcDbClass := FStringReader.ReadText;
      vString := FStringReader.ReadText;
    end;
    SeekGeneral(vPStart, [seB]); // vZombie
    vClassID := ReadBS(vPStart);
    case FVersion of
      acR2004..acR2013:
        begin
          vC := ReadBB(vPStart);
          if vC < 2 then
            Inc2(vPStart,8);
          if vC = 0 then
            Inc2(vPStart,24);
          SeekGeneral(vPStart, [seBS,seBS,seBS,seBS]);
        end;
    end;
    Dec(vN,500);
    if vN < 0 then
      Continue;
    vString := AnsiUpperCase(vString);
    vC := CodeFromName(vString);
    if vC=0 then
      if (vClassID = 498) {and (vZombie = 1)} then
        vC := cnstProxyObjectIndex // see NewObject
      else
        Continue;
    if FClasses.Count <= vN then
      FClasses.Count := vN+1;
    if (vAcDbClass <> '') and (vC <> cnstProxyObjectIndex) then
      FAcDbClasses.AddObject(vAcDbClass, TObject(vN + 500));
    FClasses[vN] := vC;
  end;
end;

procedure TdwgReader.ReadHeadVars(ASeek,ASize: Integer);
var
  vPBit: TsgInt64;
  I: Integer;
  vEndBit: Cardinal;
  vCode: Byte;
  vPHeadVar: PsgHeadVarStruct;
  vObj: TdwgObject;
  vSentinel: TsgDWGSentinel;
begin
  CRead(ASeek, ASize);
  if not CheckSentinel(FMem, cnstHeaderVariablesBeginSentinel) then
    Exit;
  vObj := TdwgEntity.Create;
  try
    InitInt64(FMem, vPBit);
    vObj.Reader := Self;
    vPHeadVar := GetPHeadVarStruct;
    if (FVersion > acR2007) and (FMetadata.ReleaseVersion > 3) then
    begin
      ReadBytesDoublePair(vPBit, vSentinel, $4);//ReadBytes(vPBit, cnstSnHeaderVariables, $10);
      SeekGeneral(vPBit,[seRS,seRL,seRS]);
    end
    else
      Inc2(vPBit,160);
    if FVersion > acR2004 then
    begin
      vObj.FStrsStart := vPBit;
      Init2007ObjectData(vPBit, vObj.FStrsStart, vObj.FHndsStart, vEndBit);
      FStringReader.Create(@vObj.FStrsStart, Conv.CodePage);
      vObj.FPHnds := @vObj.FHndsStart;
    end
    else
    begin
      FStringReader.Create(@vPBit, Conv.CodePage);
      vObj.FPHnds := @vPBit;
    end;
    vObj.FStringReader := FStringReader;

    if FVersion > acR2010 then
      ReadBUL(vPBit); //REQUIREDVERSIONS
    {
       if the DWG is correct the following 4 floating point values must be
         ReadBD 412148564080.0
         ReadBD 1.0
         ReadBD 1.0
         ReadBD 1.0
    }
    SeekGeneral(vPBit,[se3D,seBD]);
    for I := 0 to 3 do FStringReader.ReadText;
    SeekGeneral(vPBit,[seBL,seBL]);
    if FVersion < acR2000 then
      SeekGeneral(vPBit, [seBS]);
    if FVersion < acR2004 then
      vObj.ReadID;
    Inc2(vPBit,15);
    if FVersion < acR2000 then
      Inc2(vPBit,5);
    if FVersion >= acR2004 then
      Inc2(vPBit,1);
    FConverter.DefaultLayoutIndex := ReadBit(vPBit) xor 1;
    vPHeadVar.TileMode := FConverter.DefaultLayoutIndex xor 1;
    Inc2(vPBit,4);
    if FVersion < acR2000 then
      Inc2(vPBit,1);
    SeekGeneral(vPBit, [seBS]);
    if FVersion < acR2000 then
      SeekGeneral(vPBit, [seBS]);
    for I := 0 to 3 do
      SeekGeneral(vPBit, [seBS]);

    SeekGeneral(vPBit, [seBS]);//AUPREC
    if FVersion < acR2000 then
      SeekGeneral(vPBit, [seBS]);//OSMODE

    vPHeadVar.AttMode := GetAttributeMode(ReadBS(vPBit));
    if FVersion < acR2000 then
      SeekGeneral(vPBit, [seBS]);//COORDS

    FConverter.PointDisplayMode := ReadBS(vPBit);
    vPHeadVar.PointDisplayMode := FConverter.PointDisplayMode;
    if FVersion < acR2000 then
      SeekGeneral(vPBit, [seBS]);
  //  if FVersion >= acR2004 then Inc2(P,102);
    if FVersion >= acR2004 then
      for I := 0 to 2 do
        SeekGeneral(vPBit,[seBL]);
    for I := 0 to 15 do
      SeekGeneral(vPBit, [seBS]);
    FUnits := ReadBS(vPBit);
    SeekGeneral(vPBit, [seBS,seBS]);
    FConverter.LTScale := ReadBD(vPBit);
    vPHeadVar.LTScale := FConverter.LTScale;
    vPHeadVar.TextSize := ReadBD(vPBit);
    SeekGeneral(vPBit, [se2D]);
    vPHeadVar.FilletRadius := ReadBD(vPBit);
    SeekGeneral(vPBit, [se2D]);
    vPHeadVar.PointDisplaySize := ReadBD(vPBit);
    for I := 0 to 11 do
      SeekGeneral(vPBit,[seBD]);
    vPHeadVar.CELTScale := ReadBD(vPBit);
    FStringReader.ReadText;
    for I := 0 to 7 do
      SeekGeneral(vPBit,[seBL]);
    if FVersion >= acR2004 then
      for I := 0 to 2 do
        SeekGeneral(vPBit,[seBL]);
    vPHeadVar.CEColor :=  ReadColorCAD(vObj, vPBit);
    FMaxHandle := ReadHandle(vPBit, vCode, 0);
    TsgDXFConverterAccess(FConverter).SetHandSeed(FMaxHandle);
    FHeaderHandles.CLAYER := vObj.ReadID;
    FHeaderHandles.TEXTSTYLE := vObj.ReadID;
    FHeaderHandles.CELTYPE := vObj.ReadID;
    if FVersion >= acR2007 then
      vObj.ReadID;
    FHeaderHandles.DIMSTYLE := vObj.ReadID;
    FHeaderHandles.CMLSTYLE := vObj.ReadID;
    if FVersion >= acR2000 then
      SeekGeneral(vPBit,[seBD]); // PSVPSCALE
    PMSpace(vPBit, vObj, vPHeadVar);
    FConverter.Extents := PMSpace(vPBit, vObj, vPHeadVar);
    if FVersion >= acR2000 then
    begin
      vPHeadVar.DimProps.Post := FStringReader.ReadText;
      vPHeadVar.DimProps.APost := FStringReader.ReadText;
    end
    else
    begin
      SeekGeneral(vPBit, [seB,seB]); // DIMTOL, DIMLIM
      vPHeadVar.DimProps.Tih := ReadBit(vPBit) <> 0;
      vPHeadVar.DimProps.Toh := ReadBit(vPBit) <> 0;
      vPHeadVar.DimProps.SE1 := ReadBit(vPBit) <> 0;
      vPHeadVar.DimProps.SE2 := ReadBit(vPBit) <> 0;
      vPHeadVar.DimProps.Alt := ReadBit(vPBit) <> 0;
      Inc2(vPBit, 1);// DIMTOFL
      vPHeadVar.DimProps.Sah := ReadBit(vPBit) <> 0; // DIMSAH
      vPHeadVar.DimProps.Tix := ReadBit(vPBit);
      Inc2(vPBit, 17);
      vPHeadVar.DimProps.SD1 := ReadBit(vPBit) <> 0;
      vPHeadVar.DimProps.SD2 := ReadBit(vPBit) <> 0;
      Inc2(vPBit, 49);
      vPHeadVar.DimProps.Tad := ReadRC(vPBit);
      SeekGeneral(vPBit, [seBS,seBS]); // DIMUNIT, IMAUNIT
      vPHeadVar.DimProps.Dec := ReadBS(vPBit);
      SeekGeneral(vPBit, [seBS,seBS,seBS]); // DIMTDEC, DIMALTU, DIMALTTD
      vObj.ReadID;
    end;
    vPHeadVar.DimProps.Scale := ReadBD(vPBit);
    vPHeadVar.DimProps.Asz := ReadBD(vPBit);
    vPHeadVar.DimProps.Exo := ReadBD(vPBit);
    SeekGeneral(vPBit,[seBD]);
    vPHeadVar.DimProps.Exe := ReadBD(vPBit);
    SeekGeneral(vPBit,[se3D,seBD]);
    if FVersion >= acR2007 then //DimtFill, DimtFillColor
    begin
      SeekGeneral(vPBit, [seBD,seBD,seBS]);
      ReadCMC(vObj, vPBit);
    end;
    if FVersion >= acR2000 then
    begin
      SeekGeneral(vPBit, [seB,seB]); // DIMTOL, DIMLIM
      vPHeadVar.DimProps.Tih := ReadBit(vPBit) <> 0;
      vPHeadVar.DimProps.Toh := ReadBit(vPBit) <> 0;
      vPHeadVar.DimProps.SE1 := ReadBit(vPBit) <> 0; // DIMSE1
      vPHeadVar.DimProps.SE2 := ReadBit(vPBit) <> 0; // DIMSE2
      vPHeadVar.DimProps.Tad := ReadBS(vPBit);
      SeekGeneral(vPBit, [seBS,seBS]);
    end;
    if FVersion >= acR2007 then
      SeekGeneral(vPBit, [seBS]);
    vPHeadVar.DimProps.Txt := ReadBD(vPBit);
    vPHeadVar.DimProps.Cen := ReadBD(vPBit); // DIMCEN
    SeekGeneral(vPBit, [seBD]); // DIMTSZ
    vPHeadVar.DimProps.AltF := ReadBD(vPBit);
    vPHeadVar.DimProps.LFac := ReadBD(vPBit);
    SeekGeneral(vPBit,[seBD,seBD]); // DIMTVP, DIMTFAC
    vPHeadVar.DimProps.Gap := ReadBD(vPBit);
    if FVersion < acR2000 then
    begin
      vPHeadVar.DimProps.Post := FStringReader.ReadText;
      vPHeadVar.DimProps.APost := FStringReader.ReadText;
      vPHeadVar.DimProps.Arrows.Blk := GetArrowTypeByName(FStringReader.ReadText, datClosedfilled);
      vPHeadVar.DimProps.Arrows.Blk1 := GetArrowTypeByName(FStringReader.ReadText, datUndefined);
      vPHeadVar.DimProps.Arrows.Blk2 := GetArrowTypeByName(FStringReader.ReadText, datUndefined);
      if (vPHeadVar.DimProps.Arrows.Blk = datUndefined) and
         (vPHeadVar.DimProps.Arrows.Blk1 <> datUndefined) and
         (vPHeadVar.DimProps.Arrows.Blk1 = vPHeadVar.DimProps.Arrows.Blk2) then
        vPHeadVar.DimProps.Arrows.Blk := vPHeadVar.DimProps.Arrows.Blk1;
    end
    else
    begin
      SeekGeneral(vPBit,[seBD]);
      vPHeadVar.DimProps.Alt := ReadBit(vPBit) <> 0;
      SeekGeneral(vPBit, [seBS]);
      Inc2(vPBit,1); // DIMTOFL
      vPHeadVar.DimProps.Sah := ReadBit(vPBit) <> 0; // DIMSAH
      vPHeadVar.DimProps.Tix := ReadBit(vPBit);
      Inc2(vPBit,1);
    end;
    vPHeadVar.DimProps.ClrD := ReadColorCAD(vObj, vPBit);
    vPHeadVar.DimProps.ClrE := ReadColorCAD(vObj, vPBit);
    vPHeadVar.DimProps.ClrT := ReadColorCAD(vObj, vPBit);
    if FVersion >= acR2000 then
    begin
      SeekGeneral(vPBit, [seBS]);
      vPHeadVar.DimProps.Dec := ReadBS(vPBit);
      for I := 0 to 8 do
        SeekGeneral(vPBit, [seBS]);
      vPHeadVar.DimProps.SD1 := ReadBit(vPBit) <> 0;
      vPHeadVar.DimProps.SD2 := ReadBit(vPBit) <> 0;
      for I := 0 to 3 do
        SeekGeneral(vPBit, [seBS]);
      Inc2(vPBit,1);
      SeekGeneral(vPBit, [seBS]);
      if FVersion >= acR2007 then
        Inc2(vPBit,1);
      FHeaderHandles.DIMTXTSTY := vObj.ReadID;
      FHeaderHandles.DIMLDRBLK := vObj.ReadID;
      FHeaderHandles.DIMBLK := vObj.ReadID;
      FHeaderHandles.DIMBLK1 := vObj.ReadID;
      FHeaderHandles.DIMBLK2 := vObj.ReadID;
      if FVersion >= acR2007 then
        for I := 0 to 2 do
          vObj.ReadID;
      vPHeadVar.DimProps.LwD := ReadBS(vPBit);
      vPHeadVar.DimProps.LwE := ReadBS(vPBit);
    end;
    // BLOCK CONTROL OBJECT (hard owner)
    FBlockRecords.FHandle := vObj.ReadID;
    // LAYER CONTROL OBJECT (hard owner)
    FLayerControl := vObj.ReadID;
    // STYLE CONTROL OBJECT (hard owner)
    FStyleControl := vObj.ReadID;
    // LINETYPE CONTROL OBJECT (hard owner)
    FLTypeControl := vObj.ReadID;
    for I := 0 to 2 do
      vObj.ReadID;
    // APPID CONTROL OBJECT (hard owner)
    FAppIDControl := vObj.ReadID;
    // DIMSTYLE CONTROL OBJECT (hard owner)
    FDimStyleControl := vObj.ReadID;
    if FVersion <= acR2000 then
      vObj.ReadID;
    vObj.ReadID; // DICTIONARY (ACAD_GROUP) (hard pointer)
    FMLStylesDict := vObj.ReadID; // DICTIONARY (ACAD_MLINESTYLE) (hard pointer)
    FNamedObjects := vObj.ReadID; //DICTIONARY (NAMED OBJECTS) (hard owner)
    if FVersion >= acR2000 then
    begin
      SeekGeneral(vPBit, [seBS,seBS]);
      FStringReader.ReadText;
      FStringReader.ReadText;
      FLayoutsDict := vObj.ReadID;
      for I := 0 to 1 do
        vObj.ReadID;
      if FVersion >= acR2004 then
      begin
        FMaterialDict := vObj.ReadID;
        FColors := vObj.ReadID; // DICTIONARY (ACAD_COLOR) (hard pointer)
        if FVersion >= acR2007 then
          vObj.ReadID;
        if FVersion >= acR2013 then
          vObj.ReadID;
      end;
      vPHeadVar.CELWeight := GetLineWeight(ReadBL(vPBit) and $1F);  //R2013 !!!
      vPHeadVar.InsUnits := ReadBS(vPBit);

      if ReadBS(vPBit) = 3 then
        vObj.ReadID;
      FStringReader.ReadText;
      FStringReader.ReadText;

      if FVersion >= acR2004 then
      begin
        SeekGeneral(vPBit, [seRC,seRC,seRC,seRC,seRC,seRC,seBS,seBS,seRC,seRC]);
        FStringReader.ReadText;
      end;
    end;

    FPaper.BlockRecord.Handle := vObj.ReadID; //BLOCK_RECORD (*PAPER_SPACE) (hard pointer)
    FModel.BlockRecord.Handle := vObj.ReadID; //BLOCK_RECORD (*MODEL_SPACE) (hard pointer)
    FLTByLayer := vObj.ReadID;     //LTYPE (BYLAYER) (hard pointer)
    FLTByBlock := vObj.ReadID;     //LTYPE (BYBLOCK) (hard pointer)
    FLTContinious := vObj.ReadID;  //LTYPE (CONTINUOUS) (hard pointer)
  finally
    vObj.FStringReader := nil;
    vObj.Free;
  end;
end;

procedure TdwgReader.ReadMeasurement(ASeek: Integer);
var
  vPHeadVar: PsgHeadVarStruct;
begin
  Read(ASeek,4);
  vPHeadVar := GetPHeadVarStruct;
  vPHeadVar.Measurement := PInteger(FMem)^ <> 0;
end;

procedure TdwgReader.ReadMetadata(const Stream: TStream; const FileHeader: TdwgFileHeader);
var
  vPos: Int64;
  vPBit: TsgInt64;
  vBuf: array[0..5] of Byte;
  vBuffer: TMemoryStream;
begin
  if FVersion >= acR2004 then
  begin
    vPos := Stream.Position;
    vBuffer := TMemoryStream.Create;
    try
      Stream.Position := 0;
      vBuffer.CopyFrom(Stream, 0);
      InitInt64(vBuffer.Memory, vPBit);
      ReadBytesCustom(vPBit, vBuf, 6);  //ReadBytes(vPBit, vBuf, 6);
      ReadBytesCustom(vPBit, vBuf, 5);  //ReadBytes(vPBit, vBuf, 5);
      FMetadata.ReleaseVersion := ReadRC(vPBit);
      ReadRC(vPBit);//unknown
      FMetadata.PreviewAddress := ReadRL(vPBit);
      FMetadata.OrigFileSavedVer := ReadRC(vPBit);
      FMetadata.OrigFileSavedReleaseVer := ReadRC(vPBit);
      FMetadata.CodePage := ReadRS(vPBit);
      ReadRC(vPBit);//must to be zero
      ReadRC(vPBit);//not sure must be equal OrigFileSavedVer?
      ReadRC(vPBit);//not sure must be OrigFileSavedReleaseVer?
      FMetadata.SecurityFlags := ReadRL(vPBit);
      ReadRL(vPBit);//must to be zero
      FMetadata.SummaryInfoAddress := ReadRL(vPBit);
      FMetadata.VBAProjectAddress := ReadRL(vPBit);
      ReadRL(vPBit);//must to be $00000080
    finally
       vBuffer.Free;
       Stream.Position := vPos;
    end;
  end;
end;

(*function TdwgReader.ReadObject(ASeek: Integer; AHandle: UInt64;
  AIndex: Integer): TsgDXFEntity;
var
  vSize, vBitSize, vCode: Integer;
  vBitSizeVal: Byte;
  vBitSizeShift: Cardinal;
  vIdsBitSize, vIdsPos: UInt64;
  vEndBit: Cardinal;
  vPBit, vPStart, vObjectBeginning: TsgInt64;
  vObj: TdwgObject;
  vOwner: TsgDXFEntity;
  vHCode: Byte;
  vStrsStart, vHndsStart, vIdsStrart: TsgInt64;
  vMapElement: TdwgMapElementList;
begin
  Result := nil;
  Read(ASeek, 256);

  if FObjMap.ObjectLoadedCount[AIndex] > 2 then //Object can be loaded just two times
  begin
    vMapElement := FObjMap.MapElement[AIndex];
    if vMapElement.Handle = AHandle then
    begin
      Result := TsgDXFEntity(vMapElement.Obj);
      Exit;
    end;
  end;

  vSize := ReadMS(Pointer(FMem));
  InitInt64(FMem, vPBit);
  vObjectBeginning := vPBit;
  vObj := nil;
  if FVersion > acR2007 then
  begin
    vBitSizeShift := 0;
    vIdsBitSize := 0;
    while True do
    begin
      vBitSizeVal := Byte(ReadRC(vPBit));
      vIdsBitSize := UInt64(vBitSizeVal and $7F shl vBitSizeShift) or vIdsBitSize;
      Inc(vBitSizeShift, 7);
      if vBitSizeVal and $80 = 0 then
        Break;
    end;
    vBitSize := vSize shl 3;
    vIdsPos := vBitSize - vIdsBitSize;
    vIdsStrart := vPBit;
    Inc2(vIdsStrart, vIdsPos);
    Init2010ObjectData(vPBit, vStrsStart, vHndsStart, vIdsPos, vEndBit);
    NewObject(ReadDWGType(vPBit), vObj);
  end
  else
  begin
    vCode := ReadBS(vPBit);
    if FVersion = acR2007 then
      vCode := Code2007ByClassName(vObjectBeginning, vPBit, vCode);
    NewObject(vCode, vObj);
  end;
  DoProgress(psRunning);
  if Assigned(vObj) then
  try
    case FVersion of
      acR2007..acR2013:
        begin
          if FVersion < acR2010 then
          begin
            vObj.FStrsStart := vPBit;
            vPStart := vObjectBeginning;
            Init2007ObjectData(vPStart, vObj.FStrsStart, vObj.FHndsStart,
              vEndBit);
            vPBit := vPStart;
          end
          else
          begin
            vObj.FStrsStart := vStrsStart;
            vObj.FHndsStart := vHndsStart;
            vObj.FIdsStrart := vIdsStrart;
          end;
          vObj.FDataEnd := vObjectBeginning;
          Inc2(vObj.FDataEnd, vSize shl 3);
        end;
    end;
    FObjMap.Objects[AIndex] := vObj.FEntity;
    vObj.ObjectBeginning := vObjectBeginning;
    vObj.FHandle := AHandle;
    vObj.FEntity.Handle := AHandle;
    case FVersion of
      acR2000..acR2004:
        vObj.BitSize := ReadRL(vPBit);
    end;
    ReadHandle(vPBit, vHCode, AHandle);
    vObj.ReadEEDItems(vPBit);
    DoReadData(vObj, vPBit);
    vObj.References(Self);
    vOwner := vObj.GetOwner(Self);
    if not Assigned(vOwner) or (vObj.OwnerAdd(vOwner) < 0) then
      FreeAndNil(vObj.FEntity);
    Result := vObj.FEntity;
    FObjMap.Objects[AIndex] := Result;
  finally
    vObj.Free;
  end;
end;*)

procedure TdwgReader.ReadObjMap(ASeek,ASize: Integer);
var
  vPStart, vPEnd: PAnsiChar;
  vH: UInt64;
  vLenght: Integer;
  vSize: Word;
begin
  CRead(ASeek, ASize);
  vPStart := FMem;
  vSize := Swap(PWord(vPStart)^);
  while vSize > 2 do
  begin
    vPEnd := vPStart + vSize;
    Inc(vPStart,2);
    vH := 0;
    vLenght := 0;
    if FVersion >= acR2004 then
      vLenght := ASeek + ASize;
    while vPStart < vPEnd do
    begin
      vH := vH + ReadMC(Pointer(vPStart));
      vLenght := vLenght + ReadMCSigned(Pointer(vPStart));
      FObjMap.AddDwgElement(vH, vLenght);
    end;
    Inc(vPStart,2);
    vSize := Swap(PWord(vPStart)^);
  end;
  FObjMap.Sort;
end;

{procedure TdwgReader.ReadPart(AFirst,ALast: Integer; AList: TsgInt64List);
var
  vHandle,N: Int64;
  vIndex, vLocation: Integer;
  J: Integer;
  procedure GetNext;
  begin
    if AList <> nil then
    begin
      if J >= AList.Count then
        FNext := 0
      else
        FNext := AList[J];
    end;
  end;
begin
  N := FNext;
  FNext := 0;
  vLocation := 0;
  J := 0;
  vHandle := 0;
  if AList <> nil then
    AFirst := FObjMap.Count;
  GetNext;
  repeat
    if Stopped then Exit;
    if FNext <> 0 then
    begin
      vLocation := FindLocation(FNext,vIndex);
      if vIndex < 0 then
        FNext := 0;
      if (vIndex > -1) and (FObjMap.MapElement[vIndex].Obj <> nil) then
        FNext := 0
      else
        vHandle := FNext;
    end;
    if (FNext = 0) and (AFirst <= FObjMap.Count) then
    begin
      vHandle := FObjMap.MapElement[AFirst].Handle;
      vLocation := FObjMap.MapElement[AFirst].Location;
      vIndex := AFirst;
      Inc(AFirst);
    end;
    if (vIndex > -1) and (FObjMap.MapElement[vIndex].Obj = nil) then
      FObjMap.Objects[vIndex] := ReadObject(vLocation, vHandle, vIndex);
    if vIndex = ALast then Break;// Hide by commenting this line for previous version
    Inc(J);
    GetNext;
  until ((FNext = 0) and (AFirst > ALast));
  FNext := N;
end;}

{procedure TdwgReader.ReadPart(AFirst, ALast: Integer);
var
  I: Integer;
begin
  for I := 0 to FObjMap.Count do
    if FObjMap.MapElement[I].Obj = nil then
      FObjMap.Objects[I] := ReadObject(FObjMap.MapElement[I].Location, FObjMap.MapElement[I].Handle, I);
end;}

procedure TdwgReader.ReadSummaryInfo(ASeek, ASize: Integer);
begin
end;

procedure TdwgReader.ReadTemplate(ASeek, ASize: Integer);
var
  vPBit: TsgInt64;
  vSize: Integer;
  vTemplateDesc: WideString;
  vHeadVar: PsgHeadVarStruct;
begin
  CRead(ASeek, ASize);
  InitInt64(FMem, vPBit);
  vSize := ReadRS(vPBit);
  if (vSize = 0) or (vSize * 2 + 2 > ASize) then
    Exit;
  SetLength(vTemplateDesc, vSize);
  ReadBytesCustom(vPBit, vTemplateDesc[1], vSize shl 1); //ReadBytes(vPBit, vTemplateDesc[1], vSize shl 1);
  vHeadVar := GetPHeadVarStruct;
  vHeadVar^.Measurement := ReadRS(vPBit) <> 0;
end;

function TdwgReader.VarCode(ACode: Integer): Integer;
begin
  Result := ACode;
  Dec(ACode,500);
  if (FClasses <> nil) and (ACode < FClasses.Count) then
    Result := FClasses[ACode];
  if Result=0 then
    Result := ACode+500;
end;

{protected}

procedure TdwgReader.ReadHeader;
type
  TUnpackDWG = function(Version: TsgDWGVersion; MS: TCustomMemoryStream; var SecCount: Integer): TMemoryStream;
var
  vLCount,vPos: Integer;
  vPFileHeader: PdwgFileHeader;
  vLocator,vLocator0: PdwgLocator;
  vUnpackFunc: TUnpackDWG;
  vPosition: Int64;
begin
  vPos := FStream.Position;
  CRead(vPos, SizeOf(TdwgFileHeader));
  vPFileHeader := PdwgFileHeader(FMem);
  FImage := vPFileHeader.ImageSeeker;
  if CADPreview then
  begin
    vPosition := FStream.Position;
    try
      ReadImage;
    finally
      if TsgDWGConverter(FConverter).FImage = nil then
        FStream.Position := vPosition;
    end;
  end;
  if TsgDWGConverter(FConverter).FImage <> nil then Exit;
  if vPFileHeader.CodePage <= High(arDWGCodePages) then
    TsgDWGConverter(FConverter).SetCodePage(arDWGCodePages[vPFileHeader.CodePage])
  else
    TsgDWGConverter(FConverter).SetCodePage(CP_ACP);
  vLCount := vPFileHeader.Locators;
  if (FVersion >= acR2004) and (vLCount and $FF000000 <> 0) then
    raise EdwgError.Create(sEncryptedByPassword);
  if FVersion >= acR2004 then
    vLCount := 0;
  Read(-1, vLCount * SizeOf(TdwgLocator));
  vLocator := PdwgLocator(FMem);
  vLocator0 := vLocator;
  FMem := nil;
  FSize := 0;
  FStream.Position := vPos;
  FConverter.SetSourceStream(FStream);
  FSource := FConverter.Source;
  @vUnpackFunc := nil;
  case FVersion of
    //acR2004: vUnpackFunc := Unpack2004;
    acR2007: vUnpackFunc := UnpackR18Plus;
    acR2004, acR2010, acR2013:
      vUnpackFunc := UnpackR24Up;
  end;
  if @vUnpackFunc <> nil then
  begin
    FSource := vUnpackFunc(FVersion, FSource, vLCount);
    FConverter.OwnSource := True;
    FConverter.Source := FSource;
    Read(SizeOf(Tdwg2004FileHeader) - SizeOf(TdwgLocators), SizeOf(TdwgLocator));
    vLocator := PdwgLocator(FMem);
  end;
  case FVersion of
    acR2007..acR2013: FStringReader := TdwgWideStringReader.Create(nil, Conv.CodePage);
  else
    FStringReader := TdwgAnsiStringReader.Create(nil, Conv.CodePage);
  end;
  try
    while vLCount > 0 do
    begin
      case vLocator.RecNumber of
        cntDWGSectHeaderIndex:
          begin
            ReadMetadata(FStream, vPFileHeader^);
            ReadHeadVars(vLocator.Seeker, vLocator.Size);
          end;
        cntDWGSectClassesIndex: ReadClasses(vLocator.Seeker, vLocator.Size);
        cntDWGSectHandlesIndex: ReadObjMap(vLocator.Seeker, vLocator.Size);
        cntDWGSectSummaryInfoIndex:
          case FVersion of
             acR2004..acR2013:
               ReadSummaryInfo(vLocator.Seeker, vLocator.Size);
             else
               ReadMeasurement(vLocator.Seeker);
           end;
        cntDWGSectTemplateIndex:
          case FVersion of
             acR2007..acR2013: ReadTemplate(vLocator.Seeker, vLocator.Size);
           end;
        cntDWGSectPrototypeIndex:
           ReadPrototype(vLocator.Seeker, vLocator.Size);
      end;
      Inc(vLocator);
      Dec(vLCount);
    end;
  finally
    FreeMem(vLocator0);
  end;
end;

procedure TdwgReader.ReadImage;
var
  I,vOffset: Integer;
  vPointer: PAnsiChar;
  vStream: TMemoryStream;
  vBitmap: TBitmap;
  vImage: TdwgImage;
begin
  FStream.Position := FImage;
  FStream.Read(vImage,SizeOf(vImage));
  if not CheckSentinel(@vImage, cnstImageDataBeginSentinel) then
    Exit;
  for I := 0 to vImage.Count - 1 do
  begin
    if vImage.Images[I].RecNumber <> 2 then
      Continue;
    FStream.Position := vImage.Images[I].Seeker;
    vStream := TMemoryStream.Create;
    try
      vStream.Size := vImage.Images[I].Size + SizeOf(TBitmapFileHeader);
      vPointer := PAnsiChar(vStream.Memory) + SizeOf(TBitmapFileHeader);
      FStream.ReadBuffer(vPointer^, vImage.Images[I].Size);
      vOffset := PBitmapInfoHeader(vPointer).biSizeImage;
      PBitmapFileHeader(vStream.Memory)^.bfType := $4D42;
      PBitmapFileHeader(vStream.Memory)^.bfSize := vStream.Size;
      PBitmapFileHeader(vStream.Memory)^.bfReserved1 := 0;
      PBitmapFileHeader(vStream.Memory)^.bfReserved2 := 0;
      PBitmapFileHeader(vStream.Memory)^.bfOffBits := vStream.Size - vOffset;
      vStream.Position := 0;
      vBitmap := TBitmap.Create;
      try
        vBitmap.LoadFromStream(vStream);
        TsgDWGConverter(FConverter).FImage := vBitmap;
      except
        vBitmap.Free;
      end;
    finally
      vStream.Free;
    end;
    Exit;
  end;
end;

procedure TdwgReader.ReadObjects;
var
  I: Integer;
  vLayouts: TsgDXFEntity;
  vVPorts: TsgDXFEntity;
  vVport: TsgDXFEntity;
begin
  if FObjMap.Count < 0 then
    Exit;
  DoProgress(psStarting);

  Conv.Clear;
  vLayouts := Conv.Sections[csLayouts];
  Conv.Sections[csObjects].RemoveEntity(vLayouts);
  Conv.Sections[csLayouts] := nil;
  vLayouts.Free;
  Conv.FillMainSection;

//  FDataBase.Child[FAppIDControl];
//  FDataBase.Child[FStyleControl];
//  FDataBase.Child[FLTypeControl];
//  FDataBase.Child[FLayerControl];
//  FDataBase.Child[FBlockControl];
//  FDataBase.Child[FDimStyleControl];
//
//  FDataBase.Child[FNamedObjects];

  ObjByHandle(FAppIDControl, nil);
  ObjByHandle(FStyleControl, nil);
  ObjByHandle(FLTypeControl, nil);
  ObjByHandle(FLayerControl, nil);

  I := FObjMap.IndexOfHandle(FBlockRecords.FHandle);
  if I >= 0 then
  begin
    FTables.ReadPredefined(FObjMap.MapElement[I].Location, FBlockRecords, I);
    FBlockRecords.OwnerAdd(FBlockRecords.GetOwner(Self));
    FBlockRecords.References(Self);
  end;

  ObjByHandle(FDimStyleControl, nil);

  ObjByHandle(FNamedObjects, nil);

  FDataBase.ReadSubEnts(Self);
  //ReadPart(0, FObjMap.Count);
  ForceDictionarySection(sAcadLayoutDictionary, Conv.Sections[csLayouts], cnstObjectsLAYOUTS);
  ForceDictionarySection(sAcadImageDict, Conv.Sections[csImageDefs], cnstObjectsIMAGEDEFS);
  ForceDictionarySection(sAcadMLineStyleDictionary, Conv.Sections[csMLineStyles], cnstObjectsMLINESTYLES);
  ForceDictionarySection(sAcadTableStyleDictionary, Conv.Sections[csTableStyles], cnstObjectsTABLESTYLES);

  ForceDictionarySection(sAcadPlotSettingsDictionary, nil, cnstObjectsPLOTSETTINGS);
  ForceDictionarySection(sAcadImageVars, nil, sRasterVariables);
  ForceDictionarySection(sAcadWipeOutVarsDictionary, nil, cntClassDXFWIPEOUTVARIABLES);
  ForceDictionarySection(sAcDbVariableDictionary, nil, sAcDbVariableDictionary);
{$IFDEF DATA_LINK}
  ForceDictionarySection(sDictionaryAcadDataLink, nil, sDictionaryAcadDataLink);
{$ENDIF}
  ForceDictionarySection(sAcadColor, nil, cnstObjectsCOLORS);
  ForceDictionarySection(sAcadScaleList, nil, cnstObjectsSCALELIST);
  ForceDictionarySection(sAcadMaterialDictionary, nil, cnstObjectsMATERIALS);
  InitLayouts;

  vVport := nil;
  vVPorts := Conv.Sections[csVPorts];
  if Assigned(vVPorts) then
    if FActiveViewport <> cnstBadHandle then
      vVport := vVPorts.FindEntByHandle(FActiveViewport)
    else
    begin
      // do not use vVPorts.FindEntByName(sActiveVPort)
      // because first entlist item needed
      I := 0;
      while (I < vVPorts.Count) and not Assigned(vVport) do
        if sgSameText(vVPorts[I].Name, sActiveVPort) then
          vVport := vVPorts[I]
        else
          Inc(I);
    end;
  if not Assigned(vVport) then
    vVport := Conv.ActiveVPort;
  Conv.ActiveVPort := TsgDXFVport(vVport); // perform initialize viewtwistmatrix

  LoadHeaderHandles;

  LinkDataBase(Conv);
  TsgDXFConverterAccess(Conv).ApplyXRecodData;
  LoadDataBase(Conv);
  //FConv.Loads(FConv.Sections[csEntities]);// previous version, now see TsgDXFLayout.Loaded
  DoProgress(psEnding);
end;

function TdwgReader.Stopped: Boolean;
begin
  Result := TsgDWGConverter(FConverter).FStopped or Assigned(FExceptionClass);
end;

{public}

constructor TdwgReader.Create(AConv: TsgDXFConverter; S: TStream);
begin
  FObjMap := TsgObjectsMap.Create;
  FConverter := AConv;
  FStream := S;

  FMetadata.ReleaseVersion := 6;
  FAcDbClasses := TsgStringList.Create;
  FAcDbClasses.CaseSensitive := False;
  FAcDbClasses.Sorted := True;
  FSegmentedFile := nil;

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

  FDataBase := TdwgDataBase.Create;
  FDataBase.Reader := Self;

  FTables := TdwgTables.Create;
  FTables.Reader := Self;
  FTables.FEntity := Conv.Sections[csTables];

  FBlockRecords := TdwgBlockControl.Create;
  FBlockRecords.Reader := Self;
  FBlockRecords.FEntity := TsgDXFBlockRecords.Create;
  EntAddRef(FBlockRecords.FEntity);
  TsgDXFBlockRecordsAccess(FBlockRecords.FEntity).Blocks := Conv.Sections[csBlocks];

  FModel := TsgDXFBlock.Create;
  FModel.Name := sModelSpace;
  EntAddRef(FModel);

  FPaper := TsgDXFBlock.Create;
  FPaper.Name := sPaperSpace;
  EntAddRef(FPaper);

  FViewports := TsgCollection.Create;
  FViewports.Sorted := True;

  FArrows := TStringList.Create;
  FArrows.Sorted := True;

  FDummy := TsgDXFGroupName.Create;
  TsgDXFEntityAccess(FDummy).SetConverter(Conv);
end;

function TdwgReader.GetStringReader(
  var APBit: TsgInt64): TdwgStringReader;
begin
  Result := FStringReader;
  Result.Create(@APBit, Conv.CodePage);
end;

destructor TdwgReader.Destroy;
begin
  FObjMap.Free;
  FClasses.Free;
  FAcDbClasses.Free;
  FSegmentedFile.Free;
  if FSource = nil then
    FreeMem(FMem);
  FStylesByFont.Free;
  if (EntRelease(FPaper) = 0) and (FPaper.Owner = nil) then
    FreeAndNil(FPaper);
  if (EntRelease(FModel) = 0) and (FModel.Owner = nil) then
    FreeAndNil(FModel);
  if (EntRelease(FBlockRecords.FEntity) = 0) and (FBlockRecords.FEntity.Owner = nil) then
    FreeAndNil(FBlockRecords.FEntity);
  FBlockRecords.Free;
  FTables.Free;
  FDataBase.Free;
  while FViewports.Count > 0 do
  begin
    TObject(FViewports.Last.Data).Free;
    FViewports.Delete(FViewports.Count - 1);
  end;
  FViewports.Free;
  while FArrows.Count > 0 do
  begin
    FArrows.Objects[FArrows.Count - 1].Free;
    FArrows.Delete(FArrows.Count - 1);
  end;
  FArrows.Free;
  FDummy.Free;
  FStringReader.Free;
end;

procedure TdwgReader.ReadFile;
begin
  ReadHeader;
  if TsgDWGConverter(FConverter).FImage = nil then
    ReadObjects;
end;

{ TsgDWGConverter }

{protected}

function TsgDWGConverter.GetDWGVersion(const AString: AnsiString; var AVersion: TsgDWGVersion): Integer;
begin
  Result := inherited GetDWGVersion(AString, AVersion);
  case Result of
    0: ;
    1, 2:  raise EdwgError.CreateFmt(sUnsupportedOldDWGVer + ' "%s"', [AString])
  else
    raise EdwgError.CreateFmt(sUnsupportedNewDWGVer + ' "%s"', [AString]);
  end;
end;

procedure TsgDWGConverter.Initialize;
begin
  inherited Initialize;
  InitializeSectionsBegin;
end;

{public}

destructor TsgDWGConverter.Destroy;
begin
  FImage.Free;
  inherited Destroy;
end;

procedure TsgDWGConverter.StopLoading;
begin
  FStopped := True;
end;

{ TsgDWGImage }

{private}

function TsgDWGImage.Bitmap: TBitmap;
begin
  Result := TsgDWGConverter(Converter).FImage;
end;

{protected}

function TsgDWGImage.CreateConverter: TsgDXFConverter;
begin
  CBFormat := CF_DWG;
  Result := TsgDWGConverter.CreateEx(GetConverterParams);
end;

procedure TsgDWGImage.Draw(ACanvas: TCanvas; const ARect: TRect);
begin
  if Bitmap=nil then
    inherited Draw(ACanvas,ARect)
  else
    TdwgBitmap(Bitmap).Draw(ACanvas,ARect);
end;

function TsgDWGImage.GetEmpty: Boolean;
begin
  Result := inherited GetEmpty and (Bitmap=nil);
end;

function TsgDWGImage.GetHeight: Integer;
begin
  if Bitmap <> nil then
    Result := Bitmap.Height
  else
    Result := inherited GetHeight;
end;

function TsgDWGImage.GetWidth: Integer;
begin
  if Bitmap <> nil then
    Result := Bitmap.Width
  else
    Result := inherited GetWidth;
end;

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

{public}

procedure TsgDWGImage.Assign(ASource: TPersistent);
begin
  if TsgDWGImage(ASource).Bitmap = nil then
    inherited Assign(ASource)
  else
  begin
    TsgDWGConverter(Converter).FImage := TBitmap.Create;
    TsgDWGConverter(Converter).FImage.Assign(TsgDWGImage(ASource).Bitmap);
  end;
end;

procedure TsgDWGImage.LoadFromStream(AStream: TStream);
var
  vReader: TdwgReader;
  vDWGVersion: TsgDWGVersion;
  vVersion: array[0..5] of AnsiChar;
  vHeadVar: PsgHeadVarStruct;
//  vSortentsTable, vSortentsVar, vVarDict: TsgDXFEntity;

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

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

begin
  inherited LoadFromStream(AStream);
  Loading := Self;
  try
    if AStream.Size = 0 then
    begin
      Loading := nil;
      GetExtents;
      Exit;
    end;
    AStream.ReadBuffer(vVersion,6);
    AStream.Position := AStream.Position - 6;
    TsgDWGConverter(Converter).GetDWGVersion(vVersion, vDWGVersion);
    vHeadVar := TsgDWGConverter(Converter).PHeadVarStruct;
    if vHeadVar <> nil then
      vHeadVar^.Version := Byte(vDWGVersion);
    case vDWGVersion of
      acR09..acR11: vReader := Tdwg11Reader.Create(Converter, AStream);
      acR12: vReader := Tdwg12Reader.Create(Converter, AStream);
    else
      vReader := TdwgReader.Create(Converter,AStream);
    end;
    try
      TsgDXFConverterAccess(Converter).SetLoading(True, nil);
      vReader.Version := vDWGVersion;
      vReader.FOnProgress := DoOnProgress;
      vReader.ReadFile;
      Millimetres := vReader.FUnits <> 0;
      TsgDXFConverterAccess(Converter).SetLoading(False, nil);
      vReader.DoException;
//      TsgDXFConverterAccess(vReader.Converter).ResetBlockRecords;
      Converter.SortEntities;
      vReader.InitViewportsByList;
      // sort entities
      (*
      vVarDict := Converter.Sections[csObjects].FindEntByName(sAcDbVariableDictionary);
      vSortentsVar := nil;
      if Assigned(vVarDict) then
        vSortentsVar := vVarDict.FindEntByName(sDictionaryVarSORTENTS);
      vSortentsTable := Converter.Sections[csObjects].FindEntByName(sDictionaryVarSORTENTS);
      if Assigned(vSortentsTable) then // dictionary
        CustomSort
      else
      begin
        if Assigned(vVarDict) then
        begin
          if Assigned(vSortentsVar) {and (StrToIntDef(TsgDXFDictionaryVar(vSortentsVar).Value, 0) and $03 <> 0)} then // dictionaryvar
            SortPapersByHandle
          else
            CustomSort
        end
        else
          CustomSort;
      end;
      *)
      SetDefaultViewPort(Converter);
      if Preview = nil then
        GetExtents;
    finally
      vReader.Free;
    end;
  finally
    Loading := nil;
  end;
end;

procedure TsgDWGImage.LoadPreviewFromFile(const AFileName: string);
var
  vOld: Boolean;
begin
  vOld := CADPreview;
  CADPreview := True;
  try
    LoadFromFile(AFileName);
  finally
    CADPreview := vOld;
  end;
end;

procedure TsgDWGImage.SaveToStream(AStream: TStream);
begin
  inherited SaveToStream(AStream);
end;

{ ************* Objects ***************}

{TdwgBlock}

{protected}

constructor TdwgBlockRecord.Create;
begin
  inherited Create;
  FBlock := TdwgBlock.Create;
end;

destructor TdwgBlockRecord.Destroy;
begin
  FBlock.Free;
  inherited Destroy;
end;

function TdwgBlockRecord.GetOwner(AReader: TdwgReader): TsgDXFEntity;
begin
  Result := inherited GetOwner(AReader);
  if not Assigned(Result) then
    Result := AReader.Conv.Sections[csBlockRecords];
end;

function TdwgBlockRecord.IsAnonymous: Boolean;
begin
  Result := FFlags and 1 <> 0;
  if not Result then
    if (Length(FEntryName) = 2) and (FEntryName[1] = cnstAsterisk) then
      Result := CharInSet(FEntryName[2], ['E', 'D']); // ? = *[A|B|C|...]
end;

function TdwgBlockRecord.OwnerAdd(AOwner: TsgDXFEntity): Integer;
begin
  Result := AOwner.IndexOfEntity(FEntity);
  if Result < 0 then
    Result := AOwner.AddEntity(FEntity);
end;

procedure TdwgBlockRecord.ReadData(var APBit: TsgInt64);
var
  I: Integer;
  vPaperIndex: Integer;
  vPreviewSize, vInsertCount: Integer;
begin
  inherited ReadData(APBit);
  FFlags := FFlags or ReadBit(APBit);
  FFlags := FFlags or ReadBit(APBit) shl 1;
  FFlags := FFlags or ReadBit(APBit) shl 2;
  FFlags := FFlags or ReadBit(APBit) shl 3;
  if IsAnonymous then
  begin
    if Reader.FBlockRecords.Find(FHandle, I) then
    begin
      FEntryName := FEntryName + IntToStr(I);
      if FFlags and 1 = 0 then
        FFlags := FFlags or 1;
    end;
  end
  else
  begin
    vPaperIndex := GetPaperIndex(FEntryName);
    case vPaperIndex of
      0:; // [*|$]Model_space
      1:
        begin
          if FHandle <> Reader.Paper.BlockRecord.Handle then
          begin
            if Reader.FBlockRecords.Find(FHandle, I) then
              FEntryName := FEntryName + IntToStr(I);
          end
          else
          begin
            if Reader.Paper.BlockRecord <> FEntity then
            begin
              FEntity.Free;
              FEntity := Reader.Paper.BlockRecord;
            end;
          end;
          // else [*|$]Paper_space
        end;
    end;
  end;
  FBlock.FEntity := TsgDXFBlockRecordAccess(FEntity).Block;
  FEntity.Name := FEntryName;
  if Reader.Version >= acR2000 then
    SeekGeneral(APBit, [seB]);
  if (FFlags and $C = 0) and (Reader.Version >= acR2004) then
    FSubEnts := ReadBL(APBit);
  TsgDXFBlockAccess(FBlock.FEntity).SetFlags(FFlags);
  TsgDXFBlock(FBlock.FEntity).Offset := Read3D(APBit);
  TsgDXFBlock(FBlock.FEntity).XrefPath := FStringReader.ReadText;
  vInsertCount := 0;
  if Reader.Version >= acR2000 then
  begin
    while ReadRC(APBit) <> 0 do
      Inc(vInsertCount);
    FStringReader.ReadText;
    vPreviewSize := ReadBL(APBit);
    Inc2(APBit, vPreviewSize shl 3);
    if Reader.Version >= acR2007 then
    begin
      //Insert units BS 70; Explodable B 280; Block scaling RC 281
      SeekGeneral(APBit, [seBS, seB, seRC]);
    end;
  end;
  //-------------------------- Handle refs --------------------------
  // Block control handle (soft pointer)
  //[Reactors (soft pointer)]
  // +xdicobjhandle (hard owner) for Reader.Version < acR2004
  // NULL (hard pointer)
  ReadHandleRefs(APBit);
  //BLOCK entity. (hard owner)
  FBlock.FHandle := ReadID(APBit);
  //-------------------------- Handle refs --------------------------
  ReadSubEntIDs(APBit, FFlags);
  FBlockEnd := ReadID(APBit); // ENDBLK entity. (hard owner)
  if Reader.Version >= acR2000 then
  begin
    // Insert Handles H N insert handles, where N corresponds to the number
    // of insert count entries above (soft pointer).
    while vInsertCount > 0 do
    begin
      ReadID(APBit);
      Dec(vInsertCount);
    end;
    //Layout Handle H (hard pointer)
    FLayout := ReadID(APBit);
  end;
end;

procedure TdwgBlockRecord.References(AReader: TdwgReader);
var
  I: Integer;
begin
  inherited References(AReader);
  FBlock.Reader := AReader;
  I := AReader.FObjMap.IndexOfHandle(FBlock.FHandle);
  if (I >= 0) and (AReader.FObjMap.MapElement[I].Obj = nil) then
  begin
    ReadPredefined(AReader.FObjMap.MapElement[I].Location, FBlock, I);
    FBlock.References(AReader);
  end;
  //AReader.ObjByHandle(FLayout, TsgDXFLayout);
//  if (FLayout = cnstBadHandle) and (FFlags and 1 = 0) then // non anonomus blocks
//    TsgDXFGroupAccess(TsgDXFBlockRecordAccess(FEntity).Block).SortEntByHandle;
end;

{TdwgDimStyle}

{protected}

constructor TdwgDimStyle.Create;
begin
  inherited Create;
end;

destructor TdwgDimStyle.Destroy;
begin
  FBlockArrow.Free;
  FBlockArrowL.Free;
  FBlockArrow1.Free;
  FBlockArrow2.Free;
  inherited Destroy;
end;

function TdwgDimStyle.GetOwner(AReader: TdwgReader): TsgDXFEntity;
begin
  Result := inherited GetOwner(AReader);
  if not Assigned(Result) then
    Result := AReader.Conv.Sections[csDimStyles];
end;

type
  TsgLinkObjectAccess = class(TsgLinkObject);

procedure TdwgDimStyle.ReadData(var APBit: TsgInt64);
var
  vDS: TsgDXFDimensionStyleAccess;

  procedure ReadGroupCode_40_48;
  begin
    vDS.Scale := ReadBD(APBit);//DIMSCALE
    vDS.ArrowSize := ReadBD(APBit);//DIMASZ
    vDS.ExtLineOffset := ReadBD(APBit);//DIMEXO
    SeekGeneral(APBit,[seBD]); //DIMDLI
    vDS.ExtLineExt := ReadBD(APBit);//DIMEXE
    // DIMRND, DIMDLE, DIMTP, DIMTM
    SeekGeneral(APBit,[seBD,seBD,seBD,seBD]);
  end;
  procedure ReadGroupCode_71_76;
  begin
    SeekGeneral(APBit, [seB,seB]); // DIMTOL, DIMLIM
    vDS.DIMTIH := ReadBit(APBit) = 1;
    vDS.DIMTOH := ReadBit(APBit) = 1;
    vDS.DIMSE1 := ReadBit(APBit) = 1;
    vDS.DIMSE2 := ReadBit(APBit) = 1;
  end;
  procedure ReadGroupCode_140_147;
  begin
    vDS.TextHeight := ReadBD(APBit);//DIMTXT
    vDS.SizeCenterMark := ReadBD(APBit);//DIMCEN
    SeekGeneral(APBit,[seBD,seBD]); //DIMTSZ, DIMALTF
    vDS.DIMLFAC := ReadBD(APBit);
    SeekGeneral(APBit,[seBD,seBD]); //DIMTVP, DIMTFAC
    vDS.TextOffset := ReadBD(APBit);//DIMGAP
  end;
  procedure ReadGroupCode_172_175;
  begin
    Inc2(APBit, 1); // DIMTOFL
    vDS.DIMSAH := ReadBit(APBit) <> 0; // DIMSAH
    vDS.DIMTIX := ReadBit(APBit);
    SeekGeneral(APBit, [seB]); //DIMSOXD
  end;
  procedure ReadGroupCode_176_178;
  begin
    vDS.DIMCLRD := ReadColorCAD(Self, APBit);//FReader.FConv.IntToColor(ReadBS(APBit));
    vDS.DIMCLRE := ReadColorCAD(Self, APBit);//FReader.FConv.IntToColor(ReadBS(APBit));
    vDS.DIMCLRT := ReadColorCAD(Self, APBit);//FReader.FConv.IntToColor(ReadBS(APBit));
  end;
  procedure ReadGroupCode_271_274;
  begin
    vDS.DIMDEC := ReadBS(APBit);
    SeekGeneral(APBit, [seBS,seBS,seBS]); //DIMTDEC, DIMALTU, DIMALTTD
  end;
  procedure ReadGroupCode_281_282;
  begin
    vDS.DIMSD1 := ReadBit(APBit) = 1;
    vDS.DIMSD2 := ReadBit(APBit) = 1;
  end;
  procedure ReadGroupCode_3_7;
  var
    vIsDimStyleActive: Boolean;

    procedure DoSetBlock(AStyle: TsgDXFDimensionStyle; AArrowName: string;
      AType: TsgDimNameVal; AIsDimStyleActive: Boolean);
    var
      vArrowType: TsgDimArrowType;
    begin
      vArrowType := GetArrowTypeByName(AArrowName, datUndefined);
      if AIsDimStyleActive and (AArrowName = '') then
      begin
        if vArrowType = datUndefined then
        begin
          if Reader.Conv.HeadVarStruct.DimProps.Arrows.Blks[AType] <> datUndefined then
            vArrowType := Reader.Conv.HeadVarStruct.DimProps.Arrows.Blks[AType];
        end;
      end;
      if vArrowType <> datUndefined then
        AArrowName := sgDimensionArrowTypeNames[vArrowType];
      case AType of
        vnDIMBLK: TsgDXFDimensionStyleAccess(AStyle).DIMBLKT := vArrowType;
        vnDIMBLK1: TsgDXFDimensionStyleAccess(AStyle).DIMBLK1T := vArrowType;
        vnDIMBLK2: TsgDXFDimensionStyleAccess(AStyle).DIMBLK2T := vArrowType;
      end;
      //TsgDXFDimensionStyleAccess(AStyle).SetBlocks(AType, AArrowName, Reader.Conv);
    end;

  begin
    FStringReader.ReadText;
    FStringReader.ReadText;
    vIsDimStyleActive := Reader.FHeaderHandles.DIMSTYLE = vDS.Handle;
    FBlockArrow := TsgLinkObject.Create(FStringReader.ReadText);
    FBlockArrow1 := TsgLinkObject.Create(FStringReader.ReadText);
    FBlockArrow2 := TsgLinkObject.Create(FStringReader.ReadText);
    DoSetBlock(vDS, FBlockArrow.Name, vnDIMBLK, vIsDimStyleActive);
    DoSetBlock(vDS, FBlockArrow1.Name, vnDIMBLK1, vIsDimStyleActive);
    DoSetBlock(vDS, FBlockArrow2.Name, vnDIMBLK2, vIsDimStyleActive);
  end;
begin
  inherited ReadData(APBit);
  FEntity.Name := FEntryName;
  vDS := TsgDXFDimensionStyleAccess(FEntity);
  if SameText(vDS.Name, Reader.Conv.HeadVarStruct.DimStyle)  then
    vDS.InitProps(@Reader.Conv.HeadVarStruct);
  if Reader.Version < acR2000 then
  begin
    ReadGroupCode_71_76;
    vDS.FDimProps.Alt := ReadBit(APBit) <> 0; //DIMALT
    ReadGroupCode_172_175;
    SeekGeneral(APBit, [seRC,seRC]); //DIMALTD, DIMZIN
    ReadGroupCode_281_282;
    // DIMTOLJ, DIMJUST, DIMFIT, DIMUPT
    SeekGeneral(APBit, [seRC,seRC,seRC,seB]);
    SeekGeneral(APBit, [seRC,seRC,seRC]); //DIMTZIN, DIMALTZ, DIMALTTZ
    vDS.TextPosVert := TsgDimTextPosVert(ReadRC(APBit));//DIMTAD
    SeekGeneral(APBit, [seBS,seBS]); //DIMUNIT, DIMAUNIT
    ReadGroupCode_271_274;
    ReadGroupCode_40_48;
    ReadGroupCode_140_147;
    ReadGroupCode_3_7;
    ReadGroupCode_176_178;
  end
  else
  begin
    vDS.FDimProps.Post := FStringReader.ReadText;  //DIMPOST
    vDS.FDimProps.APost := FStringReader.ReadText; //DIMAPOST
    ReadGroupCode_40_48;
    if Reader.Version >= acR2007 then
    begin
      // DIMFXL, DIMJOGANG, DIMTFILL, DIMTFILLCLR  (ReadCMC)
      SeekGeneral(APBit,[seBD,seBD,seBS,seRGB]);
    end;
    ReadGroupCode_71_76;
    vDS.TextPosVert := TsgDimTextPosVert(ReadBS(APBit));//DIMTAD
    SeekGeneral(APBit, [seBS,seBS]); //DIMZIN, DIMAZIN
    if Reader.Version >= acR2007 then
      SeekGeneral(APBit, [seBS]); //DIMARCSYM
    ReadGroupCode_140_147;
    SeekGeneral(APBit,[seBD,seB]); //DIMALTRND, DIMALT
    SeekGeneral(APBit, [seBS]); //DIMALTD
    ReadGroupCode_172_175;
    ReadGroupCode_176_178;
    SeekGeneral(APBit, [seBS]); //DIMADEC
    ReadGroupCode_271_274;
    // DIMAUNIT, DIMFRAC, DIMLUNIT, DIMDSEP, DIMTMOVE, DIMJUST
    SeekGeneral(APBit, [seBS,seBS,seBS,seBS,seBS,seBS]);
    ReadGroupCode_281_282;
    //DIMTOLJ, DIMTZIN, DIMALTZ, DIMALTTZ, DIMUPT, DIMFIT
    SeekGeneral(APBit, [seBS,seBS,seBS,seBS,seB,seBS]);
    if Reader.Version >= acR2007 then
      SeekGeneral(APBit, [seB]); //DIMFXLON
    vDS.DIMLWD := ExpandLWeight(ReadBS(APBit));
    vDS.DIMLWE := ExpandLWeight(ReadBS(APBit));
  end;
  vDS.Flags := vDS.Flags or ReadBit(APBit); // code 70, bit 0
  ReadHandleRefs(APBit);
  FTextStyle := ReadID(APBit);
  if Reader.Version >= acR2000 then
  begin
    FBlockArrowL := TsgLinkObject.Create(ReadID(APBit));
    FBlockArrow := TsgLinkObject.Create(ReadID(APBit));
    FBlockArrow1 := TsgLinkObject.Create(ReadID(APBit));
    FBlockArrow2 := TsgLinkObject.Create(ReadID(APBit));
  end;
end;

procedure TdwgDimStyle.References(AReader: TdwgReader);
var
  vDS: TsgDXFDimensionStyleAccess;

  function GetBlock(ALObj: TsgLinkObjectAccess; AType: TsgDimNameVal): TsgDXFEntity;
  begin
    Result := nil;
    if Assigned(ALObj) then
    begin
      case ALObj.LinkType of
        lodtHandle: Result := AReader.ObjByHandle(ALObj.FData.Handle, TsgDXFBlockRecord);
        lodtName,
        lodtDimArrow: Result := TsgDXFEntity(ALObj.GetObject(AReader.Conv.Sections[csBlocks]));
      end;
    end;
    if Assigned(Result) then
      TsgDXFDimensionStyleAccess(FEntity).SetBlocks(AType, TsgDXFBlock(Result));
  end;

begin
  inherited References(AReader);
  vDS := TsgDXFDimensionStyleAccess(FEntity);
  if FTextStyle = cnstBadHandle then
    FTextStyle := Reader.FHeaderHandles.DIMTXTSTY;
  vDS.TextStyle := TsgDXFStyle(AReader.ObjByHandle(FTextStyle, TsgDXFStyle));
  if not Assigned(vDS.TextStyle) then
    vDS.TextStyle := Reader.Conv.StyleByName(AReader.Conv.HeadVarStruct.DimTextStyle);

  GetBlock(TsgLinkObjectAccess(FBlockArrow), vnDIMBLK);
  if Reader.Version >= acR2000 then
    GetBlock(TsgLinkObjectAccess(FBlockArrowL), vnDIMLRBLK);
  GetBlock(TsgLinkObjectAccess(FBlockArrow1), vnDIMBLK1);
  GetBlock(TsgLinkObjectAccess(FBlockArrow2), vnDIMBLK2);
end;

{TdwgEntity}

{protected}

function TdwgEntity.IsEntity: Boolean;
begin
  Result := True;
end;

procedure TdwgEntity.ReadData(var APBit: TsgInt64);
var
  I: Integer;
  vLinks, vPlot, vMaterial, vIsByLayer: Boolean;
  vNeedDbColorFlag: Integer;
  vColorTmp: TsgColorCAD;

  procedure ReadLL;
  begin
    FLayer := ReadID(APBit);
    if not vIsByLayer then
      FLType := ReadID(APBit);
  end;

begin
  if ReadBit(APBit) <> 0 then
    ReadEntProxyData(APBit);
  if Reader.Version < acR2000 then
    BitSize := ReadRL(APBit);
  FMode := ReadBB(APBit);
  FReactorsCount := ReadBL(APBit);
  if Reader.Version < acR2000 then
    vIsByLayer := ReadBit(APBit) <> 0
  else
    vIsByLayer := False;
  vLinks := ReadBit(APBit) = 0;
  if Reader.Version >= acR2013 then
    Inc2(APBit, 1); //Unknown DWG 2013 flag
  //
  //FColor := ReadColorCAD(Self, APBit);//ReadENC(APBit);
  vNeedDbColorFlag := ReadBS(APBit);
  vColorTmp := ReadENCSection(vNeedDbColorFlag, Self, APBit);
  if FColor.Active <> acRGBColor then
    FColor := vColorTmp;
  FLineTypeScale := ReadBD(APBit);
  vPlot := False;
  vMaterial := False;
  if Reader.Version >= acR2000 then
  begin
    FStandardLType := ReadBB(APBit);
    vIsByLayer := FStandardLType <> 3;
    if Reader.Version >= acR2007 then //ID Material
    begin
      vMaterial := ReadBB(APBit) = 3;
      SeekGeneral(APBit, [seRC]);
    end;
    vPlot := ReadBB(APBit) = 3;
  end;
  if Reader.Version > acR2007 then
  begin
    for I := 1 to 3 do
      if ReadBit(APBit) = 1 then //hasVstyle
        ReadID(APBit); //needs to check
  end;
  FVisibility := (ReadBS(APBit) <> 1);
  if Reader.Version >= acR2000 then
    ReadLineWeight(ReadRC(APBit));
  ReadEntData(APBit);
  if not FCorrectData then
    Exit;
  ReadHandleRefs(APBit);
  if Reader.Version < acR2000 then
    ReadLL;
  if not vLinks then
    FSibling := FHandle + 1
  else
  begin
    if Reader.Version < acR2004 then
      ReadID(APBit);
    FSibling := ReadID(APBit);
  end;
  if vNeedDbColorFlag and $4000 <> 0 then
    FDbColor := ReadID(APBit);// (Reader.Version >= acR2004)
  if Reader.Version >= acR2000 then
    ReadLL;
  if vPlot then
    ReadID(APBit);
  if vMaterial then// (Reader.Version >= acR2007)
    ReadID(APBit);
end;

procedure TdwgEntity.ReadEntData(var APBit: TsgInt64);
begin
end;

procedure TdwgEntity.ReadEntProxyData(var APBit: TsgInt64);
var
  vSize: Integer;
begin
  // Skipping PROXY DATA
  if Reader.Version > acR2007 then
    vSize := ReadUInt64(APBit) shl 3
  else
    vSize := ReadRL(APBit) shl 3;
  Inc2(APBit, vSize);
end;

procedure TdwgEntity.ReadHandleRefs(var APBit: TsgInt64);
begin
  if FMode = 0 then
    FOwner := ReadID(APBit);
  SkipHandles(APBit);
end;

procedure TdwgEntity.ReadOwner(AReader: TdwgReader);
begin
  case FMode of
    0: FOwnerObject := AReader.ObjByHandle(FOwner, nil);
    1: FOwnerObject := AReader.Paper;
  else
    FOwnerObject := AReader.Model;
  end;
end;

procedure TdwgEntity.References(AReader: TdwgReader);
var
  vDbColor: TsgDXFEntity;
begin
  inherited References(AReader);
  FEntity.LineWeight := FLineWeight;
  FEntity.Visibility := FVisibility;
  FEntity.LineTypeScale := FLineTypeScale;
  case FStandardLType of
    1: FEntity.LineType := AReader.LTypeByIndex(-2); // ByBlock
    2: FEntity.LineType := AReader.LTypeByIndex(0);  // continious
    3: FEntity.LineType := TsgDXFLineType(AReader.ObjByHandle(FLType, TsgDXFLineType));
  else
    if FLType <> cnstBadHandle then
      FEntity.LineType := TsgDXFLineType(AReader.ObjByHandle(FLType, TsgDXFLineType))
    else
      FEntity.LineType := AReader.LTypeByIndex(-1); // 0: 'ByLayer'
  end;
  FEntity.Layer := TsgDXFLayer(AReader.ObjByHandle(FLayer, TsgDXFLayer));
  vDbColor := AReader.ObjByHandle(FDbColor, nil);
  if Assigned(vDbColor) then
    FEntity.ColorCAD := vDbColor.ColorCAD
  else
    FEntity.ColorCAD := FColor;
end;

{TdwgLayer}

{protected}

constructor TdwgLayer.Create;
begin
  inherited Create;
  FLineWeight := fLineWeightDefault;
  FIsPlotting := True;
end;

function TdwgLayer.GetOwner(AReader: TdwgReader): TsgDXFEntity;
begin
  Result := inherited GetOwner(AReader);
  if not Assigned(Result) then
    Result := AReader.Conv.Sections[csLayers];
end;

procedure TdwgLayer.ReadData(var APBit: TsgInt64);
var
  vFlagsR2000Plus: Integer;
begin
  inherited ReadData(APBit);
  if Reader.Version >= acR2000 then
  begin
    vFlagsR2000Plus := ReadBS(APBit);
    FIsPlotting := vFlagsR2000Plus and $10 <> 0;
    ReadLineWeight(vFlagsR2000Plus and $3E0 shr 5);
    FFlags := FFlags or (vFlagsR2000Plus and $1); //contains frozen (1 bit)
    FFlags := FFlags or ((vFlagsR2000Plus and $4) shr 1 ); //rozen by default in new viewports (4 bit)
    FFlags := FFlags or ((vFlagsR2000Plus and $8) shr 1 ); //locked (8 bit)
    FVisible := vFlagsR2000Plus and $2 = 0;
  end
  else
  begin
    FFlags := FFlags or ReadBit(APBit); //if frozen (1 bit)
    FVisible := ReadBit(APBit) = 0; //if on.
    FFlags := FFlags or ReadBit(APBit) shl 1; //if frozen by default in new viewports (2 bit)
    FFlags := FFlags or ReadBit(APBit) shl 2; //if locked (4 bit)
  end;
  FColor := ReadColorCAD(Self, APBit);// MakeColorCAD(acRGBColor, ReadCMC());
  ReadHandleRefs(APBit);
  if Reader.Version >= acR2000 then
  begin
    ReadID(APBit);
    if Reader.Version >= acR2007 then
      ReadID(APBit);
  end;
  FLType := ReadID(APBit);
end;

procedure TdwgLayer.References(AReader: TdwgReader);
begin
  inherited References(AReader);
  TsgDXFConverterAccess.SetLayerNameOfPassingInspection(TsgDXFLayer(FEntity), FEntryName);
  FEntity.LineWeight := FLineWeight;
  TsgDXFLayer(FEntity).IsPlotting := FIsPlotting;
  FEntity.Visible := FVisible;
  FEntity.ColorCAD := FColor;
  TsgDXFLayer(FEntity).Flags := FFlags;
  FEntity.LineType := TsgDXFLineType(AReader.ObjByHandle(FLType, TsgDXFLineType));
end;

{ TdwgCustomControl }

{protected}

procedure TdwgCustomControl.ReadOwner(AReader: TdwgReader);
begin
  FOwnerObject := AReader.Conv.Sections[csTables];
end;

function TdwgCustomControl.GetOwner(AReader: TdwgReader): TsgDXFEntity;
begin
  Result := AReader.Conv.Sections[csTables];
end;

procedure TdwgCustomControl.InitializeTable(ASection: TConvSection;
  AName: string);
var
  vEnt: TsgDXFEntity;
begin
  FEntity.Name := AName;
  if Assigned(Reader.Conv.Sections[ASection]) then
  begin
    vEnt := Reader.Conv.Sections[ASection];
    Reader.Conv.Sections[csTables].RemoveEntity(vEnt);
    Reader.Conv.Sections[ASection] := nil; // not need
    vEnt.Free;
    Reader.Conv.Sections[ASection] := TsgDXFGroup(FEntity);
  end;
end;

procedure TdwgCustomControl.ReadData(var APBit: TsgInt64);
begin
  ReadObjHeader(APBit);
  FSubEnts := ReadBL(APBit);
  ReadHandleRefs(APBit);
  ReadSubEntIDs(APBit);
end;

procedure TdwgCustomControl.ReadSubEntIDs(var APBit: TsgInt64;
  const AFlags: Integer);
var
  I: Integer;
  vHandle: UInt64;
  vHCode: Byte;
begin
  if FSubEnts > 0 then
    FChildren := TsgInt64List.Create(0, FSubEnts);
  for I := 0 to FSubEnts - 1 do
  begin
    vHandle := ReadID(APBit, vHCode);
    if vHCode = cntDWGObjHandleSoftOwner then
      FChildren.Add(vHandle);
  end;
end;

procedure TdwgCustomControl.ReadSubEnts(AReader: TdwgReader);
begin
  ReadSubEntsR2004(AReader);
end;

procedure TdwgCustomControl.References(AReader: TdwgReader);
begin
  inherited References(AReader);
end;

{TdwgLType}

{protected}

function TdwgLType.GetOwner(AReader: TdwgReader): TsgDXFEntity;
begin
  Result := inherited GetOwner(AReader);
  if not Assigned(Result) then
    Result := AReader.Conv.Sections[csLTypes];
end;

procedure TdwgLType.ReadData(var APBit: TsgInt64);
var
  vLineType: TsgDXFLineType;
  I, vCount: Integer;
  vElement: PsgLTypeElement;
  vStringArea: array [0..255] of AnsiChar;
  wStringArea: array [0..127] of WideChar absolute vStringArea;
begin
  inherited ReadData(APBit);
  FEntity.Name := FEntryName;
  vLineType := TsgDXFLineType(FEntity);
  vLineType.Flags := FFlags;
  FStringReader.ReadText;
  SeekGeneral(APBit, [seBD,seRC]);
  vCount := ReadRC(APBit);
  for I := 0 to vCount-1 do
  begin
    New(vElement);
    vElement^.Text := '';
    vElement^.Dash := ReadBD(APBit);
    vElement^.ShapeNumber := ReadBS(APBit);
    vElement^.XOffset := ReadRD(APBit);
    vElement^.YOffset := ReadRD(APBit);
    vElement^.Scale := ReadBD(APBit);
    vElement^.Rotation := Degree(ReadBD(APBit));
    vElement^.ComplexType := ReadBS(APBit);
    vLineType.Lines.Add(vElement);
  end;
  ReadBytesDoublePair(APBit, vStringArea, $40); //ReadBytes(APBit, vStringArea, $100);
  ReadHandleRefs(APBit);
  for I := 0 to vCount - 1 do
  begin
    vElement := vLineType.Lines.Elements[I];
    if vElement^.ComplexType and 2 <> 0 then
    begin
      if Reader.Version < acR2007 then
        vElement^.Text := string(vStringArea)// vElement^.ShapeNumber is index in string area
      else
        vElement^.Text := WideString(wStringArea);
      vElement^.ShapeNumber := 0;
    end;
    vElement^.HStyle := ReadID(APBit);// first initialisation, further see TdwgLType.References
  end;
end;

procedure TdwgLType.References(AReader: TdwgReader);
var
  LineType: TsgDXFLineType;
  vPElement: PsgLTypeElement;
  I: Integer;
begin
  inherited References(AReader);
  LineType := TsgDXFLineType(FEntity);
  for I := LineType.Lines.ElementsCount - 1 downto 0 do
  begin
    vPElement := LineType.Lines.Elements[I];
    vPElement^.Style := TsgDXFStyle(AReader.ObjByHandle(vPElement^.HStyle, TsgDXFStyle));
  end;
end;

{TdwgMLStyle}

{protected}

constructor TdwgMLStyle.Create;
begin
  inherited Create;
  FLTypes := TsgIntegerList.Create;
end;

destructor TdwgMLStyle.Destroy;
begin
  FLTypes.Free;
  inherited Destroy;
end;

function TdwgMLStyle.GetOwner(AReader: TdwgReader): TsgDXFEntity;
begin
  Result := inherited GetOwner(AReader);
  if not Assigned(Result) then
    Result := AReader.Conv.Sections[csMLineStyles];
end;

procedure TdwgMLStyle.ReadData(var APBit: TsgInt64);
var
  vMLineStyle: TsgMLineStyle;
  vOffset: Double;
  vLines, vLtIndex: Integer;
  vColor: Cardinal;

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

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

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

begin
  ReadObjHeader(APBit);
  FEntity.Name := FStringReader.ReadText;
  FStringReader.ReadText;
  vMLineStyle := TsgMLineStyle(FEntity);
  vMLineStyle.Flags := DWGCodesToDXF(ReadBS(APBit));
  vMLineStyle.ColorCAD := ReadColorCAD(Self, APBit); //MakeColorCAD(acRGBColor, ReadCMC(Self, APBit));
  SeekGeneral(APBit,[seBD,seBD]);
  vLines := ReadRC(APBit);
  while vLines > 0 do
  begin
    vOffset := ReadBD(APBit);
    vColor := ReadCMC(Self, APBit);
    vLtIndex := ReadBS(APBit);
    FLTypes.Add(vLtIndex);
    vMLineStyle.NewEntry(vOffset, MakeColorCAD(acRGBColor, vColor), nil);
    Dec(vLines);
  end;
  ReadHandleRefs(APBit);
  // wrong decision
  //      V
  //if Reader.Version <> acR2004 then
  //  vMLineStyle.Invert;
end;

procedure TdwgMLStyle.References(AReader: TdwgReader);
var
  vMLineStyle: TsgMLineStyle;
  I, vIndex: Integer;
begin
  inherited References(AReader);
  vMLineStyle := TsgMLineStyle(FEntity);
  for I := 0 to vMLineStyle.Count - 1 do
  begin
    vIndex := FLTypes[I];
    case vIndex of
      $7FFF: vIndex := -1;
      $7FFE: vIndex := -2;
    end;
    vMLineStyle[I].LineType := AReader.LTypeByIndex(vIndex);
  end;
end;

{TdwgSortEntsTable}

{protected}

function TdwgSortEntsTable.GetOwner(AReader: TdwgReader): TsgDXFEntity;
begin
  Result := AReader.Dictionary[sDictionaryVarSORTENTS];
end;

procedure TdwgSortEntsTable.ReadData(var APBit: TsgInt64);
var
  I, vNumEntries: Integer;
  vHCode: Byte;
begin
  ReadObjHeader(APBit);
  vNumEntries := ReadBL(APBit);
  for I := 0 to vNumEntries - 1 do
    TsgDXFSortEntsTable(FEntity).HandlesNew.Add(ReadHandle(APBit, vHCode, FHandle));
  ReadHandleRefs(APBit);
  FObject := ReadID(APBit, vHCode);
  for I := 0 to vNumEntries - 1 do
    TsgDXFSortEntsTable(FEntity).HandlesOld.Add(ReadID(APBit, vHCode));
end;

procedure TdwgSortEntsTable.References(AReader: TdwgReader);
begin
  inherited References(AReader);
  TsgDXFSortEntsTable(FEntity).SortObject := AReader.ObjByHandle(FObject, nil);
end;

{TdwgVPort}

{protected}

function TdwgVPort.GetOwner(AReader: TdwgReader): TsgDXFEntity;
begin
  Result := inherited GetOwner(AReader);
  if not Assigned(Result) then
    Result := AReader.Conv.Sections[csVPorts];
end;

procedure TdwgVPort.ReadData(var APBit: TsgInt64);
var
  vVPort: TsgDXFVPort;
begin
  inherited ReadData(APBit);
  FEntity.Name := AnsiUpperCase(FEntryName);
  vVPort := TsgDXFVPort(FEntity);
  vVPort.ViewHeight := ReadBD(APBit);
  vVPort.ViewAspectRatio := ReadBD(APBit);
  if vVPort.ViewHeight <> 0 then
    vVPort.ViewAspectRatio := vVPort.ViewAspectRatio / vVPort.ViewHeight;
  vVPort.ViewCenterPoint := Read2RD(APBit);
  vVPort.ViewTarget := Read3D(APBit);
  vVPort.ViewDirection := Read3D(APBit);
  vVPort.ViewTwistAngle := ReadBD(APBit) * f180DividedByPi;
  SeekGeneral(APBit,[se3D]);
  Inc2(APBit,4);
  if Reader.Version >= acR2000 then
    Inc2(APBit,8);
  if Reader.Version >= acR2007 then
  begin
    //ReadID(APBit);
    //ReadID(APBit);
    //Inc2(APBit, 9);
    //SeekGeneral(APBit, [seBD,seBD,seBS,seBL,seRC]);
    //ReadID(APBit);
    SeekGeneral(APBit, [seB, seRC, seBD, seBD]);
    ReadCMC(Self, APBit);
  end;
  SeekGeneral(APBit,[se2RD,se2RD]);
  Inc2(APBit,1);
  vVPort.CircleZoomPercent := ReadBS(APBit);
  Inc2(APBit,4);
  SeekGeneral(APBit,[se2RD]);
  Inc2(APBit,2);
  SeekGeneral(APBit, [seBS,seBD,se2RD,se2RD]);
  if Reader.Version >= acR2000 then
  begin
    Inc2(APBit,1);
    vVPort.UCSVP := ReadBit(APBit) <> 0;
    vVPort.UCSOrigin := Read3D(APBit);
    vVPort.UCSXDir := Read3D(APBit);
    vVPort.UCSYDir := Read3D(APBit);
    SeekGeneral(APBit, [seBD, seBS]);
    if Reader.Version >= acR2007 then
      SeekGeneral(APBit, [seBS, seBS]);
  end;
  ReadHandleRefs(APBit);
//
//  R2007+:
//Background handle H 332 soft pointer
//Visual Style handle H 348 hard pointer
//Sun handle H 361 hard owner
//R2000+:
//Named UCS Handle H 345 hard pointer
//Base UCS Handle H 346 hard pointer
end;

procedure TdwgVPort.References(AReader: TdwgReader);
begin
  inherited References(AReader);
  if (AReader.FActiveViewport = cnstBadHandle) and sgSameText(FEntryName, sActiveVPort) then
    AReader.FActiveViewport := FHandle;
end;

{ TdwgWipeoutVar }

{protected}

function TdwgWipeoutVar.GetOwner(AReader: TdwgReader): TsgDXFEntity;
begin
  Result := inherited GetOwner(AReader);
  if not Assigned(Result) then
    Result := AReader.Conv.Sections[csObjects];
end;

procedure TdwgWipeoutVar.ReadData(var APBit: TsgInt64);
begin
  ReadObjHeader(APBit);
  TsgCADWipeoutVariables(FEntity).DisplayImageFrame := ReadBL(APBit) <> 0;
  ReadHandleRefs(APBit);
end;

{Tdwg3DFace}

{protected}

procedure Tdwg3DFace.ReadEntData(var APBit: TsgInt64);
  function ReadDP(const DP: TFPoint): TFPoint;
  begin
    Result.X := ReadDD(APBit, DP.X);
    Result.Y := ReadDD(APBit, DP.Y);
    Result.Z := ReadDD(APBit, DP.Z);
  end;
var
  v3dFace: TsgDXF3dFace;
  vPoint: TFPoint;
  vHasF,vZ0: Boolean;
begin
  v3dFace := TsgDXF3dFace(FEntity);
  if Reader.Version < acR2000 then
  begin
    v3dFace.Point := Read3D(APBit);
    v3dFace.Point1 := Read3D(APBit);
    v3dFace.Point2 := Read3D(APBit);
    v3dFace.Point3 := Read3D(APBit);
    vHasF := True;
  end
  else
  begin
    vHasF := ReadBit(APBit) = 0;
    vZ0 := ReadBit(APBit) <> 0;
    vPoint := Read2RD(APBit);
    if not vZ0 then
      vPoint.Z := ReadRD(APBit);
    v3dFace.Point := vPoint;
    v3dFace.Point1 := ReadDP(vPoint);
    v3dFace.Point2 := ReadDP(v3dFace.Point1);
    v3dFace.Point3 := ReadDP(v3dFace.Point2);
  end;
  if vHasF then
    v3dFace.Flags := ReadBS(APBit);
end;

{TdwgBlock}

{protected}

function TdwgBlock.GetOwner(AReader: TdwgReader): TsgDXFEntity;
begin
  Result := AReader.Conv.Sections[csBlocks];
end;

function TdwgBlock.OwnerAdd(AOwner: TsgDXFEntity): Integer;
var
  vEnt: TsgDXFEntity;
begin
  if not Assigned(FOwnerObject) then
    Result := -1
  else
  begin
    Result := -1;
    if Assigned(FEntity) then
    begin
      Result := AOwner.IndexOfEntity(FEntity);
      if Result < 0 then
      begin
        vEnt := AOwner.FindEntByName(FEntity.Name);
        if not Assigned(vEnt) then
          Result := AOwner.AddEntity(FEntity)
        else
          Result := AOwner.IndexOfEntity(vEnt);
      end;
    end;
  end;
end;

procedure TdwgBlock.ReadEntData(var APBit: TsgInt64);
begin
  {FEntity.Name := }FStringReader.ReadText;
end;

{TdwgCircle}

{protected}

procedure TdwgCircle.ReadEntData(var APBit: TsgInt64);
var
  vCircle: TsgDXFCircle;
begin
  vCircle := TsgDXFCircle(FEntity);
  vCircle.Point := Read3D(APBit);
  vCircle.Radius := ReadBD(APBit);
  vCircle.ZThick := ReadBT(APBit,Reader.Version);
  vCircle.Extrusion := ReadBE(APBit,Reader.Version);
end;

{TdwgEllipse}

{protected}

procedure TdwgEllipse.ReadEntData(var APBit: TsgInt64);
var
  vEllipse: TsgDXFEllipse;
begin
  vEllipse := TsgDXFEllipse(FEntity);
  vEllipse.Point := Read3D(APBit);
  vEllipse.EndPoint := Read3D(APBit);
  vEllipse.Extrusion := Read3D(APBit);
  vEllipse.Ratio := ReadBD(APBit);
  vEllipse.StartAngle := ReadBD(APBit) * f180DividedByPi;
  vEllipse.EndAngle := ReadBD(APBit) * f180DividedByPi;
end;

{TdwgHatch}

{private}

procedure TdwgHatch.AddBoundaryDataCurve(const ABoundaryList: Tsg2DBoundaryList;
  const ACurve: Tsg2DCurve);
begin
  if ACurve <> nil then
  begin
    ABoundaryList.Add(ACurve)
  end;
end;

function TdwgHatch.Read2DArc(const ACircle: Boolean;
  var APBit: TsgInt64): Tsg2DArc;
begin
  if ACircle then
  begin
    Result := Tsg2DArc.Create;
    Result.CenterPoint := ReadF2DPoint(APBit);
  end
  else
  begin
    Tsg2DEllipse(Result) := Tsg2DEllipse.Create;
    Tsg2DEllipse(Result).CenterPoint := ReadF2DPoint(APBit);
    Tsg2DEllipse(Result).MajorPoint := ReadF2DPoint(APBit);
    Tsg2DEllipse(Result).IsAngleInParam := False;
  end;
  Result.Radius := ReadBD(APBit);
  Result.StartParam := ReadBD(APBit) * f180DividedByPi;
  Result.EndParam := ReadBD(APBit) * f180DividedByPi;
  Result.CounterClockWise := ReadBit(APBit) <> 0;
end;

function TdwgHatch.Read2DLine(var APBit: TsgInt64): Tsg2DLine;
begin
  Result := Tsg2DLine.Create;
  Result.SetStartPoint(ReadF2DPoint(APBit));
  Result.SetEndPoint(ReadF2DPoint(APBit));
end;

function TdwgHatch.Read2DPolyline(var APBit: TsgInt64; AIsMPolygon: Boolean): Tsg2DPolyline;
var
  I, vNumVectexes: Integer;
  vBulges: Boolean;
begin
  Result := Tsg2DPolyline.Create;
  if AIsMPolygon then
  begin
    Result.Closed := ReadBit(APBit) <> 0;
    vBulges := ReadBit(APBit) <> 0;
  end
  else
  begin
    vBulges := ReadBit(APBit) <> 0;
    Result.Closed := ReadBit(APBit) <> 0;
  end;
  vNumVectexes := ReadBL(APBit);
  for I := 1 to vNumVectexes do
  begin
    Result.AddVertex(ReadF2DPoint(APBit));
    if vBulges then
      Result.AddBulge(ReadBD(APBit));
  end;
end;

function TdwgHatch.Read2DSpline(var APBit: TsgInt64): Tsg2DSpline;
var
  I, vNumKnots, vNumControlPoints: Integer;
  vFitPtsNum: Integer;
begin
  Result := Tsg2DSpline.Create;
  Result.Degree := ReadBL(APBit); // degree of the Read2DSpline
  Result.Rational := ReadBit(APBit) <> 0; //1 if rational (has weights), else 0
  Result.Periodic :=  ReadBit(APBit) <> 0;  //1 if periodic, else 0
  vNumKnots := ReadBL(APBit);
  vNumControlPoints := ReadBL(APBit);
  for I := 0 to vNumKnots-1 do
    Result.AddKnot(ReadBD(APBit));
  for I := 0 to vNumControlPoints-1 do
  begin
    Result.AddControl(ReadF2DPoint(APBit));
    if Result.Rational then
      Result.AddWeight(ReadBD(APBit));
  end;
  if Reader.FVersion > acR2007 then
  begin
    vFitPtsNum := ReadBL(APBit);//new feature builds curve by fit points
    if vFitPtsNum > 0 then //this code needs to be checked
    begin
      for I := 0 to vFitPtsNum - 1 do
        SeekGeneral(APBit,[se2RD]);
      SeekGeneral(APBit,[se2RD,se2RD]);
    end;
  end;
end;

procedure TdwgHatch.ReadGradietParams(var APBit: TsgInt64);
var
  vCurvePolygon: TsgCADCurvePolygon;
  vGrad: Boolean;
  I, vNumColor: Integer;
begin
  vCurvePolygon := TsgCADCurvePolygon(FEntity);
  vGrad := ReadBL(APBit) <> 0;
  SeekGeneral(APBit,[seBL]);
  vCurvePolygon.GradientAngle := RadToDeg(ReadBD(APBit));
  vCurvePolygon.GradientUseCenter :=  Abs(ReadBD(APBit)) < fAccuracy;
  // | seBL - Gradient one color mode Boolean
  // v seBD - Luminance value
  SeekGeneral(APBit,[seBL,seBD]);
  vNumColor := ReadBL(APBit);//Number of colors
  for I := 1 to vNumColor do
  begin
    SeekGeneral(APBit,[seBD]);
    case I of
      1, 2: vCurvePolygon.GradientColorCAD[I-1] := ReadColorCAD(Self, APBit);
    else
      ReadCMC(Self, APBit);
    end;
  end;
  vCurvePolygon.GradientName := FStringReader.ReadText;
  if vGrad then
    FColor := vCurvePolygon.ColorCAD
  else
    vCurvePolygon.GradientName := '';
end;

procedure TdwgHatch.ReadPatternData(var APBit: TsgInt64);
var
  vHatch: TsgCADHatchAccess;
  I, J, vNumPatterns, vDashNum: Integer;
  vPData: PsgHatchPatternData;
begin
  vHatch := TsgCADHatchAccess(FEntity);
  vHatch.PatternData.Angle := Degree(ReadBD(APBit));
  vHatch.PatternData.Scale := ReadBD(APBit);
  Inc2(APBit,1);//is doublehatch
  vNumPatterns := ReadBS(APBit);
  for I := 1 to vNumPatterns do
  begin
    New(vPData);
    vHatch.HatchPatternData.Add(vPData);
    vPData.IsDash := False;
    vPData.Lines := nil;
    vPData.LineAngle := ReadBD(APBit) * f180DividedByPi;
    vPData.BaseP := Read2D(APBit);
    vPData.Offset := Read2D(APBit);
    vDashNum := ReadBS(APBit);
    vPData.DashNum := vDashNum;
    if vDashNum = 0 then
      Continue;
    vPData.IsDash := True;
    vPData.Lines := TsgDoubleList.Create(vDashNum);
    for J := 0 to vDashNum - 1 do
      vPData.Lines[J] := ReadBD(APBit);
  end;
end;

{protected}

function TdwgHatch.DoSolidHatch(const AIsSolid: Boolean): TsgCADCurvePolygon;
begin
  Result := TsgCADCurvePolygon(FEntity);
  if AIsSolid then
  begin
    Result := TsgCADCurvePolygon.Create;
    try
      Result.Clone(TsgCADCurvePolygon(FEntity));
      //AReader.FConv.RemoveEntity(FEnt, True);
      //if Assigned(AReader.FConv.OnCreate) then AReader.FConv.OnCreate(P);
      FEntity.Free;
    finally
      FEntity := Result;
    end;
  end
end;

procedure TdwgHatch.ReadAssociative(var APBit: TsgInt64);
begin
  Inc2(APBit,1);
end;

function TdwgHatch.ReadBoundaryData(var APBit: TsgInt64): Boolean;
var
  vCurvePolygon: TsgCADCurvePolygon;
  I, J, vNumPaths, vNumPathSegments, vPathFlag: Integer;
  vCurve: Tsg2DCurve;
  vBoundaryList: Tsg2DBoundaryList;
begin
  Result := False;
  vCurvePolygon := TsgCADCurvePolygon(FEntity);
  vNumPaths := ReadBL(APBit);
  for I := 1 to vNumPaths do
  begin
    vPathFlag := ReadBL(APBit);
    vBoundaryList := vCurvePolygon.AddBoundaryList(vPathFlag);
    vBoundaryList.BoundaryType := vPathFlag;
    Result := Result or (vPathFlag and 4 <> 0);
    if vPathFlag and 2 = 0 then
    begin
      vNumPathSegments := ReadBL(APBit);
      for J := 0 to vNumPathSegments - 1 do
      begin
        case ReadRC(APBit) of
          1: vCurve := Read2DLine(APBit);
          2: vCurve := Read2DArc(True, APBit);
          3: vCurve := Read2DArc(False, APBit);
          4: vCurve := Read2DSpline(APBit);
        else
          vCurve := nil;
        end;
        AddBoundaryDataCurve(vBoundaryList, vCurve);
      end;
    end
    else
      AddBoundaryDataCurve(vBoundaryList, Read2DPolyline(APBit,
        vCurvePolygon.EntType = ceMPolygon));
    SeekGeneral(APBit,[seBL]);
  end;
end;

procedure TdwgHatch.ReadEntData(var APBit: TsgInt64);
var
  I, vNumSeedPoints: Integer;
  vCurvePolygon: TsgCADCurvePolygon;
  vPixSize: Boolean;
begin
  vCurvePolygon := TsgCADCurvePolygon(FEntity);
  if Reader.Version >= acR2004 then
    ReadGradietParams(APBit);
  if Reader.Version >= acR2007 then
    vCurvePolygon.HatchName := FStringReader.ReadText;
  vCurvePolygon.Elevation := MakeFPoint(0, 0, ReadBD(APBit));
  vCurvePolygon.Extrusion := Read3D(APBit);
  if Reader.Version < acR2007 then
    vCurvePolygon.HatchName := FStringReader.ReadText;
  vCurvePolygon := DoSolidHatch(ReadBit(APBit) <> 0);
  ReadAssociative(APBit);
  vPixSize := ReadBoundaryData(APBit);
  ReadStyleAndPatternType(APBit);
  if not vCurvePolygon.SolidFill then
    ReadPatternData(APBit);
  if vPixSize then
    SeekGeneral(APBit,[seBD]);
  ReadFillColorAndOffset(APBit);
  vNumSeedPoints := ReadBL(APBit);
  for I := 1 to vNumSeedPoints do
    SeekGeneral(APBit,[se2RD]);
end;

procedure TdwgHatch.ReadFillColorAndOffset(var APBit: TsgInt64);
begin
end;

procedure TdwgHatch.ReadStyleAndPatternType(var APBit: TsgInt64);
begin
  SeekGeneral(APBit, [seBS, seBS]);
end;

{ TdwgMPolygon }

{protected}

function TdwgMPolygon.DoSolidHatch(const AIsSolid: Boolean): TsgCADCurvePolygon;
begin
  Result := TsgCADCurvePolygon(FEntity);
  Result.SolidFill := AIsSolid;
end;

procedure TdwgMPolygon.ReadAssociative(var APBit: TsgInt64);
begin
end;

function TdwgMPolygon.ReadBoundaryData(var APBit: TsgInt64): Boolean;
var
  vMPolygon: TsgCADMPolygon;
  I, vNumPaths: Integer;
  vBoundaryList: Tsg2DBoundaryList;
begin
  Result := False;
  vMPolygon := TsgCADMPolygon(FEntity);
  vNumPaths := ReadBL(APBit);
  for I := 1 to vNumPaths do
  begin
    vBoundaryList := vMPolygon.AddBoundaryList(7);
    AddBoundaryDataCurve(vBoundaryList, Read2DPolyline(APBit, True));
  end;
end;

procedure TdwgMPolygon.ReadEntData(var APBit: TsgInt64);
begin
  SeekGeneral(APBit, [seBL]);
  inherited ReadEntData(APBit);
end;

procedure TdwgMPolygon.ReadFillColorAndOffset(var APBit: TsgInt64);
begin
  TsgCADMPolygon(FEntity).FillColor := ReadColorCAD(Self, APBit);
  TsgCADMPolygon(FEntity).Offset := Read2RD(APBit);
end;

procedure TdwgMPolygon.ReadStyleAndPatternType(var APBit: TsgInt64);
begin
  SeekGeneral(APBit, [seBS]);
end;

{TdwgImageDef}

{protected}

function TdwgImageDef.GetOwner(AReader: TdwgReader): TsgDXFEntity;
begin
  Result := inherited GetOwner(AReader);
  if not Assigned(Result) then
    Result := AReader.Conv.Sections[csImageDefs];
end;

procedure TdwgImageDef.ReadData(var APBit: TsgInt64);
var
  vClsVer: Integer;
  vCode: Integer;
begin
  ReadObjHeader(APBit);
  vClsVer := ReadBL(APBit);
  if (vClsVer >= 500) and (FReader.VarCode(vClsVer) = 55) then
  begin
    Inc2(APBit, 103); //??
    vCode := 1;
    while Comp2(APBit, FDataEnd) and (vCode <> 0) do
    begin
      vCode := ReadBS(APBit);
      case vCode of
        1:  TsgDXFImageDef(FEntity).FileName := FStringReader.ReadText;
        10: SeekGeneral(APBit, [se3D]); // Image size in pixels
        11: SeekGeneral(APBit, [se3D]); // Default size of one pixel in AutoCAD units
        90: SeekGeneral(APBit, [seBL]); // Class version 0
        100:
          begin
            FStringReader.ReadText; // 'cn:AcDbRasterImageDef'
            FStringReader.ReadText; // 'AcDbRasterImageDef'
          end;
        280: SeekGeneral(APBit, [seBS]); // Image-is-loaded flag. 0 = Unloaded; 1 = Loaded
        281: SeekGeneral(APBit, [seBS]); // Resolution units. 0 = No units; 2 = Centimeters; 5 = Inch
      end;
    end
  end
  else
  begin
    SeekGeneral(APBit, [se2RD]);
    TsgDXFImageDef(FEntity).FileName := FStringReader.ReadText;
    SeekGeneral(APBit, [seB, seRC, se2RD]);
  end;
  ReadHandleRefs(APBit);
  if FEntity.Name = '' then
    FEntity.Name := FEntity.EntName;
end;

{TdwgInsert}

{protected}

procedure TdwgInsert.ReadData(var APBit: TsgInt64);
begin
  inherited ReadData(APBit);
  FBlockRecord := ReadID(APBit);
  if FComplex then
    ReadSubEntIDs(APBit);// ReadLimits(APBit,Self);
end;

procedure TdwgInsert.ReadEntData(var APBit: TsgInt64);
var
  vInsert: TsgDXFInsert;
  vPoint: TFPoint;
  vDataFlag: Byte;
begin
  vInsert := TsgDXFInsert(FEntity);
  vInsert.Point := Read3D(APBit);
  if Reader.Version < acR2000 then
    vPoint := Read3D(APBit) // X Y Z scale
  else
  begin
    vDataFlag := ReadBB(APBit);
    if vDataFlag and 1 <> 0 then
      vPoint.X := 1.0
    else
      vPoint.X := ReadRD(APBit);
    vPoint.Y := vPoint.X; vPoint.Z := vPoint.X;
    if vDataFlag < 2 then
    begin
      vPoint.Y := ReadDD(APBit, vPoint.X);
      vPoint.Z := ReadDD(APBit, vPoint.X);
    end;
  end;
  vInsert.Scale := vPoint;
  vInsert.Angle := ReadBD(APBit) * f180DividedByPi;
  vInsert.Extrusion := Read3D(APBit);
  FComplex := ReadBit(APBit) <> 0;
  if FComplex and (Reader.Version >= acR2004) then
    FSubEnts := ReadBL(APBit);
end;

procedure TdwgInsert.References(AReader: TdwgReader);
begin
  inherited References(Reader);
  TsgDXFInsert(FEntity).BlockRecord :=
    TsgDXFBlockRecord(AReader.ObjByHandle(FBlockRecord, TsgDXFBlockRecord));
end;

{TdwgLayout}

{protected}

procedure TdwgLayout.ReadData(var APBit: TsgInt64);
var
  I, vViewPortCount: Integer;
  vLayout: TsgDXFLayout;
  vPlotSettingsData : PsgPlotSettingsData;
begin
  vLayout := TsgDXFLayout(FEntity);
  vPlotSettingsData := TsgDXFPlotSettingsAccess(vLayout.PlotSettings).PlotData;
  ReadObjHeader(APBit);
  //PlotSettings
  Reader.ReadPlotSettings(Self, vPlotSettingsData, APBit);
  vLayout.Name := FStringReader.ReadText;
  SeekGeneral(APBit,[seBS,seBS,se3D,se2RD,se2RD,se3D,se3D,se3D,
    seBD,seBS,se3D,se3D]);
  if Reader.Version >= acR2004 then
    vViewPortCount := ReadBS(APBit) // RL??
  else
    vViewPortCount := 0;
// Handle refs:
  // ParentHandle (soft pointer)
  // reactors (soft pointer)
  ReadHandleRefs(APBit);
  if Reader.Version >= acR2004 then
  begin
    //plot view handle (hard pointer)
    ReadID(APBit);
    //Visual Style handle (soft pointer)
    if Reader.Version >= acR2007 then
      ReadID(APBit);
  end;
  //330 associated paperspace block record handle (soft pointer)
  FPaperSpaceHandle := ReadID(APBit);
  FActiveViewport := ReadID(APBit);//331 last active viewport handle (soft pointer)
  //346 base ucs handle (hard pointer)
  //345 named ucs handle (hard pointer)
  for I := 0 to 1 do
    ReadID(APBit);
  //Viewport handle (repeats Viewport count times) (soft pointer)
  if (Reader.Version >= acR2004) and (vViewPortCount > 0) then
  begin
    FViewports := TsgInt64List.Create(0, vViewPortCount);
    for I := 0 to vViewPortCount - 1 do
      FViewports.Add(ReadID(APBit));
  end;
// --------- old code ---------------
//  if Reader.Version >= acR2007 then
//  begin
//    repeat
//      FPaperSpaceHandle := ReadID(APBit)
//    until (FPaperSpaceHandle = 0) and (vHCode = 4);
//    FPaperSpaceHandle := ReadID(APBit)
//  end
//  else
//  begin
//    repeat
//      FPaperSpaceHandle := ReadID(APBit)
//    until (FPaperSpaceHandle = 0) or (vHCode = 3) or (vHCode = 5);
//    repeat
//      FPaperSpaceHandle := ReadID(APBit)
//    until vHCode = 4;
//  end;
// --------- old code ---------------
end;

procedure TdwgLayout.References(AReader: TdwgReader);
var
  E: TsgDXFEntity;
  vPaperBlockRec: TsgDXFBlockRecordAccess absolute E;
begin
  inherited References(AReader);
  if FPaperSpaceHandle = AReader.FPaper.BlockRecord.Handle then
    E := AReader.FPaper.BlockRecord
  else
    if FPaperSpaceHandle = AReader.FModel.BlockRecord.Handle then
    begin
      E := AReader.FModel.BlockRecord;
      if FActiveViewport <> cnstBadHandle then
        AReader.FActiveViewport := FActiveViewport;
    end
    else
      E := AReader.ObjByHandle(FPaperSpaceHandle, TsgDXFBlockRecord);
  if not Assigned(vPaperBlockRec.Block.Layout) then//dublicate FPaperSpaceHandle
  begin
     TsgDXFLayout(FEntity).PaperSpaceBlock := vPaperBlockRec.Block;
     if Assigned(FViewports) then
       AReader.FViewports.Add(FPaperSpaceHandle, FViewports);
  end;
end;

{TdwgLeader}

{protected}


function TdwgLeader.GetBlockLink(AVal: TsgDimNameVal; AName: string): TsgDXFBlock;
var
  J: Integer;
  vType: TsgDimArrowType;
begin
  Include(FOverrides, AVal);
  Result := TsgDXFBlock(Reader.Conv.Sections[csBlocks].FindEntByName(AName));
  if not Assigned(Result) then
  begin
    J := Reader.FArrows.IndexOf(AName);
    if J = -1 then
    begin
      vType := GetArrowTypeByName(AName, datUndefined);
      if vType <> datUndefined then
      begin
        AName := sgDimensionArrowTypeNames[vType];
        Result := TsgDXFBlock(TsgLinkObject.Create(AName));
        Reader.FArrows.AddObject(AName, Result);
      end;
    end
    else
      Result := TsgDXFBlock(Reader.FArrows.Objects[J]);
  end;
end;

function TdwgLeader.ApplyEED(const AEEData: TsgCADExtendedData;
  const AAppID: UInt64): Boolean;
var
  I: Integer;
  vCode: Integer;
  vFlag: Boolean;
  vLeader: TsgDXFLeaderAccess;

  function BlockByHandle(AVal: TsgDimNameVal; const AHandle: UInt64): TsgDXFBlock;
  var
    vObj: TObject absolute Result;
  begin
    Include(FOverrides, AVal);
    vObj := Reader.ObjByHandle(AHandle, nil);
    if vObj = nil then
      vObj := TsgLinkObject.Create(Reader.Conv.HeadVarStruct.DimProps.Arrows.Blks[AVal]);
  end;

begin
  Result := False;
  if not FCanApplyEED then Exit;
  Result := inherited ApplyEED(AEEData, AAppID);
  vLeader := TsgDXFLeaderAccess(FEntity);
  if Assigned(AEEData) and (AAppID = Reader.FACADAppID) then
  begin
    I := 0;
    vFlag := False;
    vCode := 0;
    while I < AEEData.DataCount do
    begin
      case AEEData.DataType[I] of
        edtString:
          if vFlag then
          begin
            case vCode of
              5: vLeader.DIMBLK := GetBlockLink(vnDIMBLK, AEEData.DataString[I]);
              6: vLeader.DIMBLK1 := GetBlockLink(vnDIMBLK1, AEEData.DataString[I]);
              7: vLeader.DIMBLK2 := GetBlockLink(vnDIMBLK2, AEEData.DataString[I]);
            end;
          end;
        edtDouble:
          if vFlag then
          begin
            case (*AEEData.DataCode[I - 1]*) vCode of
              40:
                begin
                  Include(FOverrides, vnDIMSCALE);
                  FArrowScaleOverrides := AEEData.DataDouble[I];
                end;
              41:
                begin
                  Include(FOverrides, vnDIMASZ);
                  FArrowSizeOverrides := AEEData.DataDouble[I];
                end;
              147: FGAP := AEEData.DataDouble[I];
            end;
          end;
        edtint64:
          case vCode of
            340: vLeader.TextStyle := TsgDXFStyle(Reader.ObjByHandle(AEEData.DataInt64[I], TsgDXFStyle));
            341: vLeader.DIMLDRBLK := BlockByHandle(vnDIMLRBLK, AEEData.DataInt64[I]);
            342: vLeader.DIMBLK := BlockByHandle(vnDIMBLK, AEEData.DataInt64[I]);
            343: vLeader.DIMBLK1 := BlockByHandle(vnDIMBLK1, AEEData.DataInt64[I]);
            344: vLeader.DIMBLK2 := BlockByHandle(vnDIMBLK2, AEEData.DataInt64[I]);
          end;
        edtInt16:
        begin
          if vFlag then
          begin
            case (*AEEData.DataInt16[I - 1]*) vCode of
              77: FTAD := AEEData.DataInt16[I];
            end;
          end;
          case AEEData.DataCode[I] of
            1070: vCode := AEEData.DataInt16[I];
          end;
        end;
        edtByte:
          case AEEData.DataCode[I] of
            1002: begin vFlag := not vFlag; end;
          end;
      end;
      Inc(I);
    end;
  end;
end;

function TdwgLeader.CanEEDApply(const AAppID: UInt64): Boolean;
begin
  Result := inherited CanEEDApply(AAppID);
  Result := Result or Reader.IsFamiliarApplication(AAppID, FHandle);
end;

constructor TdwgLeader.Create;
begin
  inherited Create;
  FHooklineDirectional := 1;
  FHooklineVector := cnstXOrtAxis;
  FTAD := -1;
  FGAP := 0;
  FAnnotationType := 3;
  FArrowSize := 0;
  FArrowScaleOverrides := 0;
  FCanApplyEED := False;
end;

procedure TdwgLeader.ReadData(var APBit: TsgInt64);
begin
  inherited ReadData(APBit);
  ReadID(APBit);
  FDimStyle := ReadID(APBit);
end;

procedure TdwgLeader.ReadEntData(var APBit: TsgInt64);
var
  vLeader: TsgDXFLeader;
  vNumPoints: Integer;
begin
  vLeader := TsgDXFLeader(FEntity);
  Inc2(APBit,1);
  FAnnotationType := ReadBS(APBit);
  vLeader.IsSpline := ReadBS(APBit) = 1; //path type
  vNumPoints := ReadBL(APBit);
  while vNumPoints > 0 do
  begin
    vLeader.Controls.Add(Read3D(APBit));
    Dec(vNumPoints);
  end;
  SeekGeneral(APBit,[se3D]);
  vLeader.Extrusion := Read3D(APBit);
  FHooklineVector := Read3D(APBit);
  SeekGeneral(APBit,[se3D]);
  if Reader.Version > acR13 then
    SeekGeneral(APBit,[se3D]);
  if Reader.Version < acR2000 then
    FGAP := ReadBD(APBit);

  if Reader.FVersion < acR2010 then
  begin
    SeekGeneral(APBit,[seBD]);
    FTextAnnotationWidth := ReadBD(APBit);
  end
  else
    FTextAnnotationWidth := 0.0;

  FHooklineDirectional := ReadBit(APBit);
  vLeader.Arrowhead := ReadBit(APBit) <> 0;
  if Reader.Version < acR2000 then
  begin
    SeekGeneral(APBit, [seBS]);
    FArrowSize := ReadBD(APBit);// contains a size including the scale
    Inc2(APBit,2);
    SeekGeneral(APBit, [seBS]);
  end;
  SeekGeneral(APBit, [seBS]);
  Inc2(APBit,2);
end;

procedure TdwgLeader.References(AReader: TdwgReader);
var
  I: Integer;
  vLeader: TsgDXFLeaderAccess;
  vScale: Double;
  vExData: TsgCADExtendedData;
begin
  inherited References(Reader);
  vLeader := TsgDXFLeaderAccess(FEntity);
  vLeader.DimStyle := TsgDXFDimensionStyle(AReader.ObjByHandle(FDimStyle, TsgDXFDimensionStyle));
  if vLeader.DimStyle = nil then
    vLeader.DimStyle := AReader.Conv.DimensionStyleByName(sStandardName);

  if Assigned(FEEDataList) then
  begin
    FCanApplyEED := True;
    for I := 0 to FEEDataList.Count - 1 do
    begin
      vExData := TsgCADExtendedData(FEEDataList[I]);
      ApplyEED(vExData, vExData.DataInt64[0]);
    end;
  end;

  vScale := vLeader.ArrowScale;
  if Reader.Version < acR2000 then
    vLeader.ArrowSize := FArrowSize;

  if vnDIMASZ in FOverrides then
  begin
    vLeader.ArrowSize := FArrowSizeOverrides;
    vLeader.ArrowScale := vScale;
  end;

  if ([vnDIMSCALE, vnDIMASZ] * FOverrides = [vnDIMSCALE, vnDIMASZ]) or
     ((Reader.Version >= acR2000) and (vnDIMSCALE in FOverrides)) then
  begin
    if FArrowScaleOverrides <> 0 then
      vLeader.ArrowScale := FArrowScaleOverrides
    else
      vLeader.ArrowScale := vScale;
  end;

  // always perform DIMLDRBLK in this case ??
  if not (vnDIMLRBLK in FOverrides) then
    if vLeader.DIMLDRBLK = nil then
    begin
      if (vLeader.DIMBLK1 <> nil) and (vLeader.DIMBLK1 = vLeader.DIMBLK2) then
      begin
        if (vLeader.DIMBLK <> nil) or ([vnDIMBLK1, vnDIMBLK2] * FOverrides = [vnDIMBLK1, vnDIMBLK2]) then
          vLeader.DIMLDRBLK := vLeader.DIMBLK1
        else
          if TsgDXFDimensionStyleAccess(vLeader.DimStyle).FDimProps.Arrows.Blk <> datUndefined then
            vLeader.DIMLDRBLK := GetBlockLink(vnDIMLRBLK, sgDimensionArrowTypeNames[datClosedfilled])
          else
            vLeader.DIMLDRBLK := vLeader.DIMBLK1;
      end;
    end
    else
    begin
      if (vnDIMBLK in FOverrides) and (Reader.Version <= acR2000) then
        vLeader.DIMLDRBLK := vLeader.DIMBLK;
    end;

  if (FTAD < 0) and (vLeader.DimStyle <> nil) then
    FTAD := Byte(vLeader.DimStyle.TextPosVert);

  if FAnnotationType <> 3 then
    TsgDXFLeaderAccess(vLeader).DoAdditionalLine(0, FHooklineDirectional,
      FHooklineVector, FTAD, FGAP, FTextAnnotationWidth);
end;

{TdwgLine}

{protected}

function TdwgLine.ApplyEED(const AEEData: TsgCADExtendedData;
  const AAppID: UInt64): Boolean;
var
  I: Integer;
begin
  Result := inherited ApplyEED(AEEData, AAppID);
  if Assigned(AEEData) and (AAppID = Reader.FACADAppID) then
  begin
    I := AEEData.IndexOfCode(1071);
    if I >= 0 then
      FColor := MakeColorCAD(acRGBColor, BGRToRGB(AEEData.DataInt[I]));
  end;
end;

function TdwgLine.CanEEDApply(const AAppID: UInt64): Boolean;
begin
  Result := inherited CanEEDApply(AAppID);
  Result := Result or Reader.IsFamiliarApplication(AAppID, FHandle);
end;

procedure TdwgLine.ReadEntData(var APBit: TsgInt64);
var
  vLine: TsgDXFLine;
  vZ: Boolean;
  vStartPoint,vEndPoint: TFPoint;
begin
  vLine := TsgDXFLine(FEntity);
  if Reader.Version < acR2000 then
  begin
    vStartPoint := Read3D(APBit);
    vEndPoint := Read3D(APBit);
  end
  else
  begin
    vZ := ReadBit(APBit) = 0;
    vStartPoint.X := ReadRD(APBit);
    vEndPoint.X := ReadDD(APBit, vStartPoint.X);
    vStartPoint.Y := ReadRD(APBit);
    vEndPoint.Y := ReadDD(APBit, vStartPoint.Y);
    vStartPoint.Z := 0; vEndPoint.Z := 0;
    if vZ then
    begin
      vStartPoint.Z := ReadRD(APBit);
      vEndPoint.Z := ReadDD(APBit, vStartPoint.Z);
    end;
  end;
  vLine.Point := vStartPoint;
  vLine.Point1 := vEndPoint;
  vLine.ZThick := ReadBT(APBit,Reader.Version);
  vLine.Extrusion := ReadBE(APBit,Reader.Version);
end;

{TdwgLWPline}

{protected}

procedure TdwgLWPline.ReadEntData(var APBit: TsgInt64);
var
  vFlag, vNumPoints, vNumBulges, vNumWidths: Integer;
  vPolyline: TsgDXFPolyline;
  vVertex: TsgDXFVertex;
  vPoint: TFPoint;
  I: Integer;
begin
  vPolyline := TsgDXFLWPolyline(FEntity);
  vNumBulges := 0;
  vNumWidths := 0;
  vFlag := ReadBS(APBit);
  vPolyline.Closed := vFlag and 512 <> 0;
  vPolyline.Flags := (vPolyline.Flags and $FF7F) or
    (Byte(vFlag and 256 <> 0) shl 7);
  if vFlag and 4 <> 0 then
    vPolyline.GlobalWidth := ReadBD(APBit);
  if vFlag and 8 <> 0 then
    vPolyline.Elevation := ReadBD(APBit);
  if vFlag and 2 <> 0 then
    vPolyline.ZThick := ReadBD(APBit);
  if vFlag and 1 <> 0 then
    vPolyline.Extrusion := Read3D(APBit);
  vNumPoints := ReadBL(APBit);
  if vFlag and 16 <> 0 then
    vNumBulges := ReadBL(APBit);
  if vFlag and 32 <> 0 then
    vNumWidths := ReadBL(APBit);
  if vFlag and $400 <> 0 then
    SeekGeneral(APBit, [seBL]); // R2010+: number of vertex identifiers (when present, always the same as number of vertes)
  vPoint.Z := 0.0;
  for I := 0 to vNumPoints - 1 do
  begin
    if (Reader.Version < acR2000) or (I = 0) then
    begin
      vPoint.X := ReadRD(APBit);
      vPoint.Y := ReadRD(APBit);
    end
    else
    begin
      vPoint.X := ReadDD(APBit, vPoint.X);
      vPoint.Y := ReadDD(APBit, vPoint.Y);
    end;
    vVertex := TsgDXFVertex.Create;
    vVertex.Point := vPoint;
    vPolyline.AddEntity(vVertex);
  end;
  for I := 0 to vNumBulges - 1 do
  begin
    vPoint.X := ReadBD(APBit);
    if I < vNumPoints then
    begin
      vVertex := TsgDXFVertex(vPolyline.Entities[I]);
      vVertex.Bulge := vPoint.X;
    end;
  end;
  for I := 0 to vNumWidths - 1 do
  begin
    vPoint := Read2D(APBit);
    if I < vNumPoints then
    begin
      vVertex := TsgDXFVertex(vPolyline.Entities[I]);
      vVertex.StartWidth := vPoint.X;
      vVertex.EndWidth := vPoint.Y;
    end;
  end;
end;

{TdwgMLine}

{protected}

procedure TdwgMLine.ReadData(var APBit: TsgInt64);
begin
  inherited ReadData(APBit);
  FStyle := ReadID(APBit);
end;

procedure TdwgMLine.ReadEntData(var APBit: TsgInt64);
var
  vMLine: TsgCADMLine;
  vVertex: TsgMVertex;
  I,J,vNumSegparms,vNumAreaFillParms,vLinesInStyle,vNumVerts: Integer;
begin
  vMLine := TsgCADMLine(FEntity);
  vMLine.ScaleFactor := ReadBD(APBit);
  vMLine.Justify := ReadRC(APBit);
  vMLine.StartPoint := Read3D(APBit);
  vMLine.Extrusion := Read3D(APBit);
  vMLine.Flags := ReadBS(APBit);
  vLinesInStyle := ReadRC(APBit);
  vNumVerts := ReadBS(APBit);
  while vNumVerts > 0 do
  begin
    vVertex := TsgMVertex.Create;
    vVertex.Point := Read3D(APBit);
    vVertex.Direction := Read3D(APBit);
    vVertex.Miter := Read3D(APBit);
    for I:=0 to vLinesInStyle-1 do
    begin
      vNumSegparms := ReadBS(APBit);
      vVertex.NewList;
      for J:=0 to vNumSegparms-1 do
        vVertex.Add(ReadBD(APBit));
      vNumAreaFillParms := ReadBS(APBit);
      for J:=0 to vNumAreaFillParms-1 do
        SeekGeneral(APBit,[seBD]);
    end;
    vVertex.Complete;
    vMLine.AddEntity(vVertex);
    Dec(vNumVerts);
  end;
end;

procedure TdwgMLine.References(AReader: TdwgReader);
begin
  inherited References(Reader);
  TsgCADMLine(FEntity).Style :=
    TsgMLineStyle(AReader.ObjByHandle(FStyle, TsgMLineStyle));
end;

{TdwgMText}

{protected}

function TdwgMText.CreateStringReader(var APBit: TsgInt64;
  AVersion: TsgDWGVersion): TdwgStringReader;
begin
  case AVersion of
    acR2007..acR2013:
      Result := TdwgWideStringReader.Create(@FStrsStart, Reader.Conv.CodePage);
  else
    Result := TdwgAnsiStringReader.Create(@APBit, Reader.Conv.CodePage);
  end;
end;

procedure TdwgMText.ReadData(var APBit: TsgInt64);
begin
  inherited ReadData(APBit);
  FStyle := ReadID(APBit);
end;

procedure TdwgMText.ReadEntData(var APBit: TsgInt64);
var
  vMtext: TsgDXFMtext;
  vBackGrFlags: Integer;
//  vDir: Integer;
//  vExt: TFPoint;
//  vBackgroundScaleFactor: Double;
//  vBackgroundColor: Cardinal;
//  vBackgroundTransparency: Integer;
begin
  vMtext := TsgDXFMtext(FEntity);
  vMtext.Point := Read3D(APBit);
  vMtext.Extrusion := Read3D(APBit);
  vMtext.Point1 := Read3D(APBit);
  vMtext.RectWidth := ReadBD(APBit);
  if Reader.Version >= acR2007 then
    SeekGeneral(APBit,[seBD]);
  vMtext.Height := ReadBD(APBit);
  vMtext.Align := ReadBS(APBit);
{ TODO: Read mtext direction flag and extents
  vDir := ReadBS(APBit);
  vExt.X := ReadBD(APBit);
  vExt.Y := ReadBD(APBit);
  vExt.Z := 0; }
  SeekGeneral(APBit, [seBS, se2D]);
  vMtext.Text := ReadMText(Self);
  case Reader.Version of
    acR2000 .. acR2013:
      begin
        vMtext.LineSpacingStyle := ReadBS(APBit);
        vMtext.LineSpacingFactor := ReadBD(APBit);
        SeekGeneral(APBit, [seB]);
        if Reader.Version >= acR2004 then
        begin
          vBackGrFlags := ReadBL(APBit);//0 = no background, 1 = background fill, 2 = background fill with drawing fill color
          if vBackGrFlags and 1 <> 0 then
          begin
{ TODO: Read mtext Background
            vBackgroundScaleFactor := ReadBD(APBit);  //Background scale factor
            vBackgroundColor := ReadCMC(Self, APBit); //Background color CMC
            vBackgroundTransparency := ReadBL(APBit); //Background transparency }
            SeekGeneral(APBit, [seBD]);
            ReadCMC(Self, APBit);
            SeekGeneral(APBit, [seBL]);
          end;
        end;
      end;
  end;
end;

procedure TdwgMText.References(AReader: TdwgReader);
begin
  inherited References(Reader);
  TsgDXFMText(FEntity).Style := TsgDXFStyle(AReader.ObjByHandle(FStyle, TsgDXFStyle));
end;

{TdwgOLE2Frame}

{protected}

procedure TdwgOLE2Frame.ReadEntData(var APBit: TsgInt64);
var
  vOle2Frame: TsgDXFOle2Frame;
  vRawData: AnsiString;
  I,vDataLength: Integer;
begin
  vOle2Frame := TsgDXFOle2Frame(FEntity);
  vOle2Frame.OLEObjectType := ReadBS(APBit);
  if Reader.Version >= acR2000 then
    SeekGeneral(APBit, [seBS]);
  vDataLength :=  ReadBL(APBit) - 128;
  if vDataLength <= 0 then
  begin
    ReadError;
    Exit;
  end;
  SetLength(vRawData,vDataLength);
  Inc2(APBit,16);
  vOle2Frame.Point := Read3RD(APBit);
  SeekGeneral(APBit, [se3RD]);
  vOle2Frame.Point1 := Read3RD(APBit);
  SeekGeneral(APBit, [se3RD]);
  Inc2(APBit,176);
  vOle2Frame.Aspect := ReadRC(APBit);
  Inc2(APBit,56);
  for I := 1 to vDataLength do
    vRawData[I] := AnsiChar(ReadRC(APBit));
  vOle2Frame.BinaryData := vRawData;
  if Reader.Version >= acR2000 then
    Inc2(APBit,8);
end;

{TdwgPoint}

{protected}

procedure TdwgPoint.ReadEntData(var APBit: TsgInt64);
var
  vPoint: TsgDXFPoint;
begin
  vPoint := TsgDXFPoint(FEntity);
  vPoint.Point := Read3D(APBit);
  vPoint.ZThick := ReadBT(APBit,Reader.Version);
  vPoint.Extrusion := ReadBE(APBit,Reader.Version);
  SeekGeneral(APBit,[seBD]);
end;

{TdwgPolyline}

{protected}

constructor TdwgPolyline.Create;
begin
  inherited Create;
end;

procedure TdwgPolyline.ReadData(var APBit: TsgInt64);
begin
  inherited ReadData(APBit);
  ReadSubEntIDs(APBit);// ReadLimits(APBit,Self);
  //ReadID(APBit); // SEQEND
end;

procedure TdwgPolyline.ReadEntData(var APBit: TsgInt64);
var
  vPolyline: TsgDXFPolyline;
begin
  vPolyline := TsgDXFPolyline(FEntity);
  vPolyline.Closed := ReadBS(APBit) and 1 <> 0;
  SeekGeneral(APBit, [seBS]);
  vPolyline.StartWidth := ReadBD(APBit);
  vPolyline.EndWidth := ReadBD(APBit);
  vPolyline.ZThick := ReadBT(APBit,Reader.Version);
  vPolyline.Elevation := ReadBD(APBit);
  vPolyline.Extrusion := ReadBE(APBit,Reader.Version);
  if Reader.Version >= acR2004 then
    FSubEnts := ReadBL(APBit);
end;

{ TdwgPlotSettings }

function TdwgPlotSettings.GetOwner(AReader: TdwgReader): TsgDXFEntity;
begin
  Result := inherited GetOwner(AReader);
  if not Assigned(Result) then
    Result := AReader.Dictionary[cnstObjectsPLOTSETTINGS];
end;

procedure TdwgPlotSettings.ReadData(var APBit: TsgInt64);
var
  vPlotSettings: TsgDXFPlotSettings;
  vPlotSettingsData : PsgPlotSettingsData;
begin
  vPlotSettings := TsgDXFPlotSettings(FEntity);
  vPlotSettingsData := TsgDXFPlotSettingsAccess(vPlotSettings).PlotData;
  ReadObjHeader(APBit);
  //PlotSettings
  Reader.ReadPlotSettings(Self, vPlotSettingsData, APBit);
  ReadHandleRefs(APBit);
end;

{ TdwgRasterVariables }

function TdwgRasterVariables.GetOwner(AReader: TdwgReader): TsgDXFEntity;
begin
  Result := inherited GetOwner(AReader);
  if not Assigned(Result) then
    Result := AReader.Conv.Sections[csObjects];
end;

procedure TdwgRasterVariables.ReadData(var APBit: TsgInt64);
var
  vRasterVars: TsgCADRasterVariables;
begin
  ReadObjHeader(APBit);
  ReadBL(APBit); // Classver BL 90 classversion
  vRasterVars := TsgCADRasterVariables(FEntity);
  vRasterVars.DisplayImageFrame := ReadBS(APBit) = 1;   // Dispfrm BS 70 displayframe
  vRasterVars.ImageDisplayQuality := ReadBS(APBit) = 1; // Dispqual BS 71 display quality
  vRasterVars.UnitsForInsertingImages := ReadBS(APBit); // Units BS 72 units
  ReadHandleRefs(APBit);
end;

{TdwgSolid}

{protected}

procedure TdwgSolid.ReadEntData(var APBit: TsgInt64);
var
  vSolid: TsgDXFSolid;
  vElevation: Double;
begin
  vSolid := TsgDXFSolid(FEntity);
  vSolid.ZThick := ReadBT(APBit,Reader.Version);
  vElevation := ReadBD(APBit);
  vSolid.Point := Read2RDElevation(APBit, vElevation);
  vSolid.Point1 := Read2RDElevation(APBit, vElevation);
  vSolid.Point2 := Read2RDElevation(APBit, vElevation);
  vSolid.Point3 := Read2RDElevation(APBit, vElevation);
  vSolid.Extrusion := ReadBE(APBit,Reader.Version);
end;

{TdwgSpline}

{protected}

function TdwgSpline.ApplyEED(const AEEData: TsgCADExtendedData;
  const AAppID: UInt64): Boolean;
var
  I, vCode: Integer;
begin
  Result := inherited ApplyEED(AEEData, AAppID);
  // FEntity.SetExtData(AEEData);
  if Assigned(AEEData) and (AAppID = Reader.FACADAppID) then
  begin
    I := 0;
    vCode := 0;
    while I < AEEData.DataCount do
    begin
      case AEEData.DataType[I] of
        edtInt16: vCode := AEEData.DataInt16[I];
        edtInt:
          begin
            case vCode of
              70: TsgDXFSplineAccess(FEntity).FlagsExtented := AEEData.DataInt[I];
            end;
            vCode := 0;
          end;
      else
        vCode := 0;
      end;
      Inc(I);
    end;
  end;
end;

function TdwgSpline.CanEEDApply(const AAppID: UInt64): Boolean;
begin
  Result := inherited CanEEDApply(AAppID);
  Result := Result or (AAppID = Reader.FAppID);
end;

procedure TdwgSpline.ReadEntData(var APBit: TsgInt64);
var
  I, vScenario, vNumFit, vNumControlPoints, vNumKnots: Integer;
  vSpline: TsgDXFSpline;
  vKnot: Single;
  vWeight: Boolean;
  {vFlags1, }vSplineDataFlag: Cardinal;
begin
  vSpline := TsgDXFSpline(FEntity);
  vScenario := ReadBS(APBit);    //maybe ReadBL(APBit)
  if FReader.Version >= acR2013 then
  begin
    ReadBL(APBit); //vFlags1 := ReadBL(APBit) and 4;
    vSplineDataFlag := ReadBL(APBit);
    //if vScenario <> 1 then raise EdwgError.Create
    if vSplineDataFlag <> $F then
      Inc(vScenario);
  end;
  vSpline.Degree := ReadBS(APBit); //maybe ReadBL(APBit)
  vNumFit := 0;
  vNumControlPoints := 0;
  vNumKnots := 0;
  vWeight := False;
  if vScenario and 2 <> 0 then
  begin
    SeekGeneral(APBit,[seBD]); //  Fit Tol
    vSpline.BeginningTangent := Read3D(APBit);
    vSpline.EndingTangent := Read3D(APBit);
    vNumFit := ReadBL(APBit);
  end;
  if vScenario and 1 <> 0 then
  begin
    vSpline.Flags := vSpline.Flags or (4 * Ord(ReadBit(APBit) <> 0));// 3 bit Flags
    vSpline.Closed := ReadBit(APBit) <> 0;                           // 2 bit Flags
    vSpline.Flags := vSpline.Flags or Ord(ReadBit(APBit) <> 0);      // 1 bit Flags
    SeekGeneral(APBit, [se2D]);
    vNumKnots := ReadBL(APBit);
    vNumControlPoints := ReadBL(APBit);
    vWeight := ReadBit(APBit) <> 0;
  end;
  for I := 0 to vNumKnots-1 do
  begin
    vKnot := ReadBD(APBit);
    vSpline.Knots.Add(vKnot);
  end;
  for I := 0 to vNumControlPoints-1 do
  begin
    vSpline.Controls.Add(Read3D(APBit));
    if vWeight then
      vSpline.AddWeight(ReadBD(APBit));
  end;
  for I := 0 to vNumFit-1 do
  begin
    vSpline.Fit.Add(Read3D(APBit));
  end;
end;

{TdwgStyle}

{protected}

function TdwgStyle.ApplyEED(const AEEData: TsgCADExtendedData;
  const AAppID: UInt64): Boolean;
var
  I, vFontStyleData: Integer;
  vmvFontStyles: TmvFontStyles;
begin
  Result := inherited ApplyEED(AEEData, AAppID);
  if not Result and Assigned(AEEData) then
  begin
    I := 0;
    while I < AEEData.DataCount do
    begin
      case AEEData.DataType[I] of
        edtstring:
          begin
            TsgDXFStyle(FEntity).FontName := AEEData.DataString[I];
          end;
        edtInt:
          begin
            vmvFontStyles := [];
            vFontStyleData := AEEData.DataInt[I];
            if vFontStyleData and $1000000 <> 0 then
              Include(vmvFontStyles, fmItalic);
            if vFontStyleData and $2000000 <> 0 then
              Include(vmvFontStyles, fmBold);
            TsgDXFStyle(FEntity).FontStyle := vmvFontStyles;
          end;
      end;
      Inc(I);
    end;
  end;
end;

function TdwgStyle.CanEEDApply(const AAppID: UInt64): Boolean;
begin
  Result := inherited CanEEDApply(AAppID);
  Result := Result or Reader.IsFamiliarApplication(AAppID, FHandle);
end;

function TdwgStyle.GetOwner(AReader: TdwgReader): TsgDXFEntity;
begin
  Result := inherited GetOwner(AReader);
  if not Assigned(Result) then
    Result := AReader.Conv.Sections[csStyles];
end;

procedure TdwgStyle.ReadData(var APBit: TsgInt64);
var
  vStyle: TsgDXFStyle;
begin
  inherited ReadData(APBit);
  FEntity.Name := FEntryName;
  FFlags := FFlags or ReadBit(APBit);
  FFlags := FFlags or ReadBit(APBit) shl 3;
  vStyle := TsgDXFStyle(FEntity);
  vStyle.Flags := FFlags;
  vStyle.FixedHeight := ReadBD(APBit);
  vStyle.WidthFactor := ReadBD(APBit);
  vStyle.ObliqueAngle := ReadBD(APBit) * f180DividedByPi;
  vStyle.TextGenFlags := ReadRC(APBit);
  vStyle.LastHeightUsed := ReadBD(APBit);
  vStyle.PrimaryFont := FStringReader.ReadText;
  vStyle.BigFont := FStringReader.ReadText;
  ReadHandleRefs(APBit);
end;

{TdwgText}

{protected}

procedure TdwgText.ApplyValue;
begin
  TsgDXFText(FEntity).Text := FText;
end;

constructor TdwgText.Create;
begin
  inherited Create;
  FScale := 1.0;
end;

function TdwgText.CreateStringReader(var APBit: TsgInt64;
  AVersion: TsgDWGVersion): TdwgStringReader;
begin
  case AVersion of
    acR2007..acR2013:
      Result := TdwgWideStringReader.Create(@FStrsStart, Reader.Conv.CodePage);
  else
    Result := TdwgAnsiStringReader.Create(@APBit, Reader.Conv.CodePage);
  end;
end;

procedure TdwgText.ReadData(var APBit: TsgInt64);
begin
  inherited ReadData(APBit);
  FStyle := ReadID(APBit);
end;

procedure TdwgText.ReadEntData(var APBit: TsgInt64);
begin
  if Reader.Version < acR2000 then
  begin
    FFlags := $FF;
    FPoint.Z := ReadBD(APBit);
    FPoint := Read2RDElevation(APBit, FPoint.Z);
    FPoint1 := Read2RDElevation(APBit, FPoint.Z);
    FExtrusion := Read3D(APBit);
    SeekGeneral(APBit,[seBD]);
    FObliqueAngle := ReadBD(APBit) * f180DividedByPi;
    FRotation := ReadBD(APBit) * f180DividedByPi;
    FHeight := ReadBD(APBit);
    FScale := ReadBD(APBit);
    FText := FStringReader.ReadText;
    FGeneration := ReadBS(APBit);
    FHAlign := ReadBS(APBit);
    FVAlign := ReadBS(APBit);
  end
  else
  begin
    FFlags := not ReadRC(APBit);
    if FFlags and $01 <> 0 then
      FPoint := Read2RDElevation(APBit, ReadRD(APBit))
    else
      FPoint := Read2RD(APBit);
    if FFlags and $02 <> 0 then
    begin
      FPoint1.X := ReadDD(APBit, FPoint.X);
      FPoint1.Y := ReadDD(APBit, FPoint.Y);
      FPoint1.Z := FPoint.Z;
    end;
    FExtrusion := ReadBE(APBit,Reader.Version);
    ReadBT(APBit,Reader.Version);
    if FFlags and $04 <> 0 then
      FObliqueAngle := ReadRD(APBit) * f180DividedByPi;
    if FFlags and $08 <> 0 then
      FRotation := ReadRD(APBit) * f180DividedByPi;
    FHeight := ReadRD(APBit);
    if FFlags and $10 <> 0 then
      FScale := ReadRD(APBit);
    FText := FStringReader.ReadText;
    if FFlags and $20 <> 0 then
      FGeneration := ReadBS(APBit);
    if FFlags and $40 <> 0 then
      FHAlign := ReadBS(APBit);
    if FFlags and $80 <> 0 then
      FVAlign := ReadBS(APBit);
  end;
end;

procedure TdwgText.References(AReader: TdwgReader);
var
  vText: TsgDXFText;
begin
  inherited References(Reader);
  vText := TsgDXFText(FEntity);
  vText.Style := TsgDXFStyle(AReader.ObjByHandle(FStyle, TsgDXFStyle));
  vText.Point := FPoint;
  vText.Point1 := FPoint1;
  vText.Extrusion := FExtrusion;
  vText.ObliqueAngle := FObliqueAngle;
  vText.Rotation := FRotation;
  vText.Height := FHeight;
  vText.Scale := FScale;
  vText.Generation := FGeneration;
  vText.HAlign := FHAlign;
  vText.VAlign := FVAlign;
  ApplyValue;
end;

{TdwgTolerance}

{protected}

constructor TdwgTolerance.Create;
begin
  inherited Create;
  FDimlineColor := cnstDefaultEntityColor;
end;

function TdwgTolerance.CreateStringReader(var APBit: TsgInt64;
  AVersion: TsgDWGVersion): TdwgStringReader;
begin
  case AVersion of
    acR2007..acR2013:
      Result := TdwgWideStringReader.Create(@FStrsStart, Reader.Conv.CodePage);
  else
    Result := TdwgAnsiStringReader.Create(@APBit, Reader.Conv.CodePage);
  end;
end;

function TdwgTolerance.ApplyEED(const AEEData: TsgCADExtendedData;
  const AAppID: UInt64): Boolean;
var
  I: Integer;
  vStop, vNeedCode: Boolean;
begin
  Result := inherited ApplyEED(AEEData, AAppID);
  if Assigned(AEEData) and (AEEData.DataCount > 0) and (AAppID = Reader.FACADAppID) then
  begin
    I := 0;
    vStop := False;
    vNeedCode := False;
    repeat
      vNeedCode := not vNeedCode;
      case AEEData.DataType[I] of
        edtByte:
          begin
            vStop := AEEData.DataByte[I] = 1;
            vNeedCode := False; // if not vStop, then next string is 'DSTYLE'
          end;
        edtInt16:
          if not vNeedCode then
            case AEEData.DataInt16[I - 1] of
              176: FDimlineColor := MakeColorCAD(acIndexColor, AEEData.DataInt16[I]);
            end;
        edtDouble:
          case AEEData.DataInt16[I - 1] of
            40: TsgDXFTolerance(FEntity).DimScaleOverall := AEEData.DataDouble[I];
            140: TsgDXFTolerance(FEntity).Height := AEEData.DataDouble[I];
            147: FGAP := AEEData.DataDouble[I];
          end;
      end;
      Inc(I);
    until (I >= AEEData.DataCount) or vStop;
  end;
end;

function TdwgTolerance.CanEEDApply(const AAppID: UInt64): Boolean;
begin
  Result := inherited CanEEDApply(AAppID);
  Result := Result or Reader.IsFamiliarApplication(AAppID, FHandle);
end;

procedure TdwgTolerance.ReadData(var APBit: TsgInt64);
begin
  inherited ReadData(APBit);
  FDimStyle := ReadID(APBit);
end;

procedure TdwgTolerance.ReadEntData(var APBit: TsgInt64);
var
  vDouble: Double;
  vTolerance: TsgDXFTolerance;
begin
  vTolerance := TsgDXFTolerance(FEntity);
  if Reader.Version < acR2000 then
  begin
    SeekGeneral(APBit, [seBS]);
    vDouble := ReadBD(APBit);
    if vDouble <> 0 then
      vTolerance.Height := vDouble;
    SeekGeneral(APBit,[seBD]);
  end;
  vTolerance.Point := Read3D(APBit);
  vTolerance.Point1 := Read3D(APBit);
  vTolerance.Extrusion := Read3D(APBit);
  vTolerance.Text := ReadMText(Self);
end;

procedure TdwgTolerance.References(AReader: TdwgReader);
begin
  inherited References(Reader);
  TsgDXFTolerance(FEntity).DimStyle :=
    TsgDXFDimensionStyle(AReader.ObjByHandle(FDimStyle, TsgDXFDimensionStyle));
  TsgDXFTolerance(FEntity).DimlineColor := FDimlineColor;
  if AReader.Version = acR14 then
    TsgDXFTolerance(FEntity).GAP := FGAP;
end;

{TdwgUndefinedEntity}

{protected}

function TdwgUndefinedEntity.GetBitSize: Integer;
begin
  Result := FBitSize;
end;

function TdwgUndefinedEntity.GetObjectBeginning: TsgInt64;
begin
  Result := FObjectBeginning;
end;

procedure TdwgUndefinedEntity.ReadEntData(var APBit: TsgInt64);
var
  vPBit: TsgInt64;
begin
  vPBit := FObjectBeginning;
  Inc2(vPBit, BitSize);
  APBit := vPBit;
end;

procedure TdwgUndefinedEntity.SetBitSize(const AValue: Integer);
begin
  FBitSize := AValue;
end;

procedure TdwgUndefinedEntity.SetObjectBeginning(const AValue: TsgInt64);
begin
  FObjectBeginning := AValue;
end;

{TdwgVertex}

{protected}

procedure TdwgVertex.ReadEntData(var APBit: TsgInt64);
begin
  TsgDXFVertex(FEntity).Flags := ReadRC(APBit);
  TsgDXFVertex(FEntity).Point := Read3D(APBit);
end;

{TdwgViewport}

{protected}

function TdwgViewport.ApplyEED(const AEEData: TsgCADExtendedData;
  const AAppID: UInt64): Boolean;
var
  I: Integer;
  vViewPort: TsgDXFViewport;
begin
  Result := inherited ApplyEED(AEEData, AAppID);
  if Assigned(AEEData) and (AAppID = Reader.FACADAppID) then
  begin
    vViewPort := TsgDXFViewport(FEntity);
    I := 0;
    while I < AEEData.DataCount do
    begin
      case AEEData.DataType[I] of
        edtint64:
          case AEEData.DataCode[I] of
            1003: vViewPort.FrozenLayers.Add(AEEData.DataInt64[I]);
            1005: FHandle := AEEData.DataInt64[I];
          end;
        edtF3DPoint:
          begin
            Inc(FCount_10);
            case FCount_10 of
              1: vViewPort.ViewTarget := AEEData.DataPoint[I];
              2: vViewPort.ViewDirection := AEEData.DataPoint[I];
            end;
          end;
        edtDouble:
          begin
            Inc(FCount_40);
            case FCount_40 of
              1: vViewPort.ViewTwistAngle := AEEData.DataDouble[I] * f180DividedByPi;
              2: vViewPort.MSpaceHeight := AEEData.DataDouble[I];
              3: vViewPort.Offset(MakeFPoint(AEEData.DataDouble[I], 0, 0));
              4: vViewPort.Offset(MakeFPoint(0, AEEData.DataDouble[I], 0));
              6: vViewPort.FrontClipPlane := AEEData.DataDouble[I];
              7: vViewPort.BackClipPlane := AEEData.DataDouble[I];
            end;
          end;
      end;
      Inc(I);
    end;
  end;
end;

function TdwgViewport.CanEEDApply(const AAppID: UInt64): Boolean;
begin
  Result := inherited CanEEDApply(AAppID);
  Result := Result or Reader.IsFamiliarApplication(AAppID, FHandle);
end;

procedure TdwgViewport.ReadData(var APBit: TsgInt64);
var
  I: Integer;
  vViewport: TsgDXFViewport;
begin
  inherited ReadData(APBit);
  vViewport := TsgDXFViewport(FEntity);
  if Reader.Version >= acR2000 then
  begin
    for I := 0 to FFrozenLayerCount - 1 do
      vViewPort.FrozenLayers.Add(ReadID(APBit));
    vViewport.ClippingBoundaryHandle := ReadID(APBit);
    if Reader.Version = acR2000 then
      FEntHeaderHandle := ReadID(APBit);//  VIEWPORT ENT HEADER ((hard pointer))
    ReadID(APBit);// 345 Named UCS Handle (hard pointer)
    ReadID(APBit);// 346 Base UCS Handle (hard pointer)
    // 332 Background (soft pointer)
    // 348 Visual Style (hard pointer)
    // 333 Shadeplot ID (soft pointer)
    // 361 Sun (hard owner)
    if Reader.Version >= acR2007 then
      for I := 0 to 3 do
        ReadID(APBit);
  end
  else
    FEntHeaderHandle := ReadID(APBit);
end;

procedure TdwgViewport.ReadEntData(var APBit: TsgInt64);
var
  vViewport: TsgDXFViewport;
begin
  vViewport := TsgDXFViewport(FEntity);
  vViewport.PSpaceCenter := Read3D(APBit);
  vViewport.PSpaceWidth := ReadBD(APBit);
  vViewport.PSpaceHeight := ReadBD(APBit);
  if Reader.Version >= acR2000 then
  begin
    vViewport.ViewTarget := Read3D(APBit);
    vViewport.ViewDirection := Read3D(APBit);
    vViewport.ViewTwistAngle := ReadBD(APBit) * f180DividedByPi;
    vViewport.MSpaceHeight := ReadBD(APBit);  //View Height
    SeekGeneral(APBit,[seBD]); //Lens Length
    vViewport.FrontClipPlane := ReadBD(APBit); //Front Clip Z
    vViewport.BackClipPlane := ReadBD(APBit);  //Back Clip Z
    SeekGeneral(APBit,[seBD]);  //Snap Angle
    vViewport.MSpaceCenter := Read2RD(APBit); //View Center
    // Snap Base, Snap Spacing, Grid Spacing, Circle Zoom
    SeekGeneral(APBit,[se2RD,se2RD,se2RD,seBS]);
    if Reader.Version >= acR2007 then
      SeekGeneral(APBit, [seBS]); // Grid Major
    FFrozenLayerCount := ReadBL(APBit);
    vViewport.Flags := ReadBL(APBit);
    FStringReader.ReadText; //Style Sheet
    // Render Mode, UCS at origin, UCS per Viewport, UCS Origin
    // UCS X Axis, UCS Y Axis, UCS Elevation,UCS Ortho View Type
    SeekGeneral(APBit,[seRC,seBB,se3D,se3D,se3D,seBD,seBS]);
    if Reader.Version >= acR2004 then
      SeekGeneral(APBit,[seBB]); //ShadePlot Mode
  end;
end;

procedure TdwgViewport.References(AReader: TdwgReader);
begin
  inherited References(Reader);
  TsgDXFViewport(FEntity).SetBoundary(AReader.ObjByHandle(TsgDXFViewport(FEntity).ClippingBoundaryHandle, nil));
  // For future versions (var ViewportEntHeader: TdwgViewportEntHeader;)
  //ViewportEntHeader := TdwgViewportEntHeader(Reader.ObjByHandle(FEntHeaderHandle));
end;

(*// For future versions
{TdwgViewportEntHeader}
procedure TdwgViewportEntHeader.ReadData(var APBit: TsgInt64);
var
  HCode: Byte;
begin
  if Reader.Version < acR2000 then
    ReadRL(APBit);
  ReadBL(APBit);
  _ReadText(APBit);
  FFlags := ReadBit(APBit);
  if FFlags <> 0 then
    FFlags := FFlags or 64;
  FFlags := ReadBit(APBit);
  ReadBit(APBit);
  ReadID(APBit);
  ReadID(APBit);
  ReadID(APBit);
end;
*)

{TdwgWipeOut}

{protected}

procedure TdwgWipeOut.ReadEntData(var APBit: TsgInt64);
var
  vPoint: TFPoint;
  I: Integer;
  vWipeout: TsgCADWipeout;
  //vIsClipInverted: Boolean;
  vClsVer, vCount: Integer;
begin
  vWipeout := TsgCADWipeout(FEntity);
  vClsVer := ReadBL(APBit); //SeekGeneral(APBit,[seBL]); //  (90)  Class version
  if (vClsVer >= 500) and (FReader.VarCode(vClsVer) = 54) then
    ReadEntDataEx(APBit)
  else
  begin
    vWipeout.Point := Read3D(APBit);
    vWipeout.UVector := Read3D(APBit);
    vWipeout.VVector := Read3D(APBit);
    vWipeout.Size := Read2RD(APBit);
    vWipeout.Flags := ReadBS(APBit);
    vWipeout.UseClipping := (ReadBit(APBit) = 1);
    // |  (281) Brightness value (0-100; default = 50)
    // |  (282) Contrast value (0-100; default = 50)
    // v  (283) Fade value (0-100; default = 50)
    SeekGeneral(APBit, [seRC,seRC,seRC]);
    if Reader.Version > acR2007 then
      SeekGeneral(APBit, [seB]); //vIsClipInverted := ReadBit(APBit) <> 0;
    vWipeout.ClippingBoundaryType := ReadBS(APBit);
    case vWipeout.ClippingBoundaryType of
      1:
        begin
          vPoint := Read2RD(APBit);
          vWipeout.AddPoint(vPoint.X, vPoint.Y);
          vPoint := Read2RD(APBit);
          vWipeout.AddPoint(vPoint.X, vPoint.Y);
        end;
      2:
        begin
          vCount := ReadBL(APBit);
          for I := 0 to vCount - 1 do
          begin
            vPoint := Read2RD(APBit);
            vWipeout.AddPoint(vPoint.X, vPoint.Y);//  (14,24) Clip boundary vertex
          end;
        end;
    end;
  end;
end;

procedure TdwgWipeOut.ReadEntDataEx(var APBit: TsgInt64);
var
  vPoint: TFPoint;
  vWipeout: TsgCADWipeout;
  //vIsClipInverted: Boolean;
  vCount, vCode: Integer;
begin
  vWipeout := TsgCADWipeout(FEntity);
  Inc2(APBit, 103); // ??
  vCount := 1;
  vCode := 1;
  while Comp2(APBit, FDataEnd) and (vCount <> 0) and (vCode <> 0) do
  begin
    vCode := ReadBS(APBit);
    case vCode of
      10: vWipeout.Point := Read3D(APBit);
      11: vWipeout.UVector := Read3D(APBit);
      12: vWipeout.VVector := Read3D(APBit);
      13: vWipeout.Size := Read3D(APBit);
      14:
        begin
          vPoint := Read3D(APBit);
          vWipeout.AddPoint(vPoint.X, vPoint.Y);
          Dec(vCount);
        end;
      70: vWipeout.Flags := ReadBS(APBit);
      71: vWipeout.ClippingBoundaryType := ReadBS(APBit);
      91: vCount := ReadBL(APBit);
      100:
        begin
          FStringReader.ReadText; // 'cn:AcDb:classname'
          FStringReader.ReadText; // 'AcDb:classname'
        end;
      280: vWipeout.UseClipping := (ReadBS(APBit) = 1);
      281..283: ReadBS(APBit); //Brightness value; Contrast value; Fade value
      290: if Reader.Version > acR2007 then SeekGeneral(APBit, [seB]);
      340:;
      360:;
    end;
  end;
end;

{TdwgAcadTable}

{protected}

procedure TdwgAcadTable.ReadData(var APBit: TsgInt64);
begin
  inherited ReadData(APBit);
  FBlockRecord := ReadID(APBit);
  FTableStyle := ReadID(APBit);
end;

procedure TdwgAcadTable.ReadEntData(var APBit: TsgInt64);
begin
  TsgDXFAcadTable(FEntity).Point := Read3D(APBit);
  inherited ReadEntData(APBit);
end;

procedure TdwgAcadTable.References(AReader: TdwgReader);
{$IFDEF SG_DWG_IMPORT_ACAD_TABLE}
var
  vTableStyle: TsgDXFEntity;
{$ENDIF}
begin
  inherited References(Reader);
  TsgDXFAcadTable(FEntity).BlockRecord :=
    TsgDXFBlockRecord(AReader.ObjByHandle(FBlockRecord, TsgDXFBlockRecord));
{$IFDEF SG_DWG_IMPORT_ACAD_TABLE}
  vTableStyle := AReader.ObjByHandle(FTableStyle, TsgDXFAcadTableStyle, Self);
  TsgDXFAcadTable(FEntity).Style := TsgDXFAcadTableStyle(vTableStyle);
{$ENDIF}
end;

{ TdwgAcadTableStyle }

function TdwgAcadTableStyle.GetOwner(AReader: TdwgReader): TsgDXFEntity;
begin
  Result := inherited GetOwner(AReader);
  if not Assigned(Result) then
    Result := AReader.Dictionary[cnstObjectsTABLESTYLES];
end;

procedure TdwgAcadTableStyle.ReadData(var APBit: TsgInt64);
var
  I: Integer;
  J: TsgAcadTableCellType;
  vAcTblStyle: TsgDXFAcadTableStyle;
  vCellStyle: TsgAcadTableCellStyle;
  vSmallInt: Smallint;

  function ReadCMC2000(var ABitPos: TsgInt64): TsgColorCAD;
  var
    vColor: Cardinal;
  begin
    if Reader.Version < acR2004 then
    begin
      vColor := ReadBS(ABitPos);
      if (vColor = 0) and (Reader.Version = acR2000) then
        Result := ReadCMCSection(Self, ABitPos)
      else
        if vColor > $FFF then
          Result := ReadENCSection(vColor, Self, ABitPos)
        else
          Result := MakeColorCAD(acIndexColor, vColor);
    end
    else
      Result := ReadColorCAD(Self, ABitPos);
  end;

begin
  { TODO: TdwgAcadTableStyle.ReadData ac2010 }
  if Reader.Version >= acR2010 then
    Exit;
  ReadObjHeader(APBit);
  vAcTblStyle := TsgDXFAcadTableStyle(FEntity);
  vAcTblStyle.Description := FStringReader.ReadText;
  vAcTblStyle.FlowDirection := ReadBS(APBit);
  vAcTblStyle.Flags := ReadBS(APBit);
  vAcTblStyle.HorzCellMargin := ReadBD(APBit);
  vAcTblStyle.VertCellMargin := ReadBD(APBit);
  vAcTblStyle.TitleSuppressed := ReadBit(APBit) <> 0;
  vAcTblStyle.HeaderSuppressed := ReadBit(APBit) <> 0;
  for J := Low(TsgAcadTableCellType) to High(TsgAcadTableCellType) do
  begin
    vCellStyle := vAcTblStyle.CellStyle[J];
    vCellStyle.TextHeight := ReadBD(APBit);
    vCellStyle.CellAlignment := ReadBS(APBit);
    vCellStyle.TextColor := ReadCMC2000(APBit);
    vCellStyle.FillColor := ReadCMC2000(APBit);
    vCellStyle.BkColorOn := ReadBit(APBit) <> 0;
    for I := 0 to vCellStyle.BorderCount - 1 do
    begin
      vSmallInt := ReadBS(APBit);
      if vSmallInt < 0 then
        vCellStyle.BorderLineWeight[I] := vSmallInt
      else
        vCellStyle.BorderLineWeight[I] := 0.01 * vSmallInt;
      vCellStyle.BorderVisible[I] := ReadBit(APBit) <> 0;
      vCellStyle.BorderColor[I] := ReadCMC2000(APBit);
    end;
    if Reader.Version >= acR2007 then
      SeekGeneral(APBit, [seBS, seBS]);
  end;
  ReadHandleRefs(APBit);
  FDataTextStyle := ReadID(APBit);
  FTitleTextStyle := ReadID(APBit);
  FHeaderTextStyle := ReadID(APBit);
end;

procedure TdwgAcadTableStyle.References(AReader: TdwgReader);
var
  vAcTblStyle: TsgDXFAcadTableStyle;
begin
  inherited References(AReader);
  { TODO: TdwgAcadTableStyle.References ac2010 }
  if Reader.Version >= acR2010 then
    Exit;
  vAcTblStyle := TsgDXFAcadTableStyle(FEntity);
  vAcTblStyle.CellStyle[cttData].TextStyle :=
    TsgDXFStyle(AReader.ObjByHandle(FDataTextStyle, TsgDXFStyle));
  vAcTblStyle.CellStyle[cttTitle].TextStyle :=
    TsgDXFStyle(AReader.ObjByHandle(FTitleTextStyle, TsgDXFStyle));
  vAcTblStyle.CellStyle[cttHeader].TextStyle :=
    TsgDXFStyle(AReader.ObjByHandle(FHeaderTextStyle, TsgDXFStyle));
end;

{TdwgACISEntity}

{protected}

procedure TdwgACISEntity.ReadEntData(var APBit: TsgInt64);
const
  cnstEndAutocad: AnsiString = 'End'#14#2'of'#14#4'ACIS'#13#4'data';
  cnstEntSpatial: AnsiString = 'End-of-ACIS-data';

  function LoadSatFromMemory(Mem: Pointer; Size: Integer): Boolean;
  begin
    TsgDXFACISEntity(FEntity).Delimiter := ' ';
    TsgDXFACISEntity(FEntity).LoadFromMemory(Mem, Size, False);
    Result := TsgDXFACISEntity(FEntity).ProprietaryData.Text <> '';
    TsgDXFACISEntity(FEntity).IncorrectAttribsChecked := True;
  end;

var
  vString, vBuffer: AnsiString;
  N, vStartPos, vLength, vLenEnd, vIndex: Integer;
  vCode: Byte;
  vEncoded: Boolean;
  vEntry: TsgDataSegmentEntry;
begin
  vBuffer := '';
  try
    TsgDXFACISEntity(FEntity).ProprietaryData.Text := '';
    vEncoded := ReadBB(APBit) <> 0;
    // if not Encoded then Exit;// don't read binary ACIS
    TsgDXFACISEntity(FEntity).Encoded := vEncoded;
    if (FReader.Version >= acR2013) and Assigned(FReader.FSegmentedFile) then
    begin
      //checks DWG Version
      //ReadBL NumMaterials
      //ReadBit
      vIndex := FReader.FSegmentedFile.IndexOf(FHandle);
      if vIndex < 0 then Exit;
      vEntry := FReader.FSegmentedFile[vIndex];
      if vEntry.EntryType <> etACISBin then Exit;
      if not LoadSatFromMemory(vEntry.Data, vEntry.DataSize) then Exit;
    end
    else
    begin
      if ReadRC(APBit) <> 64 then
        Exit;
      SeekGeneral(APBit,[seBD]);
      vStartPos := 1;
      while True do
      begin
        if vEncoded then
          N := ReadBL(APBit)
        else
          N := 1024;
        if N = 0 then
          Break;
        vString := '';
        while N > 0 do
        begin
          Dec(N);
          vCode := ReadRC(APBit);
          if not vEncoded then
            vString := vString + AnsiChar(Chr(vCode))
          else
          begin
            case vCode of
              9: vString := vString + ' ';
              Byte('^'): vString := vString + AnsiChar(Chr(vCode)) + AnsiChar(' ');
              else
                vString := vString + AnsiChar(Chr(vCode));
            end;
          end;
        end;
        vBuffer := vBuffer + vString;
        if not vEncoded then
        begin
          vLenEnd := Length(cnstEndAutocad);
          N := StringPosA(cnstEndAutocad, vBuffer, vStartPos);
          if N = 0 then
          begin
            N := StringPosA(cnstEntSpatial, vBuffer, vStartPos);
            vLenEnd := Length(cnstEntSpatial);
          end;
          if N > 0 then
          begin
            Dec2(APBit, (Length(vBuffer)-N-vLenEnd) shl 3);
            SetLength(vBuffer, N-1);
          end;
        end;
        vLength := Length(vBuffer);
        if vLength > Length(cnstEndAutocad) then
          vStartPos := vLength - Length(cnstEndAutocad) - 1;
        if N > 0 then Break;
      end;
      if vEncoded then
        TsgDXFACISEntity(FEntity).ProprietaryData.Text := string(vBuffer)
      else
        if not LoadSatFromMemory(@vBuffer[1], Length(vBuffer)) then Exit;
    end;
  finally
    inherited ReadEntData(APBit);
  end;
end;

{TdwgArc}

{protected}

procedure TdwgArc.ReadEntData(var APBit: TsgInt64);
begin
  inherited ReadEntData(APBit);
  TsgDXFArc(FEntity).StartAngle := ReadBD(APBit) * f180DividedByPi;
  TsgDXFArc(FEntity).EndAngle := ReadBD(APBit) * f180DividedByPi;
end;

{TdwgAttdef}

{protected}

procedure TdwgAttdef.ReadPrompt(var APBit: TsgInt64);
begin
  if FReader.Version >= acR2010 then
    SeekGeneral(APBit, [seRC]);
  FStringReader.ReadText;
end;

procedure TdwgAttdef.References(AReader: TdwgReader);
begin
  inherited References(AReader);
  TsgDXFAttdef(FEntity).Flags := FFlags;
  TsgDXFAttdef(FEntity).LockPosition := FLockPosition;
end;

procedure TdwgAttdef.ApplyValue;
begin
  TsgDXFAttdef(FEntity).Tag := FTag;
  TsgDXFAttdef(FEntity).Value := FText;
end;

procedure TdwgAttdef.ReadEntData(var APBit: TsgInt64);
begin
  inherited ReadEntData(APBit);
  if FReader.Version > acR2007 then
    SeekGeneral(APBit, [seRC]);//raise an exception if result is not zero
  FTag := FStringReader.ReadText;
  SeekGeneral(APBit, [seBS]);
  FFlags := ReadRC(APBit);
  if FReader.Version >= acR2007 then
    FLockPosition := ReadBit(APBit) <> 0;
  ReadPrompt(APBit);
end;

{TdwgAttrib}

{protected}

procedure TdwgAttrib.ReadPrompt(var APBit: TsgInt64);
begin
end;

{TdwgDimension}

{protected}

procedure TdwgDimension.ReadData(var APBit: TsgInt64);
begin
  inherited ReadData(APBit);
  FStyle := FBlockRecord;
  FBlockRecord := ReadID(APBit);
end;

procedure TdwgDimension.ReadEntData(var APBit: TsgInt64);
var
  vDimension: TsgDXFDimension;
  vFlags: Integer;
begin
  vDimension := TsgDXFDimension(FEntity);
  if Reader.Version > acR2007 then
    SeekGeneral(APBit, [seRC]); //if ReadRC(APBit) <> 0 then raise
  vDimension.Extrusion := Read3D(APBit);
  vDimension.MiddlePoint := Read2RD(APBit);
  SeekGeneral(APBit,[seBD]); // Elevation
  vFlags := ReadRC(APBit);
  if vFlags and 1 = 0 then
    vDimension.Flags := 128;
  if vFlags and 2 <> 0 then
    vDimension.Flags := vDimension.Flags or 32;
  vDimension.TextOverride := FStringReader.ReadText;
  SeekGeneral(APBit, [se2D]);
  vDimension.Scale := Read3D(APBit);
  vDimension.Angle := ReadBD(APBit) * f180DividedByPi;
  if Reader.Version >= acR2000 then
    SeekGeneral(APBit, [seBS,seBS,se2D]);
  if Reader.Version >= acR2007 then //b73
    SeekGeneral(APBit, [seB,seB,seB]);
  vDimension.Point := Read2RD(APBit);
end;

procedure TdwgDimension.References(AReader: TdwgReader);
begin
  inherited References(Reader);
  TsgDXFDimension(FEntity).Style :=
    TsgDXFDimensionStyle(AReader.ObjByHandle(FStyle, TsgDXFDimensionStyle));
end;

{TdwgImageEnt}

{protected}

procedure TdwgImageEnt.ReadData(var APBit: TsgInt64);
begin
  inherited ReadData(APBit);
  FImageDef := ReadID(APBit);
end;

procedure TdwgImageEnt.References(AReader: TdwgReader);
begin
  inherited References(Reader);
  TsgDXFImageEnt(FEntity).ImageDef :=
    TsgDXFImageDef(AReader.ObjByHandle(FImageDef, TsgDXFImageDef));
end;

{TdwgMesh}

{protected}

procedure TdwgPolyMesh.ReadEntData(var APBit: TsgInt64);
var
  vPolyline: TsgDXFPolyline;
  I: Integer;
begin
  vPolyline := TsgDXFPolyline(FEntity);
  vPolyline.Flags := ReadBS(APBit);
  vPolyline.Closed := vPolyline.Flags and 1 <> 0;
  SeekGeneral(APBit, [seBS]);
  vPolyline.MeshM := ReadBS(APBit);
  vPolyline.MeshN := ReadBS(APBit);
  I := ReadBS(APBit);
  if I <> 0 then
    vPolyline.MeshM := I;
  I := ReadBS(APBit);
  if I <> 0 then
    vPolyline.MeshN := I;
  if Reader.Version >= acR2004 then
    FSubEnts := ReadBL(APBit);
end;

{TdwgMInsert}

{protected}

procedure TdwgMInsert.ReadEntData(var APBit: TsgInt64);
var
  vMInsert: TsgCADMInsert;
begin
  inherited ReadEntData(APBit);
  vMInsert := TsgCADMInsert(FEntity);
  vMInsert.NumCols := ReadBS(APBit);
  vMInsert.NumRows := ReadBS(APBit);
  vMInsert.ColSpacing := ReadBD(APBit);
  vMInsert.RowSpacing := ReadBD(APBit);
end;

{TdwgPFace}

{protected}

procedure TdwgPFace.ReadEntData(var APBit: TsgInt64);
var
  vPolyline: TsgDXFPolyline;
begin
  vPolyline := TsgDXFPolyline(FEntity);
  vPolyline.Flags := 64;
  vPolyline.MeshM := ReadBS(APBit);
  vPolyline.MeshN := ReadBS(APBit);
  if Reader.Version >= acR2004 then
    FSubEnts := ReadBL(APBit);
end;

{TdwgPolyline3D}

{protected}

procedure TdwgPolyline3D.ReadEntData(var APBit: TsgInt64);
begin
  SeekGeneral(APBit, [seRC]);
  TsgDXFPolyline(FEntity).Polyline3D := True;
  TsgDXFPolyline(FEntity).Closed := ReadRC(APBit) and 1 <> 0;
  if Reader.Version >= acR2004 then
    FSubEnts := ReadBL(APBit);
end;

{TdwgProxy}

{protected}

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

destructor TdwgProxy.Destroy;
begin
  FList.Free;
  FreeRecordList(FProps);
  inherited Destroy;
end;

procedure TdwgProxy.ReadEntProxyData(var APBit: TsgInt64);
var
  ProxyReader: IProxyReader;
begin
  if FReader.Version > acR2007 then //Length of the proxy data
    SeekGeneral(APBit, [seUInt64])
  else
    SeekGeneral(APBit,[seRL]);
  ProxyReader := TDWGProxyReader.Create(@APBit, Reader.Version);
  DXFConv.ReadProxyData(FList, FProps, FReader.Conv, ProxyReader);
end;

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

{TdwgShape}

{protected}

procedure TdwgShape.ReadEntData(var APBit: TsgInt64);
begin
  FPoint := Read3D(APBit);
  FHeight := ReadBD(APBit);// Scale
  FRotation := ReadBD(APBit) * f180DividedByPi;
  FScale := ReadBD(APBit);// Width factor
  FObliqueAngle := ReadBD(APBit) * f180DividedByPi;
  SeekGeneral(APBit,[seBD]);
  FShapeNumber := ReadBS(APBit);
  FExtrusion := Read3D(APBit);
end;

procedure TdwgShape.References(AReader: TdwgReader);
begin
  inherited References(AReader);
  TsgDXFShape(FEntity).ShapeNumber := FShapeNumber;
end;

{TdwgVertex2D}

{protected}

procedure TdwgVertex2D.ReadEntData(var APBit: TsgInt64);
var
  vVertex: TsgDXFVertex;
  vStartWidth: Double;
begin
  inherited ReadEntData(APBit);
  vVertex := TsgDXFVertex(FEntity);
  vStartWidth := ReadBD(APBit);
  if vStartWidth < 0.0 then
  begin
    vVertex.StartWidth := Abs(vStartWidth);
    vVertex.EndWidth := vVertex.StartWidth;
  end
  else
  begin
    vVertex.StartWidth := vStartWidth;
    vVertex.EndWidth := ReadBD(APBit);
  end;
  vVertex.Bulge := ReadBD(APBit);
  if FReader.Version >= acR2010 then
    SeekGeneral(APBit, [seBL]); // Vertex ID
  SeekGeneral(APBit, [seBD]);
end;

{TdwgVertexFace}

{protected}

procedure TdwgVertexFace.ReadEntData(var APBit: TsgInt64);
var
  vVertex: TsgDXFVertex;
begin
  vVertex := TsgDXFVertex(FEntity);
  vVertex.Flags := 128;
  vVertex.PolyFaceVertexIndex1 := ReadBS(APBit);
  vVertex.PolyFaceVertexIndex2 := ReadBS(APBit);
  vVertex.PolyFaceVertexIndex3 := ReadBS(APBit);
  vVertex.PolyFaceVertexIndex4 := ReadBS(APBit);
end;

{TdwgDimAligned}

{protected}

procedure TdwgDimAligned.ReadEntData(var APBit: TsgInt64);
var
  vDimension: TsgDXFDimension;
begin
  vDimension := TsgDXFDimension(FEntity);
  inherited ReadEntData(APBit);
  vDimension.LinDefPoint1 := Read3D(APBit);
  vDimension.LinDefPoint2 := Read3D(APBit);
  vDimension.DefPoint := Read3D(APBit);
  SeekGeneral(APBit,[seBD]);
  vDimension.Flags := vDimension.Flags or 1;
end;

{TdwgDimAngular2L}

{protected}

procedure TdwgDimAngular2L.ReadEntData(var APBit: TsgInt64);
var
  vDimension: TsgDXFDimension;
begin
  vDimension := TsgDXFDimension(FEntity);
  inherited ReadEntData(APBit);
  vDimension.ArcDefPoint := Read2RD(APBit);
  vDimension.LinDefPoint1 := Read3D(APBit);
  vDimension.LinDefPoint2 := Read3D(APBit);
  vDimension.RadDefPoint := Read3D(APBit);
  vDimension.DefPoint := Read3D(APBit);
  vDimension.Flags := vDimension.Flags or 2;
end;

{TdwgDimAngular3P}

{protected}

procedure TdwgDimAngular3P.ReadEntData(var APBit: TsgInt64);
var
  vDimension: TsgDXFDimension;
begin
  vDimension := TsgDXFDimension(FEntity);
  inherited ReadEntData(APBit);
  vDimension.DefPoint := Read3D(APBit);
  vDimension.LinDefPoint1 := Read3D(APBit);
  vDimension.LinDefPoint2 := Read3D(APBit);
  vDimension.RadDefPoint := Read3D(APBit);
  vDimension.Flags := vDimension.Flags or 5;
end;

{TdwgDimLinear}

{protected}

procedure TdwgDimLinear.ReadEntData(var APBit: TsgInt64);
var
  vDimension: TsgDXFDimension;
begin
  vDimension := TsgDXFDimension(FEntity);
  inherited ReadEntData(APBit);
  vDimension.LinDefPoint1 := Read3D(APBit);
  vDimension.LinDefPoint2 := Read3D(APBit);
  vDimension.DefPoint := Read3D(APBit);
  SeekGeneral(APBit, [se2D]);
end;

{TdwgDimOrdinate}

{protected}

procedure TdwgDimOrdinate.ReadEntData(var APBit: TsgInt64);
var
  vDimension: TsgDXFDimension;
  vFlags: Integer;
begin
  vDimension := TsgDXFDimension(FEntity);
  inherited ReadEntData(APBit);
  vDimension.DefPoint := Read3D(APBit);
  vDimension.LinDefPoint1 := Read3D(APBit);
  vDimension.LinDefPoint2 := Read3D(APBit);
  vFlags := ReadRC(APBit);
  if vFlags and 1 <> 0 then
    vDimension.Flags := vDimension.Flags or 64;
  vDimension.Flags := vDimension.Flags or 6;
end;

{TdwgDimRadius}

{protected}

procedure TdwgDimRadius.ReadEntData(var APBit: TsgInt64);
var
  vDimension: TsgDXFDimension;
begin
  vDimension := TsgDXFDimension(FEntity);
  inherited ReadEntData(APBit);
  vDimension.DefPoint := Read3D(APBit);
  vDimension.RadDefPoint := Read3D(APBit);
  SeekGeneral(APBit,[seBD]);
  SetFlags;
end;

procedure TdwgDimRadius.SetFlags;
begin
  TsgDXFDimension(FEntity).Flags := TsgDXFDimension(FEntity).Flags or 4;
end;

{TdwgDimDiameter}

{protected}

procedure TdwgDimDiameter.SetFlags;
begin
  TsgDXFDimension(FEntity).Flags := TsgDXFDimension(FEntity).Flags or 3;
end;

{ TdwgDictionary }

destructor TdwgDictionary.Destroy;
begin
  FNames.Free;
  inherited Destroy;
end;

function TdwgDictionary.GetOwner(AReader: TdwgReader): TsgDXFEntity;
begin
  Result := inherited GetOwner(AReader);
  if Assigned(Result) then
  begin
    if Result.Handle <> AReader.FNamedObjects then
    begin
      TsgDXFEntityAccess(FEntity).SetOwner(Reader.Conv.Sections[csObjects]);
      Result.Dictionary := FEntity;
    end;
    if (Result.ClassType = TsgDXFBlockRecord) or (Result.ClassType = TsgDXFLayout) or
       (Result.ClassType = TsgDXFLayer) or (FOwner = AReader.FLayoutsDict) or
       (FOwner = AReader.FLayerControl) then
      Result := AReader.Conv.Sections[csObjects];
  end
  else
  begin
    if FReactors.Count > 0 then
      Result := AReader.ObjByHandle(FReactors.First, nil);
    if not Assigned(Result) then
      Result := AReader.Conv.Sections[csObjects];
  end;
end;

procedure TdwgDictionary.NewObject(ACode: Integer; AHandle: UInt64;
  var AObj: TdwgObject);
begin
  inherited NewObject(ACode, AHandle, AObj);
  if Assigned(AObj) then
  begin
    AObj.FEntity.Name := FNames[FChildIndex];
    if (FHandle = Reader.FMaterialDict) and AObj.InheritsFrom(TdwgMaterial) then
    begin
      TdwgMaterial(AObj).FOwnerDictionary := Self;
      TdwgMaterial(AObj).FOwnerObject := FEntity;
      TdwgMaterial(AObj).FOwner := FHandle;
    end;
  end;
end;

function TdwgDictionary.OwnerAdd(AOwner: TsgDXFEntity): Integer;
begin
  if Assigned(AOwner) and not AOwner.InheritsFrom(TsgDXFTable) then
    AOwner := Reader.Conv.Sections[csObjects];
  Result := inherited OwnerAdd(AOwner);
end;

procedure TdwgDictionary.PerformName;
begin
  if FHandle = Reader.FLayoutsDict then
    FEntity.Name := sAcadLayoutDictionary
  else
  if FHandle = Reader.FMLStylesDict then
    FEntity.Name := sAcadMLineStyleDictionary
  else
  if FHandle = Reader.FImageDefDict then
    FEntity.Name := sAcadImageDict
  else
  if FHandle = Reader.FVariableDict then
    FEntity.Name := sAcDbVariableDictionary
  else
  if FHandle = Reader.FColors then
    FEntity.Name := sAcadColor
  else
  if FHandle = Reader.FMaterialDict then
    FEntity.Name := sAcadMaterialDictionary
  else
    if FEntity.Name = '' then
      FEntity.Name := cnstDictionary;
end;

procedure TdwgDictionary.ReadData(var APBit: TsgInt64);
var
  I: Integer;
  vCloningFlag: Integer;
  //vHardOwnerFlag: Integer;
begin
  ReadObjHeader(APBit);
  FSubEnts := ReadBL(APBit);
  if Reader.Version = acR14 then
    SeekGeneral(APBit, [seRC]);
  if Reader.Version >= acR2000 then
  begin
    vCloningFlag := ReadBS(APBit);
    SeekGeneral(APBit, [seRC]);   //vHardOwnerFlag := ReadRC(APBit)
    if vCloningFlag = 256 then
      SeekGeneral(APBit, [seRC]); //?? not documented
  end;
  if FSubEnts > 0 then
  begin
    FNames := TsgStringList.Create;
    FChildren := TsgInt64List.Create(0, FSubEnts);
  end;
  for I := 0 to FSubEnts - 1 do
    FNames.AddObject(FStringReader.ReadText, TObject(I));
  ReadHandleRefs(APBit);
  ReadSubEntIDs(APBit);
end;

procedure TdwgDictionary.ReadSubEntIDs(var APBit: TsgInt64;
  const AFlags: Integer);
var
  I: Integer;

  function UpdateHandle(var AHandle: UInt64; const AName: string): Integer;
  begin
    if AHandle = cnstBadHandle then
    begin
      Result := FNames.IndexOf(AName);
      if Result >= 0 then
        AHandle := FChildren[Result];
    end
    else
      Result := -1;
  end;

begin
  for I := 0 to FSubEnts - 1 do
    FChildren.Add(ReadID(APBit));
  if FHandle = Reader.FNamedObjects then
  begin
    UpdateHandle(Reader.FLayoutsDict, sAcadLayoutDictionary);
    UpdateHandle(Reader.FMLStylesDict, sAcadMLineStyleDictionary);
    UpdateHandle(Reader.FImageDefDict, sAcadImageDict);
    UpdateHandle(Reader.FVariableDict, sAcDbVariableDictionary);
    UpdateHandle(Reader.FColors, sAcadColor);
    UpdateHandle(Reader.FMaterialDict, sAcadMaterialDictionary);
  end;
  PerformName;
end;

procedure TdwgDictionary.ReadSubEnts(AReader: TdwgReader);
begin
  ReadSubEntsR2004(AReader);
end;

procedure TdwgDictionary.References(AReader: TdwgReader);
var
  I: Integer;
  vEnt: TsgDXFEntity;
begin
  inherited References(AReader);
  if Assigned(FChildren) then
    if FEntity.Handle <> AReader.FLayoutsDict then
      for I := 0 to FChildren.Count - 1 do
      begin
        vEnt := FEntity.FindEntByHandle(FChildren[I]);
        if Assigned(vEnt) then
          vEnt.Name := FNames[I];
      end;
  PerformName;
end;

{ TdwgDbColor }

function TdwgDbColor.GetOwner(AReader: TdwgReader): TsgDXFEntity;
begin
  Result := inherited GetOwner(AReader);
  if not Assigned(Result) then
    Result := AReader.Conv.Sections[csObjects];
end;

procedure TdwgDbColor.ReadData(var APBit: TsgInt64);
var
  vColorCAD: TsgColorCAD;
begin
  ReadObjHeader(APBit);
  vColorCAD := ReadColorCAD(Self, APBit);
  //vColorCAD.AlbumString := Self.FColorName;
  FEntity.ColorCAD := vColorCAD;
  ReadHandleRefs(APBit);
end;

{ TdwgAppID }

procedure TdwgAppID.ReadData(var APBit: TsgInt64);
begin
  inherited ReadData(APBit);
  FEntity.Name := FEntryName;
  TsgDXFPenTableItem(FEntity).Flags := FFlags;
  SeekGeneral(APBit, [seRC]); // Unknown
  ReadHandleRefs(APBit);
end;

{ TdwgLTControl }

procedure TdwgLTControl.ReadData(var APBit: TsgInt64);
var
  I: Integer;
begin
  InitializeTable(csLTypes, cnstTableLTYPE);
  inherited ReadData(APBit);
  FByBlock := ReadID(APBit); // BYBLOCK hard owner
  FByLayer := ReadID(APBit); // BYLAYER hard owner

  if not Assigned(FChildren) then
    FChildren := TsgInt64List.Create;
  I := FChildren.IndexOf(Reader.FLTContinious);
  if I < 0 then
    FChildren.Add(Reader.FLTContinious);
  I := FChildren.IndexOf(FByBlock);
  if I < 0 then
    FChildren.Add(FByBlock);
  I := FChildren.IndexOf(FByLayer);
  if I < 0 then
    FChildren.Add(FByLayer);
end;

procedure TdwgLTControl.References(AReader: TdwgReader);

  function PopEntByHandle(const AHandle: UInt64): TsgDXFEntity;
  begin
    Result := FEntity.FindEntByHandle(AHandle);
    if Assigned(Result) then
    begin
      FEntity.RemoveEntity(Result);
      FEntity.InsertEntity(0, Result);
    end;
  end;

begin
  inherited References(AReader);
  TsgDXFGroupAccess(FEntity).SortEntByHandle;
  PopEntByHandle(AReader.FLTContinious);
  PopEntByHandle(FByLayer);
  PopEntByHandle(FByBlock);
end;

{ TdwgLayersControl }

procedure TdwgLayerControl.ReadData(var APBit: TsgInt64);
begin
  InitializeTable(csLayers, cnstTableLAYER);
  inherited ReadData(APBit);
end;

procedure TdwgLayerControl.References(AReader: TdwgReader);
var
  vLayer0: TsgDXFEntity;
begin
  inherited References(AReader);
  TsgDXFGroupAccess(FEntity).SortEntByHandle;
  vLayer0 := FEntity.FindEntByName('0');
  if not Assigned(vLayer0) then
  begin
    vLayer0 := TsgDXFLayer.Create;
    vLayer0.Name := '0';
    TsgDXFConverterAccess(AReader.Conv).SetHandle(vLayer0);
  end
  else
    FEntity.RemoveEntity(vLayer0);
  FEntity.InsertEntity(0, vLayer0);
end;

{ TdwgStyleControl }

procedure TdwgStyleControl.ReadData(var APBit: TsgInt64);
begin
  InitializeTable(csStyles, cnstTableSTYLE);
  inherited ReadData(APBit);
end;

procedure TdwgStyleControl.References(AReader: TdwgReader);
var
  I, J: Integer;
  S: string;
begin
  inherited References(AReader);
  for I := 0 to FEntity.Count - 1 do
  begin
    S := TsgDXFStyle(FEntity[I]).GetPrimaryFontName;
    if S <> '' then
      AReader.FStylesByFont.AddObject(S, FEntity[I]);
    S := TsgDXFStyle(FEntity[I]).FontName;
    if S <> '' then
      AReader.FStylesByFont.AddObject(S, FEntity[I]);
    S := FEntity[I].Name;
    if S = '' then
    begin
      J := 0;
      repeat
        S := 'SHAPE' + IntToStr(J);
        Inc(J);
      until FEntity.FindEntByName(S) = nil;
      FEntity[I].Name := S;
    end;
  end;
end;

{ TDWGProxyReader }

constructor TDWGProxyReader.Create(APos: Pointer; AVersion: TsgDWGVersion);
begin
  FPos := APos;
  GetMem(FStack, SizeOf(TsgInt64));
  PsgInt64(FStack)^ := PsgInt64(FPos)^;
end;

destructor TDWGProxyReader.Destroy;
begin
  FreeMem(FStack, SizeOf(TsgInt64));
  inherited Destroy;
end;

procedure TDWGProxyReader.PopPosition;
begin
  PsgInt64(FPos)^ := PsgInt64(FStack)^;
end;

procedure TDWGProxyReader.PushPosition;
begin
  PsgInt64(FStack)^ := PsgInt64(FPos)^;
end;

function TDWGProxyReader.ReadByte: Byte;
begin
  Result := ReadRC(PsgInt64(FPos)^);
end;

procedure TDWGProxyReader.ReadBytes(var Dest; const ACount: UInt64);
begin
  ReadBytesCustom(PsgInt64(FPos)^, Dest, ACount);
end;

function TDWGProxyReader.ReadDouble: Double;
begin
  Result := ReadRD(PsgInt64(FPos)^);
end;

function TDWGProxyReader.ReadHandle: UInt64;
begin
  ReadBytesDoublePair(PsgInt64(FPos)^, Result, 2);
end;

function TDWGProxyReader.ReadInteger: Integer;
begin
  Result := ReadRL(PsgInt64(FPos)^);
end;

function TDWGProxyReader.ReadSmallInt: SmallInt;
begin
  Result := ReadRS(PsgInt64(FPos)^);
end;

function TDWGProxyReader.ReadWord: Word;
begin
  Result := Word(ReadRS(PsgInt64(FPos)^));
end;

procedure TDWGProxyReader.Seek(ASize: Integer);
begin
  Inc2(PsgInt64(FPos)^, ASize shl 3);
end;

{ TdwgBlockControl }

procedure TdwgBlockControl.NewObject(ACode: Integer; AHandle: UInt64;
  var AObj: TdwgObject);
begin
  inherited NewObject(ACode, AHandle, AObj);
  if AHandle = Reader.FModel.BlockRecord.Handle then
  begin
    TsgDXFBlockRecordAccess(AObj.FEntity).Block.Free;
    AObj.FEntity := Reader.FModel.BlockRecord;
  end
  else
  begin
    if AHandle = Reader.FPaper.BlockRecord.Handle then
    begin
      TsgDXFBlockRecordAccess(AObj.FEntity).Block.Free;
      AObj.FEntity := Reader.FPaper.BlockRecord;
    end;
  end;
end;

procedure TdwgBlockControl.ReadData(var APBit: TsgInt64);
var
  I: Integer;
begin
  InitializeTable(csBlockRecords, cnstTableBLOCK_RECORD);
  TsgDXFEntityAccess(FEntity).SetConverter(Reader.Conv);
  inherited ReadData(APBit);
  FModel := ReadID(APBit);
  FPaper := ReadID(APBit);

  if FModel = cnstBadHandle then
    FModel := Reader.FModel.BlockRecord.Handle;
  if FPaper = cnstBadHandle then
    FPaper := Reader.FPaper.BlockRecord.Handle;

  if not Assigned(FChildren) then
    FChildren := TsgInt64List.Create;

  I := FChildren.IndexOf(FModel);
  if I < 0 then
    FChildren.Add(FModel);
  I := FChildren.IndexOf(FPaper);
  if I < 0 then
    FChildren.Add(FPaper);
end;

{ TdwgAppIDControl }

procedure TdwgAppIDControl.ReadData(var APBit: TsgInt64);
begin
  InitializeTable(Succ(High(TConvSection)), cnstAPPID);
  inherited ReadData(APBit);
end;

procedure TdwgAppIDControl.References(AReader: TdwgReader);
var
  vAppIDEnt: TsgDXFEntity;
begin
  inherited References(AReader);
  vAppIDEnt := FEntity.FindEntByName(sACADXDataAppName);
  if Assigned(vAppIDEnt) then
    AReader.FACADAppID := vAppIDEnt.Handle;
  vAppIDEnt := FEntity.FindEntByName(GetAppID);
  if Assigned(vAppIDEnt) then
    AReader.FAppID := vAppIDEnt.Handle;
  vAppIDEnt := FEntity.FindEntByName('AcadAnnotative');
  if Assigned(vAppIDEnt) then
    AReader.FAnnotativeAppID := vAppIDEnt.Handle;
end;

{ TdwgDimStyleControl }

procedure TdwgDimStyleControl.ReadData(var APBit: TsgInt64);
var
  I: Integer;
  vHandle: UInt64;
  vHCode: Byte;
begin
  InitializeTable(csDimStyles, cnstTableDIMSTYLE);
  if Reader.Version > acR2004 then
    inherited ReadData(APBit)
  else
  begin
    ReadObjHeader(APBit);
    FSubEnts := ReadBL(APBit);
    ReadID(APBit);
    ReadID(APBit); // NULL (soft pointer)
    FChildren := TsgInt64List.Create;
    I := FSubEnts;
    repeat
      vHandle := ReadID(APBit, vHCode);
      case vHCode of
        cntDWGObjHandleSoftPointer: FReactors.Add(vHandle);
        cntDWGObjHandleSoftOwner:
          begin
            FChildren.Add(vHandle);
            Dec(I);
          end;
      end;
    until (vHCode in [cntDWGObjHandleHardOwner, cntDWGObjHandleHardPointer]) or (I <= 0);
    while (I > 0) and (vHCode <> cntDWGObjHandleHardPointer) do
    begin
      vHandle := ReadID(APBit, vHCode);
      case vHCode of
        cntDWGObjHandleSoftOwner:
          begin
            FChildren.Add(vHandle);
            Dec(I);
          end;
      end;
    end;
    if FChildren.Count <= 0 then
      FreeAndNil(FChildren);
  end;
end;

{ TdwgVPortControl }

procedure TdwgVPortControl.ReadData(var APBit: TsgInt64);
begin
  InitializeTable(csVPorts, cnstTableVPORT);
  inherited ReadData(APBit);
end;

{ TdwgDictionaryVar }

procedure TdwgDictionaryVar.ReadData(var APBit: TsgInt64);
begin
  ReadObjHeader(APBit);
  TsgDXFDictionaryVar(FEntity).IntVal := ReadRC(APBit);
  TsgDXFDictionaryVar(FEntity).Value := FStringReader.ReadText;
  ReadHandleRefs(APBit);
end;

{ TdwgDataBase }

function TdwgDataBase.GetChildren(Index: Integer): UInt64;
begin
  Result := Reader.FObjMap.MapElement[Index].Handle;
end;

function TdwgDataBase.GetChildrenCount: Integer;
begin
  Result := Reader.FObjMap.Count + 1;
end;

procedure TdwgDataBase.ReadData(var APBit: TsgInt64);
begin
end;

procedure TdwgDataBase.ReadSubEnts(AReader: TdwgReader);
var
  C: Integer;
  vOwner: TsgDXFEntity;
  vObj: TdwgObject;

  procedure DoAdd(AOwner: TsgDXFEntity);
  begin
    if not Assigned(AOwner) or (vObj.OwnerAdd(AOwner) < 0) then
      FreeAndNil(vObj.FEntity);
  end;

begin
  FChildIndex := 0;
  C := ChildrenCount;
  with Reader.FObjMap do
    while (FChildIndex < C) and not AReader.Stopped do
    begin
      with MapElement[FChildIndex] do
        if Obj = nil then
        begin
          vObj := ReadChild(Location, Handle, FChildIndex);
          if Assigned(vObj) then
          try
            vObj.References(AReader);
            vOwner := vObj.GetOwner(AReader);
            if AReader.Version <= acR14 then
            begin
              if (vOwner = AReader.Model) or (vOwner = AReader.Paper) then
                DoAdd(vOwner)
              else
                if vObj.IsEntity then
                  FreeAndNil(vObj.FEntity)
                else
                  DoAdd(vOwner);
            end
            else
              DoAdd(vOwner);
            Objects[FChildIndex] := vObj.FEntity;
          finally
            FreeAndNil(vObj);
          end;
        end;
      Inc(FChildIndex);
    end;
end;

{ TdwgTableItem }

procedure TdwgTableItem.ReadData(var APBit: TsgInt64);
begin
  FEntryName := ReadObjName(APBit, FFlags);
end;

procedure TdwgTableItem.ReadHandleRefs(var APBit: TsgInt64);
begin
  inherited ReadHandleRefs(APBit);
  ReadID(APBit); // NULL (hard pointer)
end;

{ TdwgTables }

function TdwgTables.GetOwner(AReader: TdwgReader): TsgDXFEntity;
begin
  Result := AReader.Conv.Main;
end;

procedure TdwgTables.NewObject(ACode: Integer; AHandle: UInt64;
  var AObj: TdwgObject);
begin
  inherited NewObject(ACode, AHandle, AObj);
  case ACode of
    48:
      begin
        AObj.FEntity.Free;
        AObj.Free;
        AObj := Reader.FBlockRecords;
      end;
  end;
end;

{$IFDEF DATA_LINK}
procedure TdwgDataLink.ReadData(var APBit: TsgInt64);
var
  I: Integer;
  vValuesCount, vDataType: Integer;
//  vValueName: string;
  vStringReader: TdwgStringReader;
begin
  ReadObjHeader(APBit);
  FStringReader.ReadText; // 1
  FStringReader.ReadText; // 300
  FStringReader.ReadText; // 301
  TsgCADDataLink(FEntity).FileName := FStringReader.ReadText; // 302
  SeekGeneral(APBit, [seBL, seBL, seBL, seBS, seBS, seBS, seBS, seBS, seBS,
    seBS, seBS, seBL]);  // 90, 91, 92, 170..177, 93
  FStringReader.ReadText; // 304
  SeekGeneral(APBit, [seBL]); // 94
  // DATAMAP_BEGIN
  vValuesCount := ReadBL(APBit); // 90
  vStringReader := Reader.GetStringReader(APBit);
  for I := 0 to vValuesCount - 1 do
  begin
    {vValueName := }FStringReader.ReadText;  // value name - 300
    if Reader.Version >= acR2007 then
      SeekGeneral(APBit, [seBL]); // 93
    vDataType := ReadBL(APBit); // 90
    case vDataType of
      // Unknown
      0: SeekGeneral(APBit, [seBL]);
      // Int - 90
      1: SeekGeneral(APBit, [seBL]);
      // Double
      2: SeekGeneral(APBit, [seBD]);
      // text - 1
      4: vStringReader.ReadText; // nil - for not read acr2007+ strings
      // Date - BL data size N, followed by N bytes (Int64 value)
      8: Inc2(APBit, ReadBL(APBit) shl 3);
      // –Point BL data size, followed by 2RD
      16: Inc2(APBit, ReadBL(APBit) shl 3);
      // –3D Point BL data size, followed by 3RD
      32: Inc2(APBit, ReadBL(APBit) shl 3);
      // –Object Id H Read from appropriate place in handles section (soft pointer).
      64: ReadID(APBit);
      // –Buffer Unknown.
      128:;
      // –Result Buffer Unknown.
      256:;
      // –General General, BL containing the byte count followed by a byte array.
      // (introduced in R2007, use Unknown before R2007).
      512:
        if Reader.Version >= acR2007 then
          Inc2(APBit, ReadBL(APBit) shl 3);
    end;
    if Reader.Version >= acR2007 then
    begin
      SeekGeneral(APBit, [seBL]); // 94
      FStringReader.ReadText;     // 300
      FStringReader.ReadText;     // 302
    end;
  end;
  // handle references
  ReadHandleRefs(APBit);
  ReadID(APBit); // ACAD_TABLE   - 330
  ReadID(APBit); // TABLECONTENT - 330
  ReadID(APBit); // TABLECONTENT - 360
end;
{$ENDIF}

{ TdwgXRecord }

procedure TdwgXRecord.ReadData(var APBit: TsgInt64);
var
  vLen: Integer;
  vCode: SmallInt;
  vExData: TsgCADExtendedData;
  vEnd: TsgInt64;
  vHandle: UInt64;
  vStringReader: TdwgStringReader;
begin
  ReadObjHeader(APBit);
  vLen := ReadBL(APBit);
  if vLen > 0 then
  begin
    vStringReader := Reader.GetStringReader(APBit);
    vEnd := APBit;
    Inc2(vEnd, vLen shl 3);
    vExData := TsgCADExtendedData(TsgDXFXRecord(FEntity).Data);
    while Comp2(APBit, vEnd) do
    begin
      vCode := ReadRS(APBit);
      case CodeTypes^[vCode] of
        ctInteger:
          case vCode of
            280, 281, 282, 290..299: vExData.AddByte(vCode, ReadRC(APBit));
            60..79, 170..179, 270..279, 283..289, 370..389, 400..409, 1060..1070:
              vExData.AddInt16(vCode, ReadRS(APBit));
          else
            vExData.AddInt(vCode, ReadRL(APBit));
          end;
        ctDouble:
          case vCode of
            10 .. 13: vExData.AddPoint(vCode, Read3RD(APBit));
          else
            vExData.AddDouble(vCode, ReadRD(APBit));
          end;
        ctString:
          case vCode of
            1004: AddBinaryChunk(APBit, vCode, vExData);
          else
            vExData.AddString(vCode, vStringReader.ReadXrecordText);
          end;
        ctHex:
          begin
            ReadBytesDoublePair(APBit, vHandle, 2);
            vExData.AddInt64(vCode, vHandle);
          end;
      else
        case vCode of
          310 .. 319: AddBinaryChunk(APBit, vCode, vExData);
        else
          //raise EdwgError.CreateFmt('Unknown XRecord(%x) code "%d"', [FHandle, vCode]);
        end;
      end;
    end;
  end;
  if Reader.Version >= acR2000 then
    SeekGeneral(APBit, [seBS]); //Cloning flag BS 280
  ReadHandleRefs(APBit);
end;

procedure TdwgXRecord.References(AReader: TdwgReader);
begin
  inherited References(AReader);
end;

{ TdwgMesh }

constructor TdwgMesh.Create;
begin
  inherited Create;
  FVertexArray := TFPointList.Create;
  FFaceIndex := TsgIntegerList.Create;
end;

destructor TdwgMesh.Destroy;
begin
  FVertexArray.Free;
  FFaceIndex.Free;
  inherited Destroy;
end;

procedure TdwgMesh.ReadEntData(var APBit: TsgInt64);
var
//  vVer, vBlendCrease, vSubdivisionLevel: Integer;
  I: Integer;
begin
  {vVer := ReadBS(APBit);
  vBlendCrease := ReadBit(APBit);
  {vSubdivisionLevel := ReadBL(APBit);}
  SeekGeneral(APBit, [seBS, seB, seBL]);

  FVertexArray.Count := ReadBL(APBit);
  for I := 0 to FVertexArray.Count - 1 do
    FVertexArray[I] := Read3D(APBit);

  FFaceIndex.Count := ReadBL(APBit);
  for I := 0 to FFaceIndex.Count - 1 do
    FFaceIndex[I] := ReadBL(APBit);

  inherited ReadEntData(APBit);
end;

procedure TdwgMesh.References(AReader: TdwgReader);
begin
  inherited References(AReader);
  FillSubDMesh(FEntity, FVertexArray, FFaceIndex);
end;

{ TdwgMaterial }

procedure TdwgMaterial.ReadMaterialColor(var APBit: TsgInt64;
  AMaterialColor: TsgCustomMaterialColor);
begin
  AMaterialColor.Method := ReadRC(APBit);
  AMaterialColor.Factor := ReadBD(APBit);
  if AMaterialColor.Method and $01 <> 0 then
    AMaterialColor.Color := ReadCmEntityColor(APBit);
end;

procedure TdwgMaterial.ReadTexMatrix(var APBit: TsgInt64; AMaterialMap: TsgMaterialMap);
var
  I, J: Integer;
begin
  for I := 0 to 3 do
    for J := 0 to 3 do
      AMaterialMap.Mapper[I, J] := ReadBD(APBit);
end;

function TdwgMaterial.ReadMapTail(var APBit: TsgInt64; AMaterialMap: TsgMaterialMap): Boolean;
//var
//  vPreamble: Integer;
begin
  AMaterialMap.Blend := ReadBD(APBit);
  Inc2(APBit, 24);
//    vPreamble := 0;
//    ReadBytes(APBit, vPreamble, 3);
//    case vPreamble of
//      $00010101:;
//      //$00020101:;
//      $00020102: asm nop end;
//      $00010102: asm nop end;
//    else
//    end;
  ReadTexMatrix(APBit, AMaterialMap);
  AMaterialMap.MapSource := ReadRC(APBit);
  if AMaterialMap.MapSource = 1 then
    AMaterialMap.FileName := FStringReader.ReadText;
  Result := AMaterialMap.MapSource <> 2;
end;

procedure TdwgMaterial.ReadData(var APBit: TsgInt64);
var
  vMat: TsgDXFMaterial;
begin
  ReadObjHeader(APBit);
  FEntity.Name := FStringReader.ReadText;
  FStringReader.ReadText; // description - 2
  vMat := TsgDXFMaterial(FEntity);
//--------------------------------------------------------------------
  ReadMaterialColor(APBit, vMat.Ambient.MaterialColor);  // 70,40,90
//--------------------------------------------------------------------
  ReadMaterialColor(APBit, vMat.Diffuse.MaterialColor);  // 71,41,91
  if not ReadMapTail(APBit, vMat.Diffuse) then
    case ReadBB(APBit) of
      $02:
        begin
          ReadMaterialColor(APBit, vMat.Diffuse.Bleed);
          ReadMaterialColor(APBit, vMat.Diffuse.IndirectDump);
          vMat.Diffuse.ReflectanceScale := ReadBD(APBit);
          vMat.Diffuse.TransmittanceScale := ReadBD(APBit);
          vMat.Diffuse.Luminance := ReadBD(APBit);
        end;
      $01:
        begin
          vMat.Diffuse.Xrecord := TsgDXFXRecord.Create;
          vMat.Diffuse.Xrecord.Data.AddDouble(277, ReadRC(APBit));
          ReadMaterialColor(APBit, vMat.Diffuse.Normal1);
          ReadMaterialColor(APBit, vMat.Diffuse.Normal2);
          vMat.Diffuse.Xrecord.Data.AddDouble(466, ReadBD(APBit));
          vMat.Diffuse.Xrecord.Data.AddDouble(467, ReadBD(APBit));
        end;
    end;
//--------------------------------------------------------------------
  ReadMaterialColor(APBit, vMat.Specular.MaterialColor);  // 76,45,92
  ReadMapTail(APBit, vMat.Specular);
  vMat.Specular.Gloss := ReadBD(APBit);            // 44
//--------------------------------------------------------------------
  ReadMapTail(APBit, vMat.Reflection);
//--------------------------------------------------------------------
  vMat.Opacity.Percent := ReadBD(APBit);
  ReadMapTail(APBit, vMat.Opacity);
//--------------------------------------------------------------------
  ReadMapTail(APBit, vMat.Bump);
//--------------------------------------------------------------------
  vMat.Refraction.Index := ReadBD(APBit);
  ReadMapTail(APBit, vMat.Refraction);
end;

procedure TdwgMaterial.ReadOwner(AReader: TdwgReader);
begin
  if (FOwnerDictionary = nil) and (FOwner <> cnstBadHandle) then
    inherited;
end;

{ TdwgStringReader }

constructor TdwgStringReader.Create(APPBit: PsgInt64; ACodePage: Word);
begin
  FPBit := APPBit;
  FCodePage := ACodePage;
end;

procedure TdwgStringReader.DoReadRawText(ALen: Integer;
  ACP: Word; var S: sgRawByteString);
begin
  if ALen > 0 then
  begin
    SetLength(S, ALen);
{$IFDEF SGDEL_2009}
    SetCodePage(S, $FFFF, False);
{$ENDIF}
    ReadBytesCustom(FPBit^, PPointer(S)^, ALen);
{$IFDEF SGDEL_2009}
    SetCodePage(S, ACP, False);
{$ENDIF}
  end
  else
    S := '';
end;

procedure TdwgStringReader.DoReadUnicodeText(ALen: Integer; var S: sgUnicodeStr);
begin
  if ALen > 0 then
  begin
    SetLength(S, ALen);
    ReadBytesCustom(FPBit^, PPointer(S)^, ALen * SizeOf(S[1]));
    if S[ALen] = #0 then
      SetLength(S, ALen - 1);
  end
  else
    S := '';
end;

function TdwgStringReader.ReadCodePage: Word;
begin
  Result := FCodePage;
end;

function TdwgStringReader.ReadTextLen: Integer;
begin
  Result := ReadBS(FPBit^);
end;

function TdwgStringReader.ReadXrecordTextLen: Integer;
begin
  Result := ReadRS(FPBit^);
end;

procedure TdwgStringReader.TrimTextLen(ALen: Integer; var S: string);
begin
  if (ALen > 0) and (S[ALen] = #0) then
    SetLength(S, ALen - 1);
end;

{ TdwgWideStringReader }

function TdwgWideStringReader.ReadText: string;
{$IFNDEF SGDEL_2009}
var
  S: sgUnicodeStr;
{$ENDIF}
begin
{$IFDEF SGDEL_2009}
  DoReadUnicodeText(ReadTextLen, Result);
{$ELSE}
  DoReadUnicodeText(ReadTextLen, S);
  Result := ConvertToAnsiString(S, FCodePage);
{$ENDIF}
end;

function TdwgWideStringReader.ReadXrecordText: string;
{$IFNDEF SGDEL_2009}
var
  S: sgUnicodeStr;
{$ENDIF}
begin
{$IFDEF SGDEL_2009}
  DoReadUnicodeText(ReadXrecordTextLen, Result);
{$ELSE}
  DoReadUnicodeText(ReadXrecordTextLen, S);
  Result := ConvertToAnsiString(S, FCodePage);
{$ENDIF}
end;

{ TdwgAnsiStringReader }

function TdwgAnsiStringReader.ReadCodePage: Word;
begin
  Result := sgCodePageFromDWG(ReadRC(FPBit^), FCodePage);
end;

function TdwgAnsiStringReader.ReadText: string;
var
  Len: Integer;
{$IFDEF SGDEL_2009}
  S: sgRawByteString;
{$ENDIF}
begin
  Len := ReadTextLen;
{$IFDEF SGDEL_2009}
  DoReadRawText(Len, FCodePage, S);
  Result := string(S);
  Len := Length(Result);
{$ELSE}
  DoReadRawText(Len, FCodePage, Result);
{$ENDIF}
  TrimTextLen(Len, Result);
end;

function TdwgAnsiStringReader.ReadXrecordText: string;
var
  Len: Integer;
{$IFDEF SGDEL_2009}
  S: sgRawByteString;
{$ENDIF}
begin
  Len := ReadXrecordTextLen;
{$IFDEF SGDEL_2009}
  DoReadRawText(Len, ReadCodePage, S);
  Result := string(S);
  Len := Length(Result);
{$ELSE}
  DoReadRawText(Len, ReadCodePage, Result);
{$ENDIF}
  TrimTextLen(Len, Result);
end;

{ TdwgWideStringReaderParse }

function TdwgWideStringReaderParse.ReadText: string;
begin
  Result := inherited ReadText;
{$IFDEF SGDEL_2009}
  Result := ParseUnicode(Result, [puU, puM]);
{$ENDIF}
end;

{ TdwgAnsiStringReaderParse }

function TdwgAnsiStringReaderParse.ReadText: string;
begin
  Result := inherited ReadText;
{$IFDEF SGDEL_2009}
  Result := ParseUnicode(Result, [puU, puM]);
{$ENDIF}
end;

{ TdwgScale }

procedure TdwgScale.ReadData(var APBit: TsgInt64);
begin
  ReadObjHeader(APBit);
  Inc2(APBit, 2);                                             // 70 ??
  TsgDXFScale(FEntity).Description := FStringReader.ReadText; // 300
  TsgDXFScale(FEntity).LayoutScale := ReadBD(APBit);          // 140
  TsgDXFScale(FEntity).ModelScale := ReadBD(APBit);           // 141
  TsgDXFScale(FEntity).Flags := ReadBit(APBit);               // 290
  ReadHandleRefs(APBit);
end;

procedure TdwgScale.References(AReader: TdwgReader);
begin
  inherited References(AReader);
end;

{ TdwgObjectContextData }

function TdwgObjectContextData.GetBitSize: Integer;
begin
  Result := FBitSize;
end;

function TdwgObjectContextData.GetObjectBeginning: TsgInt64;
begin
  Result := FObjectBeginning;
end;

procedure TdwgObjectContextData.ReadData(var APBit: TsgInt64);
var
  vPBit: TsgInt64;
begin
  ReadObjHeader(APBit);
  vPBit := FObjectBeginning;
  Inc2(vPBit, BitSize);
  APBit := vPBit;
  ReadHandleRefs(APBit);
  FScale := ReadID(APBit);
end;

procedure TdwgObjectContextData.References(AReader: TdwgReader);
begin
  inherited References(AReader);
  TsgDXFObjectContextData(FEntity).Scale := TsgDXFScale(Reader.ObjByHandle(FScale, nil));
end;

procedure TdwgObjectContextData.SetBitSize(const AValue: Integer);
begin
  FBitSize := AValue;
end;

procedure TdwgObjectContextData.SetObjectBeginning(const AValue: TsgInt64);
begin
  FObjectBeginning := AValue;
end;

initialization
  FiderCodeFromName := nil;
  CF_DWG := RegisterClipboardFormat('SoftGold DWG Image');
  TPicture.RegisterClipboardFormat(CF_DWG, TsgDWGImage);
  TPicture.RegisterFileFormat('dwg', 'AutoCAD DWG', TsgDWGImage);
  TPicture.RegisterFileFormat('dwt', 'AutoCAD DWT', TsgDWGImage);
  TPicture.RegisterFileFormat('gp2', 'AutoCAD DWG', TsgDWGImage);

  TsgDXFConverterAccess.RegisterXRefGraphicClass('dwg', TsgDWGImage);
  TsgDXFConverterAccess.RegisterXRefGraphicClass('dwt', TsgDWGImage);
  TsgDXFConverterAccess.RegisterXRefGraphicClass('gp2', TsgDWGImage);

finalization
  FreeAndNil(FiderCodeFromName);
  TPicture.UnRegisterGraphicClass(TsgDWGImage);
  TsgDXFConverterAccess.UnRegisterXRefGraphicClass(TsgDWGImage);

end.
