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

unit CADImage;
{$INCLUDE SGDXF.INC}
{$DEFINE SG_HIDDEN}

interface

uses Windows, Classes, Graphics, TTF, sgLists, sgLines, sgFunction,
  sgMeshBuilderWrapper,
{$IFNDEF SG_CAD_DLL}
  Forms, Dialogs,
{$ENDIF}
  DXFConv, sgConsts, SHX, sgSelection
{$IFDEF SG_USEGDIPLUS}
  , GDIPlus
{$ENDIF}
{$IFDEF SGDEL_XE3}
  , System.Types, System.UITypes
{$ENDIF}
{$IFDEF SGFPC}
  , FPimage
{$ENDIF}
  ;

// For working with SaveToStream and Assign should be set sgConsts.KeepOriginal := True
// This is necessary for Fast Report Add-in.

type
  TsgDXFDrawMode = (dmNormal, dmBlack, dmGray);
  TsgDXFViewDirection = (vdDefault, vdTop, vdBottom, vdLeft, vdRight, vdFront, vdBack,
     vdSWIsometric, vdSEIsometric, vdNWIsometric, vdNEIsometric);
  TsgTTFMode = (ttfAuto, ttfGDI, ttfPolyPolyline, ttfPolyPolygon);
  TsgColorType = (ctPen, ctBrush, ctFont, ctBrushClear);
  TsgTextType = (ttTextOut, ttTextOutW, ttExTextOut, ttExtTextOutW);

  TsgSHXFontsProc = function: TsgSHXFontList of object;
  TsgGetSelectionMatrixModeProc = function: TsgSelectionMode of object;
  TsgSetSelectionMatrixModeProc = procedure (const AMode: TsgSelectionMode) of object;

  TsgExpPixel = procedure(APoint: TPoint; AColor: TColor) of object;
  TsgExpPolyline = procedure(const Points; Count: Integer) of object;
  TsgExpPolygon = procedure(const Points; Count: Integer) of object;
  TsgExpPolyPolyline = procedure(const Points; const Counts; Count: Integer) of object;
  TsgExpPolyPolygon = procedure(const Points; const Counts; Count: Integer) of object;
  TsgExpText = procedure(ATextType: TsgTextType; X, Y: Integer; Options: Longint;
    Rect: PRect; StrWideChar: PWideChar; StrChar: PAnsiChar; Count: Longint; const Dx: PInteger) of object;
  TsgExpArc = procedure(X1, Y1, X2, Y2, X3, Y3, X4, Y4: Integer) of object;
  TsgExpFillRgn = procedure(P: PRect; Count: Integer) of object;
  TsgExpClipRgn = procedure(P: PRect; Count: Integer) of object;
  TsgExpCloseFigure = procedure of object;
  TsgExpImage = procedure(const R: TRect; AImage: TGraphic) of object;
  TsgExpImageUV = procedure(const APoint1, APoint2, APoint3, APoint4: TPoint;
    AImage: TGraphic) of object;
  TsgExpSaveDC = procedure of object;
  TsgExpRestoreDC = procedure of object;
  TsgExpProgress = procedure of object;
  TsgExpSetColor = procedure(AColor: TColor; AColorType: TsgColorType) of object;
  TsgExpSetFont = procedure(AFont: TFont) of object;
  TsgExpSetStyle = procedure(AStyle: Integer; AColorType: TsgColorType) of object;
  TsgExpSetPenWidth = procedure(AWidth: Double) of object;
  TsgExpSetPenMiterLimit = procedure(ANewLimit: Single) of object;
  TsgExpSetPenGeometric = procedure(AStyle: DWORD) of object;

  // Obsolete type
  TScaling = record
    Offset: TFPoint;
    Scale: TFPoint;
    DX: Integer;
    DY: Integer;
  end;

  PsgCanvasParams = ^TsgCanvasParams;
  TsgCanvasParams = record
    Brush: TBrush;
    Font: TFont;
    Pen: TPen;
  end;

  PsgViewPortCanvasParams = ^TsgViewPortCanvasParams;
  TsgViewPortCanvasParams = record
    HDC: HDC;
    CanvasParams: TsgCanvasParams;
  end;

  TsgCalcCoordsStruct = record
    XScaled: Extended;
    YScaled: Extended;
    X: TsgFloat;
    Y: TsgFloat;
    Rot: TFMatrix;
    RealLayoutCenter: TFPoint;
    NullCoord: Integer;
  end;

  TsgDistanceUnits = (duNone, duInch, duMM);
  TsgAngularUnits = (auNone);
  TsgMeasurement = record
    DistanceUnits: TsgDistanceUnits;
    AngularUnits: TsgAngularUnits;
  end;

  TsgCADImage = class;
  TsgCADImageClass = class of TsgCADImage;

  { TsgCADImage }

  TsgCADImage = class(TGraphic)
  private
    FBackgroundColor: TColor;
    FChangeBackgroundColor: TColor;
    FPlotWindowAreaColor: TColor;
    FBorderSize: TsgBorderSize;
    FBorderType: TsgBorderType;
    FCachingRasterMode: TsgCachingRasterMode;
    FCanvasParams: TsgCanvasParams;
    FCBFormat: Word;
    FCenter: TFPoint;
    FClippingRect: PFRect;
    FColorToLineWeight: TStringList;
    FConverter: TsgDXFConverter;
    FConverting: Boolean;
    FCurrentLayout: TsgDXFLayout;
    FCounts: TsgIntegerList;
    F2Counts: TsgIntegerList;
    F3Counts: TsgIntegerList;
    {$IFDEF SG_HIDDEN}
    FPixel: TPoint;
    {$ENDIF}
    FDottedSingPts: TFPointList;
    FSnapLastPoint: TFPoint;
    FDxyz: TFPoint;
    FColorBrush: TColor;
    FColorFont: TColor;
    FPenWidth: Integer;
    FPixelsPerInch: Integer;
    FEntityHandle: Int64;
    FEntityLines: sgLines.TsgLines;

    FsgExpPixel: TsgExpPixel;
    FsgExpPolyline: TsgExpPolyline;
    FsgExpPolygon: TsgExpPolygon;
    FsgExpPolyPolyline: TsgExpPolyPolyline;
    FsgExpPolyPolygon: TsgExpPolyPolygon;
    FsgExpText: TsgExpText;
    FsgExpArc: TsgExpArc;
    FsgExpFillRgn: TsgExpFillRgn;
    FsgExpClipRgn: TsgExpClipRgn;
    FsgExpCloseFigure: TsgExpCloseFigure;
    FsgExpImage: TsgExpImage;
    FsgExpImageUV: TsgExpImageUV;
    FsgExpSaveDC: TsgExpSaveDC;
    FsgExpRestoreDC: TsgExpRestoreDC;
    FsgExpProgress: TsgExpProgress;
    FsgExpSetColor: TsgExpSetColor;
    FsgExpSetFont: TsgExpSetFont;
    FsgExpSetStyle: TsgExpSetStyle;
    FsgExpSetPenWidth: TsgExpSetPenWidth;
    FsgExpSetPenMiterLimit: TsgExpSetPenMiterLimit;
    FsgExpSetPenGeometric: TsgExpSetPenGeometric;

    FDefaultColor: TColor;
    FDrawingBox: TFRect;
    FDrawMode: TsgDXFDrawMode;
    FExportToDXFMode: Boolean;
    FExtents: TFRect;
    FFileInfo: string;
    FFileName: string;
    FIndex: Integer;
    FIntPoints: TsgIntegerList;
    FDotsPoints: TsgIntegerList;
    //evg looks like the following FIPoints has too many functional in the same field
    FIPoints: array [0..cIPointsCnt + 1] of TPoint; // FIPoints[cIPointsCnt] - for closed polylines
    FIRect: TRect; //evg - this should be divided - for all entities  visual check and for images drawing
    FIsDraw3DAxes: Boolean;
    FIsPlotting: Boolean;
    FIsProcessMessages: Boolean;
    FIsShowBackground: Boolean;
    FIsWithoutBorder: Boolean;
    FLast: Integer;
    FLibraryGDIPlusExists: Boolean;
    FMillimetres: Integer;
    FBadRotation: Boolean;
    FNullWidth: Double;
    FOnBeforeRotate: TNotifyEvent;
    FOnAfterRotate: TNotifyEvent;
    FOnLayoutChange: TNotifyEvent;
    FOnLayoutBeforeChange: TNotifyEvent;

    //If set in the main CADImage these fields will be set in all internal CADImages.
    FOnInsert: TsgDXFInsert;// -  an insert for which the block entities will be drawn separately on the bitmap.
    FOnInsertMode: Boolean;// - a mode of separate drawing the entities on the bitmap for the diven insert.
    FOnComplexEntity: TsgDXFEntity;

    FPoly: TsgIntegerList;
    FPureExtents: TFRect;
    FReady: Boolean;
    FZRotate: Double;
    FSelectionMatrixMode: TsgSelectionMode;
    FObjectSnapMask: TObjectSnapState;
    FOnGetBox: TsgGetBox;
    FSnapEntity: TsgDXFEntity;
    FSnapMatrix: TsgSnapMatrix;
    FSnapOnlyIterate: Boolean;
    FStoreSnapOnlyIterate: Boolean;
    FStoreInsert: TsgDXFInsert;
    FStream: TMemoryStream;
    FStretch: Boolean;
    FUseWinEllipse: Boolean;
    FShowImages: Boolean;
    FViewPortCanvasParams: PsgViewPortCanvasParams;
    FViewPortRegion: HRGN;
    FClipRegion: HRGN;
    FVisibleArea: TPoint;
    FXMax: Double;
    FXMin: Double;
    FYMax: Double;
    FYMin: Double;
    FZMax: Double;
    FZMin: Double;
    FZoom: Double;
    FViewRectangle: TFRect;
    FLineWeightScale: TsgFloat;
    FResizeDisproportionateDrawing: Boolean;
    FXrefStack: TList;
    FXDisproportionateShift: TsgFloat;
    FYDisproportionateShift: TsgFloat;
    FSHXFontsProc: TsgSHXFontsProc;
    FGetSelectionMatrixModeProc: TsgGetSelectionMatrixModeProc;
    FSetSelectionMatrixModeProc: TsgSetSelectionMatrixModeProc;
    FSelectionMatrix: TsgSelectionMatrix;
    FTTFMode: TsgTTFMode;
    FMessage: string;

    FClipRgn: HRGn;
    FSaveDC: TList;
    FOnAfterDraw: TNotifyEvent;

    FCustomDraw: Boolean;
    FOffset: TFPoint;
    FOnMatrixChanged: TNotifyEvent;
    FRotCount: Integer;
    FRotToView: Boolean;

    FOnMetafileExport: TsgObjMetafileExport;
    FUsePlotSetting: Boolean;
    FShowPlotSetting: Boolean;
    FShowPlotMargins: Boolean;
    FShowPlotFrame: Boolean;
    FShowPlotForModel: Boolean;
    FPrinting: TsgPrintMode;
    FDeviceDPI: TPoint;
    FGuid: TGUID;
// saved drawing params
    FDrawSaved: TsgCADIterate;
//  the following functions are "end"-functions for GDI or for export to formats
    procedure ExpPixelInteger(const Sender: TObject; APoint: TPoint; AColor: TColor);
    procedure ExpArcInteger(const Sender: TObject; X1, Y1, X2, Y2, X3, Y3, X4, Y4: Integer);
    procedure ExpPolylineInteger(const Sender: TObject; var Points; Count: Integer);
    procedure ExpPolygonInteger(const Sender: TObject; var Points; Count: Integer);
    procedure ExpPolyPolylineLists(const Sender: TObject; APoints : TsgIntegerList;
      ACounts: Pointer; ACount: Integer; const ACheckDrawOnBitMap: Boolean = True);
    procedure ExpPolyPolygonInteger(const Sender: TObject; var Points, Counts; Count: Integer);
    procedure ExpTextInteger(ATextType: TsgTextType; X, Y: Integer; Options: Longint;
      Rect: PRect; StrWideChar: PWideChar; StrChar: PAnsiChar; Count: Longint;
      Dx:{$IFDEF SGFPC}Pointer{$ELSE}PInteger{$ENDIF});
    procedure DoSetColor(AColor: TColor; AColorType: TsgColorType;
      AUseExternalColor: Boolean = True);
    function SetColorByExternalPen(const AUseExternalColor: Boolean;
      var AColor: TColor): Boolean;
    procedure DoSetFont(AFont: TFont);
    procedure DoSetStyle(AStyle: Integer; AColorType: TsgColorType);
    procedure ExpFillRgnInternal(const ASender: TObject; const AHRng: HRgn);
    procedure ExpArrowsInternal(const ASender: TObject;
      const APoly: TsgIntegerList; const AHasZTick: Boolean);
    procedure ExpSolidInternal(const ASender: TObject;
      var ASolid, APts: array of TPoint; AHasZTick: Boolean);
    procedure ExpOle2FrameInternal(const ASender: TObject; const ARect: TF2DRect);
    procedure ExpTextInternal(const ASender: TObject; ATextGlyph: TsgTextGlyph;
      const AText: string; const ATextW: WideString; const AMatrix: PFMatrix);
    procedure ExpImageGDIInternal(const ASender: TObject; const R: TRect;
      AGraphic: TGraphic);
    procedure ApplyText;
    {$IFDEF SG_HIDDEN}
    procedure AddLastPixelToPoly(APoints, ACounts: TsgIntegerList);
    {$ENDIF}
    procedure BeginRead(Sender: TObject);
    procedure BoxPoint(const P: TFPoint);
    function CalcCADCoordsParameters({AXScaled, AYScaled: Extended;
               var AX, AY: TsgFloat; var ARot: TFMatrix;
               var ARealLayoutCenter: TFPoint; var ANullCoord: Integer}var AStruct: TsgCalcCoordsStruct): Boolean;
    function CoordinateBorderCorrect(var AXScaled, AYScaled: Extended): Boolean;
    procedure DoProgress(Stage: TProgressStage);
    procedure DoRead(Sender: TObject);
    procedure DoPolylineArrow(const AEnt: TsgDXFEntity; const ALines: TsgLines;
      const AMatrix: PFMatrix);
    procedure DrawArc(Sender: TObject);
    procedure DrawCircle(Sender: TObject);
    procedure DrawFace(Sender: TObject);
    procedure DrawCADFill(Sender: TObject);
    procedure DrawHatch(Sender: TObject);
    procedure DrawMPolygon(Sender: TObject);
    function DrawDimension(Sender: TObject): Integer;
    procedure DrawLeader(Sender: TObject);
    procedure DrawLine(Sender: TObject);
    procedure DrawPoint(Sender: TObject);
    procedure DrawPoly(Sender: TObject);
    procedure DrawACISEntity(Sender: TObject);
    procedure DrawSpline(Sender: TObject);
    procedure DrawSolid(Sender: TObject);
    procedure DrawShape(Sender: TObject);
    procedure DrawText(Sender: TObject);
    procedure DrawViewPort(Sender: TObject);
    procedure DrawImage(Sender: TObject);
    procedure DrawImageGDIPlus(const AImgEnt: TsgDXFImageEnt; const APoints: array of TPoint);
    procedure DrawImageEnt(Sender: TObject);
{$IFDEF SG_USEGDIPLUS}
    procedure DrawTilesImage(const AGraphics: TsgGDIPlusGraphics;
      const AImgEnt: TsgDXFImageEnt;
      const APoints: array of TPoint;
      const ImageAttributes: TsgGDIPlusImageAttributes = nil);
{$ENDIF}
    procedure DrawFlatPoly(Sender: TObject);
    procedure DrawFlatHatch(Sender: TObject);
    procedure DrawOle2Frame(Sender: TObject);
    procedure DrawPointsListByPolyline(const AObj: TObject; const DottedSingPts: TFPointList; AClosed: Boolean);
    procedure DrawPointsListByPolyPolyline(const AObj: TObject;
      const DottedSingPts: TFPointList; AClosed: Boolean = False);
    procedure DrawWipeout(Sender: TObject);
    procedure DrawXRef(Sender: TObject);
{$IFDEF SG_BTI}
    procedure DrawPolyPolyLine2D(Sender: TObject);
{$ENDIF}
    procedure EndRead(Sender: TObject);
    procedure EnterViewport(Sender: TObject);
    procedure EnterXRef(Sender: TObject);
    procedure FillFromFlat(FP: TsgFlatEntity);
    function NeedToAddOnePixel: Boolean;{$IFDEF SG_INLINE}inline;{$ENDIF}
    function GetBackgroundColor: TColor;
    function GetDefaultColor: TColor;
    function GetBlock(Index: Integer): TsgDXFBlock;
    function GetClipping: TsgClipping;
    function GetEntity(Index: Integer): TsgDXFEntity;
    function GetIsLoading: Boolean;
    function GetIsDrawingRotated: Boolean;
    function GetLayout(Index: Integer): TsgDXFLayout;
    function GetLayoutsCount: Integer;
    function GetLineWeightScale: TsgFloat;
    function GetScale: TFPoint;
    function GetOwnSource: Boolean;
    function GetSHXFontsProc: TsgSHXFontList;
    function GetSelectionMatrixProc: TsgSelectionMode;
    function GetRealClip: PFRect;
    function InitializeLineType(AEntity: TsgDXFPenEntity): Boolean;
    function PolyRgn(PL: TsgCADBasePolyline): HRgn;
    procedure ResetExtents;
    procedure SetBackgroundColor(Value: TColor);
    procedure SetPlotWindowAreaColor(Value: TColor);
    procedure SetDefaultColor(Value: TColor);
    procedure SetDrawingBox(const ABox: TFRect);
    procedure SetDrawMode(Value: TsgDXFDrawMode);
    procedure SetIsShowBackground(Value: Boolean);
    procedure SetShowLineWeight(Value: Boolean);
    procedure SetIsWithoutBorder(Value: Boolean);
    procedure SetSelectionMatrixProc(const AMode: TsgSelectionMode);
    procedure SetStretch(Value: Boolean);
    procedure SetUseWinEllipse(Value: Boolean);
    procedure SetShowImages(Value: Boolean);
    procedure SetDimensionsVisible(AVisible: Boolean);
    procedure SetTextVisible(AVisible: Boolean);
    procedure SetOwnSource(Value: Boolean);
    procedure SetClip(AInsert: TsgCADClipInsert);
    procedure DrawEntityOnSnapMatrix(Entity: TsgDXFEntity);
    procedure SetupSnapMatrix;
    procedure SetPixelSnapEx(const APt: TFPoint; Pt: TPoint;
      const ASnapState: TObjectSnapState);
    procedure SetPixelSnap(const APt: TFPoint;
      const ASnapState: TObjectSnapState);
    function GetNullWidth: Integer;
    procedure SetNullWidth(const Value: Integer);
    function CheckRastrByFastMode(Sender: TObject;
      var AGraphic: TGraphic; const APoints: array of TPoint): Boolean;
    function CheckOrthoRaster(const AAngle: Double): Boolean;
    procedure SetOnAfterDraw(const Value: TNotifyEvent);
    procedure SetListsCapacity(const ASetDefault: Boolean);
    procedure SetOffset(const AValue: TFPoint);
    procedure SetUsePlotSetting(const Value: Boolean);
    procedure SetShowPlotSetting(const Value: Boolean);
    procedure SetShowPlotFrame(const Value: Boolean);
    procedure SetShowPlotMargins(const Value: Boolean);
    procedure SetShowPlotForModel(const Value: Boolean);
    function GetIsCurLayoutShowPlot: Boolean;
    procedure SetPrinting(const AValue: TsgPrintMode);
    procedure SetClipping(const AClip: TsgClipping);
  protected
    FAddOnePixel: Boolean;
    FCanvas: TCanvas;
    FDraw: TsgCADIterate;
    FDrawExternlProps: TsgExternalProps;
    FIsShowLineWeight: Boolean;
    FDimensionsVisible: Boolean;
    FTextVisible: Boolean;
    FmmToPixelX: Double;
    FMsg: string;
    FDrawRect: TRect;
    FColorPen: TColor;
    FPixelColor: TColor;
    FPrecision: Double;
    FUsePrecision: Boolean;
    FIsIterator: Boolean;
//
    procedure RestoreDrawParams;
    procedure SaveDrawParams;

    procedure ApplyLineWeightFactor(var ALineWeight: Double); virtual;
    procedure ApplyLineWeightFactorBase(var ALineWeight: Double);
    procedure DrawPaperSpace;
    function CreateDefaultViewPort(const AHandle: UInt64): TsgDXFViewport;
    function CreateDefaultVPort(const Handle: UInt64): TsgDXFVPort;
    procedure CalcDottedSingPts(AEntity: TsgDXFEntity;
      AEntityLines: sgLines.TsgLines;
      ConvertMatrixCurrentIndertToWCS: TFMatrix;
      ADottedPoints: TFPointList);
    function GetPlotSettingsRGN: HRGN;
    procedure ExpBitBlt(const ASender: TObject; const X, Y, Width,
      Height: Integer; const ABitMap: TBitmap; const SX: Integer = 0;
      const SY: Integer = 0; const ARop: Cardinal = SRCCOPY);
    function ExpClipRgnInternal(const ASender: TObject; const AHRng: HRgn): Boolean;
    procedure ExpFillRectInternal(const Sender: TObject; const ARect: TRect);
    function ExpSaveDCInternal(const ASender: TObject): Integer;
    procedure ExpRestoreDCInternal(const ASender: TObject; const AIndex: Integer);
    function IsDisableSnapMatrix: Boolean;
    function IsNotScaledLType: Boolean;
    function IsNoWidth: Boolean;
    procedure Load2DPointToPoints(const AList: TF2DPointList);
    procedure ApplyPen(Sender: TObject); virtual;
    procedure AddSelectionMatrix(const APointer: Pointer);
    procedure ApplyScale(const ARect: TRect); overload;
    procedure ApplyScale(const ARectLeft, ARectTop, ARectRight, ARectBottom: Double); overload;
    procedure AssignTo(Dest: TPersistent); override;
    function CheckActiveVPort: Boolean;
    procedure ClearMatrices(const ARect: TRect);
    function CreateConverter: TsgDXFConverter; virtual;
    function CurrXRef: TsgDXFXref;
    procedure GetPixelSize(ANumberOfPixels: Double; var Adx, Ady: Double;
      const AScaled: Boolean);
    procedure DoAfterRotate; dynamic;
    procedure DoBeforeRotate; dynamic;
    function DoDraw(Entity: TsgDXFEntity): Integer; virtual;
    function DoFinish(Entity: TsgDXFEntity): Integer; virtual;
    {$IFNDEF SGFPC}
    procedure DoMetafileExport(const MC: TMetafileCanvas; const ARect: TRect);
    {$ENDIF}
    procedure DoMatrixChanged; dynamic;
    procedure DoOnProgress(Stage: TProgressStage; Done, Count: Integer); virtual;
    procedure Draw3DAxes;  //cadimage
    procedure Draw(Canvas: TCanvas; const Rect: TRect); override;
    {$IFNDEF SGFPC}
    procedure DrawOnMetafile(const AMetafile: TMetafile;
      const AUseLogicMetrix: Boolean; const ADrawProc: TsgObjProcDraw = nil);
    {$ENDIF}
    function DrawEntity(Entity: TsgDXFEntity): Integer;
    function DrawComplexEntity(Sender: TObject): Integer;
    procedure DrawImageGDI(Sender: TObject; const AGraphic: TGraphic;
      const APoints: array of TPoint); virtual;
    function DrawInsert(Sender: TObject): Integer;
    procedure EnterComplexEntity(Sender: TObject);
    procedure EnterInsert(Sender: TObject);
    procedure EntityCreated(Sender: TObject);
    procedure FillBoxForCoordsCalc(ACoord: Integer; var ABox: TFRect); virtual;
    procedure Fill2Counts(AMax: Integer);
    procedure InitializeVersionData(const AIsTrial: Boolean; const AMessage: string);
    function IsDrawOnBitMap: Boolean;
    function IsDrawOnCanvas: Boolean;
    function IsAutocadLType: Boolean; virtual;
    function IsRotatedTextInternal(const AText: TsgDXFText;
      const ADrawMatrix: TFMatrix): Boolean;
    function IsRotatedText(const AText: TsgDXFText; const ADrawMatrix: TFMatrix): Boolean; virtual;
    procedure GetAngles(const AImageEnt: TsgDXFImageEnt; var Angle1, Angle2: Double);
    function GetConverterParams: TsgConverterParams; virtual;
    function GetDefaultView: TsgDefaultView; virtual;
    function GetDefaultImageSize: TFRect;
    function GetEmpty: Boolean; override;
    {$IFDEF SGFPC}
    function GetTransparent: Boolean; override;
    {$ENDIF}
    function GetFPoint(const P: TFPoint): TFPoint;
    function GetHeight: Integer; override;
    function GetLineTypeScale: Double;
    function GetMillimetres: Boolean; virtual;
    function GetGDIPlusColor(const AColor: TColor): Cardinal;
    function GetOnInsertMode: TsgDXFInsert;
    function GetPalette: HPalette; override;
    function GetPolygonFillingMode: Integer; virtual;
    function GetRect(const ARect: TFRect): TRect;
    function GetRealImageMatrix: TFMatrix;
    function GetEntLineWeight(const AEntity, AInsert: TsgDXFEntity): Double;
    function GetLineWeightFactor: Double; virtual;
    function GetLineWeightFactorBase: Double;
    function GetShowLineWeight: Boolean;// virtual;
    function GetStretchBltModeInt: Integer;
    function GetWidth: Integer; override;
    function GetDefSolidRotView: TsgDXFViewDirection; virtual;
    function GetDrawPenColor: TColor;
    function GetDrawBackgroundColor: TColor;
    procedure Progress(Sender: TObject; Stage: TProgressStage; PercentDone: Byte;
      RedrawNow: Boolean; const R: TRect; const Msg: string); override;
    procedure RotateImageEnt();
    procedure SetSelectClipRgn(Region: HRGN);
    procedure SetCurrentLayout(const ALayout: TsgDXFLayout); virtual;
    procedure SetDefaultViewPort(AConverter: TsgDXFCOnverter);
    procedure SetDefaultPlotSettings(const ACheckSize: Boolean = False); virtual;
    procedure SetEntityVisibility(ACADFile: TObject);
    procedure SetExtentsParameters(const ARect: TFRect; const AIs3DExtents: Boolean); virtual;
    function SetLineWeigth(const AEntity: TsgDXFEntity;
      const ALineWeightScaled: Boolean; AMetric: Double = 1.0): Integer;
    procedure SetSHXFontsProc(const AValue: TsgSHXFontsProc);//for internal use
    procedure SetLineWeightScale(const Value: TsgFloat);
    procedure SetOnInsertMode(const AIns: TsgDXFInsert);
    procedure SetHeight(Value: Integer); override;
    procedure SetMillimetres(Value: Boolean); virtual;
    procedure SetPenWidth(AWidth: Double);
    procedure SetPenStyle(const AStylePen: DWORD; const AMiterLimit: Single);
    procedure SetPenGeometric(AStyle: DWORD);
    function SetRGN(const ASender: TObject; const ARGN: HRGN;
      const ADeleteRgn : Boolean = True): HRGN; virtual;
    procedure SetStretchBltModeInt(const AMode: Integer);
    procedure SetWidth(Value: Integer); override;
    {$IFDEF SGFPC}
    procedure SetTransparent(Value: Boolean); override;
    {$ENDIF}
    procedure Set3DRotDef(const ABox: TFRect; var ANeed2DViewByDefault: Boolean); virtual;
    procedure TransformToUCS(var APoint: TFPoint);
    procedure TransformToWorldCS(var APoint: TFPoint);
    property DefaultView: TsgDefaultView read GetDefaultView;
    property FColor: TColor read FDraw.Color write FDraw.Color;
    property FHCoef: Single read FDraw.YScale write FDraw.YScale;
    property IsRotToView: Boolean read FRotToView;
    property FAngle: Single read FDraw.Angle write FDraw.Angle;
    property FileInfo: string read FFileInfo write FFileInfo;
    property ObjectSnapMask: TObjectSnapState read FObjectSnapMask write FObjectSnapMask;
    property OnLayoutBeforeChange: TNotifyEvent read FOnLayoutBeforeChange write FOnLayoutBeforeChange;
    property OnMatrixChanged: TNotifyEvent read FOnMatrixChanged write FOnMatrixChanged;
    property OnMetafileExport: TsgObjMetafileExport read FOnMetafileExport
      write FOnMetafileExport;//set before export
    property RotCount: Integer read FRotCount;
    property LibraryGDIPlusExists: Boolean read FLibraryGDIPlusExists write FLibraryGDIPlusExists;
    property Stream: TMemoryStream read FStream write FStream;
    property SHXFontsProc: TsgSHXFontsProc read FSHXFontsProc{ write FSHXFontsProc};
  public
    constructor Create; override;
    destructor Destroy; override;
    procedure DrawRectInt(Rect: TRect; APrecision: Double = -1);
    function AbsSize: TF2DPoint;
    function AbsHeight: Extended;
    function AbsWidth: Extended;
    procedure AddScaledDXF(ACADFile: TObject; AName: string; APos, AScale: TFPoint; Rotation: Single);
    function AddScaledDXFEx(ACADFile: TObject; AName: string;
      APos, AScale: TFPoint; Rotation: Single;
      const AddXrefLayers: Boolean = True): TsgDXFInsert;
    procedure Assign(Source: TPersistent); override; //cadimage
    function CommonToInternalUnits(Pt: TFPoint): TFPoint; virtual;
{$IFDEF SGDEL_4}
{$IFNDEF SGFPC}
    function ExportToMetafile(AWidth,AHeight: Integer): TMetafile; overload;
    function ExportToMetafile(MaxDim: Integer): TMetafile; overload;
    function ExportToMetafile(var OffsetX, OffsetY, UnitSize: TsgFloat): TMetafile; overload;
{$ENDIF}
{$ELSE}
    procedure ExportToMetafile(const FileName: string; AWidth,AHeight: Integer);
{$ENDIF}
    procedure DrawRect(DC: HDC; SourceRect: TFRect; DestRect: TRect);
    procedure GetExtents;
{$IFDEF SGDEL_4}
    function GetCADCoords(const AXScaled, AYScaled: Extended): TFPoint; overload;
    function GetCADCoords(const AXScaled, AYScaled: Extended; var CoordsInUCS: TFPoint): TFPoint; overload;
{$ELSE}
    function GetCADCoords(const AXScaled, AYScaled: Extended): TFPoint;
{$ENDIF}
    function GetEntityColor(AEntity: TsgDXFEntity; AInsert: TsgDXFInsert): TColor; virtual;
    function GetDrawingExtents: TFRect;
    function GetPoint(const P: TFPoint): TPoint;
    function GetPointUCS(P: TFPoint): TPoint;
    function GetRealImagePoint(const P: TFPoint): TFPoint;
    function GetSnapData(const P: TPoint): PSnapData;
    function GetObjectSnapMask: TObjectSnapState;
    function GetExternalFiles(const AList: TStringList;
      const AMode: TsgExternalFilesModes = [efAddXref, efAddImageDef
      {$IFDEF DATA_LINK}, efDataLink{$ENDIF}]): Boolean;
    procedure SetObjectSnapMask(AValue: TObjectSnapState);
    function InternalToCommonUnits(Pt: TFPoint): TFPoint; virtual;
    procedure LoadFromClipboardFormat(Fmt: Word; Data: THandle; Pal: HPALETTE); {$IFNDEF SGFPC} override; {$ENDIF}
    procedure LoadFromFile(const FileName: string); override;
    procedure LoadFromStream(S: TStream); override;
    function Measurement: TsgMeasurement; virtual;
    procedure RefreshCurrentLayout;
    procedure ResetDrawingBox;

    procedure Rotate(Axis: TsgAxes; Angle: Extended);
    procedure SetDrawMatrix(const AMatrix: TFMatrix);
    procedure ScaleDrawMatrix(ASx, ASy, ASz: Double);
    procedure TranslateDrawMatrix(ADx, ADy, ADz: Double);

    procedure RotDefault;
    procedure RotToView(const A3DView: TsgDXFViewDirection);
    procedure SaveToClipboardFormat(var Fmt: Word; var Data: THandle; var Pal: HPALETTE); {$IFNDEF SGFPC} override; {$ENDIF}
    procedure SaveToFile(const FileName: string); override;
    procedure SaveToStream(S: TStream); override;
    procedure SetClippingRect(Value: PFRect);// not documented, only for internal using (!)
    procedure SetClippingRectExt(const AValue: TFRect);// not documented, only for internal using (!)
    procedure SetVisibleArea(Data: TPoint);
    procedure SetDefaultViewModePlotSettings; virtual;
    function GetVisibleArea: TPoint;
    procedure StopLoading; virtual;

    property CustomDraw: Boolean read FCustomDraw write FCustomDraw;

    property BackgroundColor: TColor read GetBackgroundColor write SetBackgroundColor;
    property PlotWindowAreaColor: TColor read FPlotWindowAreaColor write SetPlotWindowAreaColor;
    property Blocks [Index: Integer]: TsgDXFBlock read GetBlock;
    property BorderSize: TsgBorderSize read FBorderSize write FBorderSize;
    property BorderType: TsgBorderType read FBorderType write FBorderType;
    property CBFormat: Word read FCBFormat write FCBFormat;
    property Center: TFPoint read FCenter;
    property Clipping: TsgClipping read GetClipping write SetClipping;// not documented, only for internal using (!)
    property ClippingRect: PFRect read FClippingRect write SetClippingRect;// not documented, only for internal using (!)
    property ColorToLineWeight: TStringList read FColorToLineWeight;
    property Converter: TsgDXFConverter read FConverter;
    property CurrentLayout: TsgDXFLayout read FCurrentLayout write SetCurrentLayout;
    property DefaultColor: TColor read GetDefaultColor write SetDefaultColor;
    property DrawingBox: TFRect read FDrawingBox write SetDrawingBox;
    property DrawMode: TsgDXFDrawMode read FDrawMode write SetDrawMode;
    property Entities [Index: Integer]: TsgDXFEntity read GetEntity;
    property Extents: TFRect read FExtents write FExtents;
    property FileName: string read FFileName write FFileName;
    property IsDraw3DAxes: Boolean read FIsDraw3DAxes write FIsDraw3DAxes;
    property IsLoading: Boolean read GetIsLoading;
    property IsPlotting: Boolean read FIsPlotting write FIsPlotting;
    property IsProcessMessages: Boolean read FIsProcessMessages write FIsProcessMessages;
    property IsDrawingRotated: Boolean read GetIsDrawingRotated;
    property IsShowBackground: Boolean read FIsShowBackground write SetIsShowBackground;
    property IsShowLineWeight: Boolean read GetShowLineWeight write SetShowLineWeight;
    property IsCurLayoutShowPlot: Boolean read GetIsCurLayoutShowPlot;
    property IsWithoutBorder: Boolean read FIsWithoutBorder write SetIsWithoutBorder;
    property Layouts[Index: Integer]: TsgDXFLayout read GetLayout;
    property LayoutsCount: Integer read GetLayoutsCount;
    property LineScaled: Boolean read GetShowLineWeight write SetShowLineWeight;//old version
    property LineWeightScale: TsgFloat read GetLineWeightScale write SetLineWeightScale;
    property TTFMode: TsgTTFMode read FTTFMode write FTTFMode;
    property Guid: TGUID read FGuid;
    property Millimetres: Boolean read GetMillimetres write SetMillimetres;
    property NullWidth: Integer read GetNullWidth write SetNullWidth;
    property NullWidthExt: Double read FNullWidth write FNullWidth;

    property OnBeforeRotate: TNotifyEvent read FOnBeforeRotate write FOnBeforeRotate;
    property OnAfterRotate: TNotifyEvent read FOnAfterRotate write FOnAfterRotate;
    property OnAfterDraw: TNotifyEvent read FOnAfterDraw write SetOnAfterDraw;
    property OnLayoutChange: TNotifyEvent read FOnLayoutChange write FOnLayoutChange;
    property PureExtents: TFRect read FPureExtents;
    property ResizeDisproportionateDrawing: Boolean read FResizeDisproportionateDrawing
               write FResizeDisproportionateDrawing;
    property Scale: TFPoint read GetScale;
{Transferred from the protected visibility scope to the public visibility scope for internal use in "Editor" demo.
start}
    property SelectionMatrix: TsgSelectionMatrix read FSelectionMatrix write FSelectionMatrix;
    property GetMatrixMode: TsgGetSelectionMatrixModeProc read FGetSelectionMatrixModeProc;
    property SetMatrixMode: TsgSetSelectionMatrixModeProc read FSetSelectionMatrixModeProc;
{end}
    property ShowImages: Boolean read FShowImages write SetShowImages;
    property Stretch: Boolean read FStretch write SetStretch;
    property DeviceDPI: TPoint read FDeviceDPI write FDeviceDPI;
    property UseWinEllipse: Boolean read FUseWinEllipse write SetUseWinEllipse;
    property ViewRectangle: TFRect read FViewRectangle write FViewRectangle;
    property DimensionsVisible: Boolean read FDimensionsVisible write SetDimensionsVisible;
    property DrawMatrix: TFMatrix read FDraw.Matrix;
    property TextVisible: Boolean read FTextVisible write SetTextVisible;
    property OwnSource: Boolean read GetOwnSource write SetOwnSource;
    property Offset: TFPoint read FOffset write SetOffset;
    property CachingRasterMode: TsgCachingRasterMode read FCachingRasterMode write FCachingRasterMode;
    property UsePlotSetting: Boolean read FUsePlotSetting write SetUsePlotSetting;
    property ShowPlotSetting: Boolean read FShowPlotSetting write SetShowPlotSetting;
    property ShowPlotForModel: Boolean read FShowPlotForModel write SetShowPlotForModel;
    property ShowPlotFrame: Boolean read FShowPlotFrame write SetShowPlotFrame;
    property ShowPlotMargins: Boolean read FShowPlotMargins write SetShowPlotMargins;
    property Printing: TsgPrintMode read FPrinting write SetPrinting;
             //events for export
    property ExpPixel: TsgExpPixel read FsgExpPixel write FsgExpPixel;
    property ExpArc: TsgExpArc read FsgExpArc write FsgExpArc;
    property ExpPolyline: TsgExpPolyline read FsgExpPolyline write FsgExpPolyline;
    property ExpPolygon: TsgExpPolygon read FsgExpPolygon write FsgExpPolygon;
    property ExpPolyPolyline: TsgExpPolyPolyline read FsgExpPolyPolyline write FsgExpPolyPolyline;
    property ExpPolyPolygon: TsgExpPolyPolygon read FsgExpPolyPolygon write FsgExpPolyPolygon;
    property ExpText: TsgExpText read FsgExpText write FsgExpText;
    property ExpSetFont: TsgExpSetFont read FsgExpSetFont write FsgExpSetFont;
    property ExpSetStyle: TsgExpSetStyle read FsgExpSetStyle write FsgExpSetStyle;
    property ExpFillRgn: TsgExpFillRgn read FsgExpFillRgn write FsgExpFillRgn;
    property ExpClipRgn: TsgExpClipRgn read FsgExpClipRgn write FsgExpClipRgn;
    property ExpCloseFigure: TsgExpCloseFigure read FsgExpCloseFigure write FsgExpCloseFigure;
    property ExpImage: TsgExpImage read FsgExpImage write FsgExpImage;
    property ExpImageUV: TsgExpImageUV read FsgExpImageUV write FsgExpImageUV;
    property ExpSaveDC: TsgExpSaveDC read FsgExpSaveDC write FsgExpSaveDC;
    property ExpRestoreDC: TsgExpRestoreDC read FsgExpRestoreDC write FsgExpRestoreDC;
    property ExpProgress: TsgExpProgress read FsgExpProgress write FsgExpProgress;
    property ExpSetColor: TsgExpSetColor read FsgExpSetColor write FsgExpSetColor;
    property ExpSetPenWidth: TsgExpSetPenWidth read FsgExpSetPenWidth write FsgExpSetPenWidth;
    property ExpSetPenMiterLimit: TsgExpSetPenMiterLimit read FsgExpSetPenMiterLimit write FsgExpSetPenMiterLimit;
    property ExpSetPenGeometric: TsgExpSetPenGeometric read FsgExpSetPenGeometric write FsgExpSetPenGeometric;
    property PixelsPerInch: Integer read FPixelsPerInch write FPixelsPerInch default 1;
    property mmToPixelX: Double read FmmToPixelX write FmmToPixelX;
    property IsIterator: Boolean read FIsIterator write FIsIterator default False;
    property OnGetBox: TsgGetBox read FOnGetBox write FOnGetBox;
  end;

  TsgVectorImage = class(TsgCADImage)
  protected
    procedure ApplyLineWeightFactor(var ALineWeight: Double); override;
    function GetLineWeightFactor: Double; override;
    procedure SetDefaultPlotSettings(const ACheckSize: Boolean = False); override;
  public
    constructor Create; override;
    procedure SetDefaultViewModePlotSettings; override;
  end;

  TsgImageWithHandles = class(TsgCADImage)   // dwg, dxf
  protected
    function GetConverterParams: TsgConverterParams; override;
  public
    constructor Create; override;
    procedure SetDefaultViewModePlotSettings; override;
  end;

  TsgDXFImage = TsgCADImage;
  TsgDXFImageClass = class of TsgDXFImage;

  IsgChange = interface
    [cnstGUID_Change]
    procedure _BeginEnt(const AEnt: TsgDXFEntity; const AInternal: Boolean);
    procedure _BeginList(const AList: TList; const ACount: Integer; const AInternal: Boolean);
    procedure _Changed;
    procedure _EndEnt(const AEnt: TsgDXFEntity);
    procedure _EndList(const AList: TList; const ACount: Integer);
  end;

  function GetCADFile(const AFileName: string): TsgCADImage;
  procedure RotateBitmap(Bitmap: TBitmap; Angle: Double; BackColor: TColor);
  procedure RotatePicture(Picture: TPicture; Angle: Double; BackColor: TColor);
  function IsDrawGDI(var AAngleX, AAngleY: Double): Boolean;

var
  Drawing: TsgCADImage;
  MinDXFSize: Integer;
{$IFNDEF BCB}
threadvar
  Loading: TsgCADImage;
{$ELSE}
var
  Loading: TsgCADImage;
{$ENDIF}


implementation
uses
  ActiveX, ComObj, Math, SysUtils, MVFont, sgBitmap, sgIterator;

const
  cnstMaxTextHeight = 8192;// Solution of the big fonts GDI-problem
  cnstMaxCapacity  = 1000000;
  cnstDefaultTextAlign = (TA_LEFT or TA_TOP) and TA_NOUPDATECP;
  cnstDefaultCapacity = 100000;
  cnstDefaultLineWeightFactor = 1.0;
  cnstCADLineWeightMax =  8.875;

type
  PTriVertex = ^TTriVertex;
  TTriVertex = record
    X,Y: Integer;
    Red,Green,Blue,Alpha: Word;
  end;
  TGradFill = function(DC: HDC; PV: PTriVertex; NumV: Integer; PMesh: Pointer; NMesh,Mode: Integer): LongBool; stdcall;
  TsgDXFConverterAccess = class(TsgDXFConverter);
  TsgCADGradientPolygonAccess = class(TsgCADGradientPolygon);
  TsgCADWipeoutAccess = class(TsgCADWipeout);
  TsgDXFImageEntAccess = class(TsgDXFImageEnt);
  TsgDXFPointAccess = class(TsgDXFPoint);
  TsgBitmapAccess = class(TsgBitMap);
  TsgDXFCircleAccess = class(TsgDXFCircle);
  TsgCADBasePolyLineAccess = class(TsgCADBasePolyline);
  TsgDXFPolylineAccess = class(TsgDXFPolyline);
  TsgDXFEntityAccess = class(TsgDXFEntity);
  TsgDXFInsertAccess = class(TsgDXFInsert);
  TsgDXFGroupAccess = class(TsgDXFGroup);
  TsgDXFViewportAccess = class(TsgDXFViewport);
  TsgDXFOle2FrameAccess = class(TsgDXFOle2Frame);
  TsgDXFTextAccess = class(TsgDXFText);
  TsgDXF3dFaceAccess = class(TsgDXF3dFace);
  TsgDXFSolidAccess = class(TsgDXFSolid);

var
  AcadPal: HPalette;
  Msimg32: THandle;
  GradientFill: TGradFill;
  StdLines: TsgLines = nil;


function PLibraryGDIPlusExists: Boolean;
{$IFDEF SG_USEGDIPLUS}
// Use GDI +
var
  GdiPlus: THandle;
{$ENDIF}
begin
{$IFDEF SG_USEGDIPLUS}
  GdiPlus := 0;
  try
    GdiPlus := LoadLibrary('GdiPlus.dll');
  finally
    Result := GdiPlus <> 0;
    FreeLibrary(GdiPlus);
  end;
{$ELSE}
  Result := False;
{$ENDIF}
end;

function GFStub(DC: HDC; PV: PTriVertex; NumV: Integer; PMesh: Pointer; NMesh,Mode: Integer): LongBool; stdcall;
var
  HBr: HBrush;
  R: TRect;
begin
  Result := NumV > 1;
  if not Result then Exit;
  R.TopLeft := Point(PV.X, PV.Y); Inc(PV);
  R.BottomRight := Point(PV.X, PV.Y); Dec(PV);
  HBr := CreateSolidBrush(PV.Red and $FF00 shr 8 + PV.Green and $FF00 + PV.Blue and $FF00 shl 8);
  FillRect(DC,R,HBr);
  DeleteObject(HBr);
end;

procedure InitGradFill;
begin
  GradientFill := GFStub;
  Msimg32 := LoadLibrary('msimg32.dll');
  if Msimg32 <> 0 then GradientFill := GetProcAddress(Msimg32,'GradientFill');
end;

procedure CreateAcadPal;
var
  I: Integer;
  P: TMaxLogPalette;
  LP: TLogPalette absolute P;
begin
  P.palVersion := $300;
  P.palNumEntries := 216;
  for I:=0 to 215 do
  begin
    P.palPalEntry[I].peRed := I mod 6 * 51;
    P.palPalEntry[I].peGreen := I div 6 mod 6 * 51;
    P.palPalEntry[I].peBlue := I div 36 * 51;
    P.palPalEntry[I].peFlags := 0;
  end;
  AcadPal := CreatePalette(LP);
end;

function GetCADFile(const AFileName: string): TsgCADImage;
var
  vPicture: TPicture;
begin
  Result := nil;
  vPicture := TPicture.Create;
  try
    vPicture.LoadFromFile(AFileName);
    if vPicture.Graphic is TsgCADImage then
    begin
      Result := TsgCADImageClass(vPicture.Graphic.ClassType).Create;
      Result.Assign(vPicture.Graphic);
      Result.IsWithoutBorder := True;
    end;
  finally
    vPicture.Free;
  end;
end;

function GetPointOfRotateByCenter(const APoint, ACenter: TPoint; const Angle: Double): TPoint;
var
  vAngle, vDistance, vDX, vDY: Double;
  S, C: Extended;
begin
  vDX := APoint.X - ACenter.X;
  vDY := APoint.Y - ACenter.Y;
  vDistance := vDX * vDX + vDY * vDY;
  if vDistance > fAccuracy then
    vDistance := Sqrt(vDistance)
  else
    vDistance := 0;
  vAngle := (GetAngleByPoints(MakeFPoint(ACenter.X,ACenter.Y),
    MakeFPoint(APoint.X,APoint .Y), False, 0) + Angle) * fPiDividedBy180;
  SinCos(vAngle, S, C);
  Result.X := ACenter.X + Round(vDistance * C);
  Result.Y := ACenter.Y + Round(vDistance * S);
end;

procedure SetListCapacity(const AList: TsgBaseList; const ASetDefault: Boolean);
begin
  AList.Count := 0;
  if ASetDefault then
    AList.Capacity := cnstDefaultCapacity
  else
  begin
    if AList.Capacity > cnstMaxCapacity then
      AList.Capacity := cnstMaxCapacity;
  end;
end;

procedure RotatePicture(Picture: TPicture; Angle: Double; BackColor: TColor);
var
  SG: TsgBitmap;
  Bitmap: TGraphic;
begin
  Bitmap := Picture.Graphic;
  if Bitmap is TsgBitmap then begin
    TsgBitmap(Bitmap).Rotate(Round(Angle));
    Exit;
  end;
  if not (Bitmap is TBitmap) then Exit;
  SG := TsgBitmap.Create;
  try
    SG.Assign(Bitmap);
    SG.Rotate(Round(Angle));
    Picture.Graphic := SG;
  finally
    SG.Free;
  end;
end;

function IsDrawGDI(var AAngleX, AAngleY: Double): Boolean;
begin
  if sgIsZero(AAngleX - 0) then
    AAngleX := 0;
  if sgIsZero(AAngleY - 90) then
    AAngleY := 90;
  Result := (AAngleX = 0) and (AAngleY = 90);
end;

procedure RotateBitmap(Bitmap: TBitmap; Angle: Double; BackColor: TColor);
const
  cnstMaxBmpHeight = 8191;
type
  TRGB = record
    B, G, R: Byte;
  end;
  pRGB = ^TRGB;
var
  x, y, W, H, v1, v2: Integer;
  Dest, Src: pRGB;
  VertArray: array[0..cnstMaxBmpHeight] of pByteArray;
  Bmp: TBitmap;
begin
  Angle := Angle - Floor(Angle / 360) * 360;
  try
    while Angle < 0 do
    Angle := Angle + 360;
    Bitmap.PixelFormat := pf24Bit;
    Bmp := TBitmap.Create;
    try
      Bmp.Assign(Bitmap);
      Bmp.FreeImage;
      W := Bitmap.Width - 1;
      H := Bitmap.Height - 1;
      if H > cnstMaxBmpHeight then
        H := cnstMaxBmpHeight;
      case Trunc(Angle) of
        90, 270:
        begin
          Bitmap.Width := H + 1;
          Bitmap.Height := W + 1;
          v1 := 0;
          v2 := 0;
          if Trunc(Angle) = 90 then
            v1 := H
          else
            v2 := W;
          for y := 0 to H do
            VertArray[y] := Bmp.ScanLine[Abs(v1 - y)];
          for x := 0 to W do
          begin
            Dest := Bitmap.ScanLine[x];
            for y := 0 to H do
            begin
              v1 := Abs(v2 - x)*3;
              with Dest^ do
              begin
                B := VertArray[y, v1];
                G := VertArray[y, v1+1];
                R := VertArray[y, v1+2];
              end;
              Inc(Dest);
            end;
          end
        end;
        180:
        begin
          for y := 0 to H do
          begin
            Dest := Bitmap.ScanLine[y];
	          Src := Bmp.ScanLine[H - y];
            Inc(Src, W);
            for x := 0 to W do
            begin
              Dest^ := Src^;
              Dec(Src);
              Inc(Dest);
            end;
          end;
        end;
      end;
    finally
      Bmp.Free;
    end;
    if not Bitmap.Modified then Bitmap.Modified := True;
  except
  end;
end;

procedure DrawPolyLine(DC: HDC; IntPoints: TsgIntegerList);
begin
  Windows.Polyline(DC, IntPoints.List[0], IntPoints.Count shr 1);
end;

procedure DrawPolyPolyLine(DC: HDC; IntPoints: TList);
var
  I, N, C: Integer;
  P: Pointer;
begin
  N := IntPoints.Count shr 2;
  if N = 0 then
    Exit;
  C := IntPoints.Count;
  for I := 0 to N - 1 do
    IntPoints.Add(Pointer(2));
  P := IntPoints.List;
  Inc(PInteger(P), C);
  PolyPolyline(DC, IntPoints.List[0], P^, N);
end;

procedure AddPtToList(AList: TList; const AP1: TPoint); overload;
begin
  if AList = nil then
    Exit;
  AList.Add(Pointer(AP1.X));
  AList.Add(Pointer(AP1.Y));
end;

procedure AddPtToList(AList: TsgIntegerList; const AP1: TPoint); overload;
begin
  if AList = nil then
    Exit;
  AList.Add(AP1.X);
  AList.Add(AP1.Y);
end;

procedure SetNewBox(const P1, P2, P3, P4: TPoint; var NewBox: TRect);
begin
  ExpandRect(NewBox, P1);
  ExpandRect(NewBox, P2);
  ExpandRect(NewBox, P3);
  ExpandRect(NewBox, P4);
end;

{ TsgCADImage }

constructor TsgCADImage.Create;
begin
{$IFDEF SG_MODULE_LOG}
  Log.Add('$' + IntToHex(TsgNativeUInt(Self), 0) + ' := '+ ClassName + '.Create;');
{$ENDIF}
  if CreateGUID(FGuid) <> 0 then
    FGuid := cnstFailCreateGuid;
//  SetDefaultViewPlotSettingsMode;
  FAddOnePixel := True;
  FCustomDraw := True;
  LibraryGDIPlusExists := PLibraryGDIPlusExists;
  FDraw.Matrix := cnstIdentityMat;
  FFileName := '';
  FLineWeightScale := 1.0;
  FViewRectangle := BadRect;
  FConverter := CreateConverter;
  FPoly := TsgIntegerList.Create;
  FCanvasParams.Brush := TBrush.Create;
  FCanvasParams.Font := TFont.Create;
  FCanvasParams.Pen := TPen.Create;
  FConverter.OnCreate := EntityCreated;
  FConverter.BeforeRead := BeginRead;
  FConverter.AfterRead := EndRead;
  FConverter.OnRead := DoRead;
  FStretch := True;
  FIsShowBackground := True;
  FIsShowLineWeight := True;
  FShowImages := True;
  FDrawMode := dmNormal;
  FBackgroundColor := clWhite;
  FChangeBackgroundColor := GetColorByBackgroud(FBackgroundColor);
  FDefaultColor := clBlack;
  FPlotWindowAreaColor := cnstPlotWindowAreaColor;
  FMillimetres := -1;
  FIntPoints := TsgIntegerList.Create;
  FDotsPoints := TsgIntegerList.Create;
  FCounts := TsgIntegerList.Create; //evg
  FCounts.Capacity := 100; //evg
  FDottedSingPts := TFPointList.Create; //evg
  F2Counts := TsgIntegerList.Create;
  F3Counts := TsgIntegerList.Create;
  FColorToLineWeight := TStringList.Create;
  FIsProcessMessages := True; // process the messages
  FDrawingBox := BadRect;
  FStream := TMemoryStream.Create;
  FDimensionsVisible := True;
  FTextVisible := True;
  FBorderSize := cnstBorderSize;
  FBorderType := cnstBorderType;
  ContainerOfTextGlyphs.Reference;
  FSHXFontsProc := GetSHXFontsProc;
  FVisibleArea := Point(0, 0);
  FSelectionMatrixMode := smDisabled;
  FGetSelectionMatrixModeProc := GetSelectionMatrixProc;
  FSetSelectionMatrixModeProc := SetSelectionMatrixProc;
  FCachingRasterMode := bCachingRasterMode;
  FXrefStack := TList.Create;
  FSnapMatrix := TsgSnapMatrix.Create;
  //FIsDraw3DAxes := True;
  SetListsCapacity(True);
  FUsePrecision := False;
  FPrecision := -1;
end;

destructor TsgCADImage.Destroy;
begin
  FSelectionMatrix.Free;
  FIntPoints.Free;
  FDotsPoints.Free;
  Fcounts.Free;
  FDottedSingPts.Free;
  F2Counts.Free;
  F3Counts.Free;
  FPoly.Free;
  FCanvasParams.Brush.Free;
  FCanvasParams.Font.Free;
  FCanvasParams.Pen.Free;
  FColorToLineWeight.Free;
  FConverter.Release;
  ContainerOfTextGlyphs.Release;
  DisposeAndNil(FClippingRect);
  FStream.Free;
  FSnapMatrix.Free;
  FXrefStack.Free;
  inherited Destroy;
end;


function GetDrawRect(const ADrawRect: TRect; const AExtents: TFRect;
  const AClippingRect: PFRect): TRect;
var
  K: Double;
  vRectWidth, vRectHeight: Integer;
begin
  Result := ADrawRect;
  if Assigned(AClippingRect) then
  begin
    vRectWidth := Result.Right - Result.Left;
    K := 1;
    if AClippingRect^.Right - AClippingRect^.Left <> 0 then
      K := vRectWidth / (AClippingRect^.Right - AClippingRect^.Left);
    Result.Left := Result.Left - Round(AClippingRect^.Left * K);
    if AClippingRect^.Right - AClippingRect^.Left <> 0 then
      K := (AExtents.Right - AExtents.Left) / (AClippingRect^.Right - AClippingRect^.Left);
    Result.Right := Result.Left + Round(vRectWidth * K);
    vRectHeight := Result.Bottom - Result.Top;
    if AClippingRect^.Bottom - AClippingRect^.Top <> 0 then
      K := vRectHeight / (AClippingRect^.Bottom - AClippingRect^.Top);
    Result.Top := Result.Top - Round(AClippingRect^.Top * K);
    if AClippingRect^.Bottom - AClippingRect^.Top <> 0 then
      K := (AExtents.Top - AExtents.Bottom) / Abs(AClippingRect^.Bottom - AClippingRect^.Top);
    Result.Bottom := Result.Top + Round(vRectHeight * K);
  end;
end;
//evg
procedure TsgCADImage.DrawRectInt(Rect: TRect; APrecision: Double = -1);
var
  vRect, vPrint: TRect;
  I: Integer;
  vClippingRect: PFRect;
  vPlotPrintable: TFRect;
  vRGN: HRGN;
begin
  if FCurrentLayout = nil then Exit;
  vClippingRect := GetRealClip;
  vRect := GetDrawRect(Rect,  GetDrawingExtents, vClippingRect);
  Drawing := Self;
  try
    ApplyScale(vRect)
  except
    Exit
  end;
  FDrawRect := Rect;
  if APrecision <> -1 then
  begin
    FPrecision := APrecision;
    SetDrawMatrix(cnstIdentityMat);
    FDrawRect := Classes.Rect(-maxint, -maxint, maxint, maxint);
  end;
  // Set converter initial parameters
  Converter.AutoInsert := False;
  Converter.Params := @FDraw;
  FSnapLastPoint.X := MaxDouble;     //evg
  FSnapLastPoint.Y := MaxDouble;//evg
  GetPixelSize(1, FDxyz.X, FDxyz.Y, True);
  //evg - to DrawRect!!!
  FColorPen := clWhite; //evg - temp
  FColorBrush := clWhite; //evg - temp
  DoSetColor(clBlack, ctPen);

  vPlotPrintable := CurrentLayout.PlotSettings.PlotMarginsArea;
  vPrint := cnstBad2DRect;
  ExpandRect(vPrint, GetPoint(vPlotPrintable.TopLeft));
  ExpandRect(vPrint, GetPoint(vPlotPrintable.BottomRight));

  DoSetColor(clBlack, ctBrush);
  FSaveDC := TList.Create;
  if Assigned(vClippingRect) then
    vRGN := CreateRectRgnIndirect(Rect)
  else
  begin
    vRGN := GetPlotSettingsRGN;
  end;
  ExpClipRgnInternal(nil, vRGN);
  CurrentLayout.Iterate(Converter, DrawEntity, DoFinish);
  if FIsDraw3DAxes then
    Draw3DAxes;
  FZRotate := 0;
  for I:=0 to FSaveDC.Count-1 do
    DeleteObject(HRgn(FSaveDC[I]));
  FreeAndNil(FSaveDC);
  DeleteObject(FClipRgn);
  FClipRgn := 0;
end;

function TsgCADImage.AbsHeight: Extended;
begin
  Result := AbsSize.Y;
end;

function TsgCADImage.AbsSize: TF2DPoint;
var
  vRect: PFRect;
  vExtents: TFRect;
begin
  Result.X := FXMax - FXMin;
  Result.Y := FYMax - FYMin;
  if UsePlotSetting then
  begin
    vExtents := GetDrawingExtents;
    Result.X := Abs(vExtents.Right - vExtents.Left);
    Result.Y := Abs(vExtents.Bottom - vExtents.Top);
  end
  else
  begin
    vRect := GetRealClip;
    if vRect <> nil then
    begin
      Result.X := vRect.Right - vRect.Left;
      Result.Y := vRect.Bottom - vRect.Top;
    end;
  end;
end;

function TsgCADImage.AbsWidth: Extended;
begin
  Result := AbsSize.X;
end;

procedure TsgCADImage.SetEntityVisibility(ACADFile: TObject);
begin
  if ACADFile is TsgCADImage then
  begin
    TsgCADImage(ACADFile).TextVisible := TextVisible;
    TsgCADImage(ACADFile).DimensionsVisible := DimensionsVisible;
  end;
end;

procedure TsgCADImage.AddScaledDXF(ACADFile: TObject; AName: string; APos, AScale: TFPoint;
  Rotation: Single);
begin
  SetEntityVisibility(ACADFile);
  Converter.AddXRef(ACADFile, AName, APos, AScale, Rotation);
  GetExtents;
end;

function TsgCADImage.AddScaledDXFEx(ACADFile: TObject; AName: string; APos, AScale: TFPoint;
  Rotation: Single; const AddXrefLayers: Boolean = True): TsgDXFInsert;
begin
  SetEntityVisibility(ACADFile);
  Result := Converter.AddXRefEx(ACADFile, AName, APos, AScale, Rotation,
    CurrentLayout, AddXrefLayers);
  GetExtents;
end;

procedure TsgCADImage.Assign(Source: TPersistent);
var
  vPos: Integer;
begin
  if Source is TsgCADImage then
  begin
    FConverter.Release;
    FConverter := TsgCADImage(Source).Converter;
    FConverter.Reference;
    Self.FXMin := TsgCADImage(Source).FXMin;
    Self.FXMax := TsgCADImage(Source).FXMax;
    Self.FYMin := TsgCADImage(Source).FYMin;
    Self.FYMax := TsgCADImage(Source).FYMax;
    Self.FZMin := TsgCADImage(Source).FZMin;
    Self.FZMax := TsgCADImage(Source).FZMax;
    Self.FCenter := TsgCADImage(Source).FCenter;
    Self.FColorToLineWeight.Assign(TsgCADImage(Source).FColorToLineWeight);
    Self.FCurrentLayout := TsgCADImage(Source).FCurrentLayout;
    Self.FBackgroundColor := TsgCADImage(Source).FBackgroundColor;
    Self.FChangeBackgroundColor := TsgCADImage(Source).FChangeBackgroundColor;
    Self.FDefaultColor := TsgCADImage(Source).FDefaultColor;
    Self.DimensionsVisible := TsgCADImage(Source).DimensionsVisible;
    Self.DrawingBox := TsgCADImage(Source).DrawingBox;
    Self.DrawMode := TsgCADImage(Source).DrawMode;
    Self.SetClippingRect(TsgCADImage(Source).FClippingRect);
    Self.UsePlotSetting := TsgCADImage(Source).UsePlotSetting;
//    Self.ShowPlotSetting := TsgCADImage(Source).ShowPlotSetting; // this use to actual cadImage ONLY
    Self.PlotWindowAreaColor := TsgCADImage(Source).PlotWindowAreaColor;
    Self.TextVisible := TsgCADImage(Source).TextVisible;
    Self.UseWinEllipse := TsgCADImage(Source).UseWinEllipse;
    Self.BorderSize := TsgCADImage(Source).BorderSize;
    Self.BorderType := TsgCADImage(Source).BorderType;
    Self.IsWithoutBorder := TsgCADImage(Source).IsWithoutBorder;
    Self.FileInfo := TsgCADImage(Source).FileInfo;
    if KeepOriginal then
    begin
      vPos := TsgCADImage(Source).Stream.Position;
      TsgCADImage(Source).Stream.Position := 0;
      Self.FStream.Clear;
      Self.FStream.CopyFrom(TsgCADImage(Source).Stream, TsgCADImage(Source).Stream.Size);
      TsgCADImage(Source).Stream.Position := vPos;
      Self.FStream.Position := 0;
    end;
    ResetExtents;
    Changed(Self);
  end
  else
    inherited Assign(Source);
end;

function TsgCADImage.GetIsCurLayoutShowPlot: Boolean;
begin
  Result := ShowPlotSetting and ((CurrentLayout.IsModel and ShowPlotForModel) or
    (not CurrentLayout.IsModel));
end;

function TsgCADImage.GetIsDrawingRotated: Boolean;
  function IsMatrixRotated(const M: TFMatrix): Boolean;
  var
    I, J: Integer;
  begin
    for I := 0 to 2 do
      for J := 0 to 2 do
      begin
        Result := Abs(M.M[I,J]-Ord(I=J)) > fAccuracy;// if I=J, then M[I,J]<>1
        if Result then
          Exit;
      end;
  end;
begin
  Result := IsMatrixRotated(FCurrentLayout.RotMatrix);
end;

procedure TsgCADImage.ExpPolylineInteger(const Sender: TObject; var Points; Count: Integer);
begin
  if Assigned(FsgExpPolyline) then //evg
    FsgExpPolyline(Points, Count)
  else
  begin
    if IsDrawOnBitMap then
    begin
      AddSelectionMatrix(Sender);
      SelectionMatrix.Changed;
      Windows.Polyline(SelectionMatrix.Handle, Points, Count);
    end;
    if IsDrawOnCanvas then
      Windows.Polyline(FCanvas.Handle, Points, Count);
  end;
end;

procedure TsgCADImage.ExpPolyPolylineLists(const Sender: TObject; APoints : TsgIntegerList;
  ACounts: Pointer; ACount: Integer; const ACheckDrawOnBitMap: Boolean = True);
var
  I: Integer;
  vPPoint: PPoint;
begin
 {$IFDEF NOGDI} Exit; {$ENDIF}
   if Assigned(FsgExpPolyPolyline) then //evg
    FsgExpPolyPolyline(APoints.List[0], ACounts^, ACount)
  else
  begin
    if IsDrawOnBitMap and ACheckDrawOnBitMap then
    begin
      AddSelectionMatrix(Sender);
      SelectionMatrix.Changed;
    end;
    vPPoint := PPoint(APoints.List);
    if APoints.Count < 4000 then   // polypolyline works fast only for limited nubmer of points
    begin
      if IsDrawOnBitMap and ACheckDrawOnBitMap then
        Windows.PolyPolyline(SelectionMatrix.Handle, APoints.List[0], ACounts^, ACount);
      if IsDrawOnCanvas then
        Windows.PolyPolyline(FCanvas.Handle, APoints.List[0], ACounts^, ACount);
    end
    else
      for I := 0 to ACount - 1 do
      begin
        if IsDrawOnBitMap and ACheckDrawOnBitMap then
          Windows.Polyline(SelectionMatrix.Handle, vPPoint^, Integer(ACounts^));
        if IsDrawOnCanvas then
          Windows.Polyline(FCanvas.Handle, vPPoint^, Integer(ACounts^));
        Inc(vPPoint, Integer(ACounts^));
        Inc(PInteger(ACounts));
      end;
  end;
end;

procedure TsgCADImage.ExpFillRectInternal(const Sender: TObject; const ARect: TRect);
var
  vPoints: array [0..4] of TPoint;
begin
  vPoints[0] := ARect.TopLeft;
  vPoints[1] := Point(ARect.Right, ARect.Top);
  vPoints[2] := ARect.BottomRight;
  vPoints[3] := Point(ARect.Left, ARect.Bottom);
  vPoints[4] := vPoints[0];
  ExpPolygonInteger(Sender, vPoints, 5);
end;

procedure TsgCADImage.ExpRestoreDCInternal(const ASender: TObject;
  const AIndex: Integer);
begin
  if FIsIterator then
  begin
    if Assigned(FsgExpRestoreDC) and Assigned(FsgExpSaveDC) then
    begin
      if FSaveDC.Count > 0 then
      begin
        DeleteObject(FClipRgn);
        FClipRgn := HRgn(FSaveDC.Last);
        FSaveDC.Count := FSaveDC.Count - 1;
      end;
      FsgExpRestoreDC;
    end;
  end
  else
  begin
    if ASender <> nil then
    begin
      RestoreDC(FCanvas.Handle, AIndex);
      GetclipBox(FCanvas.Handle, FDrawRect);
    end;
  end;
end;

function TsgCADImage.ExpSaveDCInternal(const ASender: TObject): Integer;
var
  R: HRgn;
begin
  if FIsIterator then
  begin
    if Assigned(FsgExpSaveDC) and Assigned(FsgExpRestoreDC) then
    begin
      R := FClipRgn;
      if R <> 0 then
      begin
        R := CreateRectRgn(0,0,0,0);
        CombineRgn(R, FClipRgn, 0, RGN_COPY);
      end;
      FSaveDC.Add(Pointer(R));
      FsgExpSaveDC;
    end;
    Result := 0;
  end
  else
  begin
    Result := 0;
    if ASender <> nil then
      Result := SaveDC(FCanvas.Handle);
  end;
end;

procedure TsgCADImage.ExpSolidInternal(const ASender: TObject; var ASolid,
  APts: array of TPoint; AHasZTick: Boolean);

type
  TCustomDrawPoly = function(DC: HDC; const Points; Count: Integer): BOOL; stdcall;

  function DoExportPolyline(AContext: TsgNativeUInt; const APoints; Count: Integer): BOOL; stdcall;
  begin
    TsgCADImage(AContext).FsgExpPolyline(APoints, Count);
    Result := Count > 0;
  end;

  function DoExportPolygon(AContext: TsgNativeUInt; const APoints; Count: Integer): BOOL; stdcall;
  begin
    TsgCADImage(AContext).FsgExpPolygon(APoints, Count);
    Result := Count > 0;
  end;

  procedure DoCustomDrawSolid(const ASolids, APoints: array of TPoint;
    ACustomDrawPolyLine, ACustomDrawPolygon: TCustomDrawPoly; AContext: TsgNativeUInt);
  var
    I: Integer;
    P: array[0 .. 1] of TPoint;
  begin
    if AHasZTick then
    begin
      ACustomDrawPolyLine(AContext, ASolids, High(ASolids) - Low(ASolids) + 1);
      if Length(APoints) > 0 then
      begin
        ACustomDrawPolyLine(AContext, APoints, High(APoints) - Low(APoints) + 1);
        for I := Low(APoints) to High(APoints) do
        begin
          P[0] := ASolids[I];
          P[1] := APoints[I];
          ACustomDrawPolyLine(AContext, P[0], 2);
        end;
      end;
    end
    else
      ACustomDrawPolygon(AContext, ASolids, High(ASolids) - Low(ASolids) + 1);
  end;

  procedure DoDrawSolid(ACustomDrawPolyLine, ACustomDrawPolygon: TCustomDrawPoly;
    AContext: TsgNativeUInt);
  begin
    DoCustomDrawSolid(ASolid, APts, ACustomDrawPolyLine, ACustomDrawPolygon,
      AContext);
  end;

begin
  if FIsIterator then
    DoDrawSolid(@DoExportPolyline, @DoExportPolygon, TsgNativeUInt(Self))
  else
  begin
    if IsDrawOnBitMap then
    begin
      AddSelectionMatrix(ASender);
      SelectionMatrix.Pen.Width := 0;
      SelectionMatrix.Brush.Style := bsSolid;
      SelectionMatrix.Changed;
      DoDrawSolid(@Windows.Polyline, @Windows.Polygon, SelectionMatrix.Handle);
      SelectionMatrix.Brush.Style := bsClear;
    end;
    if IsDrawOnCanvas then
      DoDrawSolid(@Windows.Polyline, @Windows.Polygon, FCanvas.Handle);
  end;
end;

procedure TsgCADImage.ExpPixelInteger(const Sender: TObject; APoint: TPoint; AColor: TColor);
begin
 {$IFDEF NOGDI} Exit; {$ENDIF}
 if AColor = clNone then
    AColor := GetDrawPenColor;
  if Assigned(FsgExpPixel) then //evg
    FsgExpPixel(APoint, AColor)
  else
  begin
    if IsDrawOnBitMap then
    begin
      AddSelectionMatrix(Sender);
      SelectionMatrix.Changed;
      SetPixelV(SelectionMatrix.Handle, APoint.X, APoint.Y, TColor(SelectionMatrix.CurrColor - 1));
    end;
    if IsDrawOnCanvas then
      if IsPlotting then
      begin //printer
        DoSetColor(AColor, ctPen);
        FCanvas.MoveTo(APoint.X, APoint.Y);
        FCanvas.LineTo(APoint.X, APoint.Y + 1);
      end
      else
        SetPixelV(FCanvas.Handle, APoint.X, APoint.Y, AColor)
  end;
end;

procedure TsgCADImage.ExpArcInteger(const Sender: TObject; X1, Y1, X2, Y2, X3, Y3, X4, Y4: Integer);
begin
 {$IFDEF NOGDI} Exit; {$ENDIF}
  if Assigned(FsgExpArc) then
    FsgExpArc(X1, Y1, X2, Y2, X3, Y3, X4, Y4)
  else
  begin
    if IsDrawOnBitMap then
    begin
      AddSelectionMatrix(Sender);
      SelectionMatrix.Changed;
      Windows.Arc(SelectionMatrix.Handle, X1, Y1, X2, Y2, X3, Y3, X4, Y4)
    end;
    if IsDrawOnCanvas then
      Windows.Arc(FCanvas.Handle, X1, Y1, X2, Y2, X3, Y3, X4, Y4)
  end;
end;

procedure TsgCADImage.ExpArrowsInternal(const ASender: TObject;
  const APoly: TsgIntegerList; const AHasZTick: Boolean);
type
  PsgArrow = ^TsgArrow;
  TsgArrow = array [0..3] of TPoint;
  TsgArrowClosed = array [0..4] of TPoint;

  procedure DrawArrowClosed(const AArrow: PsgArrow);
  var
    vArrowClosed: TsgArrowClosed;
  begin
    if AArrow <> nil then
    begin
      CopyMemory(@vArrowClosed, AArrow, SizeOf(TsgArrow));
      vArrowClosed[4] := vArrowClosed[0];
      ExpPolylineInteger(ASender, vArrowClosed, 5);
    end;
  end;

var
  I, J, vCnt, vCntSub8: Integer;
  A1, A2: PsgArrow;
  vLines: TsgIntegerList;
begin
  vLines := TsgIntegerList.Create;
  try
    if AHasZTick then
    begin
      Fill2Counts(5);
      vCnt := APoly.Count div 2;
    end
    else
      vCnt := APoly.Count;
    vCntSub8 := APoly.Count - 8;
    I := 0;
    while I < vCnt do
    begin
      A1 := @APoly.List[I];
      if AHasZTick then
      begin
        J := I + vCnt;
        if J <= vCntSub8 then
          A2 := @APoly.List[J]
        else
          A2 := nil;
        Inc(I, 8);
        DrawArrowClosed(A1);
        if A2 <> nil then
        begin
          DrawArrowClosed(A2);
          vLines.Count := 0;
          for J := 0 to 3 do
            vLines.AppendArray([A1^[J].X, A1^[J].Y, A2^[J].X, A2^[J].Y]);
          vLines.AppendArray([A1^[0].X, A1^[0].Y, A2^[0].X, A2^[0].Y]);
          ExpPolyPolylineLists(ASender, vLines, F2Counts.List, 5);
        end;
      end
      else
      begin
        Inc(I, 8);
        ExpPolygonInteger(ASender, A1^, 4);
      end;
    end;
  finally
    vLines.Free;
  end;
end;

procedure TsgCADImage.ExpBitBlt(const ASender: TObject; const X, Y, Width,
  Height: Integer; const ABitMap: TBitmap; const SX: Integer = 0;
  const SY: Integer = 0; const ARop: Cardinal = SRCCOPY);
var
  vRect: TRect;
  vIsDrawOnBitMap: Boolean;
begin
  if FIsIterator then
  begin
    vRect := Rect(X, Y, X + Width, Y + Height);
    ExpImageGDIInternal(ASender, vRect, ABitMap);
  end
  else
  begin
    vIsDrawOnBitMap := IsDrawOnBitMap;
    if (ASender is TsgDXFImageEnt) and (TsgDXFImageEnt(ASender).Flags and 1 <> 0) then
      vIsDrawOnBitMap := False;
    if vIsDrawOnBitMap then
    begin
      vRect := Rect(X, Y, X + Width, Y + Height);
      AddSelectionMatrix(ASender);
      SelectionMatrix.Brush.Style := bsSolid;
      SelectionMatrix.Changed;
      Windows.FillRect(SelectionMatrix.Handle, vRect, SelectionMatrix.Brush.Handle);
      SelectionMatrix.Brush.Style := bsClear;
    end;
    if IsDrawOnCanvas then
      BitBlt(FCanvas.Handle, X, Y, Width, Height, ABitMap.Canvas.Handle, SX, SY, ARop);
  end;
end;

function TsgCADImage.ExpClipRgnInternal(const ASender: TObject;
  const AHRng: HRgn): Boolean;
var
  P,R: PRgnDataHeader;
  Size: Integer;
begin
  Result := True;
  if FIsIterator  then
  begin
    if Assigned(FsgExpFillRgn) then
    begin
      if FClipRgn = 0 then
      begin
        Result := False;
        FClipRgn := AHRng;
      end
      else
        CombineRgn(FClipRgn, FClipRgn, AHRng, RGN_AND);
      Size := GetRegionData(AHRng,0,nil);
      GetMem(P,Size);
      try
        if GetRegionData(AHRng, Size, PRgnData(P)) = 0 then
          Exit;
        R := P;
        Inc(R);
        FsgExpClipRgn(PRect(R), P.nCount);
      finally
        FreeMem(P);
      end;
    end;
  end
  else
    if ASender <> nil then
      SetRGN(ASender,AHRng);
end;

procedure TsgCADImage.ExpFillRgnInternal(const ASender: TObject;
  const AHRng: HRgn);
var
  P,R: PRgnDataHeader;
  Size: Integer;
begin
  if FIsIterator and Assigned(FsgExpFillRgn) then
  begin
    Size := GetRegionData(AHRng,0,nil);
    GetMem(P,Size);
    try
      if GetRegionData(AHRng, Size, PRgnData(P)) = 0 then
        Exit;
      R := P;
      Inc(R);
      FsgExpFillRgn(PRect(R), P.nCount);
    finally
      FreeMem(P);
    end;
  end
  else
  begin
    if IsDrawOnBitMap then
    begin
      AddSelectionMatrix(ASender);
      SelectionMatrix.Brush.Style := bsSolid;
      SelectionMatrix.Changed;
      FillRgn(SelectionMatrix.Handle, AHRng, SelectionMatrix.Brush.Handle);
      SelectionMatrix.Brush.Style := bsClear;
    end;
    if IsDrawOnCanvas then
      FillRgn(FCanvas.Handle, AHRng, FCanvas.Brush.Handle);
  end;

end;

procedure TsgCADImage.ExpImageGDIInternal(const ASender: TObject;
  const R: TRect; AGraphic: TGraphic);
begin
  if IsIterator then
  begin
    if Assigned(FsgExpImage) then
        FsgExpImage(FIRect, AGraphic);  //evg
  end
  else
    FCanvas.StretchDraw(FIRect, AGraphic);
end;

procedure TsgCADImage.ExpOle2FrameInternal(const ASender: TObject;
  const ARect: TF2DRect);
var
  vDC: HDC;
  vBrushStyle: TBrushStyle;
  BM: Graphics.TBitmap;
  vDrawingRect: TRect;
  vWidth, vHeight: Double;
  vPrevTextAlign: Integer;
begin
  if FIsIterator and Assigned(FsgExpImage) then
  begin
    vDrawingRect := cnstBad2DRectExport;
    ExpandRect(vDrawingRect, Point(Round(ARect.Left), Round(ARect.Top)));
    ExpandRect(vDrawingRect, Point(Round(ARect.Right),Round(ARect.Bottom)));
    vWidth := ARect.Right - ARect.Left;
    vHeight := ARect.Bottom - ARect.Top;
    BM := TBitmap.Create;
    try
      TsgDXFOle2FrameAccess(ASender).ConvertOleToBitmap(vWidth, vHeight, vDrawingRect, BM);
      FsgExpImage(vDrawingRect,BM);
    finally
      BM.Free;
    end;
  end
  else
  begin
    vDrawingRect := GetBoxOfF2Rect(ARect);
    if IsDrawOnBitMap then
    begin
      AddSelectionMatrix(ASender);
      SelectionMatrix.Brush.Style := bsSolid;
      SelectionMatrix.Changed;
      FillRect(SelectionMatrix.Handle, vDrawingRect, SelectionMatrix.Brush.Handle);
      SelectionMatrix.Brush.Style := bsClear;
    end;
    if IsDrawOnCanvas then
    begin
      vPrevTextAlign := SetTextAlign(FCanvas.Handle, cnstDefaultTextAlign);
      vBrushStyle := FCanvas.Brush.Style;
      try
        FCanvas.Brush.Style := bsSolid;
        FCanvas.Brush.Color := clWindow;
        FCanvas.FillRect(vDrawingRect);
        vDC := FCanvas.Handle;
        try
          OleCheck(OleDraw(TsgDXFOle2Frame(ASender).OleObject,
            TsgDXFOle2Frame(ASender).Aspect, vDC, vDrawingRect));
        except
          if GetObjectType(vDC) <> 0 then
            Rectangle(vDC, vDrawingRect.Left, vDrawingRect.Top,
              vDrawingRect.Right, vDrawingRect.Bottom);
        end;
      finally
        FCanvas.Brush.Style := vBrushStyle;
        SetTextAlign(FCanvas.Handle, vPrevTextAlign);
      end;
    end;
  end;
end;

procedure TsgCADImage.ExpPolygonInteger(const Sender: TObject; var Points; Count: Integer);
begin
 {$IFDEF NOGDI} Exit; {$ENDIF}
  if Assigned(FsgExpPolygon) then
    FsgExpPolygon(Points, Count)
  else
  begin
    if IsDrawOnBitMap then
    begin
      AddSelectionMatrix(Sender);
      SelectionMatrix.Brush.Style := bsSolid;
      SelectionMatrix.Changed;
      Windows.Polygon(SelectionMatrix.Handle, Points, Count);
      SelectionMatrix.Brush.Style := bsClear;
    end;
    if IsDrawOnCanvas then
      Windows.Polygon(FCanvas.Handle, Points, Count);
  end
end;

procedure TsgCADImage.ExpPolyPolygonInteger(const Sender: TObject; var Points, Counts;
  Count: Integer);
begin
 {$IFDEF NOGDI} Exit; {$ENDIF}
  if Assigned(FsgExpPolyPolygon) then
    FsgExpPolyPolygon(Points, Counts, Count)
  else
  begin
    if IsDrawOnBitMap then
    begin
      SelectionMatrix.Pen.Width := 0;
      AddSelectionMatrix(Sender);
      SelectionMatrix.Changed;
      Windows.PolyPolygon(SelectionMatrix.Handle, Points, Counts, Count);
    end;
    if IsDrawOnCanvas then
    begin
      SetPenWidth(1);
      Windows.PolyPolygon(FCanvas.Handle, Points, Counts, Count);
    end;
  end;
end;

procedure TsgCADImage.ExpTextInteger(ATextType: TsgTextType; X, Y: Integer; Options: Longint;
  Rect: PRect; StrWideChar: PWideChar; StrChar: PAnsiChar; Count: Longint;
  Dx:{$IFDEF SGFPC}Pointer{$ELSE}PInteger{$ENDIF});
begin
 {$IFDEF NOGDI} Exit; {$ENDIF}
  if Assigned(FsgExpText) then
    FsgExpText(ATextType, X, Y, Options,
     Rect, StrWideChar, StrChar, Count, Dx)
  else
  begin
    //
    // Bugfix Delphi XE2
    //
    TmvExtFont(FCanvas.Font).Escapement := 0;

    case ATextType of
{$IFDEF UNICODE}
      ttTextOutW: TextOutW(FCanvas.Handle, X, Y, StrWideChar, Count);
      ttExtTextOutW: ExtTextOutW(FCanvas.Handle, X, Y, Options,
        Rect, StrWideChar, Count, Dx);
{$ELSE}
      ttTextOut: TextOut(FCanvas.Handle, X, Y, StrChar, Count);
      ttTextOutW: TextOutW(FCanvas.Handle, X, Y, StrWideChar, Count);
      ttExTextOut: ExtTextOut(FCanvas.Handle, X, Y, Options, Rect, StrChar, Count, Dx);
      ttExtTextOutW: ExtTextOutW(FCanvas.Handle, X, Y, Options,
        Rect, StrWideChar, Count, Dx);
{$ENDIF}
    end;
  end;
end;

procedure TsgCADImage.ExpTextInternal(const ASender: TObject;
  ATextGlyph: TsgTextGlyph; const AText: string; const ATextW: WideString;
  const AMatrix: PFMatrix);
var
  vList: TList;
  vListCount: TsgIntegerList;
  vPointsList: TList;
  vPPoint: PFPoint;
  vPointSize: TFPoint;
  I, J, vIndex : Integer;
  vStyle: {$IFDEF SGFPC}Integer{$ELSE}Byte{$ENDIF};
begin
  vStyle := {$IFDEF SGFPC}Integer{$ELSE}Byte{$ENDIF}(TsgDXFText(ASender).Font.Style);
  if FIsIterator then
  begin
    if not (Assigned(FsgExpPolyPolygon) or Assigned(FsgExpPolyPolyline)) then
      Exit;
    vList := TList.Create;
    vListCount := TsgIntegerList.Create;
    GetPixelSize(1.5, vPointSize.X, vPointSize.Y, True);
    vPointSize.Z := vPointSize.X;
    try
      FPoly.Count := 0;
      ATextGlyph.GetPolyPolylineW(AText, ATextW, vStyle, AMatrix, vList, nil,
       @vPointSize);
      vListCount.Count := vList.Count;
      for I := 0 to vList.Count - 1 do
      begin
        vPointsList := vList.List[I];
        vListCount.List[I] := vPointsList.Count;
        vIndex := FPoly.Count;
        FPoly.Count := FPoly.Count + vPointsList.Count shl 1;
        for J := 0 to vPointsList.Count - 1  do
        begin
          vPPoint := vPointsList.List[J];
          FPoly.List[vIndex] := Round(vPPoint^.X);
          Inc(vIndex);
          FPoly.List[vIndex] := Round(vPPoint^.Y);
          Inc(vIndex);
          Dispose(vPPoint);
        end;
        vPointsList.Free;
      end;
      if ATextGlyph.FillText then
      begin
        if Assigned(FsgExpPolyPolygon) then
          FsgExpPolyPolygon(FPoly.List^, vListCount.List^, vListCount.Count);
      end
      else
      begin
        if Assigned(FsgExpPolyPolyline) then
          FsgExpPolyPolyline(FPoly.List^, vListCount.List^, vListCount.Count);
      end;
    finally
      vListCount.Free;
      vList.Free;
    end;
  end
  else
  begin
    FCanvas.Pen.Width := 0;
    DoSetColor(FColorFont, ctPen);//FCanvas.Pen.Color := FCanvas.Font.Color
    DoSetColor(FColorFont, ctBrush);//FCanvas.Brush.Color := FCanvas.Pen.Color;
    ATextGlyph.DrawTextExtW(FCanvas.Handle, TmvFontStyles(vStyle), AText, ATextW, AMatrix);
    DoSetColor(FColorBrush, ctBrushClear);
  end;
end;

procedure TsgCADImage.DoSetColor(AColor: TColor; AColorType: TsgColorType;
  AUseExternalColor: Boolean = True);
var
 vChanged: Boolean;
begin
  if not SetColorByExternalPen(AUseExternalColor, AColor) then
  begin
    if AColor = clNone then
      AColor := GetDrawPenColor;
  end;
  if Assigned(FsgExpSetColor) then
    FsgExpSetColor(AColor, AColorType)
  else
  begin
    case AColorType of
      ctPen:
        begin
          vChanged := AColor <> FColorPen;
          if vChanged then
            FColorPen := AColor;
        end;
      ctBrush:
        begin
          vChanged := (AColor <> FColorBrush) or (FCanvas.Brush.Style = bsClear) or
            (AColor <> FCanvas.Brush.Color);  // FCanvas.Brush.Color something changes
              // without calling DoSetColor
          if vChanged then
            FColorBrush := AColor;
        end;
      ctFont:
        begin
          vChanged := AColor <> FColorFont;
          if vChanged then
            FColorFont := AColor;
        end;
      ctBrushClear: vChanged := True;
    else
      vChanged := False;
    end;
    if vChanged then
    begin
      case AColorType of
        ctPen:   FCanvas.Pen.Color := AColor;
        ctBrush: FCanvas.Brush.Color := AColor;
        ctFont:  FCanvas.Font.Color := AColor;
        ctBrushClear:
         begin
           if FColorBrush <> GetDrawBackgroundColor then
           begin
             FColorBrush := GetDrawBackgroundColor;
             FCanvas.Brush.Color := FColorBrush;
           end;
           if not Assigned(FDrawExternlProps) then
             FCanvas.Brush.Style := bsClear;
         end;
      end;
    end;
  end;
end;

function TsgCADImage.SetColorByExternalPen(const AUseExternalColor: Boolean;
  var AColor: TColor): Boolean;
begin
  Result := False;
  if AUseExternalColor and Assigned(FDrawExternlProps) then
  begin
    case FDrawExternlProps.UseExternalPen of
      epmInternal:
        begin
          if FDrawExternlProps.EntityHandle = FEntityHandle then
          begin
            AColor := FDrawExternlProps.Mode.Color;
            Result := True;
          end;
        end;
      epmExternal:
        begin
          AColor := FDrawExternlProps.Mode.Color;
          Result := True;
        end;
    end;
  end;
end;

procedure TsgCADImage.DoSetFont(AFont: TFont);
begin
  if Assigned(FsgExpSetFont) then
    FsgExpSetFont(AFont)
  else
    FCanvas.Font := AFont;
  FColorFont := AFont.Color;
end;

procedure TsgCADImage.DoSetStyle(AStyle: Integer; AColorType: TsgColorType);
begin
  if Assigned(FsgExpSetStyle) then
    FsgExpSetStyle(AStyle, AColorType)
  else
    case AColorType of
      ctPen:         FCanvas.Pen.Style := TPenStyle(AStyle);
      ctBrush:       FCanvas.Brush.Style := TBrushStyle(AStyle);
      ctFont:        FCanvas.Font.Style := TFontStyles({$IFDEF SGFPC}Integer{$ELSE}Byte{$ENDIF}(AStyle));
      ctBrushClear:  DoSetColor(FColorBrush, ctBrushClear);
    end;
end;

procedure TsgCADImage.SetPenGeometric(AStyle: DWORD);
var
  vStyle: DWORD;
  vLB: TLogBrush;
begin
  vStyle := PS_GEOMETRIC or PS_SOLID or AStyle;
  if Assigned(FsgExpSetPenGeometric) then
    FsgExpSetPenGeometric(vStyle)
  else
  begin
    vLB.lbStyle := BS_SOLID;
    vLB.lbColor := ColorToRGB(FColorPen);
    vLB.lbHatch := 0;
    FCanvas.Pen.Handle := ExtCreatePen(vStyle, FPenWidth, vLB, 0, nil);
  end;
end;

procedure TsgCADImage.SetPenStyle(const AStylePen: DWORD; const AMiterLimit: Single);
begin
  SetPenGeometric(AStylePen);
  if (AStylePen and PS_JOIN_MITER) <> 0 then
  begin
    if Assigned(ExpSetPenMiterLimit) then
      ExpSetPenMiterLimit(AMiterLimit)
    else
      SetMiterLimit(FCanvas.Handle, AMiterLimit, nil);
  end;
end;

procedure TsgCADImage.SetPenWidth(AWidth: Double);
var
  vPenWidthTemp: Integer;
begin
  if Assigned(FsgExpSetPenWidth) then
    FsgExpSetPenWidth(AWidth);
  vPenWidthTemp := Ceil(AWidth);
  if vPenWidthTemp = FPenWidth then
    Exit;
  FPenWidth := vPenWidthTemp;
  if not Assigned(FsgExpSetPenWidth) then
    FCanvas.Pen.Width := vPenWidthTemp;
end;

// evg: the function GetPixelSize should be completely changed
procedure TsgCADImage.GetPixelSize(ANumberOfPixels: Double; var Adx, Ady: Double;
  const AScaled: Boolean);
begin
  if AScaled then
    Adx := GetCADPixelSize(FDraw.Matrix, ANumberOfPixels)
  else
    Adx := GetCADPixelSize(FDraw.DrawMatrix, ANumberOfPixels);
  Ady :=  Adx;
end;

procedure TsgCADImage.SetClipping(const AClip: TsgClipping);
begin
  case AClip.ClipMode of
    1:  SetClippingRect(@AClip.ClipRect);
    2:  SetClippingRectExt(AClip.ClipRect);
    3:  SetClippingRectExt(AClip.ClipRect);//clip of view rect
    4:  SetClippingRect(nil);//clip is draw rect
  else
    SetClippingRect(nil);
  end;
end;

procedure TsgCADImage.SetClippingRect(Value: PFRect);
begin
  if FClippingRect = nil then
    New(FClippingRect);
  if Value = nil then
  begin
    Dispose(FClippingRect);
    FClippingRect := nil;
  end
  else
    FClippingRect^ := Value^;
  Changed(Self);
end;

procedure TsgCADImage.SetClippingRectExt(const AValue: TFRect);
var
  vPicRect: TF2DRect;
  vClippingRect, vNewExts, vViewBox: TFRect;
begin
  vNewExts := Extents;
  vPicRect := MakeF2DRect(vNewExts.Left, vNewExts.Bottom, vNewExts.Right, vNewExts.Top);
  ApplyScale(vPicRect.Left, vPicRect.Top, vPicRect.Right, vPicRect.Bottom);
  vViewBox := AValue;
  TransRectCorners(vViewBox, DrawMatrix);
  SwapDoubles(vViewBox.Top, vViewBox.Bottom);
  // Clipping rectangle (ignoring Z-coordinate)
  vClippingRect.Left := (vViewBox.Left - vPicRect.Left);
  vClippingRect.Top := (vViewBox.Top - vPicRect.Top);
  vClippingRect.Right := vClippingRect.Left + (vViewBox.Right - vViewBox.Left);
  vClippingRect.Bottom := vClippingRect.Top + (vViewBox.Bottom - vViewBox.Top);
  vClippingRect.Z1 := 0;
  vClippingRect.Z2 := 0;
  SetClippingRect(@vClippingRect);
end;

{$IFDEF SGDEL_4}   //cadimage
{$IFNDEF SGFPC}
function TsgCADImage.ExportToMetafile(AWidth, AHeight: Integer): TMetafile;
var
  MF: TMetafile;
  MC: TMetafileCanvas;
  mmToPixelX: Double;
  mmToPixelY, Ratio: Double;
  vMax: Integer;
  vDc: HDC;
  R: TRect;
begin
   vMax := 3276500;
   vDc := GetDc(0);
   try
     mmToPixelX := GetDeviceCaps(vDc, HORZSIZE) /
       GetDeviceCaps(vDc,HORZRES);
     mmToPixelY := GetDeviceCaps(vDc, VERTSIZE) /
       GetDeviceCaps(vDc,VERTRES);
   finally
     ReleaseDC(0, vDc);
   end;
   if AHeight <> 0 then
     Ratio := AWidth / AHeight
   else
     Ratio := 1;
   if mmToPixelX <= mmToPixelY then
     vMax := Round(vMax * mmToPixelX)
   else
     vMax := Round(vMax * mmToPixelY);
   if (AWidth > vMax) or (AHeight > vMax) then
     if Ratio <= 1 then
     begin
       AHeight := vMax;
       AWidth := Round(vMax * Ratio);
     end
     else
     begin
       AWidth := vMax;
       AHeight := Round(vMax / Ratio);
     end;

   MF := TMetafile.Create;
   MF.MMWidth := AWidth;
   MF.MMHeight := AHeight;
   MC := TMetafileCanvas.Create(MF, 0);
   try
     FConverting := True;
     R := Rect(0, 0, Round(AWidth / (100 * mmToPixelX)),
       Round(AHeight / (100 * mmToPixelY)));
     Draw(MC, R);
     DoMetafileExport(MC, R);
   finally
     OnMetafileExport := nil;
     FConverting := False;
     MC.Free;
   end;
   result := MF;
end;

function TsgCADImage.ExportToMetafile(MaxDim: Integer): TMetafile;
var
  AWidth, AHeight: Integer;
  Ratio: Double;
begin
   if MaxDim > 3276700 then
     MaxDim := 3276700;
   Ratio := Width / Height;
   if Ratio <= 1 then
   begin
     AHeight := MaxDim;
     AWidth := round(MaxDim * Ratio);
   end
   else
   begin
     AWidth := MaxDim;
     AHeight := round(MaxDim / Ratio);
   end;
   Result := ExportToMetafile(AWidth, AHeight);
end;

function TsgCADImage.ExportToMetafile(var OffsetX, OffsetY, UnitSize: TsgFloat): TMetafile;
const
  iMaxMetafileSizeWin98 = 32765;
  iMaxMetafileSizeWinNT = 64000000;
var
  MF: TMetafile;
  MC: TMetafileCanvas;
  vMaxDim, vRatio, vHeight, vWidth, RatioKoef: Double;
  OSVersionInfo: TOSVersionInfo;
  vFlag1, vFlag2, vFlag3: Boolean;
  vPrevRots: TFMatrix;
  S, S1: string;
  I: Integer;
  vRealExtents: TFRect;
  vDs: Char;
  R: TRect;
begin
  FExportToDXFMode := True;
  try
    if IsBadRect(FDrawingBox) then
      vRealExtents := PureExtents
    else
      vRealExtents := FDrawingBox;
    vFlag1 := Transparent;
    vFlag2 := IsWithoutBorder;
    vFlag3 := Converter.UseSHXFonts;
    vPrevRots := CurrentLayout.RotMatrix;
    Transparent :=  True;
    IsWithoutBorder := True;
    Converter.UseSHXFonts := False;
    OSVersionInfo.dwOSVersionInfoSize := Sizeof(TOSVersionInfo);
    GetVersionEx(OSVersionInfo);
    (* // For future versions
    if OSVersionInfo.dwPlatformId = VER_PLATFORM_WIN32_NT then
      vMaxDim := iMaxMetafileSizeWinNT
    else
      vMaxDim := iMaxMetafileSizeWin98;*)
    vMaxDim := iMaxMetafileSizeWin98;
    vRatio := AbsWidth / AbsHeight;
    if vRatio <= 1 then
      UnitSize := AbsHeight
    else
      UnitSize := AbsWidth;
    UnitSize := UnitSize / vMaxDim;
    vDs := SetDecimalSeparator('.');
    try
      try
        S := FloatToStr(UnitSize);
        for I := 1 to Length(S) do
          if not CharInSet(S[I], ['0', GetDecimalSeparator]) then
          begin
            S1 := S1 + '1';
            Break;
          end
          else
            S1 := S1 + S[I];
      except
        S1 := '';
      end;
      UnitSize := ConvToFloatDef(S1, UnitSize) * 10;
      I := Pos('E', AnsiUpperCase(S));
      if I > 0 then
        UnitSize := UnitSize * Power(10, StrToIntDef(Copy(S, I+1, MaxInt), 1));
    finally
      SetDecimalSeparator(vDs);
    end;
    RatioKoef := 1 / UnitSize;
    if vRatio <= 1 then
    begin
      vHeight := RatioKoef * AbsHeight;
      vWidth := vHeight * vRatio;
    end
    else
    begin
      vWidth := RatioKoef * AbsWidth;
      vHeight := vWidth / vRatio;
    end;
    MF := TMetafile.Create;
    OffsetX := Round(RatioKoef * vRealExtents.Left);
    OffsetY := Round(RatioKoef * vRealExtents.Top);
    MC := TMetafileCanvas.Create(MF, 0);
    try
      FConverting := True;
      R := Rect(0, 0, Round(vWidth), Round(vHeight));
      Draw(MC, R);
    finally
      FConverting := False;
      MC.Free;
      Transparent := vFlag1;
      IsWithoutBorder := vFlag2;
      Converter.UseSHXFonts := vFlag3;
      CurrentLayout.SetRotMatrix(vPrevRots);
      GetExtents;
    end;
    Result := MF;
  finally
    FExportToDXFMode := False;
  end;
end;
{$ENDIF}
{$ELSE}
procedure TsgCADImage.ExportToMetafile(const FileName: string;
  AWidth, AHeight: Integer);
var
  MF: TMetafile;
begin
  MF := ExportToMetafile(AWidth, AHeight);
  try
    MF.SaveToFile(FileName);
  finally
    MF.Free;
  end;
end;
{$ENDIF}

function TsgCADImage.GetPoint(const P: TFPoint): TPoint;
var
  vFPoint: TFPoint;
begin
  Result := FPointXMat2DLongint(P, FDraw.Matrix);
  if FUsePrecision then
  begin
    vFPoint := GetFPoint(P);
    Result.X := Round(vFPoint.X / FPrecision);
    Result.Y := Round(vFPoint.Y / FPrecision);
  end;
end;

function TsgCADImage.GetFPoint(const P: TFPoint): TFPoint;
begin
  Result := FPointXMat(P, FDraw.Matrix);
end;

function TsgCADImage.GetGDIPlusColor(const AColor: TColor): Cardinal;
var
  vIn: array[0..3] of Byte absolute AColor;
  vOut: array[0..3] of Byte absolute Result;
begin
 if (AColor = clByBlock) or (AColor = clByLayer) or (AColor = clNone) then //evg
    Result := GetDrawPenColor
 else
  case FDrawMode of
    dmBlack:
      case GetBackgroundColor of
        clWhite:  Result := IfThen(AColor <> clWhite, clBlack, clWhite);
        clBlack:  Result := IfThen(AColor <> clBlack, clWhite, clBlack);
      else
        Result := GetDrawPenColor;
      end;
    dmGray: Result := clGray;
  else
    Result := BGRToRGB(AColor);
  end;
  vOut[3] := 255 - vIn[3];
end;

function TsgCADImage.GetPointUCS(P: TFPoint): TPoint;
begin
  TransformToWorldCS(P);
  Result := GetPoint(P);
end;

function TsgCADImage.GetPolygonFillingMode: Integer;
begin
  Result := ALTERNATE;
end;

function TsgCADImage.GetRealClip: PFRect;
begin
  Result := nil;
  if FClippingRect <> nil then
    Result := FClippingRect;
end;

procedure TsgCADImage.CalcDottedSingPts(AEntity: TsgDXFEntity;
      AEntityLines: sgLines.TsgLines;
      ConvertMatrixCurrentIndertToWCS: TFMatrix;
      ADottedPoints: TFPointList);
var
  vPoint1, vPoint2, vScale: TFPoint;
  vIsNotScaledLType: Boolean;

  vPLine: TsgCADBasePolyLineAccess;
  PL: TsgDXFPolyLine;

  vOldUniform, vPLineGen, vOldAutocadMetod: Boolean;

  procedure BeforeBreakdown(ALine: TsgCADBasePolyLineAccess;
    APLineGen: Boolean; var AScale: TFPoint; AOnlyScale: Boolean = True);
  begin
    if ALine.Closed and IsAutocadLType and APLineGen and (not AOnlyScale) then
    begin
      ALine.PolyPoints.CyclicShiftRight(Integer(TsgDXFPolyLine(ALine).PointsCounts[0]));
      ALine.PolyPoints.Add(ALine.PolyPoints.First);
    end;
    if vIsNotScaledLType then
    begin
      AScale := ExtractMatrixAbsoluteScale(ConvertMatrixCurrentIndertToWCS);
      ScaleList(ALine.PolyPoints, AScale);
    end;
  end;

  procedure AfterBreakdown(ALine: TsgCADBasePolyLineAccess; APLineGen: Boolean;
    AScale: TFPoint; ArrowDraw: Boolean = False; AOnlyScale: Boolean = True);
  begin
    if vIsNotScaledLType then
    begin
      AScale := ReverseScale(AScale);
      ScaleList(ADottedPoints, AScale);
      ScaleList(vPLine.PolyPoints, AScale);
      if ArrowDraw then
        DoPolylineArrow(vPLine, FEntityLines, @ConvertMatrixCurrentIndertToWCS);
    end
    else
      if ArrowDraw then
        DoPolylineArrow(vPLine, FEntityLines, nil);

    if ALine.Closed and IsAutocadLType and APLineGen and (not AOnlyScale)then
    begin
      ALine.PolyPoints.Count := ALine.PolyPoints.Count -1;
      ALine.PolyPoints.CyclicShiftLeft(Integer(TsgDXFPolyLine(ALine).PointsCounts[0]));
    end;
  end;

begin
  vIsNotScaledLType := IsNotScaledLType;
  if AEntity.EntType = ceLine then
  begin
    vPoint1 := TsgDXFLine(AEntity).Point;
    vPoint2 := TsgDXFLine(AEntity).Point1;
    if vIsNotScaledLType then
    begin
      vScale := ExtractMatrixAbsoluteScale(ConvertMatrixCurrentIndertToWCS);
      vPoint1 := MultiplyFPoint(vPoint1, vScale);
      vPoint2 := MultiplyFPoint(vPoint2, vScale);
    end;
    AEntityLines.Line(vPoint1, vPoint2, ADottedPoints);
    if vIsNotScaledLType then
    begin
      vScale := ReverseScale(vScale);
      ScaleList(ADottedPoints, vScale);
    end;
  end
  else
  begin
    vPLine := TsgCADBasePolyLineAccess(AEntity);
    if not (AEntity is TsgDXFPolyLine) then
      PL := nil
    else
      PL := TsgDXFPolyLine(AEntity);

    vOldUniform := AEntityLines.IsUniform;
    vOldAutocadMetod := AEntityLines.IsAutocadMetod;
    try
      vPLineGen := vPLine.IsPLinegen and (IsAutocadLType) and
        (not TsgDXFPolylineAccess(vPLine).HasWidth);//change in future version
      if vPLineGen then
      begin
        AEntityLines.IsUniform := True;
        if IsAutocadLType then
          AEntityLines.IsAutocadMetod := True;
        AEntityLines.Loaded(vPLine.Converter);
      end;

      case vPLine.EntType of
        cePolyline, ceLWPolyline:
        begin
          BeforeBreakdown(vPLine, vPLineGen, vScale, False);
          AEntityLines.Vertexes(vPLine.PolyPoints, PL.PointsCounts, ADottedPoints, vPLine.Closed);
          AfterBreakdown(vPLine, vPLineGen, vScale, True, False);
        end;
        ceWipeOut, ceImageEnt:
          begin
            BeforeBreakdown(vPLine, vPLineGen, vScale);
            AEntityLines.Poly(vPLine.PolyPoints, ADottedPoints, vPLine.Closed);
            AfterBreakdown(vPLine, vPLineGen, vScale);
          end
          else // for circles, arcs, splines, etc.
          begin
            BeforeBreakdown(vPLine, vPLineGen, vScale);
            if vPLine.EntType = ceCircle then
              AEntityLines.Curve(vPLine.PolyPoints, ADottedPoints, vPLine.Closed)
            else
            begin
              AEntityLines.Curve(vPLine.PolyPoints, ADottedPoints, False);
            end;
            AfterBreakdown(vPLine, vPLineGen, vScale);
          end;
        end;
    finally
      AEntityLines.IsUniform := vOldUniform;
      AEntityLines.IsAutocadMetod := vOldAutocadMetod;
    end;
  end;
end;

function TsgCADImage.GetPlotSettingsRGN: HRGN;
var
  vPrint: TRect;
begin
  Result := 0;
  if UsePlotSetting then
  begin
    if CurrentLayout.PlotSettings.PlotType = ptWindowSpecified then
      vPrint := GetRect(CurrentLayout.PlotSettings.PlotPrintableArea)
    else
      vPrint := GetRect(CurrentLayout.PlotSettings.PlotMarginsArea);
    InflateRect(vPrint, 1, 1);
    Result := CreateRectRgn(vPrint.Left, vPrint.Top, vPrint.Right, vPrint.Bottom);
  end;
end;


function TsgCADImage.GetRealImageMatrix: TFMatrix;
begin
  Result := FCurrentLayout.RotMatrix;
  // TransPoseMat(Result);// only for future versions
end;

function TsgCADImage.GetRealImagePoint(const P: TFPoint): TFPoint;
begin
  Result := FPointXMat(P, GetRealImageMatrix);
end;

procedure TsgCADImage.LoadFromFile(const FileName: string);
var
  S: TFileStream;
  Dir: string;
 // Ticks: Cardinal;      //evg
begin
 // Ticks := GetTickCount; //evg
  Dir := GetCurrentDir;
  S := TFileStream.Create(FileName, fmOpenRead or fmShareDenyNone);
  try
{$IFDEF SG_MODULE_LOG}
    Log.Add('TFileStream.Create(FileName: ' + FileName + ', Mode: $' + IntToHex(fmOpenRead or fmShareDenyNone, 0) + ')');
{$ENDIF}
    SetCurrentDir(ExtractFilePath(FileName));
    Self.FFileName := FileName;
    Converter.FileName := ExtractFileName(FileName);
    Converter.SHXFonts.SearchPath.Insert(0, ExtractFilePath(FileName));
    try
      {// For future versions
      OwnSource := True;
      Converter.SetSourceStream(S); }
      LoadFromStream(S);
    finally
      S.Free;
      SetCurrentDir(Dir);
    end;
  except
    OwnSource := False;
    raise;
  end;
   // Ticks := GetTickCount - Ticks; //evg
  //  ShowMessage('file loading time is ' + FloatToStr(Ticks) + 'mlsek'); //evg
end;

procedure TsgCADImage.SetDefaultViewModePlotSettings;
begin
  ShowPlotSetting := True;
  ShowPlotMargins := True;
  ShowPlotForModel := False;
end;

procedure TsgCADImage.SetDefaultViewPort(AConverter: TsgDXFCOnverter);
begin
  FRotToView := True;
  try
    DoBeforeRotate;
    try
      TsgDXFConverterAccess(AConverter).GetModelLayout.SetRotMatrix(AConverter.ViewTwistMatrix);
    finally
      DoAfterRotate;
    end;
  finally
    FRotToView := False;
  end;
end;

procedure TsgCADImage.LoadFromStream(S: TStream);
var
  vPos: Integer;
begin
{$IFDEF SG_MODULE_LOG}
  Log.Add(ClassName + '($' + IntToHex(TsgNativeUInt(Self), 0) + ').LoadFromStream(S);');
{$ENDIF}
  if KeepOriginal then
  begin
    vPos := S.Position;
    Stream.Clear;
    Stream.CopyFrom(S, S.Size - S.Position);
    S.Position := vPos;
    Stream.Position := 0;
  end;
end;

procedure TsgCADImage.RefreshCurrentLayout;
var
  vBox: TFRect;
begin
  if FCurrentLayout <> nil then
  begin
    vBox := FCurrentLayout.Box;
    if UsePlotSetting then
      vBox := GetDrawingExtents;
    SetExtentsParameters(vBox, FCurrentLayout.CADSpace <> csUndefined);
  end;
end;

procedure TsgCADImage.ResetDrawingBox;
begin
  SetDrawingBox(BadRect);
end;

procedure TsgCADImage.ResetExtents;
var
  W, H: TsgFloat;
begin
  Extents := MakeFRect(FXMin, FYMax, FZMin, FXMax, FYMin, FZMax);
  W := AbsWidth;
  H := AbsHeight;
  if W < H then
    SwapSGFloats(W,H);
  if H = 0 then
    H := 1E-20;
  if W = 0 then
    W := 1E-20;
  if W < 10 then
    FZoom := 10
  else
  begin
    W := $7FFF / W;
    FZoom := MinDXFSize / H;
    if FZoom < 1 then
      FZoom := 1;
    if FZoom > W then
      FZoom := W;
  end;
end;

procedure TsgCADImage.RestoreDrawParams;
begin
  FDraw := FDrawSaved;
end;

procedure TsgCADImage.Rotate(Axis: TsgAxes; Angle: Extended);
var
  vAngle: Extended;
begin
  vAngle := Angle;
  Angle := Angle - Int(Angle / 360.0) * 360.0;
  if (not (Axis=axisZ) and (Angle <> 0))
    or ((Axis=axisZ) and ((Round(Abs(Angle)) mod 90) <> 0)) then
    FBadRotation := True;
  DoBeforeRotate;
  try
    FCurrentLayout.SetRotMatrix(FMatXMat(FCurrentLayout.RotMatrix,
      BuildRotMatrix(Axis, DegToRad(vAngle))));
    if Axis = axisZ then
      FZRotate := FZRotate + Angle;
  finally
    DoAfterRotate;
  end;
end;

procedure TsgCADImage.RotateImageEnt;
var
  vProc: TsgIteratorProc;
  vIterator: TsgIteratorBase;
begin
  vProc := TsgRotateImage.Create;
  vIterator := TsgIteratorBase.Create(vProc);
  try
    vIterator.Iterate(Self);
  finally
    vIterator.Free;
    vProc.Free;
  end;
end;

procedure TsgCADImage.RotDefault;
begin
  RotToView(vdDefault);
end;

procedure TsgCADImage.RotToView(const A3DView: TsgDXFViewDirection);
var
  vM: TFMatrix;
begin
  FRotToView := True;
  try
    if A3DView = vdDefault then
    begin
      FBadRotation := False;
      vM := Converter.ViewTwistMatrix;
    end
    else
      vM := cnstIdentityMat;
    DoBeforeRotate;
    try
      FConverter.DoExtents;
      FCurrentLayout.SetRotMatrix(vM);
      case A3DView of
        vdDefault, vdTop:
          begin
            FZRotate := -FCurrentLayout.RotZAngle;
          end;
        vdFront:
          begin
            Rotate(AxisX, -90);
          end;
        vdBottom:
          begin
            Rotate(AxisY, 180);
          end;
        vdLeft:
          begin
            Rotate(AxisY, 90);
            Rotate(AxisZ, 90);
          end;
        vdRight:
          begin
            Rotate(AxisY, -90);
            Rotate(AxisZ, -90);
          end;
        vdBack:
          begin
            Rotate(AxisX, 90);
            Rotate(AxisZ, 180);
          end;
        vdSWIsometric:
          begin
            Rotate(AxisZ, 45);
            Rotate(AxisX, -fIsometricRotation);
          end;
        vdSEIsometric:
          begin
            Rotate(AxisZ, -45);
            Rotate(AxisX, -fIsometricRotation);
          end;
        vdNWIsometric:
          begin
            Rotate(AxisZ, 135);
            Rotate(AxisX, -fIsometricRotation);
          end;
        vdNEIsometric:
          begin
            Rotate(AxisZ, -135);
            Rotate(AxisX, -fIsometricRotation);
          end;
      end;
    finally
      DoAfterRotate;
    end;
  finally
    FRotToView := False;
  end;
end;

procedure TsgCADImage.SaveToFile(const FileName: string);
var
  S: TFileStream;
begin
  S := TFileStream.Create(FileName, fmCreate);
  try
    SaveToStream(S)
  finally
    S.Free
  end;
end;

procedure TsgCADImage.SaveToStream(S: TStream);
var
  P: Pointer;
begin
  if KeepOriginal then
  begin
    Stream.Position := 0;
    GetMem(P, Stream.Size);
    try
      Stream.Read(P^, Stream.Size);
      S.Write(P^, Stream.Size);
      Stream.Position := 0;
    finally
      FreeMem(P);
    end;
  end
  else
    if FConverter.Source <> nil then FConverter.Source.SaveToStream(S);
end;

procedure TsgCADImage.ScaleDrawMatrix(ASx, ASy, ASz: Double);
begin
  SetDrawMatrix(FMatScale(DrawMatrix, MakeFPoint(ASx, ASy, ASz)));
end;

procedure TsgCADImage.SetSelectClipRgn(Region: HRGN);
var
  vDC: HDC;
  vResult: Integer;
begin
  vDC := FCanvas.Handle;
  vResult := SelectClipRgn(vDC, Region);
  if vResult < NULLREGION then
    SelectClipRgn(vDC, 0);
  GetClipBox(vDC, FDrawRect);
end;

procedure TsgCADImage.SetCurrentLayout(const ALayout: TsgDXFLayout);
var
  vNewLayout: Boolean;
  vBox: TFRect;
begin
  if Assigned(OnLayoutBeforeChange) then
    OnLayoutBeforeChange(Self);
  vNewLayout := (FCurrentLayout <> ALayout) and Assigned(ALayout);
  FCurrentLayout := ALayout;
  if Assigned(FCurrentLayout) then
  begin
    if not FCustomDraw and vNewLayout then
      FDraw.Matrix := GetRealImageMatrix;
    vBox := FCurrentLayout.Box;
    if UsePlotSetting then
      vBox := GetDrawingExtents;
    SetExtentsParameters(vBox, FCurrentLayout.CADSpace <> csUndefined);
  end
  else
  begin
    FDraw.Matrix := cnstIdentityMat;
    SetExtentsParameters(cnstBadRect, False);
  end;
  if Assigned(OnLayoutChange) then
    OnLayoutChange(Self);
end;

procedure TsgCADImage.AssignTo(Dest: TPersistent);
begin
  if Dest is TBitmap then
    AssignToBitmap(Self, TBitmap(Dest))
  else
  {$IFNDEF SGFPC}
    if Dest is TMetafile then
      AssignToMetafile(Self, TMetafile(Dest))
    else
  {$ENDIF}
    inherited AssignTo(Dest);
end;

procedure TsgCADImage.AddSelectionMatrix(const APointer: Pointer);
begin
  if (FOnComplexEntity = nil) and
    ((FDraw.Insert = nil) or (FOnInsertMode and (FDraw.Insert = FOnInsert))) then
    SelectionMatrix.AddElement(APointer)
  else
    SelectionMatrix.AddElement(nil);
end;

procedure TsgCADImage.ClearMatrices(const ARect: TRect);
begin
  if SelectionMatrix <> nil then
    SelectionMatrix.ClearRect(ARect);
  FSnapMatrix.ClearRect(ARect);
end;

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

function TsgCADImage.CreateDefaultViewPort(
  const AHandle: UInt64): TsgDXFViewport;
var
  vBox, vExtents: TFRect;
  vDrawRect: TFRect;
  vDrawW, vDrawH, vScaleX, vScaleY, vViewTwistAngle: Double;
  vViewCenter: TFPoint;
  vM, vtm0: TFMatrix;
  vViewSize: TPoint;
begin
  Result := TsgDXFViewPort.Create;
  Result.Handle := AHandle;
  vM := Layouts[0].RotMatrix;
  vBox := Layouts[0].Box;
  vExtents := GetRealBox(vBox, vM);
  Result.PSpaceWidth := vExtents.Right - vExtents.Left;
  Result.PSpaceHeight := vExtents.Top - vExtents.Bottom;
  vViewCenter := MiddleFPoint(vBox.TopLeft, vBox.BottomRight);
  if CurrentLayout.IsModel then
  begin
    vViewSize := GetVisibleArea;
    if (vViewSize.X <> 0) and (vViewSize.Y <> 0) then
    begin
      vDrawRect := GetRealBox(vBox, DrawMatrix);
      vDrawW := vDrawRect.Right - vDrawRect.Left;
      vDrawH := vDrawRect.Top - vDrawRect.Bottom;
      if  (vDrawW <> 0) and (vDrawH <> 0) then
      begin
        Result.PSpaceWidth := Result.PSpaceWidth * vViewSize.X / vDrawW;
        Result.PSpaceHeight := Result.PSpaceHeight * vViewSize.Y / vDrawH;
        vViewCenter := MakeFPoint(vViewSize.X / 2, vViewSize.Y / 2);
        vScaleX := (vViewCenter.X - vDrawRect.Left) / vDrawW;
        vScaleY := 1.0 - (vViewCenter.Y - vDrawRect.Bottom) / vDrawH;
        vViewCenter := GetCADCoords(vScaleX, vScaleY);
        // or
        //vViewCenter := FPointXMat(vViewCenter, FMatInverse(vCADImage.DrawMatrix));
      end;
    end;
  end;
  if Result.PSpaceHeight = 0 then
    Result.PSpaceHeight := 1;
  if Result.PSpaceWidth = 0 then
    Result.PSpaceWidth := 1;
  Result.PSpaceCenter := FPointXMat(vViewCenter, vM);
  Result.MSpaceCenter := Result.PSpaceCenter;
  Result.ViewTarget := cnstFPointZero;
  // calc ViewDirection and ViewTwistAngle
  Result.ViewDirection := MakeFPoint(vM.EX.Z, vM.EY.Z, vM.EZ.Z);
  vtm0.E0 := cnstFPointZero;
  DoNewAutoCADAxes(Result.ViewDirection, vtm0.EX, vtm0.EY, vtm0.EZ);
  vtm0 := FMatXMat(vtm0, vM);
  if Abs(vtm0.M[0, 0]) >= 1.0 then
  begin
    if vtm0.M[0, 0] < 0 then
      vViewTwistAngle := cnstPi
    else
      vViewTwistAngle := 0
  end
  else
  begin
    vViewTwistAngle := ArcCos(vtm0.M[0, 0]);
    if vtm0.M[0, 1] < 0 then
      vViewTwistAngle := -vViewTwistAngle;
  end;
  Result.ViewTwistAngle := RadToDeg(vViewTwistAngle);
  Result.FrontClipPlane := 0;
  Result.BackClipPlane := 0;
  Result.MSpaceHeight := Result.PSpaceHeight;
end;

function TsgCADImage.CreateDefaultVPort(const Handle: UInt64): TsgDXFVPort;
var
  vViewPort: TsgDXFViewPort;
begin
  Result := TsgDXFVport.Create;
  Result.Name := sActiveVPort;
  Result.Handle := Handle;
  vViewPort := CreateDefaultViewPort(cnstBadHandle);
  try
    Result.ViewHeight := vViewPort.PSpaceHeight;
    if not IsZero(vViewPort.PSpaceHeight) then
      Result.ViewAspectRatio := vViewPort.PSpaceWidth / vViewPort.PSpaceHeight
    else
      Result.ViewAspectRatio := 1;
    Result.ViewCenterPoint := vViewPort.MSpaceCenter;
    Result.ViewTarget := vViewPort.ViewTarget;
    Result.ViewDirection := vViewPort.ViewDirection;
    Result.ViewTwistAngle := vViewPort.ViewTwistAngle;
    Result.CircleZoomPercent := cntViewPortCircleZoomPercent;
    Result.UCSOrigin := cnstFPointZero;
    Result.UCSXDir := cnstXOrtAxis;
    Result.UCSYDir := cnstYOrtAxis;
    Result.UCSVP := False;
  finally
    vViewPort.Free;
  end;
end;

function TsgCADImage.CurrXRef: TsgDXFXref;
begin
  if FXrefStack.Count > 0 then
    Result := TsgDXFXref(FXrefStack.Last)
  else
    Result := nil;
end;

//cadimage
procedure TsgCADImage.Draw3DAxes;
var
  PtCntr: TPoint;
  vSize: Single;

  procedure DrawAxis(const AName: string; AAxis: TFPoint; AColor: TColor);
  var
    vPtAxis: TPoint;
  begin
      FCanvas.Pen.Color := AColor;
      DoSetColor(AColor, ctPen);
      DoSetColor(AColor, ctFont);
      FCanvas.Font.Color := FCanvas.Pen.Color;
      FCanvas.MoveTo(PtCntr.X, PtCntr.Y);
      vPtAxis := GetPoint(MakeFPoint(FCenter.X + AAxis.X,
        FCenter.Y + AAxis.Y, FCenter.Z + AAxis.Z));
      FCanvas.LineTo(vPtAxis.X, vPtAxis.Y);
      FCanvas.TextOut(vPtAxis.X, vPtAxis.Y, AName);
  end;

begin
  if not IsIterator then
  begin
    vSize := AbsWidth;
    if vSize > AbsHeight then
      vSize := AbsHeight;
    vSize := vSize / 4;
    if vSize <= 0 then
      vSize := 1;
    PtCntr := GetPoint(FCenter);
    if not FIsIterator then
      FCanvas.Pen.Width := 2;
    DrawAxis('X', MakeFPoint(vSize,0,0), clRed);// FNew0X
    DrawAxis('Y', MakeFPoint(0,vSize,0), TColor(RGB(68, 235, 140)));//FNew0Y
    DrawAxis('Z', MakeFPoint(0,0,vSize), clBlue);// FNew0Z
    if not FIsIterator then
    begin
      FCanvas.Font.Size := 6;
      FCanvas.Pen.Color := clAqua;
      FCanvas.Ellipse(PtCntr.X - 1, PtCntr.Y - 1, PtCntr.X + 1, PtCntr.Y + 1);
    end;
  end;
end;

function TsgCADImage.CoordinateBorderCorrect(var AXScaled, AYScaled: Extended): Boolean;
var
  vTemp: TsgFloat;
  vBorderRatio, vCorrectedBorderRatio: TsgFloat;
  vExtents: TFRect;
begin
  Result := True;
  vExtents := GetDrawingExtents;
  if IsWithoutBorder then
  begin
    AXScaled := AXScaled;
    AYScaled := AYScaled;
  end
  else
    if BorderType = btRatio then
  begin
    vCorrectedBorderRatio := BorderSize + FXDisproportionateShift;
    AXScaled := AXScaled * (1 + 2 * vCorrectedBorderRatio) - vCorrectedBorderRatio;
    vCorrectedBorderRatio := BorderSize + FYDisproportionateShift;
    AYScaled := AYScaled * (1 + 2 * vCorrectedBorderRatio) - vCorrectedBorderRatio;
  end
  else
    if BorderType = btGlobal then
  begin
    vTemp := vExtents.Right - vExtents.Left - 2 * BorderSize;
    if vTemp <> 0 then
      vBorderRatio := BorderSize / vTemp
    else
    begin
      Result := False;
      Exit;
    end;
    vCorrectedBorderRatio := vBorderRatio + FXDisproportionateShift;
    AXScaled := AXScaled * (1 + 2 * vCorrectedBorderRatio) - vCorrectedBorderRatio;
    vTemp := vExtents.Top - vExtents.Bottom - 2 * BorderSize;
    if vTemp <> 0 then
      vBorderRatio := BorderSize / vTemp
    else
    begin
      Result := False;
      Exit;
    end;
    vCorrectedBorderRatio := vBorderRatio + FYDisproportionateShift;
    AYScaled := AYScaled * (1 + 2 * vCorrectedBorderRatio) - vCorrectedBorderRatio;
  end
  else
    Result := False;
end;

procedure TsgCADImage.FillBoxForCoordsCalc(ACoord: Integer; var ABox: TFRect);
begin
  case ACoord of
    1:
    begin
      ABox.Left := FCurrentLayout.Box.Z1;
      ABox.Right := FCurrentLayout.Box.Z2;
      ABox.Bottom := FCurrentLayout.Box.Bottom;
      ABox.Top := FCurrentLayout.Box.Top;
      ABox.Z1 := FCurrentLayout.Box.Left;
      ABox.Z2 := FCurrentLayout.Box.Right;
    end;
    2:
    begin
      ABox.Left := FCurrentLayout.Box.Left;
      ABox.Right := FCurrentLayout.Box.Right;
      ABox.Bottom := FCurrentLayout.Box.Z1;
      ABox.Top := FCurrentLayout.Box.Z2;
      ABox.Z1 := FCurrentLayout.Box.Bottom;
      ABox.Z2 := FCurrentLayout.Box.Top;
    end;
  else
    ABox.Left := FCurrentLayout.Box.Left;
    ABox.Right := FCurrentLayout.Box.Right;
    ABox.Bottom := FCurrentLayout.Box.Bottom;
    ABox.Top := FCurrentLayout.Box.Top;
    ABox.Z1 := FCurrentLayout.Box.Z1;
    ABox.Z2 := FCurrentLayout.Box.Z2;
  end;
end;

function TsgCADImage.IsAutocadLType: Boolean;
begin
  Result := False;
end;

function TsgCADImage.IsDisableSnapMatrix: Boolean;
begin
  Result := (osDisabled in FObjectSnapMask) or (FObjectSnapMask = []);
end;

procedure TsgCADImage.Load2DPointToPoints(const AList: TF2DPointList);
var
  J: Integer;
  vDrawPoint: TPoint;
begin
  for J := 0 to AList.Count - 1 do// prepares TPoint array for GDI
  begin
    vDrawPoint := GetPoint(MakeFPointFrom2D(AList.List[J]));
    FPoly.Add(vDrawPoint.X);
    FPoly.Add(vDrawPoint.Y);
  end;
end;

function TsgCADImage.IsDrawOnBitMap: Boolean;
begin
  Result := (FSelectionMatrix <> nil) and (not FSelectionMatrix.IsOverflow) and
    (not Converter.ViewPortCut) and
    ((GetMatrixMode <> smDisabled) or FOnInsertMode);
end;

function TsgCADImage.IsDrawOnCanvas: Boolean;
begin
  Result := GetMatrixMode <> smMatrixOnly;
end;

function TsgCADImage.IsRotatedText(const AText: TsgDXFText;
  const ADrawMatrix: TFMatrix): Boolean;
begin
  Result := AText.UpsideDown or AText.Backward
    or IsRotatedTextInternal(AText, ADrawMatrix);
end;

function TsgCADImage.IsRotatedTextInternal(const AText: TsgDXFText;
      const ADrawMatrix: TFMatrix): Boolean;
begin
  Result := (AText.Font.Height > cnstMaxTextHeight)
    or (Abs(AText.Scale - 1) > fAccuracy)
    or ((AText.Point.Z +
      Integer(TsgDXFTextAccess(AText).HasSecond) * AText.Point1.Z) <> 0)
    or IsRotatedFMat(ADrawMatrix, True);
end;

function TsgCADImage.CalcCADCoordsParameters({AXScaled, AYScaled: Extended;
         var AX, AY: TsgFloat; var ARot: TFMatrix;
         var ARealLayoutCenter: TFPoint; var ANullCoord: Integer}var AStruct: TsgCalcCoordsStruct): Boolean;
var
  vWidth, vHeight, vZWidth, vZHeight, vZXShift, vZYShift: TsgFloat;
  vRot: TFMatrix;
  vBox: TFRect;
  vXScaledCorrect, vYScaledCorrect: Extended;

  procedure AssignCoords(I: Integer);
  var
    M: TFMatrix;
  begin
    AStruct.NullCoord := I;
    M := GetRealImageMatrix;
    FillBoxForCoordsCalc(I, vBox);
    case I of
      1:
      begin
        vRot.M[0, 0] := M.M[2, 0];
        vRot.M[1, 1] := M.M[1, 1];
        vRot.M[2, 2] := 0;
        vRot.M[0, 1] := M.M[2, 1];
        vRot.M[0, 2] := 0;
        vRot.M[1, 0] := M.M[1, 0];
        vRot.M[1, 2] := 0;
        vRot.M[2, 0] := 0;
        vRot.M[2, 1] := 0;
      end;
      2:
      begin
        vRot.M[0, 0] := M.M[0, 0];
        vRot.M[1, 1] := M.M[2, 1];
        vRot.M[2, 2] := 0;
        vRot.M[0, 1] := M.M[0, 1];
        vRot.M[0, 2] := 0;
        vRot.M[1, 0] := M.M[2, 0];
        vRot.M[1, 2] := 0;
        vRot.M[2, 0] := 0;
        vRot.M[2, 1] := 0;
      end;
    else
      vRot := M;
    end;
    vWidth := Abs((vBox.Right - vBox.Left) * vRot.M[0, 0]) + Abs((vBox.Top - vBox.Bottom) * vRot.M[1, 0]);
    vHeight := Abs((vBox.Top - vBox.Bottom) * vRot.M[1, 1]) + Abs((vBox.Right - vBox.Left) * vRot.M[0, 1]);
  end;

begin
  Result := True;
  if IsBadRect(FCurrentLayout.Box) then
  begin
    Result := False;
    Exit;
  end;

  vXScaledCorrect := AStruct.XScaled;
  vYScaledCorrect := AStruct.YScaled;
  if not CoordinateBorderCorrect(vXScaledCorrect, vYScaledCorrect) then
  begin
    Result := False;
    Exit;
  end;

  AssignCoords(0);
  if Abs(Abs(vRot.M[1, 2]) - 1) < fAccuracy then
    AssignCoords(2)
  else
    if Abs(Abs(vRot.M[0, 2]) - 1) < fAccuracy then
    AssignCoords(1);
  if (vWidth = 0) or (vHeight = 0) then
  begin
    Result := False;
    Exit;
  end;

  vZWidth := Abs((vBox.Z2 - vBox.Z1) * vRot.M[2, 0]);
  vZHeight := Abs((vBox.Z2 - vBox.Z1) * vRot.M[2, 1]);
  vZXShift := vBox.Z1 * vRot.M[2, 0] / (vZWidth + vWidth);
  vZYShift := vBox.Z1 * vRot.M[2, 1] / (vZHeight + vHeight);
  AStruct.RealLayoutCenter.X := 0.5 * (vBox.Right + vBox.Left);
  AStruct.RealLayoutCenter.Y := 0.5 * (vBox.Top + vBox.Bottom);
  AStruct.RealLayoutCenter.Z := 0.0;

  if vRot.M[2, 0] > 0 then
    AStruct.X := vWidth * ((vXScaledCorrect + vZXShift) * (vZWidth + vWidth) / vWidth - 0.5)
  else
    AStruct.X := vWidth * ((vXScaledCorrect - vZWidth / (vZWidth + vWidth) + vZXShift) * (vZWidth + vWidth) / vWidth - 0.5);
  if vRot.M[2, 1] > 0 then
    AStruct.Y := vHeight * ((vYScaledCorrect + vZYShift) * (vZHeight + vHeight) / vHeight - 0.5)
  else
    AStruct.Y := vHeight * ((vYScaledCorrect - vZHeight / (vZHeight + vHeight) + vZYShift) * (vZHeight + vHeight) / vHeight - 0.5);
  AStruct.Rot := vRot;
end;

function TsgCADImage.CheckActiveVPort: Boolean;
begin
  Result := TsgDXFConverterAccess(Converter).CheckActiveVPort(AbsHeight);
end;

function TsgCADImage.CheckOrthoRaster(const AAngle: Double): Boolean;
begin
  Result := not FBadRotation and IsEqual((Round(AAngle) div 90) * 90, AAngle);
end;

function TsgCADImage.CheckRastrByFastMode(Sender: TObject;
  var AGraphic: TGraphic; const APoints: array of TPoint): Boolean;
var
  vImageEnt: TsgDXFImageEntAccess absolute Sender;
  vHS, vWS, vHI, vWI: Double;
  vScaleMode: Integer;
begin
  Result := not (vImageEnt.GetAnimate  {$IFNDEF SGFPC} or (vImageEnt.Picture.Graphic is TMetafile){$ENDIF});
  if Result then
  begin
    if FCachingRasterMode <> crmNone then
    begin
      vImageEnt.ChangeGraphic;
      vWS := DistancePoint(APoints[0], APoints[1]);
      vHS := DistancePoint(APoints[0], APoints[3]);
      if FCachingRasterMode = crmDoubleCache then
      begin
        vHI := vImageEnt.Picture.Graphic.Width / 8;
        vWI := vImageEnt.Picture.Graphic.Height / 8;
        if (vWI >= vWS) and (vHI >= vHS) then
          vScaleMode := 8
        else
        begin
          vHI := vImageEnt.Picture.Graphic.Width / 4;
          vWI := vImageEnt.Picture.Graphic.Height / 4;
          if (vWI >= vWS) and (vHI >= vHS) then
            vScaleMode := 4
          else
            vScaleMode := 0;
        end;
      end
      else
      begin
        vHI := vImageEnt.Picture.Graphic.Width / 4;
        vWI := vImageEnt.Picture.Graphic.Height / 4;
        if (vWI >= vWS) and (vHI >= vHS) then
          vScaleMode := 4
        else
          vScaleMode := 0;
      end;
      if vScaleMode > 0 then
      begin
        if (vImageEnt.FScaleMode <> vScaleMode) and ((vImageEnt.FBitMap = nil) or (TsgBitMap(vImageEnt.Picture.Graphic).PixelFormat = pf1bit)) then
          vImageEnt.CreateImgLittle(vScaleMode);
        if vImageEnt.FBitMap <> nil then
          AGraphic := vImageEnt.FBitMap
        else
          AGraphic := vImageEnt.Picture.Graphic;
      end
      else
        AGraphic := vImageEnt.Picture.Graphic;
    end
    else
      AGraphic := vImageEnt.Picture.Graphic;
  end
  else
    AGraphic := vImageEnt.Picture.Graphic;
end;

function TsgCADImage.GetCADCoords(const AXScaled, AYScaled: Extended): TFPoint;
var
  C, N, A, B, ASubB, Intersect: TFPoint;
  T, NMulC: TsgFloat;
  SubResult: TFPoint;
  vStruct: TsgCalcCoordsStruct;

  procedure Transpose(var A: TFMatrix);
  begin
    SwapSGFloats(A.M[0,1], A.M[1,0]);
    SwapSGFloats(A.M[0,2], A.M[2,0]);
    SwapSGFloats(A.M[2,1], A.M[1,2]);
  end;

begin
  vStruct.XScaled := AXScaled;
  vStruct.YScaled := AYScaled;
  if not CalcCADCoordsParameters(vStruct) then
  begin
    Result := MakeFPoint(0, 0, 0);
    Exit;
  end;

  C := MakeFPoint(0.0, 0.0, -1.0);
  N := FPointXMat(MakeFPoint(0.0, 0.0, 1.0), vStruct.Rot);
  A := MakeFPoint(vStruct.X, vStruct.Y, 0.0);
  B := MakeFPoint(0.0, 0.0, 0.0);
  ASubB := MakeFPoint(B.X - A.X, B.Y - A.Y, B.Z - A.Z);
  NMulC := ScalarMultiplyVectors(N, C);
  if NMulC <> 0 then //It is always not null
    T := ScalarMultiplyVectors(N, ASubB) / NMulC
  else
    T := 0;
  Intersect := MakeFPoint(A.X + C.X * T, A.Y + C.Y * T, A.Z + C.Z * T);
  Transpose(vStruct.Rot);
  SubResult := FPointXMat(Intersect, vStruct.Rot);
  case vStruct.NullCoord of
    1:
    begin
      Result.X := 0;
      Result.Y := SubResult.Y + vStruct.RealLayoutCenter.Y;
      Result.Z := SubResult.X + vStruct.RealLayoutCenter.X;
    end;
    2:
    begin
      Result.X := SubResult.X + vStruct.RealLayoutCenter.X;
      Result.Y := 0;
      Result.Z := SubResult.Y + vStruct.RealLayoutCenter.Y;
    end;
  else
    Result.X := SubResult.X + vStruct.RealLayoutCenter.X;
    Result.Y := SubResult.Y + vStruct.RealLayoutCenter.Y;
    Result.Z := 0;
  end;
end;

function TsgCADImage.GetCADCoords(const AXScaled, AYScaled: Extended;
  var CoordsInUCS: TFPoint): TFPoint;
begin
  Result := GetCADCoords(AXScaled, AYScaled);
  CoordsInUCS := Result;
  TransformToUCS(CoordsInUCS);
end;

function TsgCADImage.GetClipping: TsgClipping;
begin
  if FClippingRect = nil then
    FillChar(Result, SizeOf(Result), 0)
  else
  begin
    Result.ClipMode := 1;
    Result.ClipRect := FClippingRect^;
  end;
end;

function TsgCADImage.GetConverterParams: TsgConverterParams;
begin
  FillChar(Result, SizeOf(Result), 0);
end;

function TsgCADImage.GetDefaultColor: TColor;
begin
  Result := FDefaultColor;
end;

function TsgCADImage.GetDefaultImageSize: TFRect;
begin
  Result := SGDefaultImageSize(TsgInsUnits(Converter.HeadVarStruct.InsUnits) <> iuMeters);
end;

function TsgCADImage.GetDefaultView: TsgDefaultView;
begin
  Result := df2D;
end;

function TsgCADImage.GetDefSolidRotView: TsgDXFViewDirection;
begin
  Result := vdSEIsometric;
end;

function TsgCADImage.GetDrawBackgroundColor: TColor;
begin
  if FPrinting = pntPrint then
    Result := cnstPrintBackground
  else
    Result := BackgroundColor;
end;

function TsgCADImage.GetDrawingExtents: TFRect;
begin
  if UsePlotSetting then
  begin
    Result := CurrentLayout.PlotSettings.PlotPaperArea;
    SwapDoubles(Result.Top, Result.Bottom);
  end
  else
    Result := Extents;
end;

function TsgCADImage.GetDrawPenColor: TColor;
begin
  if FPrinting = pntPrint then
    Result := cnstPrintDefaultColor
  else
    Result := DefaultColor;
end;

function TsgCADImage.GetSnapData(const P: TPoint): PSnapData;
begin
  Result := FSnapMatrix.Cells[P.X, P.Y];
end;

function TsgCADImage.GetVisibleArea: TPoint;
begin
  Result := FVisibleArea;
end;

function TsgCADImage.GetObjectSnapMask: TObjectSnapState;
begin
  Result := FObjectSnapMask;
end;

procedure TsgCADImage.SetObjectSnapMask(AValue: TObjectSnapState);
const
  osAll = [osInsert, osEndPt, osCenter, osNode, osNearest, osMiddle,
    osIntersection];
var
  B: Boolean;
begin
  FObjectSnapMask := AValue;
  SetupSnapMatrix;
  if not IsDisableSnapMatrix then
  begin
    if Converter.Params <> nil then
    begin
      FSnapOnlyIterate := True;
      B := Converter.AutoInsert;
      try
        Converter.AutoInsert := (osAll * FObjectSnapMask) = osAll;
        FCurrentLayout.Iterate(Converter, DrawEntity, DoFinish);
      finally
        Converter.AutoInsert := B;
        FSnapOnlyIterate := False;
      end;
    end;
  end;
end;

procedure TsgCADImage.SetOffset(const AValue: TFPoint);
begin
  FOffset := AValue;
end;

procedure TsgCADImage.SetupSnapMatrix;
begin
  // Clear All snap matrix
  FSnapMatrix.Clear;
  FSnapMatrix.Resize(FVisibleArea.X, FVisibleArea.Y);
end;

 //evg remove double here!!!!
procedure TsgCADImage.SetPixelSnapEx(const APt: TFPoint; Pt: TPoint;
  const ASnapState: TObjectSnapState);
var
  FSnapMatrixElement: PSnapData;
  vAbsolutePt: TFPoint;
begin
  if (ASnapState * FObjectSnapMask <> []) { and
     ((Abs(FSnapLastPoint.X - APt.X) > FDxyz.X) or
      (Abs(FSnapLastPoint.Y - APt.Y) > FDxyz.Y)) - this check is bad for "two lines in one point" tracers} then
  begin
    FSnapLastPoint := APt;
    if sgClientRectForSnap.Left <> MaxInt then
      Pt.X := Pt.X - sgClientRectForSnap.Left;
    if sgClientRectForSnap.Top <> MaxInt then
      Pt.Y := Pt.Y - sgClientRectForSnap.Top;
    if FSnapMatrix.IsCellValid(Pt.X, Pt.Y) then
    begin
      FSnapMatrixElement := FSnapMatrix.CreateNewData;
      vAbsolutePt := FPointXMat(APt, Converter.GetTransform3D);
      FSnapMatrixElement.Entity := FSnapEntity;
      FSnapMatrixElement.EntityIntersected := nil;
      FSnapMatrixElement.SnapMode := ASnapState;
      FSnapMatrixElement.Insert := FDraw.Insert;
      FSnapMatrixElement.CADPoint := vAbsolutePt;
      FSnapMatrixElement.CADPointInUCS := vAbsolutePt;
      FSnapMatrix.Cells[Pt.X, Pt.Y] := FSnapMatrixElement;
    end;
  end;
end;

function TsgCADImage.SetRGN(const ASender: TObject; const ARGN: HRGN;
  const ADeleteRgn : Boolean = True): HRGN;
begin
  sgOffsetRgn(FCanvas,ARGN);
  Result := CreateRectRgn(0, 0, 0, 0);
  if GetClipRgn(FCanvas.Handle, Result) > 0 then
  begin
    CombineRgn(ARGN, ARGN, Result, RGN_AND);
    if ADeleteRgn then
    begin
      DeleteObject(Result);
      Result := 0;
    end;
  end
  else
  begin
    DeleteObject(Result);
    Result := 0;
  end;
  if IsDrawOnCanvas then
    SetSelectClipRgn(ARGN);
  if IsDrawOnBitMap then
  begin
    SelectClipRgn(SelectionMatrix.Handle, ARGN);
    if not IsDrawOnCanvas then
      GetclipBox(SelectionMatrix.Handle, FDrawRect);
  end;
end;

procedure TsgCADImage.SetPixelSnap(const APt: TFPoint;
  const ASnapState: TObjectSnapState);
var
  Pt: TPoint;
begin
  Pt := GetPoint(APt);
  SetPixelSnapEx(APt, Pt, ASnapState);
end;

procedure TsgCADImage.SetClip(AInsert: TsgCADClipInsert);
var
  H: HRgn;
  F: TFRect;
  R: array[0..3] of TPoint;
  vIsDrawOnBitMap, vIsDrawOnCanvas: Boolean;

  function GetRgnPoint(X, Y, DX, DY: TsgFloat): TPoint;
  var
    P: TPoint;
  begin
    Result := GetPoint(MakeFPoint(X, Y, 0));
    while True do
    begin
      P := GetPoint(MakeFPoint(X+DX,Y+DY,0));
      if (P.X <> Result.X) and (P.Y <> Result.Y) then
        Break;
      DX := DX * 2;
      DY := DY * 2;
    end;
    if P.X > Result.X then
      Inc(Result.X)
    else
      Dec(Result.X);
    if P.Y > Result.Y then
      Inc(Result.Y)
    else
      Dec(Result.Y);
  end;
begin
  DoScale2D(FDraw);
  ExpSaveDCInternal(nil);
  if (FDraw.XScale = 0) or (FDraw.YScale = 0) then Exit;
  vIsDrawOnBitMap := IsDrawOnBitMap;
  vIsDrawOnCanvas := IsDrawOnCanvas;
  if not (vIsDrawOnBitMap or vIsDrawOnCanvas) then Exit;
  F := AInsert.Box;
  if IsBadRect(F) then Exit;
  R[0] := GetRgnPoint(F.Left, F.Top, -1, 1);
  R[1] := GetRgnPoint(F.Right, F.Top, 1, 1);
  R[2] := GetRgnPoint(F.Right, F.Bottom, 1, -1);
  R[3] := GetRgnPoint(F.Left, F.Bottom, -1, -1);
  H := CreatePolygonRgn(R, 4, WINDING);
  if ExpClipRgnInternal(AInsert, H) then
    DeleteObject(H);
end;

procedure TsgCADImage.Draw(Canvas: TCanvas; const Rect: TRect);
var
  vPrevMode: Integer;
  OldPal: HPalette;
  vRect, vDB: TRect;
  vSelectionMatrixMode: TsgSelectionMode;
  vHRGN, vPrintHRGN: HRGN;
  vSelectionMatrix: TsgSelectionMatrix;
  vClearfFull: Boolean;
  vSnapMask: TObjectSnapState;
  vOldConverting: Boolean;
  vClippingRect: PFRect;
  vDPIScale, vLineWeightScale: Double;
 {$IFDEF SHOWTICKS}   Ticks: Cardinal;    {$ENDIF}  //evg
begin
  if FCurrentLayout = nil then Exit;
  {$IFDEF SHOWTICKS}  Ticks := GetTickCount; {$endif}//evg
  //SetupSnapMatrix;
  vLineWeightScale := LineWeightScale;
  vSelectionMatrixMode := GetMatrixMode;
  vSelectionMatrix := nil;
  if Assigned(SelectionMatrix) then
    if (vSelectionMatrixMode <> smDisabled) or (FOnInsert <> nil) then
    begin
      vSelectionMatrix := SelectionMatrix;
      vSelectionMatrix.Size := FVisibleArea
    end
    else
    begin
      vSelectionMatrix := SelectionMatrix;
      vSelectionMatrix.Size := Point(1, 1);
    end;
  vClippingRect := GetRealClip;
  vRect := GetDrawRect(Rect, GetDrawingExtents, vClippingRect);
  Drawing := Self;
  FCanvas := Canvas;
  try
    if FCustomDraw then
      ApplyScale(vRect);
  except
    Exit
  end;
  vPrevMode := SetGraphicsMode(FCanvas.Handle, GM_COMPATIBLE);// GM_ADVANCED
  OldPal := SelectPalette(FCanvas.Handle, AcadPal, True);
  FmmToPixelX := GetDeviceCaps(FCanvas.Handle, HORZSIZE) / GetDeviceCaps(FCanvas.Handle, HORZRES);
  if FDeviceDPI.X > 0 then
  begin
    vDPIScale :=  FDeviceDPI.X * FmmToPixelX / 25.4;
    LineWeightScale := LineWeightScale * vDPIScale;
  end;
  FCanvasParams.Brush.Assign(Canvas.Brush);
  FCanvasParams.Font.Assign(Canvas.Font);
  FCanvasParams.Pen.Assign(Canvas.Pen);
  if UsePlotSetting then
  begin
    vPrintHRGN := GetPlotSettingsRGN;
    if vPrintHRGN <> 0 then
      SetRGN(nil, vPrintHRGN);
  end;
  vHRGN := CreateRectRgn(0, 0, 0, 0);
  if GetClipRgn(FCanvas.Handle, vHRGN) <= 0 then
  begin
    DeleteObject(vHRGN);
    vHRGN := 0;
  end;
  FClipRegion := vHRGN;
  vOldConverting := FConverting;
  try
    {$IFNDEF SGFPC}
    if (Canvas is TMetafileCanvas) then
      FConverting := True;
    {$ENDIF}

    RealizePalette(FCanvas.Handle);
    //evg - to DrawRect!!!
    FPixelsPerInch := FCanvas.Font.PixelsPerInch; //evg
    FColor := GetDrawPenColor;
    FColorPen := GetDrawPenColor;
    FColorBrush := GetDrawPenColor;
    FColorFont := GetDrawPenColor;
    FCanvas.Pen.Color := FColorPen;
    FCanvas.Brush.Color := FColorBrush;
    FCanvas.Font.Color := FColorFont;
    FPenWidth := 0;
    FCanvas.Pen.Style := psSolid;
    SetTextAlign(FCanvas.Handle, TA_BASELINE);    //evg
    if not Transparent then
    begin
      if IsCurLayoutShowPlot then
        DoSetColor(cnstPlotBackground, ctBrush)
      else
        DoSetColor(GetBackgroundColor, ctBrush);
      if FIsShowBackground and (vSelectionMatrixMode <> smMatrixOnly) then
        Canvas.FillRect(Rect);//vRect
      if ShowPlotSetting and (not FIsIterator) then
        DrawPaperSpace;
    end;
    Converter.AutoInsert := False;
    Converter.Params := @FDraw;
    if not IsBadRect(FDrawingBox) then
    begin
      vDB := GetRect(FDrawingBox);
      InflateRect(vDB,1,1);
      IntersectClipRect(FCanvas.Handle, vDB.Left, vDB.Top, vDB.Right, vDB.Bottom);
    end;
    if Assigned(vClippingRect) then
      IntersectClipRect(FCanvas.Handle, Rect.Left, Rect.Top, Rect.Right, Rect.Bottom);

    if FConverting then
      FDrawRect := vRect
    else
      GetclipBox(Canvas.Handle, FDrawRect); // evg
    SetStretchBltMode(FCanvas.Handle, HALFTONE);
// clear matrices
    vClearfFull := False;
    if (PtInRect(FDrawRect, cnstRectZero.TopLeft) and
       PtInRect(FDrawRect, Point(FVisibleArea.X - 1, FVisibleArea.Y - 1))) then
    begin
      if Assigned(vSelectionMatrix) then
        vSelectionMatrix.ClearFull;
      vClearfFull := True;
    end
    else
      if Assigned(vSelectionMatrix) then
        if vSelectionMatrix.IsOverflow then
        begin
          vSelectionMatrix.ClearFull;
          vClearfFull := True;
        end
        else
          vSelectionMatrix.ClearRect(FDrawRect);
    if (FSnapMatrix.ColsCount <> FVisibleArea.X) or
       (FSnapMatrix.RowsCount <> FVisibleArea.Y) then
    begin
      FSnapMatrix.Resize(FVisibleArea.X, FVisibleArea.Y);
      vClearfFull := False;
    end;
    if vClearfFull then
      FSnapMatrix.Clear
    else
      FSnapMatrix.ClearRect(FDrawRect);
    FSnapLastPoint.X := MaxDouble;     //evg
    FSnapLastPoint.Y := MaxDouble;//evg
    GetPixelSize(5, FDxyz.X, FDxyz.Y, True);
    FOnComplexEntity := nil;
    CurrentLayout.Iterate(Converter, DrawEntity, DoFinish);
    if Assigned(vSelectionMatrix) and (vSelectionMatrix.IsOverflow) then
    begin
      SetSelectionMatrixProc(smMatrixOnly);
      try
        vSnapMask := FObjectSnapMask;
        try
          Include(FObjectSnapMask, osDisabled); // do not draw to FSnapMatrix
          vSelectionMatrix.ClearFull;
          FDrawRect := Classes.Rect(0, 0, FVisibleArea.X, FVisibleArea.Y);
          CurrentLayout.Iterate(Converter, DrawEntity, DoFinish);
        finally
           FObjectSnapMask := vSnapMask;
        end;
      finally
        SetSelectionMatrixProc(vSelectionMatrixMode);
      end;
    end;
 {$IFDEF SHOWTICKS}   Ticks := GetTickCount - Ticks; //evg
    ShowMessage(FloatToStr(Ticks));  {$ENDIF} //evg

    if FIsDraw3DAxes then
      Draw3DAxes;
  finally
    LineWeightScale := vLineWeightScale;
    FConverting := vOldConverting;
    FOnComplexEntity := nil;
    SetSelectClipRgn(vHRGN);
    if vHRGN <> 0 then
      DeleteObject(vHRGN);
    FCurrentLayout.RotZAngle := FCurrentLayout.RotZAngle+FZRotate;
    FZRotate := 0;
    SelectPalette(FCanvas.Handle, OldPal, True);
    Canvas.Brush := FCanvasParams.Brush;
    Canvas.Font := FCanvasParams.Font;
    Canvas.Pen := FCanvasParams.Pen;
    SetGraphicsMode(FCanvas.Handle, vPrevMode);
    FXrefStack.Clear;
    if Assigned(FOnAfterDraw) then
      FOnAfterDraw(Self);
    SetListsCapacity(False);
  end;
end;

{$IFNDEF SGFPC}
procedure TsgCADImage.DrawOnMetafile(const AMetafile: TMetafile;
  const AUseLogicMetrix: Boolean; const ADrawProc: TsgObjProcDraw = nil);
var
  R: TRect;
  vMetafileCanvas: TMetafileCanvas;
  vOutMMWidth, vOutMMHeight, vKoef: Double;
  vUseGDIPlus, vAddOnePixel: Boolean;
begin
  vKoef := 72 / AMetafile.Inch;
  if AUseLogicMetrix then
  begin
    vOutMMWidth := AMetafile.Width;
    vOutMMHeight := AMetafile.Height;
    SetMaxSize(31000, vOutMMWidth, vOutMMHeight);
    R := Rect(0, 0, Round(vOutMMWidth), Round(vOutMMHeight));
  end;
  vAddOnePixel := FAddOnePixel;
  vUseGDIPlus := LibraryGDIPlusExists;
  vMetafileCanvas := TMetafileCanvas.Create(AMetafile, 0);
  try
    FAddOnePixel := False;
    if AUseLogicMetrix then
    begin
      LibraryGDIPlusExists := False;
      SetMapMode(vMetafileCanvas.Handle, MM_ANISOTROPIC or MM_MAX);
      SetViewportExtEx(vMetafileCanvas.Handle, Round(AMetafile.Width * vKoef), Round(AMetafile.Height * vKoef), nil);
      SetWindowExtEx(vMetafileCanvas.Handle, AMetafile.Width, AMetafile.Height, nil);
      SetWindowOrgEx(vMetafileCanvas.Handle, 0, 0, nil);
      SetWindowExtEx(vMetafileCanvas.Handle, R.Right, R.Bottom, nil);
    end
    else
      R := Rect(0, 0, Round(AMetafile.Width * vKoef), Round(AMetafile.Height * vKoef));
    InflateRect(R, -2, -2);
    vMetafileCanvas.StretchDraw(R, Self);
    if Assigned(ADrawProc) then
      ADrawProc(vMetafileCanvas, R);
  finally
    FAddOnePixel := vAddOnePixel;
    LibraryGDIPlusExists := vUseGDIPlus;
    vMetafileCanvas.Free;
  end;
end;
{$ENDIF}

function TsgCADImage.DrawComplexEntity(Sender: TObject): Integer;
begin
  Result := Integer(FOnComplexEntity = nil);
  //Exit;
  if Result = 1 then
  begin
    if (SelectionMatrix <> nil) and (not FIsIterator) then
    begin
      AddSelectionMatrix(Sender);
      SelectionMatrix.Changed;
    end;
    FOnComplexEntity := TsgDXFEntity(Sender);
  end;
end;


//evg reg
function sgRectVisible(ABaseRect, AEntityRect: TRect): Boolean;
begin
  Result := False;
  if AEntityRect.Right < ABaseRect.Left then
    Exit;
  if AEntityRect.Left > ABaseRect.Right then
   Exit;
  if AEntityRect.Bottom < ABaseRect.Top then
    Exit;
  if AEntityRect.Top > ABaseRect.Bottom then
   Exit;
  Result := True;
end;

function TsgCADImage.DrawEntity(Entity: TsgDXFEntity): Integer;
var
  vRectVisible, vAttdef: Boolean;
  vIntersectRect, vTmpIRect: TRect;
  vMatrixMode: TsgSelectionMode;
  vLayer: TsgDXFLayer;
  vLayerLines: TsgLines;
  vColor: TColor;
  {$IFDEF SG_HIDDEN}
  Temp : Boolean;
  {$ENDIF}

  function EntVisibleByLayer(E: TsgDXFEntity; Ins: TsgDXFInsert; ARealVis: Boolean = False): Boolean;
  var
    L: TsgDXFLayer;
  begin
    Result := E.Visibility and (not IsBadRect(E.Box));
    if Result then
    begin
      L := EntLayer(E, Ins);
      if ARealVis then // True, if need check insert visibility
        Result := Result and ((L = nil) or L.Visible)
      else
        Result := Result and (((L = nil) or L.Visible) or E.IsInsert);
      Result := Result and (not IsPlotting or (IsPlotting and ((L=nil) or ((L<>nil) and L.IsPlotting)))); //evg: what does it mean???
      if (L <> nil) and (L.Frozen or L.IsFrozenByViewPort) then   // why here?
        Result := False;
      if E.EntType = cePoint then
      begin
        Result := Result and (FConverter.PointDisplayMode <> 1);
        if Ins is TsgDXFDimension then
          Result := Result and EntVisibleByLayer(Ins, Ins.OwnerInsert, True); //evg
      end;
    end;
  end;

  function IsEntityInRectVisible(ARect: TRect): Boolean;
  begin
    if vMatrixMode = smMatrixOnly then
      Result := (SelectionMatrix <> nil) and sgRectVisible(FDrawRect, ARect)
    else
    begin
       Result := sgRectVisible(FDrawRect, ARect);
       if Result and FIsIterator and (FClipRgn <> 0) and (FSaveDC.Count > 0) then
       begin
         Result := RectInRegion(FClipRgn, ARect);
       end;
    end;
  end;

  function CheckDraw(AEntity: TsgDXFEntity): Boolean;
  begin
    case AEntity.EntType of
      ceAttdef, ceAttrib:
       Result := not (Converter.HeadVarStruct.AttMode = attDisable);
      ce3dFace:
       Result :=  not (TsgDXF3dFaceAccess(AEntity).Flags = $F);
    else
      Result := True;
    end;
  end;

begin
  Result := 0;
  vLayerLines := nil;
  FEntityHandle := Entity.Handle;
  FEntityLines := TsgDXFEntityAccess(Entity).GetLines;
  if Entity.LineType <> nil then
  begin
    if Entity.LineType.Name = sByBlock then
      FEntityLines := FDraw.LType
    else
      if Entity.LineType.Name = sByLayer then
      begin
        vLayer := TsgDXFLayer(EntLayer(Entity, FDraw.Insert));
        if vLayer <> nil then
        begin
          vLayerLines := TsgDXFEntityAccess(vLayer).GetLines;
          FEntityLines := vLayerLines;
        end;
      end;
  end;
  if FEntityLines = nil then
    FEntityLines := StdLines;

  if FIsIterator and Assigned(FsgExpProgress) then
    FsgExpProgress;

  vMatrixMode := GetMatrixMode;
  try
   if Entity.EntType = ceViewport then
    begin
      TsgDXFViewPort(Entity).VisibleBoundary := EntVisibleByLayer(Entity, FDraw.Insert);
      FColor := GetEntityColor(Entity, FDraw.Insert);
      DoSetColor(FColor, ctPen);
      SetPenWidth(1);
      DrawEntityOnSnapMatrix(Entity);
      Result := DoDraw(Entity);// allways call draw function for TsgDXFVewport
    end
    else
    begin
      vAttdef := Entity.EntType = ceAttdef;
      if not CheckDraw(Entity) then
        Exit;
      FReady := False;
      begin
        if FIsIterator then
          FIRect := cnstBad2DRectExport
        else
          FIRect := cnstBad2DRect;
        FIndex := 0;
        FReady := Entity.GetBoxPoints(BoxPoint, FDraw.Additional <> 0);
        if FReady and Assigned(vLayerLines) and (not vLayerLines.IsSolid) then
          FReady := False;
        vTmpIRect := FIRect;
        Inc(vTmpIRect.Right);
        Inc(vTmpIRect.Bottom);
        vRectVisible := IsEntityInRectVisible(vTmpIRect);
        if not vRectVisible and not FConverting then
          Exit;
        if not EntVisibleByLayer(Entity, FDraw.Insert) then
          Exit;
        {$IFDEF SG_HIDDEN}
        Temp := True;
        if not Assigned(FsgExpPixel) then
           Temp := (FCanvas.Pen.Mode <> pmXor) and (FCanvas.Pen.Mode <> pmNotXor);
          {$INCLUDE HIDDEN1.INC}
        {$ENDIF}
        DrawEntityOnSnapMatrix(Entity);
       // ApplyPen(Entity); //evg ??? - is any sence to show lineweight for less than 1 pixel elements?
        {evg}
        if not (osDisabled in FObjectSnapMask) and (FObjectSnapMask <> []) and
           Entity.IsInsert then
        begin
          IntersectRect(vIntersectRect, sgClientRectForSnap, vTmpIRect);
          if (not IsRectEmpty(vIntersectRect)) and  vRectVisible then //evg - the same code twice
          begin
            if FStoreInsert = nil then
            begin
              FStoreSnapOnlyIterate := FSnapOnlyIterate;
              FSnapOnlyIterate := True;
              FStoreInsert := FDraw.Insert;
            end;
            DoDraw(Entity);
            if FStoreInsert = FDraw.Insert then
            begin
              FSnapOnlyIterate := FStoreSnapOnlyIterate;
              FStoreInsert := nil;
            end;
          end;
        end;
      end;
      if vAttdef or vRectVisible or FConverting then// evg - ????? ??? metafilecanvas
      begin
        if SetColorByExternalPen(True, vColor) then
        begin
          FColor := vColor;
          DoSetColor(vColor, ctPen);
          SetPenWidth(FDrawExternlProps.Mode.LineWidth);
        end
        else
        begin
          FColor := GetEntityColor(Entity, FDraw.Insert);
          DoSetColor(FColor, ctPen);
          ApplyPen(Entity);
        end;
        Result := DoDraw(Entity);
      end;
    end;
  finally
    SetMatrixMode(vMatrixMode);
  end;
end;

//evg new
procedure TsgCADImage.DrawEntityOnSnapMatrix(Entity: TsgDXFEntity);
var
  vPt: TFPoint;
  vPoly: TsgCADBasePolyline absolute Entity;
  vEllipse: TsgDXFEllipse;
  vRect: TFRect;

  procedure PolylinePoints(APolyLine: TsgCADBasePolyline);
  var
    I: Integer;
  begin
    if APolyLine.PolyPoints.Count > 0 then
    begin
      for I := 0 to APolyLine.PolyPoints.Count - 1 do
        SetPixelSnap(APolyLine.PolyPoints.Items[I], [osEndPt]);
    end;
  end;

  procedure FlatEntityPoints(APoly: TsgFlatEntity);
  var
    I: Integer;
  begin
    if APoly.PCount > 0 then
    begin
      for I := 0 to APoly.PCount - 1 do
        SetPixelSnap(APoly.XY[I], [osEndPt]);
    end;
  end;

  procedure DoQuardrantSnap(const ACircle: TsgDXFCircle);
  var
    vAngle, I: Integer;
    vA, vB, vStart, vEnd, vSin, vCos: Double;
    vPoint: TFPoint;
  begin
    if ([osQuadrant] * FObjectSnapMask = []) or
       TsgDXFCircleAccess(ACircle).IsExtruded then Exit;
    TsgDXFCircleAccess(ACircle).Params(vA, vB, vStart, vEnd, vSin, vCos);
    CheckAngles(vStart, vEnd);
    for I := 0 to 3 do
    begin
      vAngle := 90 * I;
      if IsAngleInAngles(vAngle, vStart, vEnd) then
      begin
        if ACircle.EntType = ceEllipse then
          vPoint := GetPointOnEllipse(ACircle.Point, vA, vB, vSin, vCos, vAngle)
        else//this function has a more precise calculations
          vPoint := GetPointOnCircle(ACircle.Point, ACircle.Radius, vAngle);
        SetPixelSnap(vPoint, [osQuadrant]);
      end;
    end;
  end;

  procedure DoCircle(const ACircle: TsgDXFCircle);
  begin
    SetPixelSnap(ACircle.Point, [osCenter]);
    DoQuardrantSnap(ACircle);
  end;

  procedure DoArc(const AArc: TsgDXFArc);
  begin
    DoCircle(AArc);
    SetPixelSnap(AArc.StartPoint, [osEndPt]);
    SetPixelSnap(AArc.EndPoint, [osEndPt]);
  end;

  procedure Vertexes(APolyLine: TsgDXFPolyline);
  var
    I, Cnt: Integer;
    vVertex: TsgDXFVertex;
    vPoint2: TFPoint;
    vArc: TsgDXFArc;
    vPolyLine: TFPointList;

    function GetPointZTicks(AVertex: TsgDXFVertex; APolyLine: TFPointList;
      AIndex: Integer): TFPoint;
    begin
      if Assigned(vPolyLine) then
        Result := APolyLine[AIndex]
      else
        Result := AVertex.Point;
    end;
  begin
    if APolyLine.PolyPoints.Count > 0 then
    begin
      vArc := nil;
      vPolyLine := nil;
      try
        if (APolyLine.EntType = ceLWPolyline) and
           ([osCenter, osQuadrant] * FObjectSnapMask <> []) and
           (not TsgCADBasePolyLineAccess(APolyLine).IsExtruded) then
          vArc := TsgDXFArc.Create;
        Cnt := APolyLine.Count - 1;

        if TsgCADBasePolyLineAccess(APolyLine).IsExtruded or
           TsgCADBasePolyLineAccess(APolyLine).IsPolyZThickness or
           (TsgCADBasePolyLineAccess(APolyLine).GetElevation <> 0) then
        begin
          vPolyLine := TFPointList.Create;
          for I := 0 to Cnt do
            vPolyLine.Add(APolyLine.Vertexes[I].Point);
          TsgCADBasePolyLineAccess(APolyLine).AddZTicks(vPolyLine);
        end;

        for I := 0 to Cnt do
        begin
          vVertex := APolyLine.Vertexes[I];
          SetPixelSnap(GetPointZTicks(vVertex, vPolyLine, I), [osEndPt]);
          if (vArc <> nil) and (vVertex.Bulge <> 0) then
          begin
            if I >= Cnt then
              vPoint2 := GetPointZTicks(APolyLine.Vertexes[0], vPolyLine, 0)
            else
              vPoint2 := GetPointZTicks(APolyLine.Vertexes[I + 1], vPolyLine, I + 1);
            if not IsEqualFPoints(GetPointZTicks(APolyLine.Vertexes[I], vPolyLine, I), vPoint2) then
            begin
              SetArcParams(vArc, GetPointZTicks(APolyLine.Vertexes[I], vPolyLine, I), vPoint2, vVertex.Bulge);
              DoCircle(vArc);
            end;
          end;
        end;
      finally
        if Assigned(vPolyLine) then
          vPolyLine.Free;
        FreeAndNil(vArc);
      end;
    end;
  end;

{$IFDEF SG_BTI}
  procedure PolyPolyline2DPoints(APoly: TsgCADPolyPolyline2D);
  var
    I: Integer;
    vLine: TsgLine;
    vArcR: TsgArcR;
    vArc: TsgDXFArc;
  begin
    if APoly.CurvesCount > 0 then
    begin
      vArc := TsgDXFArc.Create;;
      try
        for I := APoly.CurvesCount - 1 downto 0 do
        begin
          if APoly.CurveVisible[I] then
            if APoly.IsCurveArc(I) and
              ([osEndPt, osCenter, osQuadrant] * FObjectSnapMask <> []) then
            begin
              vArcR := APoly.Arcs[I];
              vArc.Point := vArcR.Center;
              vArc.Radius := vArcR.Radius;
              vArc.StartAngle := vArcR.AngleS;
              vArc.EndAngle := vArcR.AngleE;
              DoArc(vArc);
            end
            else
            begin
              vLine := APoly.Lines[I];
              SetPixelSnap(vLine.Point1, [osEndPt]);
              SetPixelSnap(vLine.Point2, [osEndPt]);
            end;
        end;
      finally
        FreeAndNil(vArc);
      end;
    end;
  end;

  procedure InsertPts(const AInsert: TsgDXFInsertAccess; const AFull: Boolean);
  var
    I: Integer;
    vPts: TsgPoints4;
    vPoints: TFPointList;
  begin
    if AFull then
    begin
      vPoints := TFPointList.Create;
      try
        AInsert.GetPtsEx(vPoints);
        for I := 0 to MinI(4, vPoints.Count - 1) do
          SetPixelSnap(vPoints[I], [osEndPt]);
        for I := 5 to MinI(8, vPoints.Count - 1) do
          SetPixelSnap(vPoints[I], [osMiddle]);
      finally
        vPoints.Free;
      end;
    end
    else
    begin
      AInsert.GetPts(vPts);
      for I := Low(vPts) to High(vPts) do
        SetPixelSnap(vPts[I], [osEndPt]);
    end;
  end;
{$ENDIF}

begin
  if IsDisableSnapMatrix then
    Exit;
  FSnapEntity := Entity;
  case Entity.EntType of
    cePoint:
      begin
        SetPixelSnap(TsgDXFPoint(Entity).Point, [osEndPt]);
      end;
    ceLine, ceSolid, ceTrace, ce3dFace:
      begin
        SetPixelSnapEx(TsgDXFSolid(Entity).Point, FIPoints[0], [osEndPt]);
        SetPixelSnapEx(TsgDXFSolid(Entity).Point1, FIPoints[1], [osEndPt]);
        case Entity.EntType of
          ceSolid, ceTrace, ce3dFace:
            begin
              SetPixelSnapEx(TsgDXFSolid(Entity).Point2, FIPoints[2], [osEndPt]);
              SetPixelSnapEx(TsgDXFSolid(Entity).Point3, FIPoints[3], [osEndPt]);
            end;
        end;
      end;
    ceCircle:
      begin
        DoCircle(TsgDXFCircle(Entity));
      end;
    ceArc:
      begin
        DoArc(TsgDXFArc(Entity));
      end;
    ceEllipse:
      begin
        vEllipse := TsgDXFEllipse(Entity);
        vPt := vEllipse.Point;
        DoExtrusion(vPt, vEllipse.Extrusion);
        SetPixelSnap(vPt, [osCenter]);
        if not(Abs(vEllipse.StartAngle - vEllipse.EndAngle + 360) < FAccuracy) and
          (vEllipse.PolyPoints <> nil) then
        begin
          vPt := vEllipse.Points[0];
          SetPixelSnap(vPt, [osEndPt]);
          vPt := vEllipse.Points[vEllipse.PolyPoints.Count - 1];
          SetPixelSnap(vPt, [osEndPt]);
        end;
        DoQuardrantSnap(TsgDXFCircle(Entity));
      end;
    ceLWPolyline,
      cePolyline:
        Vertexes(TsgDXFPolyline(Entity));
      cePath,
      ceLeader:
        PolylinePoints(TsgCADBasePolyLine(Entity));
    ceWipeout,
    ceImageEnt:
        begin
          if TsgCADBasePolyLine(Entity).PolyPoints.Count > 0 then
            PolylinePoints(TsgCADBasePolyLine(Entity))
          else
          begin
            SetPixelSnap(TsgCADWipeoutAccess(Entity).GetPoint, [osEndPt]);
            SetPixelSnap(TsgCADWipeoutAccess(Entity).GetPoint1, [osEndPt]);
            SetPixelSnap(TsgCADWipeoutAccess(Entity).GetPoint2, [osEndPt]);
            SetPixelSnap(TsgCADWipeoutAccess(Entity).GetPoint3, [osEndPt]);
          end;
        end;
    ceSpline, ceHelix:
      begin
        SetPixelSnap(vPoly.Points[0], [osEndPt]);
        SetPixelSnap(vPoly.Points[vPoly.PolyPoints.Count - 1], [osEndPt]);
      end;
    ceDimension:
      begin
        if osInsert in FObjectSnapMask then
        begin
          if FDraw.Insert = nil then
            SetPixelSnap(TsgDXFDimension(FSnapEntity).DefPoint, [osInsert])
        end;
      end;
    ceACADTable,
      ceInsert,
      ceMText,
      ceMLine,
      ceTolerance:
        begin
          if osInsert in FObjectSnapMask then
          begin
            if FDraw.Insert = nil then
            begin
{$IFDEF SG_BTI}
              if TsgDXFEntityAccess(FSnapEntity).GetEntTypeEx <= cnstUndefined then
{$ENDIF}
                SetPixelSnap(TsgDXFInsert(FSnapEntity).Point, [osInsert]);
            end;
          end;
{$IFDEF SG_BTI}
          if [osEndPt, osMiddle] * FObjectSnapMask <> [] then
          begin
            case TsgDXFEntityAccess(FSnapEntity).GetEntTypeEx of
              cnstElementModifier, cnstElementBroad, cnstElementCarved:
                InsertPts(TsgDXFInsertAccess(FSnapEntity), True);
            end;
          end;
{$ENDIF}
        end;
  {  ceText,    //evg: now there is no snap here
      ceAttdef,
      ceAttrib:
        DrawText(Entity);
    ceShape:
      DrawShape(Entity);
    ce3dFace:
      DrawFace(Entity);
    cePolyPolygon,
      ceGradient,
      ceGradientPolygon,
      ceCurvePolygon,
      ceHatch:           DrawHatch(Entity);
    ceImageEnt:          DrawImageEnt(Entity);
    ceViewport:          DrawViewPort(Entity);
    ceRegion,
      ceBody, ce3DSolid: DrawACISEntity(Entity);
    ceOle2Frame:         DrawOle2Frame(Entity);  }
  //evg - removed to drawflatpoly      ceFlatPoly:          DrawFlatPoly(Entity);
    ceFlatHatch,
     ceFlatPoly3D:         FlatEntityPoints(TsgFlatEntity(Entity));
  //  ceXRef:              DrawXRef(Entity);
 //   ceWipeout:           DrawWipeout(Entity);
{$IFDEF SG_BTI}
    cePolyPolyline2D:   PolyPolyline2DPoints(TsgCADPolyPolyline2D(Entity));
{$ENDIF}
    ceOle2Frame:
      begin
        SetPixelSnap(TsgDXFOle2Frame(Entity).Point, [osEndPt]);
        SetPixelSnap(TsgDXFOle2Frame(Entity).Point1, [osEndPt]);
      end;
    ceViewPort:
      begin
        if TsgDXFViewportAccess(Entity).GetClipBoundary(FConverter) = nil then
        begin
          vRect :=  TsgDXFViewPort(Entity).Rect;
          SetPixelSnap(vRect.TopLeft, [osEndPt]);
          SetPixelSnap(vRect.BottomRight, [osEndPt]);
          SetPixelSnap(MakeFPoint(vRect.Right, vRect.Top), [osEndPt]);
          SetPixelSnap(MakeFPoint(vRect.Left, vRect.Bottom), [osEndPt]);
        end;
      end;
  end;
end;

procedure TsgCADImage.DrawRect(DC: HDC; SourceRect: TFRect; DestRect: TRect);
var
  vCanvas: TCanvas;
  vBox, vExtents, vClip: TFRect;
begin
  if SourceRect.Left > SourceRect.Right then
    SwapSGFloats(SourceRect.Left, SourceRect.Right);
  if SourceRect.Bottom > SourceRect.Top then
    SwapSGFloats(SourceRect.Top, SourceRect.Bottom);
  if SourceRect.Z1 > SourceRect.Z2 then
    SwapSGFloats(SourceRect.Z1, SourceRect.Z2);
  vCanvas := TCanvas.Create;
  try
    vCanvas.Handle := DC;
    vBox := FDrawingBox;
    try
      vExtents := GetDrawingExtents;
      vClip.Left := - vExtents.Left + SourceRect.Left;
      vClip.Top := vExtents.Top - SourceRect.Top;
      vClip.Right := - vExtents.Left + SourceRect.Right;
      vClip.Bottom := vExtents.Top - SourceRect.Bottom;
      SetClippingRect(@vClip);
      Draw(vCanvas, DestRect);
    finally
      FDrawingBox := vBox;
      SetClippingRect(nil);
    end;
  finally
    vCanvas.Free;
  end;
end;

function TsgCADImage.GetEntityColor(AEntity: TsgDXFEntity; AInsert: TsgDXFInsert): TColor;
begin
  if FDrawMode <> dmBlack then
    Result := EntColor(AEntity, AInsert)
  else
    Result := GetDrawPenColor;
  if FPrinting = pntNone then
  begin
    if (AEntity.ColorCAD.Active = acIndexColor) and (Result = GetBackgroundColor) and
     (AEntity.ColorCAD.Color > 249) and (AEntity.ColorCAD.Color < 256)  then
    begin
      Result := FChangeBackgroundColor;
    end;
  end;
end;

function TsgCADImage.GetEntLineWeight(const AEntity, AInsert: TsgDXFEntity): Double;
begin
  Result := EntLineWeight(AEntity, TsgDXFInsert(AInsert));
  if TsgDXFEntityAccess(AEntity).HasLineWeight then
  begin
    ApplyLineWeightFactor(Result);
    Result := Result / IfThen(FmmToPixelX <> 0, FmmToPixelX, 1);
    if (Result < 0) or sgIsZero(Result) then
      Result := FNullWidth;
  end;
end;

function TsgCADImage.GetEmpty: Boolean;
begin
  Result := False;//(FConverter.Counts[csEntities] = 0);
end;

{$IFDEF SGFPC}
function TsgCADImage.GetTransparent: Boolean;
begin
  Result := False;
end;
{$ENDIF}

procedure TsgCADImage.GetExtents;
begin
  FConverter.DoExtents;
  if CurrentLayout = nil then
    SetCurrentLayout(FConverter.Layouts[0])
  else
    SetCurrentLayout(CurrentLayout);
end;

function TsgCADImage.GetExternalFiles(const AList: TStringList;
  const AMode: TsgExternalFilesModes = [efAddXRef, efAddImageDef
  {$IFDEF DATA_LINK}, efDataLink{$ENDIF}]): Boolean;
var
  I: Integer;
  vStackConverters: TsgList;
  vList: TStringList;

  procedure GetXRefListBlock(const AConverter: TsgDXFConverter;
    const AList: TStringList; const AStackConverters: TsgList;
    const AMode: TsgExternalFilesModes);
  var
    I: Integer;
    vBlock: TsgDXFBlock;
    vImageDef: TsgDXFImageDef;
{$IFDEF DATA_LINK}
    J, vIndex: Integer;
    vFileName: string;
    vDataLink: TsgDXFEntity;
{$ENDIF}

  begin
    if AStackConverters.IndexOf(AConverter) < 0 then
    begin
      AStackConverters.Add(AConverter);
      try
        for I := 0 to AConverter.Counts[csBlocks] - 1 do
        begin
          vBlock := TsgDXFBlock(AConverter.Sections[csBlocks][I]);
          if Assigned(vBlock.Xref) and (efAddXRef in AMode) then
          begin
            if (efConvertXrefInFullPath in AMode) then
            begin
              if TsgCADImage(vBlock.Xref.CADImage).FileName <> '' then
                AList.Add(TsgCADImage(vBlock.Xref.CADImage).FileName);
            end
            else
              if vBlock.Xref.Path = '' then
                AList.Add(vBlock.XrefPath)
              else
                AList.Add(vBlock.Xref.Path);
            if not (efNoIterateChildren in AMode) then
              GetXRefListBlock(TsgCADImage(vBlock.Xref.CADImage).Converter,
                AList, AStackConverters, AMode);
          end;
        end;
        for I := 0 to AConverter.Counts[csImageDefs] - 1 do
        begin
          vImageDef := TsgDXFImageDef(AConverter.Sections[csImageDefs][I]);
          if Assigned(vImageDef) and (efAddImageDef in AMode) then
            AList.Add(vImageDef.FileName);
        end;

{$IFDEF DATA_LINK}
        // Data Link
        vDataLink := AConverter.Sections[csObjects].FindEntByName(sDictionaryAcadDataLink);
        if Assigned(vDataLink) and (efDataLink in AMode) then
        begin
          for I := 0 to vDataLink.Count - 1 do
          begin
            vFileName := TsgCADDataLink(vDataLink[I]).FileName;
            if Length(vFileName) > 0 then//trim excel paper link
            begin
              J := StringScan(cnstExclamationPoint, vFileName, Length(vFileName), True);
              if J > 1 then
              begin
                vIndex := StringScan(cnstExclamationPoint, vFileName, J - 1, True);
                if vIndex > 1 then
                  SetLength(vFileName, vIndex - 1);
              end;
              AList.Add(vFileName);
            end;
          end;
        end;
{$ENDIF}

      finally
        AStackConverters.Remove(AConverter);
      end;
    end;
  end;

begin
  vList := TStringList.Create;
  vStackConverters := TsgList.Create;
  try
    vList.CaseSensitive := False;
    vList.Duplicates := dupIgnore;
    vList.Sorted := True;
    GetXRefListBlock(Converter, vList, vStackConverters, AMode);
  finally
    if Assigned(AList) then
      for I := 0 to vList.Count - 1 do
        AList.Add(vList[I]);
    Result := vList.Count > 0;
    vList.Free;
    vStackConverters.Free;
  end;
end;

function TsgCADImage.GetHeight: Integer;
begin
  Result := Round(FZoom*AbsHeight + 0.5);
  if Result = 0 then
    Result := 1;
end;

function TsgCADImage.GetMillimetres: Boolean;
begin
  if (FMillimetres < 0) and (FConverter <> nil) then
    FMillimetres := Integer(FConverter.HeadVarStruct.Measurement);
  Result := FMillimetres <> 0;
end;

function TsgCADImage.GetNullWidth: Integer;
begin
  Result := Round(FNullWidth);
end;

function TsgCADImage.GetPalette: HPalette;
begin
  Result := AcadPal;
end;


function TsgCADImage.GetWidth: Integer;
begin
  Result := Round(FZoom * AbsWidth + 0.5);
  if Result = 0 then
    Result := 1;
end;

procedure TsgCADImage.LoadFromClipboardFormat(Fmt: Word; Data: THandle;
  Pal: HPALETTE);
begin
  // do nothing
end;

function TsgCADImage.PolyRgn(PL: TsgCADBasePolyline): HRgn;
var
  I: Integer;
  P: TPoint;
begin
  FPoly.Count := 0;
  for I := 0 to PL.PointCount - 1 do
  begin
    P := GetPoint(PL.Points[I]);
    FPoly.Add(P.X);
    FPoly.Add(P.Y);
  end;
  Result := CreatePolygonRgn(FPoly.List^, PL.PointCount, WINDING);
end;

procedure TsgCADImage.Progress(Sender: TObject; Stage: TProgressStage;
  PercentDone: Byte; RedrawNow: Boolean; const R: TRect; const Msg: string);
var
  T: Integer;
  {$IFDEF SG_CAD_DLL}
  Mesg: TMsg;
  {$ENDIF}
begin
  T := GetCurrentTime and not $FF;
  if (not FIsProcessMessages) or ((Stage=psRunning) and (T=FLast)) then
    Exit;
  FLast := T;
  {$IFNDEF SG_CAD_DLL}
  Application.ProcessMessages;
  {$ELSE}
  if Stage <> psStarting then
    if PeekMessage(Mesg, 0, 0, 0, PM_REMOVE) then
    begin
      TranslateMessage(Mesg);
      DispatchMessage(Mesg);
    end;
  {$ENDIF}
  inherited Progress(Sender, Stage, PercentDone, RedrawNow, R, Msg);
end;

function TsgCADImage.GetLineWeightFactor: Double;
begin
  Result := GetLineWeightFactorBase;
end;

function TsgCADImage.GetLineWeightFactorBase: Double;
begin
  if IsPlotting then
    Result := cnstDefaultLineWeightFactor
  else
    Result := fLineWeightFactor;
end;

function TsgCADImage.GetLineTypeScale: Double;
//var
//  vCurrXref: TsgDXFXref;
begin
  Result := FConverter.GetLTScale;
//  vCurrXref := CurrXRef;
//  if (vCurrXref <> nil) and (vCurrXRef.CADImage <> nil) then
//    Result := Result * TsgCADImage(vCurrXRef.CADImage).Converter.GetLScale
end;

procedure TsgCADImage.SaveDrawParams;
begin
  FDrawSaved := FDraw;
end;

procedure TsgCADImage.SaveToClipboardFormat(var Fmt: Word; var Data: THandle;
  var Pal: HPALETTE);
begin
  // do nothing
end;

procedure TsgCADImage.SetExtentsParameters(const ARect: TFRect; const AIs3DExtents: Boolean);
const
  flRatio = 16;
var
  vWidth, vHeight: TsgFloat;
  vRect: TFRect;
begin
  if IsBadRect(ARect) then
  begin
    if Assigned(FOnGetBox) then
    begin
      vRect := ARect;
      if FOnGetBox(Self, vRect) then
        FPureExtents := vRect
      else
        FPureExtents := UnitRect;
    end
    else
      FPureExtents := UnitRect;
    FXMax := FPureExtents.Right;
    FYMax := FPureExtents.Top;
    FZMax := FPureExtents.Z2;
    FXMin := FPureExtents.Left;
    FYMin := FPureExtents.Bottom;
    FZMin := FPureExtents.Z1;
    ResetExtents;
    Changed(Self);
    Exit;
  end;
  if IsBadRect(FDrawingBox) then
    vRect := ARect
  else
    vRect := FDrawingBox;

  if Assigned(FOnGetBox) then
    FOnGetBox(Self, vRect);

  FCenter.X := 0.5 * (vRect.Right + vRect.Left);
  FCenter.Y := 0.5 * (vRect.Top + vRect.Bottom);
  FCenter.Z := 0.5 * (vRect.Z1 + vRect.Z2);
  Offset := FCenter;
//  if AIs3DExtents then//It is not actual for 2D layot because it has a rotate 3D matrix
    TransRectCorners(vRect, GetRealImageMatrix);
  FXMin := 0;
  FYMin := 0;
  FPureExtents := vRect;
  if not FIsWithoutBorder then
  begin
    case FBorderType of
      btRatio:
        begin
          FXMin := (vRect.Right - vRect.Left) * FBorderSize;
          FYMin := (vRect.Top - vRect.Bottom) * FBorderSize;
        end;
      btGlobal:
        begin
          FXMin := Abs(FBorderSize);
          FYMin := Abs(FBorderSize);
        end;
    end;
    if FXMin < 0 then
      FXMin := 1;
    if FYMin < 0  then
      FYMin := 1;
  end;
  if IsBadRect(vRect) then// for unsized model or layouts
  begin
    FPureExtents := UnitRect;
    FXMax := FPureExtents.Right;
    FYMax := FPureExtents.Top;
    FZMax := FPureExtents.Z2;
    FXMin := FPureExtents.Left;
    FYMin := FPureExtents.Bottom;
    FZMin := FPureExtents.Z1;
  end
  else
  begin
    FXMax := vRect.Right + FXMin;
    FYMax := vRect.Top + FYMin;
    FZMax := vRect.Z2;
    FXMin := vRect.Left - FXMin;
    FYMin := vRect.Bottom - FYMin;
    FZMin := vRect.Z1;
  end;
  FXDisproportionateShift := 0;
  FYDisproportionateShift := 0;
  if FResizeDisproportionateDrawing then
  begin
    vWidth := Abs(FXMax - FXMin);
    vHeight := Abs(FYMax - FYMin);
    if (vWidth <> 0)and(vHeight / vWidth > flRatio) or (vWidth = 0) then
    begin
      FXDisproportionateShift := (vHeight - vWidth) / 2;
      FXMin := FXMin - FXDisproportionateShift;
      FXMax := FXMax + FXDisproportionateShift;
    end
    else
      if (vHeight <> 0)and(vWidth / vHeight > flRatio) or (vHeight = 0) then
    begin
      FYDisproportionateShift := (vWidth - vHeight) / 2;
      FYMax := FYMax + FYDisproportionateShift;
      FYMin := FYMin - FYDisproportionateShift;
    end;
  end;
  ResetExtents;
  Changed(Self);
end;

function TsgCADImage.GetOnInsertMode: TsgDXFInsert;
begin
  Result := FOnInsert;
end;

procedure TsgCADImage.SetOnAfterDraw(const Value: TNotifyEvent);
begin
  FOnAfterDraw := Value;
end;

procedure TsgCADImage.SetOnInsertMode(const AIns: TsgDXFInsert);
begin
  FOnInsert := AIns;
  FOnInsertMode := False;
end;

procedure TsgCADImage.SetHeight(Value: Integer);
begin
end;

procedure TsgCADImage.SetMillimetres(Value: Boolean);
begin
  FMillimetres := Ord(Value);
end;

procedure TsgCADImage.SetNullWidth(const Value: Integer);
begin
  FNullWidth := Value;
end;

procedure TsgCADImage.SetSelectionMatrixProc(const AMode: TsgSelectionMode);
begin
  FSelectionMatrixMode := AMode;
end;

procedure TsgCADImage.SetWidth(Value: Integer);
begin
end;

{$IFDEF SGFPC}
procedure TsgCADImage.SetTransparent(Value: Boolean);
begin

end;
{$ENDIF}

function TsgCADImage.GetSHXFontsProc: TsgSHXFontList;
begin
  Result := Converter.SHXFonts;
end;

function TsgCADImage.GetScale: TFPoint;
begin
  Result := ExtractMatrixAbsoluteScale(FDraw.Matrix);
end;

function TsgCADImage.GetSelectionMatrixProc: TsgSelectionMode;
begin
  Result := FSelectionMatrixMode;
end;

function TsgCADImage.InitializeLineType(AEntity: TsgDXFPenEntity): Boolean;
var
  vDx, vDY, vPatternSize: Double;
begin
  GetPixelSize(1.5, vdX, vdY, not IsAutocadLType);
  FEntityLines.Scale := FEntityLines.Scale * GetLineTypeScale * AEntity.LineTypeScale;
  vPatternSize := FEntityLines.MaxSizeOfPatterns *  FEntityLines.Scale;
  Result := (vPatternSize > vDx) or  (vPatternSize > vDy);
  FDottedSingPts.Count := 0;
end;

procedure TsgCADImage.ApplyLineWeightFactor(var ALineWeight: Double);
begin
  ApplyLineWeightFactorBase(ALineWeight);
end;

procedure TsgCADImage.ApplyLineWeightFactorBase(var ALineWeight: Double);
begin
  //if CurrentLayout = Layouts[0] then//is model space for future version
  begin
    ALineWeight := GetLineWeightFactor * ALineWeight;
    if ALineWeight > cnstCADLineWeightMax then
      ALineWeight := cnstCADLineWeightMax;
  end;
end;

procedure TsgCADImage.ApplyPen(Sender: TObject);
var
  I, vPos: Integer;
  Cl: TColor;
  DS: Char;
  W, vLineWeight: Double;

  function SGStringToColor(const S: string): TColor;
  begin
    if (not IdentToColor(S, Longint(Result))) then
      Result := TColor(StrToIntDef(S, 0));
  end;

begin
  W := 0;
  if IsPlotting then
    W := FNullWidth;
  if IsShowLineWeight then
  begin
    vLineWeight := GetEntLineWeight(TsgDXFEntity(Sender), FDraw.Insert);
    W := FLineWeightScale * vLineWeight;
    if (FColorToLineWeight.Count <> 0) and (not FIsIterator) then
    begin
      for I := 0 to FColorToLineWeight.Count - 1 do
      begin
        vPos := AnsiPos('=', FColorToLineWeight[I]);
        if vPos = 0 then
          Continue;
        Cl := SGStringToColor(Trim(Copy(FColorToLineWeight[I], 0, vPos - 1)));
        DS := SetDecimalSeparator('.');
        try
          if (FCanvas.Pen.Color = Cl)
            or ((FCanvas.Pen.Color = clNone) and (Cl = clBlack))
            or ((Cl = clNone) and (FCanvas.Pen.Color = GetDrawPenColor))then
            W := Round(ConvToFloatDef(Trim(Copy(FColorToLineWeight[I],
          vPos + 1, Length(FColorToLineWeight[I]))), 0.0) / FmmToPixelX);
        finally
          SetDecimalSeparator(DS);
        end;
      end;
      W := FLineWeightScale * W;
    end;
  end;
  SetPenWidth(W);
end;

procedure TsgCADImage.ApplyScale(const ARect: TRect);
begin
   ApplyScale(ARect.Left, ARect.Top, ARect.Right, ARect.Bottom);
end;

procedure TsgCADImage.ApplyScale(const ARectLeft, ARectTop, ARectRight, ARectBottom: Double);
var
  vDrawMatrix: TFMatrix;
begin
  vDrawMatrix := sgFunction.ApplyScale(GetRealImageMatrix, FOffset, GetDrawingExtents,
    ARectLeft, ARectTop, ARectRight, ARectBottom, Stretch,
    not IsIterator or not Converter.IsCrossoverMatrix);
  SetDrawMatrix(vDrawMatrix);
end;

procedure TsgCADImage.ApplyText;
begin
  case FDrawMode of
    dmBlack:
      begin
        DoSetColor(GetDrawPenColor, ctFont);
        DoSetColor(GetDrawPenColor, ctPen);
      end;
    dmGray:
      begin
        DoSetColor(clGray, ctFont);
        DoSetColor(clGray, ctPen);
      end;
  end;
end;

{$IFDEF SG_HIDDEN}
procedure TsgCADImage.AddLastPixelToPoly(APoints, ACounts: TsgIntegerList);
begin
  if APoints.Count = 0 then
    Exit;

  if NeedToAddOnePixel then
  begin
    APoints.Add(APoints[APoints.Count - 2]); //x
    APoints.Add(APoints[APoints.Count - 2] + 1); // y
    ACounts.List[ACounts.Count - 1] := ACounts[ACounts.Count - 1] + 1;
  end;
end;
{$ENDIF}

procedure TsgCADImage.BeginRead(Sender: TObject);
begin
  DoProgress(psStarting);
end;

// evg reg - see this funciton to improve speed
procedure TsgCADImage.BoxPoint(const P: TFPoint);
var
  IP: TPoint;
begin
  IP := GetPoint(P);
  ExpandRect(FIRect, IP);
  if FIndex < 8 then
    FIPoints[FIndex] := IP;
  Inc(FIndex);
end;

procedure TsgCADImage.DoPolylineArrow(const AEnt: TsgDXFEntity;
  const ALines: TsgLines; const AMatrix: PFMatrix);
var
  PL: TsgDXFPolylineAccess absolute AEnt;
begin
  if (AEnt is TsgDXFPolyline) and (PL.ArrowsLines <> ALines) and PL.HasWidth then
    PL.DoArrows(ALines, AMatrix);
end;

procedure TsgCADImage.DoProgress(Stage: TProgressStage);        // OnProgress event
const
  R: TRect = (Left: 0; Top: 0; Right: 0; Bottom: 0);
begin
  if not Assigned(OnProgress) then
    Exit;
  Progress(Self, Stage, Byte(MulDiv(FConverter.Pos, 100, FConverter.Count)),
     False, R, FMsg);
end;

procedure TsgCADImage.DoRead(Sender: TObject);
begin
  DoProgress(psRunning);
end;

procedure TsgCADImage.DrawArc(Sender: TObject);
var
  R: TRect;
  P1, P2: TPoint;
  A: TsgArc;
begin
  if FUseWinEllipse and FEntityLines.IsSolid and (Converter.VPort.X = 0)
      and (Converter.VPort.Y = 0) and (Converter.VPort.Z > 0) and (not IsDrawingRotated) then
  begin
    A := EntArc(TsgDXFArc(Sender), FDraw);
    if not A.Valid then
    begin
      DrawPoly(Sender);
      Exit;
    end;
    R.Left := Round(A.Rect.Left);
    R.Top := Round(A.Rect.Top);
    R.Right := Round(A.Rect.Right);
    R.Bottom := Round(A.Rect.Bottom);
    P1.X := Round(A.Point1.X);
    P1.Y := Round(A.Point1.Y);
    P2.X := Round(A.Point2.X);
    P2.Y := Round(A.Point2.Y);
    if (P1.X = P2.X) and (P1.Y = P2.Y) then
      ExpPixelInteger(Sender, P1, FColor)
    else
      ExpArcInteger(Sender, R.Left, R.Top, R.Right, R.Bottom, P1.X, P1.Y, P2.X, P2.Y);
  end
  else
    DrawPoly(Sender);
end;

procedure TsgCADImage.DrawCADFill(Sender: TObject);
var
  vCadFill: TsgCADFill absolute Sender;
  vStyle: TsgCADStyleFill;
  vGradient: TsgCADStyleGradient absolute vStyle;
  vPattern: TsgCADStylePattern absolute vStyle;
  vScreenRect: TRect;
{$IFDEF SG_USEGDIPLUS}
  graphics: TsgGDIPlusGraphics;
  GradP: TsgGDIPlusPathGradientBrush;
  GradL: TsgGDIPlusLinearGradientBrush;
  GBrushSolid: TsgGDIPlusSolidBrush;
  GPath: TsgGDIPlusGraphicsPath;
  GP1, GP2: TsgGPoint;
  GPen: TsgGDIPlusPen;
  GPRect, GEllipse: TsgGRect;
  vPC: TFPoint;
  I, J: Integer;
  vColors: TsgIntegerList;
  vPositions: TsgSingleList;
  vPenWidth: Double;
  vBoxNew: TRect;
  vBmp: TsgGDIPlusBitmap;
  vAttr: TsgGDIPlusImageAttributes;
  vPts: array[0..2] of TsgGPoint;
{$ENDIF}

  function GetScreenRect(ABox: TFRect): TRect;
  begin
    TransRectCorners(ABox, FDraw.Matrix);
    Result.TopLeft := Point(Ceil(ABox.Left), Ceil(ABox.Bottom));
    Result.BottomRight := Point(Ceil(ABox.Right), Ceil(ABox.Top));
  end;

{$IFDEF SG_USEGDIPLUS}
  procedure SetGP12Rel(const AP1, AP2: TFPoint);
  var
    vKX, vKY: Double;
  begin
    vKX := GPRect.Width / 100;
    vKY := GPRect.Height / 100;
    GP1.X := Round(vKX * AP1.X + vScreenRect.Left);
    GP1.Y := Round(vKY * AP1.Y + vScreenRect.Top);
    GP2.X := Round(vKX * AP2.X + vScreenRect.Left);
    GP2.Y := Round(vKY * AP2.Y + vScreenRect.Top);
  end;

  procedure DrawLinearGradient;
  begin
    if vGradient.Units = sfUserSpaceOnUse then
    begin
      GP1 := TsgGPoint(GetPoint(FPointXMat(vGradient.Point1, vGradient.Transform)));
      GP2 := TsgGPoint(GetPoint(FPointXMat(vGradient.Point2, vGradient.Transform)));
    end
    else
      SetGP12Rel(vGradient.Point1, vGradient.Point2);
    if IsEqualPoints(TPoint(GP1), TPoint(GP2)) then//REC-SVG11-20030114/pservers.html#LinearGradients
    begin
      GBrushSolid := TsgGDIPlusSolidBrush.Create(vColors.First);
      try
        graphics.FillRectangle(GBrushSolid, GPRect);
      finally
        GBrushSolid.Free;
      end;
    end
    else
    begin
      vBoxNew := vScreenRect;
      ExpandRect(vBoxNew, TPoint(GP1));
      ExpandRect(vBoxNew, TPoint(GP2));
      vPenWidth := Sqr(vBoxNew.Bottom - vBoxNew.Top) + Sqr(vBoxNew.Right - vBoxNew.Left);
      if vPenWidth > fDoubleResolution then
        vPenWidth := Sqrt(vPenWidth) * 2
      else
        vPenWidth := 1;
      GradL := TsgGDIPlusLinearGradientBrush.Create(GP1, GP2,
        TsgColor(vColors.First), TsgColor(vColors.Last));
      try
        GradL.SetInterpolationColors(@vColors.List[0], @vPositions.List[0], vColors.Count);
        GPen := TsgGDIPlusPen.Create(GradL, vPenWidth);
        try
          graphics.DrawLine(GPen, GP1, GP2);
        finally
          GPen.Free;
        end;
        GPen := TsgGDIPlusPen.Create(TsgColor(vColors.First), vPenWidth);
        try
          graphics.DrawLine(GPen, TsgGPoint(GetPointOnLineI(TPoint(GP1), TPoint(GP2), 2)), TsgGPoint(GetPointOnLineI(TPoint(GP1), TPoint(GP2), -vPenWidth)));
        finally
          GPen.Free;
        end;
        GPen := TsgGDIPlusPen.Create(TsgColor(vColors.Last), vPenWidth);
        try
          graphics.DrawLine(GPen, TsgGPoint(GetPointOnLineI(TPoint(GP2), TPoint(GP1), 2)), TsgGPoint(GetPointOnLineI(TPoint(GP1), TPoint(GP2), vPenWidth)));
        finally
          GPen.Free;
        end;
      finally
        GradL.Free;
      end;
    end;
  end;

  procedure DrawLinearCircular;
  begin
    if vGradient.Units = sfUserSpaceOnUse then
    begin
      vPC := vGradient.PointC;
      GP1 := TsgGPoint(GetPoint(FPointXMat(vPC, vGradient.Transform)));
      GP2 := TsgGPoint(GetPoint(FPointXMat(vGradient.PointF, vGradient.Transform)));
      SetNewBox(GetPoint(FPointXMat(MakeFPoint(vPC.X - vGradient.R, vPC.Y, 0), vGradient.Transform)),
                GetPoint(FPointXMat(MakeFPoint(vPC.X, vPC.Y - vGradient.R, 0), vGradient.Transform)),
                GetPoint(FPointXMat(MakeFPoint(vPC.X + vGradient.R, vPC.Y, 0), vGradient.Transform)),
                GetPoint(FPointXMat(MakeFPoint(vPC.X, vPC.Y + vGradient.R, 0), vGradient.Transform)), vBoxNew);
    end
    else
    begin
      SetGP12Rel(vGradient.PointC, vGradient.PointF);
      I := Ceil(vGradient.R * GPRect.Width / 100);
      if GPRect.Width <> GPRect.Height then
        J := Ceil(vGradient.R * GPRect.Height / 100)
      else
        J := I;
      SetNewBox(Point(GP1.X - I, GP1.Y), Point(GP1.X, GP1.Y - J),
                Point(GP1.X + I, GP1.Y), Point(GP1.X, GP1.Y + J), vBoxNew)
    end;
    GEllipse := MakeRect(vBoxNew.Left, vBoxNew.Top, vBoxNew.Right - vBoxNew.Left, vBoxNew.Bottom - vBoxNew.Top);
    GBrushSolid := TsgGDIPlusSolidBrush.Create(vColors.First);
    try
      graphics.FillRectangle(GBrushSolid, GPRect);
    finally
      GBrushSolid.Free;
    end;
    GPath := TsgGDIPlusGraphicsPath.Create;
    try
      GPath.StartFigure;
      GPath.AddEllipse(GEllipse);
      GPath.SetFillMode(FillModeWinding);
      GradP := TsgGDIPlusPathGradientBrush.Create(GPath);
      try
        GradP.SetCenterPoint(GP2);
        GradP.SetInterpolationColors(@vColors.List[0], @vPositions.List[0], vColors.Count);
        graphics.FillPath(GradP, GPath);
      finally
        GradP.Free;
      end;
    finally
      GPath.Free;
    end;
  end;
{$ENDIF}

  procedure DrawGDIGradient;
  begin
  end;

  function GetStart(const VImg, VPat, VSize: Double): Double;
  var
    vDelta, vShift: Double;
  begin
    vDelta := VImg - VPat;
    if vDelta = 0 then
      Result := 0
    else
    begin
       vShift := Floor(vDelta / VSize) * VSize;
       Result :=  VPat + vShift;
    end;
  end;

  function GetPatMatrix(const ADest: TFRect; ASource: TFRect): TFMatrix;
  var
    vSWidth, vSHeight, vDWidth, vDHeight: Double;
  begin
    Result := cnstIdentityMat;
    if ASource.Left > ASource.Right then
      SwapSGFloats(ASource.Left, ASource.Right);
    if ASource.Top < ASource.Bottom then
      SwapSGFloats(ASource.Top, ASource.Bottom);

    vSWidth := ASource.Right - ASource.Left;
    vSHeight := ASource.Bottom - ASource.Top;
    vDWidth := ADest.Right - ADest.Left;
    vDHeight := ADest.Bottom - ADest.Top;

    if vSWidth = 0 then
      vSWidth := 1;
    if vSHeight = 0 then
      vSHeight := 1;

    if vDWidth = 0 then
      vDWidth := vSWidth;
    if vDHeight = 0 then
      vDHeight := vSHeight;

    Result.M[0, 0] := vDWidth / vSWidth;
    Result.M[1, 1] := vDHeight / vSHeight;
  end;

  procedure DrawPattern;
  var
    vPatSize, vPatStart: TFPoint;
    X, Y: Integer;
    K: TPoint;
    vPatMatrix, vMatrix: TFMatrix;
    vSaved: TsgCADIterate;
    vMat: TFMatrix;
    vBoxImg: TFRect;
    vIsDraw: Boolean;
{$IFDEF SG_USEGDIPLUS}
    vPatScreenSize: TPoint;
    vPatBmp: TBitmap;
    vPatPts: array[0..3] of TFPoint;
    vPts: array[0..3] of TPoint;
{$ENDIF}
  begin
    vIsDraw := False;
    vBoxImg := vCadFill.Box;
    vPatStart := vPattern.Point1;
    vPatSize := vPattern.Size;
    if vPattern.Units = sfObjectBoundingBox then
    begin
      vMat := StdMat(MakeFPoint((vBoxImg.Right - vBoxImg.Left) / 100, (vBoxImg.Top - vBoxImg.Bottom) / 100, 1), cnstFPointZero);
      vPatStart := FPointXMat(vPatStart, vMat);
      vPatSize := FPointXMat(vPatSize, vMat);
    end;
    vPatStart.X := GetStart(vBoxImg.Left, vPatStart.X, vPatSize.X);
    vPatStart.Y := GetStart(vBoxImg.Top, vPatStart.Y, vPatSize.Y);
    vSaved := FDraw;
    try
      ExpandFRect(vBoxImg, vPatStart);
      K.X := Ceil((vBoxImg.Right - vBoxImg.Left) / vPatSize.X);
      K.Y := Ceil((vBoxImg.Top - vBoxImg.Bottom) / vPatSize.Y);
{$IFDEF SG_USEGDIPLUS}
      if FLibraryGDIPlusExists and (not FIsIterator) and vCadFill.UseBuffer then
      begin
        FillChar(vPatPts, SizeOf(vPatPts), 0);
        vPatPts[1].X := vPatSize.X;
        vPatPts[2].Y := vPatSize.Y;
        vPatPts[3] := vPatSize;
        vPts[0] := GetPoint(vPatPts[0]);
        vPts[1] := GetPoint(vPatPts[1]);
        vPts[2] := GetPoint(vPatPts[2]);
        vPatScreenSize.X := Ceil(DistancePoint(vPts[0], vPts[1]));
        vPatScreenSize.Y := Ceil(DistancePoint(vPts[0], vPts[2]));
        vPatBmp := vCadFill.CreateBMPPattern(vPatScreenSize.X, vPatScreenSize.Y, ClassType);
        try
          vPatScreenSize := Point(vPatBmp.Width, vPatBmp.Height);
          graphics := TsgGDIPlusGraphics.Create(FCanvas.Handle);
          try
           graphics.InitParams;
            vBmp := TsgGDIPlusBitmap.Create(vPatBmp.Handle, vPatBmp.Palette);
            try
              vAttr := TsgGDIPlusImageAttributes.Create;
              try
                vAttr.SetColorKey(aclWhite, aclWhite, ColorAdjustTypeBitmap);
                vMatrix := cnstIdentityMat;
                vMatrix.M[3, 1] := vPatStart.Y;
                for Y := 0 to K.Y do
                begin
                  vMatrix.M[3, 0] := vPatStart.X;
                  for X := 0 to K.X do
                  begin
                    FDraw.Matrix := FMatXMat(vMatrix, vSaved.Matrix);
                    vPts[0] := GetPoint(vPatPts[0]);
                    vPts[1] := GetPoint(vPatPts[1]);
                    vPts[2] := GetPoint(vPatPts[2]);
                    vPts[3] := GetPoint(vPatPts[3]);
                    graphics.DrawImage(vBmp, PsgGPoint(@vPts[0]), 3, 0, 0, vPatScreenSize.X, vPatScreenSize.Y, vAttr);
                    vMatrix.M[3, 0] := vMatrix.M[3, 0] + vPatSize.X;
                  end;
                  vMatrix.M[3, 1] := vMatrix.M[3, 1] - vPatSize.Y;
                end;
                vIsDraw := True;
              finally
                vAttr.Free;
              end;
            finally
              vBMP.Free;
            end;
          finally
            graphics.Free;
          end;
        finally
          vPatBmp.Free;
        end;
      end;
{$ENDIF}
      if not vIsDraw then
      begin
        FillChar(vBoxImg, Sizeof(vBoxImg), 0);
        ExpandFRect(vBoxImg, vPatSize);
        vPatMatrix := GetPatMatrix(vBoxImg, vPattern.ContainerBox);
        vMatrix := cnstIdentityMat;
        vMatrix.M[3, 1] := vPatStart.Y;
        for Y := 0 to K.Y do
        begin
          vMatrix.M[3, 0] := vPatStart.X;
          for X := 0 to K.X do
          begin
            FDraw.Matrix := FMatXMat(vMatrix, vSaved.Matrix);
            FDraw.Matrix := FMatXMat(vPatMatrix, FDraw.Matrix);
            vPattern.Iterate(Converter, DrawEntity, DoFinish);
            vMatrix.M[3, 0] := vMatrix.M[3, 0] + vPatSize.X;
          end;
          vMatrix.M[3, 1] := vMatrix.M[3, 1] - vPatSize.Y;
        end;
      end;
    finally
      FDraw := vSaved;
    end;
  end;

  procedure DrawBMPPattern(const AImg: TBitmap);
  begin
{$IFDEF SG_USEGDIPLUS}
    if Converter.IsCrossoverMatrix then
    begin
      vPts[0] := TsgGPoint(GetPoint(vCadFill.Box.TopLeft));
      vPts[1] := TsgGPoint(GetPoint(MakeFPoint(vCadFill.Box.Right, vCadFill.Box.Top, 0)));
      vPts[2] := TsgGPoint(GetPoint(MakeFPoint(vCadFill.Box.Left, vCadFill.Box.Bottom, 0)));
    end
    else
    begin
      vPts[0] := TsgGPoint(GetPoint(MakeFPoint(vCadFill.Box.Left, vCadFill.Box.Bottom, 0)));
      vPts[1] := TsgGPoint(GetPoint(MakeFPoint(vCadFill.Box.Right, vCadFill.Box.Bottom, 0)));
      vPts[2] := TsgGPoint(GetPoint(vCadFill.Box.TopLeft));
    end;
    graphics := TsgGDIPlusGraphics.Create(FCanvas.Handle);
    try
      graphics.InitParams;
      vBmp := TsgGDIPlusBitmap.Create(AImg.Handle, AImg.Palette);
      try
        vAttr := TsgGDIPlusImageAttributes.Create;
        try
          vAttr.SetColorKey(aclWhite, aclWhite, ColorAdjustTypeBitmap);
          graphics.DrawImage(vBmp, PsgGPoint(@vPts[0]), 3, 0, 0,
            AImg.Width, AImg.Height, vAttr);
        finally
          vAttr.Free;
        end;
      finally
        vBMP.Free;
      end;
    finally
      graphics.Free;
    end;
{$ENDIF}
  end;

begin
//this DrawHatch(Sender)
  vScreenRect := GetScreenRect(vCadFill.Box);
  vStyle := vCadFill.StyleFill;
  if (vStyle is TsgCADStyleGradient) and (not FIsIterator) then
  begin
{$IFDEF SG_USEGDIPLUS}
    if FLibraryGDIPlusExists then
    begin
      GPRect := MakeRect(vScreenRect.Left, vScreenRect.Top, vScreenRect.Right - vScreenRect.Left, vScreenRect.Bottom - vScreenRect.Top);
      vBoxNew := cnstBad2DRect;
      vColors := TsgIntegerList.Create;
      vPositions := TsgSingleList.Create;
      try
        vGradient.GetPositionColors(vPositions, vColors);
        for I := 0 to vColors.Count - 1 do
          vColors.List[I] := GetGDIPlusColor(vColors.List[I]);
        if vColors.Count > 0 then
        begin
          graphics := TsgGDIPlusGraphics.Create(FCanvas.Handle);
          try
            graphics.InitParams;
            if vGradient.Linear then
              DrawLinearGradient
            else
              DrawLinearCircular;
          finally
            graphics.Free;
          end;
        end;
        if vColors.Count > 0 then
        begin
          graphics := TsgGDIPlusGraphics.Create(FCanvas.Handle);
          try
            graphics.InitParams;
            if vGradient.Linear then
              DrawLinearGradient
            else
              DrawLinearCircular;
          finally
            graphics.Free;
          end;
        end;
      finally
        vPositions.Free;
        vColors.Free;
      end;
    end
    else
{$ENDIF}
      DrawGDIGradient;
  end
  else
  begin
{$IFDEF SG_USEGDIPLUS}
    if FLibraryGDIPlusExists and (not FIsIterator) and vCadFill.UseBuffer and
      vCadFill.CreateBMPFill(FDraw.Matrix, Self.ClassType) then
      DrawBMPPattern(vCadFill.BMPImage)
    else
{$ENDIF}
      DrawPattern;
  end;
end;

procedure TsgCADImage.DrawCircle(Sender: TObject);
var
  C: TsgDXFCircle absolute Sender;
  R: TRect;

  function CBounds: TRect;
  var
    OffsetPt: TPoint;
  begin
    Result.TopLeft := GetPoint(C.Point);
    Result.BottomRight := Result.TopLeft;
    DoScale2D(FDraw);
    OffsetPt.X := Abs(Round(C.Radius * FDraw.XScale {* Scale.X}));
    OffsetPt.Y := Abs(Round(C.Radius * FDraw.YScale {* Scale.Y}));
    InflateRect(Result, OffsetPt.X, OffsetPt.Y);
  end;
begin
  if FUseWinEllipse and (not Converter.Is3D)
    and FEntityLines.IsSolid and (Converter.VPort.X = 0)
      and (Converter.VPort.Y = 0) and (Converter.VPort.Z > 0) and (not IsDrawingRotated) then
  begin
    R := CBounds;
    if IsDrawOnBitMap then
    begin
      AddSelectionMatrix(Sender);
      SelectionMatrix.Brush.Style := bsClear;
      SelectionMatrix.Changed;
      Ellipse(SelectionMatrix.Handle ,R.Left, R.Top, R.Right, R.Bottom);
    end;
    if IsDrawOnCanvas then
    begin
      FCanvas.Brush.Style := bsClear;
      FCanvas.Ellipse(R.Left, R.Top, R.Right, R.Bottom);
    end;
  end
  else
    DrawPoly(Sender);
end;

procedure TsgCADImage.DrawFace(Sender: TObject);
  procedure Edge(Lines: TsgLines; const F1, F2: TFPoint);
  var
    P: TPoint;
    I: Integer;
    AList: TFPointList;
  begin
    if Lines.IsSolid then
    begin
      FIntPoints.Count := 0;
      for I := 0 to 1 do
      begin
      if I = 0 then
        P := GetPoint(F1)
      else
        P := GetPoint(F2);
        FIntPoints.Add(P.X);
        FIntPoints.Add(P.Y);
      end;

      ExpPolylineInteger(Sender, FIntPoints.List[0], FIntPoints.Count shr 1);
    end
    else
    begin
      AList := TFPointList.Create;
      try
        Lines.Line(F1, F2, AList);
        DrawPointsListByPolyPolyline(Sender, AList);
      finally
        AList.Free;
      end;
    end;
  end;
var
  F: TsgDXF3dFace absolute Sender;
begin
  if F.Flags and 1 = 0 then
    Edge(FEntityLines, F.Point, F.Point1);
  if F.Flags and 2 = 0 then
    Edge(FEntityLines, F.Point1, F.Point2);
  if F.Flags and 4 = 0 then
    Edge(FEntityLines, F.Point2, F.Point3);
  if F.Flags and 8 = 0 then
    Edge(FEntityLines,F.Point3, F.Point);
end;

procedure TsgCADImage.DrawHatch(Sender: TObject);
var
  P1: TPoint;
  vPolygon: TsgCADPolyPolygon;
  vRgn,vMainRGN, vClipRgn, vRGNTmp: HRGN;
  I, SaveIndex: Integer;
  vRect: TRect;
  Vert: array[0..1] of TTriVertex;
  vIsDrawOnCanvas, vIsDrawOnBitMap: Boolean;

  procedure SetVert(var V: TTriVertex; const P: TPoint; C: TColor);
  begin
    V.X := P.X; V.Y := P.Y;
    V.Red := C and $FF shl 8;
    V.Green := C and $FF00;
    V.Blue := C and $FF0000 shr 8;
    V.Alpha := 0;
  end;

  procedure SetClipRGN;
  begin
    GetRgnBox(vMainRGN, vRect);
    sgOffsetRgn(FCanvas,vMainRGN);
    P1 := Point(0,1);
    vRGNTmp := CreateRectRgn(0, 0, 0, 0);
    if GetClipRgn(FCanvas.Handle, vRGNTmp) > 0 then
      CombineRgn(vMainRGN, vMainRGN, vRGNTmp, RGN_AND);
    DeleteObject(vRGNTmp);
    SelectClipRgn(FCanvas.Handle, vMainRGN);
  end;


{$IFDEF SG_USEGDIPLUS}
  (*
  procedure DrawGDIPlusGradientEx(const DC: HDC; const ABox: TRect; const AGrad: TsgDXFGradient);
  var
    graphics: TsgGDIPlusGraphics;
    GradP: TsgGDIPlusPathGradientBrush;
    GradL: TsgGDIPlusLinearGradientBrush;
    GBrushSolid: TsgGDIPlusSolidBrush;
    GPath: TsgGDIPlusGraphicsPath;
    GP1, GP2: TsgGPoint;
    GPen: TsgGDIPlusPen;
    GPRect, GEllipse: TsgGRect;
    vPC: TFPoint;
    I, J: Integer;
    vColors, vPositions: TList;
    vPenWidth: Double;
    vBoxNew: TRect;

    procedure SetGP12Rel(const AP1, AP2: TFPoint);
    var
      vKX, vKY: Double;
    begin
      vKX := GPRect.Width / 100;
      vKY := GPRect.Height / 100;
      GP1.X := Round(vKX * AP1.X + ABox.Left);
      GP1.Y := Round(vKY * AP1.Y + ABox.Top);
      GP2.X := Round(vKX * AP2.X + ABox.Left);
      GP2.Y := Round(vKY * AP2.Y + ABox.Top);
    end;

  begin
    GPRect := MakeRect(ABox.Left, ABox.Top, ABox.Right - ABox.Left, ABox.Bottom - ABox.Top);
    vBoxNew := cnstBad2DRect;
    vColors := TList.Create;
    vPositions := TList.Create;
    try
      vColors.Count := AGrad.Colors.Count;
      vPositions.Count := vColors.Count;
      for I := 0 to vColors.Count - 1 do
      begin
        if AGrad.IsSpheric then
          J := vColors.Count - 1 - I
        else
          J := I;
        vColors.List^[J] := Pointer(GetGDIPlusColor(TColor(AGrad.Colors.List^[I])));
        Single(vPositions.List^[I]) := Single(AGrad.Positions.List^[I]) * 0.01;
      end;
      graphics := TsgGDIPlusGraphics.Create(DC);
      try
        if AGrad.IsSpheric then
        begin
          if AGrad.AbsParams then
          begin
            vPC := AGrad.PointC;
            GP1 := TsgGPoint(GetPoint(FPointXMat(vPC, AGrad.Transform)));
            GP2 := TsgGPoint(GetPoint(FPointXMat(AGrad.PointF, AGrad.Transform)));
            SetNewBox(GetPoint(FPointXMat(MakeFPoint(vPC.X - AGrad.Radius, vPC.Y, 0), AGrad.Transform)),
                      GetPoint(FPointXMat(MakeFPoint(vPC.X, vPC.Y - AGrad.Radius, 0), AGrad.Transform)),
                      GetPoint(FPointXMat(MakeFPoint(vPC.X + AGrad.Radius, vPC.Y, 0), AGrad.Transform)),
                      GetPoint(FPointXMat(MakeFPoint(vPC.X, vPC.Y + AGrad.Radius, 0), AGrad.Transform)), vBoxNew);
          end
          else
          begin
            SetGP12Rel(AGrad.PointC, AGrad.PointF);
            I := Ceil(AGrad.Radius * GPRect.Width / 100);
            if GPRect.Width <> GPRect.Height then
              J := Ceil(AGrad.Radius * GPRect.Height / 100)
            else
              J := I;
            SetNewBox(Point(GP1.X - I, GP1.Y), Point(GP1.X, GP1.Y - J),
                      Point(GP1.X + I, GP1.Y), Point(GP1.X, GP1.Y + J), vBoxNew)
          end;
          GEllipse := MakeRect(vBoxNew.Left, vBoxNew.Top, vBoxNew.Right - vBoxNew.Left, vBoxNew.Bottom - vBoxNew.Top);
          GBrushSolid := TsgGDIPlusSolidBrush.Create(Cardinal(vColors.First));
          try
            graphics.FillRectangle(GBrushSolid, GPRect);
          finally
            GBrushSolid.Free;
          end;
          GPath := TsgGDIPlusGraphicsPath.Create;
          try
            GPath.StartFigure;
            GPath.AddEllipse(GEllipse);
            GPath.SetFillMode(FillModeWinding);
            GradP := TsgGDIPlusPathGradientBrush.Create(GPath);
            try
              GradP.SetCenterPoint(GP2);
              GradP.SetInterpolationColors(@vColors.List^[0], @vPositions.List^[0], vColors.Count);
              graphics.FillPath(GradP, GPath);
            finally
              GradP.Free;
            end;
          finally
            GPath.Free;
          end;
        end
        else
        begin
          if AGrad.AbsParams then
          begin
            GP1 := TsgGPoint(GetPoint(FPointXMat(AGrad.Point1, AGrad.Transform)));
            GP2 := TsgGPoint(GetPoint(FPointXMat(AGrad.Point2, AGrad.Transform)));
          end
          else
            SetGP12Rel(AGrad.Point1, AGrad.Point2);
          if IsEqualPoints(TPoint(GP1), TPoint(GP2)) then//REC-SVG11-20030114/pservers.html#LinearGradients
          begin
            GBrushSolid := TsgGDIPlusSolidBrush.Create(Cardinal(vColors.First));
            try
              graphics.FillRectangle(GBrushSolid, GPRect);
            finally
              GBrushSolid.Free;
            end;
          end
          else
          begin
            vBoxNew := ABox;
            ExpandRect(vBoxNew, TPoint(GP1));
            ExpandRect(vBoxNew, TPoint(GP2));
            vPenWidth := Sqr(vBoxNew.Bottom - vBoxNew.Top) + Sqr(vBoxNew.Right - vBoxNew.Left);
            if vPenWidth > fDoubleResolution then
              vPenWidth := Sqrt(vPenWidth) * 2
            else
              vPenWidth := 1;
            GradL := TsgGDIPlusLinearGradientBrush.Create(GP1, GP2, TsgColor(vColors.First), TsgColor(vColors.Last));
            try
              GradL.SetInterpolationColors(@vColors.List^[0], @vPositions.List^[0], vColors.Count);
  //            graphics.FillRectangle(GradL, GPRect);
              GPen := TsgGDIPlusPen.Create(GradL, vPenWidth);
              try
                graphics.DrawLine(GPen, GP1, GP2);
              finally
                GPen.Free;
              end;
              GPen := TsgGDIPlusPen.Create(TsgColor(vColors.First), vPenWidth);
              try
                graphics.DrawLine(GPen, TsgGPoint(GetPointOnLineI(TPoint(GP1), TPoint(GP2), 2)), TsgGPoint(GetPointOnLineI(TPoint(GP1), TPoint(GP2), -vPenWidth)));
              finally
                GPen.Free;
              end;
              GPen := TsgGDIPlusPen.Create(TsgColor(vColors.Last), vPenWidth);
              try
                graphics.DrawLine(GPen, TsgGPoint(GetPointOnLineI(TPoint(GP2), TPoint(GP1), 2)), TsgGPoint(GetPointOnLineI(TPoint(GP1), TPoint(GP2), vPenWidth)));
              finally
                GPen.Free;
              end;
            finally
              GradL.Free;
            end;
          end;
        end;
      finally
        graphics.Free;
      end;
    finally
      vPositions.Free;
      vColors.Free;
    end;
  end;
  *)
  procedure DrawGDIPlusHatch(DC: HDC; AColor: TColor);
  var
    graphics: TsgGDIPlusGraphics;
    Solid: TsgGDIPlusSolidBrush;
    GPRect: TsgGRect;
    vColor: TColor;
  begin
    SetClipRGN;
    GPRect := MakeRect(vRect.TopLeft.X, vRect.TopLeft.Y, vRect.BottomRight.X - vRect.TopLeft.X, vRect.BottomRight.Y - vRect.TopLeft.Y);
    graphics := TsgGDIPlusGraphics.Create(DC);
    try
      graphics.InitParams;
      case AColor of
        clByBlock, clByLayer, clNone: vColor := GetDrawPenColor;
      else
        vColor := AColor;
      end;
      Solid := TsgGDIPlusSolidBrush.Create(GetGDIPlusColor(vColor));
      try
        graphics.FillRectangle(Solid, GPRect);
      finally
        Solid.Free;
      end;
    finally
      graphics.Free;
    end;
  end;

  function GetRectMaxSize(const ARect: TsgGRect): TsgGRect;
  begin
    if ARect.Width < ARect.Height then
      Result.Width := ARect.Height
    else
      Result.Width := ARect.Width;
    Result.Height := ARect.Width;
    Result.X := ARect.X - (Result.Width - ARect.Width) div 2;
    Result.Y := ARect.Y - (Result.Height - ARect.Height) div 2;
  end;

  function GetRectRotated(const ARect: TRect; const Angle: Double): TRect;
  var
    vC: TPoint;
  begin
    Result := ARect;
    vC.X := (ARect.Left + ARect.Right) div 2;
    vC.Y := (ARect.Top + ARect.Bottom) div 2;
    ExpandRect(Result, GetPointOfRotateByCenter(Point(ARect.Left, ARect.Top), vC, Angle));
    ExpandRect(Result, GetPointOfRotateByCenter(Point(ARect.Right, ARect.Top), vC, Angle));
    ExpandRect(Result, GetPointOfRotateByCenter(Point(ARect.Right, ARect.Bottom), vC, Angle));
    ExpandRect(Result, GetPointOfRotateByCenter(Point(ARect.Left, ARect.Bottom), vC, Angle));
  end;

  procedure DrawGDIPlusCADGradient(const ACADGradinet: TsgCADGradientPolygonAccess);
  const
    cnstCounts: Integer = 3;
    cnstBlendFactorsByCylinder: array [0..2] of Single = (0, 1, 0);
    cnstBlendPositionsByCylinder: array [0..2] of Single = (0, 0.5, 1);
    cnstBlendFactorsByCylinderNotCenter: array [0..2] of Single = (0, 1, 0);
    cnstBlendPositionsByCylinderNotCenter: array [0..2] of Single = (0, 0.2, 1);
    cnstBlendFactorsByLiner: array [0..2] of Single = (0, 0.5, 1);
    cnstBlendPositionsByLinear: array [0..2] of Single = (0, 0.2, 1);
  var
    vColors: array [0..1] of TsgColor;
    graphics: TsgGDIPlusGraphics;
    GRect, GR: TsgGRect;
    GCenter: TsgGPoint;
    GMatrix: TsgGDIPlusMatrix;
    GGradL: TsgGDIPlusLinearGradientBrush;

    procedure DrawSolid(const AColor: TsgColor);
    var
      GSolid: TsgGDIPlusSolidBrush;
    begin
      GSolid := TsgGDIPlusSolidBrush.Create(AColor);
      try
        graphics.FillRectangle(GSolid, GRect);
      finally
        GSolid.Free;
      end;
    end;

    procedure DrawSpheric(const ARect: TsgGRect; const ACenter: TsgGPoint);
    var
      GPath: TsgGDIPlusGraphicsPath;
      GGrad: TsgGDIPlusPathGradientBrush;
      vCount: Integer;
    begin
      GPath := TsgGDIPlusGraphicsPath.Create;
      try
        GPath.StartFigure;
        GPath.AddEllipse(ARect);
        GGrad := TsgGDIPlusPathGradientBrush.Create(GPath);
        try
          vCount := 1;
          //GGrad.MultiplyTransform(GMatrix);
          GGrad.SetCenterColor(vColors[1]);
          GGrad.SetCenterPoint(ACenter);
          GGrad.SetSurroundColors(@vColors[0], vCount);
          graphics.FillPath(GGrad, GPath);
        finally
          GGrad.Free;
        end;
      finally
        GPath.Free;
      end;
    end;

  begin
    vColors[0] := GetGDIPlusColor(ACADGradinet.GradientColor[0]);
    vColors[1] := GetGDIPlusColor(ACADGradinet.GradientColor[1]);
    if ACADGradinet.FType in [gtInvCurved, gtInvCylinder, gtInvHemiSpherical, gtInvSpherical] then
      SwapInts(vColors[0], vColors[1]);
    vRect := GetRectRotated(vRect, 360 - ACADGradinet.GradientAngle);
    GRect := MakeRectI(vRect);
    graphics := TsgGDIPlusGraphics.Create(FCanvas.Handle);
    try
      graphics.InitParams;
      case ACADGradinet.FType of
        gtLinear:
          begin
            GMatrix := TsgGDIPlusMatrix.Create(1, 0, 0, 1, 0, 0);
            try
              if Abs(ACADGradinet.GradientAngle) > fAccuracy then
                GMatrix.RotateAt(360 - ACADGradinet.GradientAngle, PointIToPointF(GetCenter(TsgGRect(GRect))));
              GGradL := TsgGDIPlusLinearGradientBrush.Create(GRect, vColors[0], vColors[1],LinearGradientModeHorizontal);
              try
                GGradL.MultiplyTransform(GMatrix);
                if not ACADGradinet.GradientUseCenter then
                  GGradL.SetBlend(@cnstBlendFactorsByLiner, @cnstBlendPositionsByLinear, cnstCounts);
                graphics.FillRectangle(GGradL, GRect);
              finally
                GGradL.Free;
              end;
            finally
              GMatrix.Free;
            end;
          end;
        gtCylinder, gtInvCylinder:
          begin
            GMatrix := TsgGDIPlusMatrix.Create(1, 0, 0, 1, 0, 0);
            try
              if Abs(ACADGradinet.GradientAngle) > fAccuracy then
                GMatrix.RotateAt(360 - ACADGradinet.GradientAngle, PointIToPointF(GetCenter(GRect)));
              GGradL := TsgGDIPlusLinearGradientBrush.Create(GRect, vColors[0], vColors[1],LinearGradientModeHorizontal);
              try
                GGradL.MultiplyTransform(GMatrix);
                if ACADGradinet.GradientUseCenter then
                  GGradL.SetBlend(@cnstBlendFactorsByCylinder, @cnstBlendPositionsByCylinder, cnstCounts)
                else
                  GGradL.SetBlend(@cnstBlendFactorsByCylinderNotCenter, @cnstBlendPositionsByCylinderNotCenter, cnstCounts);
                graphics.FillRectangle(GGradL, GRect);
              finally
                GGradL.Free;
              end;
            finally
              GMatrix.Free;
            end;
          end;
        gtSpherical, gtInvSpherical:
          begin
            DrawSolid(vColors[0]);
            GR := GetRectMaxSize(GRect);
            if ACADGradinet.GradientUseCenter then
              GCenter := GetCenter(GR)
            else
            begin
              GCenter.X := GR.X + Round(0.2 * GR.Width);
              GCenter.Y := GR.Y + Round(0.2 * GR.Height);
              GR.X := GCenter.X - GR.Width div 2;
              GR.Y := GCenter.Y - GR.Height div 2;
            end;
            DrawSpheric(GR, GCenter);
          end;
        gtHemiSpherical, gtInvHemiSpherical:
          begin
            DrawSolid(vColors[0]);
            if ACADGradinet.GradientUseCenter then
            begin
              GCenter.X := GRect.X + GRect.Width div 2;
              GCenter.Y := GRect.Y + GRect.Height;
            end
            else
            begin
              GCenter.X := GRect.X;
              GCenter.Y := GRect.Y + GRect.Height;
            end;
            if GRect.Width > GRect.Height then
              GR.Width := GRect.Width shl 1
            else
              GR.Width := GRect.Height shl 1;
            GR.Height := GR.Width;
            GR.X := GCenter.X - GR.Width div 2;
            GR.Y := GCenter.Y - GR.Height div 2;
            DrawSpheric(GR, GCenter);
          end;
        gtCurved, gtInvCurved:
          begin
            //GGradL := TsgGDIPlusLinearGradientBrush.Create(GRect, vColors[0], vColors[1], LinearGradientModeVertical);
            GGradL := TsgGDIPlusLinearGradientBrush.Create(GRect, vColors[0], vColors[1], ACADGradinet.GradientAngle+90, False);
            try
              graphics.FillRectangle(GGradL, GRect);
            finally
              GGradL.Free;
            end;
          end;
      end;
    finally
      graphics.Free;
    end;
  end;


{$ENDIF}

  procedure DrawGradient;
  var
    //Per: TsgFloat;
    //L: Integer;
    vP1,vP2: TPoint;
    //vGradient: TsgDXFGradient;
    //vRectEnt: TRect;
    //vR: TFRect;
  begin
    vP1 := vRect.TopLeft;
    vP2 := vRect.BottomRight;
    //if Sender.ClassType <> TsgDXFGradient then
    begin
{$IFDEF SG_USEGDIPLUS}
      if FLibraryGDIPlusExists then
        DrawGDIPlusCADGradient(TsgCADGradientPolygonAccess(vPolygon))
      else
{$ENDIF}
      begin
        SetVert(Vert[0], vP1, TsgCADGradientPolygon(vPolygon).GradientColor[0]);
        SetVert(Vert[1], vP2, TsgCADGradientPolygon(vPolygon).GradientColor[1]);
        GradientFill(FCanvas.Handle, @Vert, 2, @P1, 1, 1);
      end;
    end
    (*
    else
    begin

      vGradient := TsgDXFGradient(Sender);
      vR := vGradient.Box;
      TransRectCorners(vR, FDraw.Matrix);
      vRectEnt.TopLeft := Point(Round(vR.TopLeft.X), Round(vR.TopLeft.Y));
      vRectEnt.BottomRight := Point(Round(vR.BottomRight.X), Round(vR.BottomRight.Y));
      SwapInts(vRectEnt.TopLeft.Y, vRectEnt.BottomRight.Y);
{$IFDEF SG_USEGDIPLUS}
      if FLibraryGDIPlusExists then
        DrawGDIPlusGradientEx(FCanvas.Handle, vRectEnt, vGradient)
      else
{$ENDIF}
      begin
        if vGradient.IsVertical then
          Per := (vRectEnt.Bottom - vRectEnt.Top) / 100
        else
          Per := (vRectEnt.Right - vRectEnt.Left) / 100;
        for L := 0 to vGradient.Colors.Count - 2 do
        begin
          if vGradient.IsVertical then
          begin
            vP1.Y := vRectEnt.TopLeft.Y + Round(Single(vGradient.Positions[L]) * Per);
            vP2.Y := vRectEnt.TopLeft.Y + Round(Single(vGradient.Positions[L + 1]) * Per);
          end
          else
          begin
            vP1.X := vRectEnt.TopLeft.X + Round(Single(vGradient.Positions[L]) * Per);
            vP2.X := vRectEnt.TopLeft.X + Round(Single(vGradient.Positions[L + 1]) * Per);
          end;
          SetVert(Vert[0], vP1, TColor(vGradient.Colors[L]));
          SetVert(Vert[1], vP2, TColor(vGradient.Colors[L + 1]));
          GradientFill(FCanvas.Handle, @Vert, 2, @P1, 1, Integer(vGradient.IsVertical));
        end;
      end;

    end;  *)
  end;
var
  vClippingRect: PFRect;
begin
  vIsDrawOnCanvas := IsDrawOnCanvas;
  vIsDrawOnBitMap := IsDrawOnBitMap;
  vClippingRect := GetRealClip;
  if not (vIsDrawOnCanvas or vIsDrawOnBitMap) then
    Exit;
  vPolygon := TsgCADPolyPolygon(Sender);
  if (vPolygon.EntType = ceHatch) and (TsgCADHatch(vPolygon).FillStyle = fsCAD) then
  begin
    if (TsgCADHatch(vPolygon).ParsedLines = nil) or (TsgCADHatch(vPolygon).ParsedLines.Count = 0) then
     Exit;
  end;
  vClipRgn := 0;
  vMainRGN := CreateRectRgn(0, 0, 0, 0);// FCanvas.ClipRect.Right, FCanvas.ClipRect.Bottom);
  SaveIndex := ExpSaveDCInternal(Sender);
  try
    if (sgClientRect.Left <> MaxInt)and(sgClientRect.Top <> MaxInt) then
      vClipRgn := CreateRectRgn(sgClientRect.Left, sgClientRect.Top, sgClientRect.Right, sgClientRect.Bottom)
    else
      if (vClippingRect <> nil) and (sgClientRect.Right <> -MaxInt) then
        vClipRgn := CreateRectRgn(0, 0, sgClientRect.Right, sgClientRect.Bottom);

    for I := 0 to vPolygon.Boundaries.Count - 1 do
    begin
      FPoly.Count := 0;
      Load2DPointToPoints(vPolygon.Boundaries[I]);
      vRGN := CreatePolygonRgn(FPoly.List^, FPoly.Count shr 1, GetPolygonFillingMode);
      if vClipRgn <> 0 then
        CombineRgn(vRGN, vClipRgn, vRGN,  RGN_AND);
      CombineRgn(vMainRGN, vRGN, vMainRGN,  RGN_XOR);
      DeleteObject(vRGN);
    end;

    if (sgClientRect.Left <> MaxInt)and(sgClientRect.Top <> MaxInt) then
    begin
      DeleteObject(vClipRgn);
      GetRgnBox(vMainRGN, vRect);
      if vRect.Right = vRect.Left then
        Exit;
    end;
    {$IFNDEF SGFPC}
    if FCanvas is TMetafileCanvas then
    begin
      vRGN := CreateRectRgn(0, 0, 0, 0);
      GetClipRgn(FCanvas.Handle, vRGN);
      GetRgnBox(vRGN, vRect);
      if vRect.Right <> vRect.Left then
        CombineRgn(vMainRGN, vMainRGN, vRGN, RGN_AND);
      DeleteObject(vRGN);
    end;
    {$ENDIF}
    if vPolygon.SolidFill then
    begin
      if IsCADGradient(vPolygon) and not FIsIterator then
      begin
        if vIsDrawOnCanvas then
        begin
          SetClipRGN;
          if vPolygon is TsgCADFill then
            DrawCADFill(Sender)
          else
            DrawGradient;
        end;
        if vIsDrawOnBitMap then
        begin
          AddSelectionMatrix(Sender);
          SelectionMatrix.Brush.Style := bsSolid;
          SelectionMatrix.Changed;
          if vPolygon.Boundaries.Count = 1 then
            Polygon(SelectionMatrix.Handle, FPoly.List^, FPoly.Count shr 1)
          else
            FillRgn(SelectionMatrix.Handle, vMainRGN, SelectionMatrix.Brush.Handle);
          SelectionMatrix.Brush.Style := bsClear;
        end;
      end
      else
      begin
        if not FLibraryGDIPlusExists or FIsIterator or FConverting then
        begin
          if vPolygon is TsgCADFill then//for future version
          begin
            ExpClipRgnInternal(Sender, vMainRGN);
            DrawCADFill(Sender);
          end
          else
          begin
            if IsCADGradient(vPolygon) then
              FColor := TsgCADGradientPolygon(Sender).GradientColor[0];
            DoSetColor(FColor, ctBrush);
            if vPolygon.Boundaries.Count = 1 then
            begin
              ExpPolygonInteger(Sender, FPoly.List^, FPoly.Count shr 1);
            end
            else
              ExpFillRgnInternal(Sender, vMainRGN);
          end;
        end
{$IFDEF SG_USEGDIPLUS}
        else
        begin
          if vIsDrawOnBitMap then
          begin
            AddSelectionMatrix(Sender);
            SelectionMatrix.Brush.Style := bsSolid;
            SelectionMatrix.Changed;
            if vPolygon.Boundaries.Count = 1 then
              Polygon(SelectionMatrix.Handle, FPoly.List^, FPoly.Count shr 1)
            else
              FillRgn(SelectionMatrix.Handle, vMainRGN, SelectionMatrix.Brush.Handle);
            SelectionMatrix.Brush.Style := bsClear;
          end;
          if vIsDrawOnCanvas then
            DrawGDIPlusHatch(FCanvas.Handle, FColor);
        end;
{$ENDIF}
      end;
      Exit;
    end;
    case TsgCADHatch(vPolygon).FillStyle of
      fsClear:  begin end;
      fsCAD: DrawPointsListByPolyPolyline(Sender, TsgCADHatch(vPolygon).ParsedLines);
    else
      DoSetColor(FColor, ctBrush);
      DoSetStyle(Integer(TsgCADHatch(vPolygon).FillStyle), ctBrush);
      ExpFillRgnInternal(Sender, vMainRGN);
    end;
  finally
    ExpRestoreDCInternal(Sender, SaveIndex);
    DeleteObject(vMainRGN);
    DoSetColor(FColor, ctBrushClear);
  end;
end;

procedure TsgCADImage.DrawMPolygon(Sender: TObject);
var
  I: Integer;
  vMPolygon: TsgCADMPolygon;
  vColor: TsgColorCAD;
  vIsDrawOnCanvas, vIsDrawOnBitMap: Boolean;
begin
  vMPolygon := TsgCADMPolygon(Sender);
  vColor := vMPolygon.ColorCAD;
  try
    vMPolygon.ColorCAD := vMPolygon.FillColor;
    FColor := GetEntityColor(vMPolygon, FDraw.Insert);
    DoSetColor(FColor, ctPen);
    DrawHatch(Sender);
  finally
    vMPolygon.ColorCAD := vColor;
  end;
  if not IsEqualColorCAD(vMPolygon.ColorCAD,vMPolygon.FillColor) then
  begin
    FColor := GetEntityColor(vMPolygon, FDraw.Insert);
    DoSetColor(FColor, ctPen);
    ApplyPen(Sender);
  end;
  vIsDrawOnCanvas := IsDrawOnCanvas;
  vIsDrawOnBitMap := IsDrawOnBitMap;
  if vIsDrawOnBitMap or vIsDrawOnCanvas then
  begin
    if FIsIterator then
    begin
      FPoly.Count := 0;
      for I := 0 to vMPolygon.Boundaries.Count - 1 do
      begin
        Load2DPointToPoints(vMPolygon.Boundaries[I]);
        if Assigned(FsgExpPolyline) then
          FsgExpPolyline(FPoly.List^, FPoly.Count shr 1);
        FPoly.Count := 0;
      end;
    end
    else
    begin
      if vIsDrawOnBitMap then
      begin
        AddSelectionMatrix(Sender);
        SelectionMatrix.Brush.Style := bsClear;
        SelectionMatrix.Changed;
      end;
      FPoly.Count := 0;
      for I := 0 to vMPolygon.Boundaries.Count - 1 do
      begin
        Load2DPointToPoints(vMPolygon.Boundaries[I]);
        if vIsDrawOnCanvas then
          DrawPolyLine(FCanvas.Handle, FPoly);
        if vIsDrawOnBitMap then
         DrawPolyLine(SelectionMatrix.Handle, FPoly);
        FPoly.Count := 0;
      end;
    end;
  end;
end;

function TsgCADImage.DrawInsert(Sender: TObject): Integer;
var
  Ins: TsgDXFInsert absolute Sender;
{$IFDEF SG_BTI}
   function DrawElementModifier(Sender: TObject): Integer;
   var
     vInsAccess: TsgDXFInsertAccess absolute Sender;
     I: Integer;
     vPts: TsgPoints4;
     vPoints: array [0..4] of TPoint;
   begin
     Result := 2;//Draw only attribs
     vInsAccess.GetPts(vPts);
     for I := 0 to 3 do
       vPoints[I] := GetPoint(vPts[I]);
     vPoints[4] := vPoints[0];
     if (vInsAccess.GetOwnerConstruction = nil) and IsDrawOnCanvas then
       ExpPolylineInteger(Sender, vPoints, High(vPoints) + 1);
   end;
{$ENDIF}
begin
{$IFDEF SG_BTI}
  if TsgDXFEntityAccess(Ins).GetEntTypeEx = cnstElementModifier then
    Result := DrawElementModifier(Sender)
  else
{$ENDIF}
  begin
    Result := Integer(Ins.Block <> nil);
    if Result = 1 then
    begin
      if FOnInsert = Sender then
        FOnInsertMode := True;
      if (SelectionMatrix <> nil) and (not FIsIterator) then
      begin
        AddSelectionMatrix(Sender);
        SelectionMatrix.Changed;
      end;
    end;
    if Ins is TsgCADClipInsert then
      SetClip(TsgCADClipInsert(Ins));
  end;
end;

function TsgCADImage.DrawDimension(Sender: TObject): Integer;
var
  vDim: TsgDXFDimension absolute Sender;
begin
  Result := Integer(FDimensionsVisible and (vDim.Block <> nil));
  if (Result = 1) and (SelectionMatrix <> nil) then
  begin
    AddSelectionMatrix(Sender);
    SelectionMatrix.Changed;
  end;
end;

procedure TsgCADImage.DrawViewPort(Sender: TObject);
var
  vIsDrawOnBitMap: Boolean;
  vIsDrawOnCanvas: Boolean;
  ClipBoundary: TsgDXFEntity;
  ViewPort: TsgDXFViewPort;
  TopLeft, BottomRight, TopRight, BottomLeft: TPoint;
  vFRect: TFRect;
  I: Integer;
  vRgn: HRGN;

  procedure AddPolyPoint(APoint: TPoint);
  begin
    FPoly.Add(APoint.X);
    FPoly.Add(APoint.Y);
  end;

  procedure CreateHRGNByRegion(vRegion: TsgDXFRegion);
  var
    J: Integer;
    vEntity: TsgDXFEntity;
    vLine: TsgDXFLine absolute vEntity;

    procedure AddCurve(const APoly: TsgCADBasePolyline);

      function GetCoEdgeReversed(APoly: TsgCADBasePolyline): Boolean;
      begin
        Result := (APoly.Flags and 8) <> 0;
      end;

    var
      K: Integer;
    begin
      if GetCoEdgeReversed(APoly) then
      begin
        for K := APoly.PolyPoints.Count - 1 downto 0 do
          AddPolyPoint(GetPoint(APoly.Points[K]));
      end
      else
      begin
        for K := 0 to APoly.PolyPoints.Count - 1 do
          AddPolyPoint(GetPoint(APoly.Points[K]));
      end;
    end;

  begin
    J := 0;
    FViewPortRegion := CreateRectRgn(0, 0, 0, 0);
    repeat
      FPoly.Clear(False);
      while J < vRegion.Count do
      begin
        vEntity := vRegion.Entities[J];
        Inc(J);
        if vEntity.EntType <> ceEntity then
        begin
          if vEntity is TsgDXFLine then
          begin
            AddPolyPoint(GetPoint(vLine.Point));
            AddPolyPoint(GetPoint(vLine.Point1));
          end
          else
          begin
            if vEntity is TsgCADBasePolyline then
              AddCurve(TsgCADBasePolyline(vEntity))
            else
              Continue;
          end;
        end
        else
          Break;
      end;
      if FPoly.Count > 0 then
      begin
        vRGN := CreatePolygonRgn(FPoly.List^, FPoly.Count shr 1, ALTERNATE);
        CombineRgn(FViewPortRegion, FViewPortRegion, vRGN, RGN_XOR);
        DeleteObject(vRGN);
        if ViewPort.VisibleBoundary then
        begin
          FCanvas.Brush.Style := bsClear;
          if IsDrawOnBitMap then
          begin
            SelectionMatrix.Changed;
            Windows.Polyline(SelectionMatrix.Handle, FPoly.List^, FPoly.Count shr 1);
          end;
          if IsDrawOnCanvas then
            Windows.Polyline(FCanvas.Handle, FPoly.List^, FPoly.Count shr 1);
        end;
      end;
    until J >= vRegion.Count;
  end;

begin
  ViewPort := TsgDXFViewPort(Sender);
  if not ViewPort.IsDraw  then
    Exit;
  vIsDrawOnBitMap := IsDrawOnBitMap;
  vIsDrawOnCanvas := IsDrawOnCanvas;
  if vIsDrawOnBitMap then
    SelectionMatrix.SaveClipRGN;
  New(FViewPortCanvasParams);
  FViewPortCanvasParams^.HDC := ExpSaveDCInternal(Sender); //SaveDC(FCanvas.Handle);
  FViewPortCanvasParams^.CanvasParams.Brush := TBrush.Create;
  FViewPortCanvasParams^.CanvasParams.Font := TFont.Create;
  FViewPortCanvasParams^.CanvasParams.Pen := TPen.Create;
  if not FIsIterator then
  begin
    FViewPortCanvasParams^.CanvasParams.Brush.Assign(FCanvas.Brush);
    FViewPortCanvasParams^.CanvasParams.Font.Assign(FCanvas.Font);
    FViewPortCanvasParams^.CanvasParams.Pen.Assign(FCanvas.Pen);
  end;
  ViewPort := TsgDXFViewPort(Sender);
  vFRect := ViewPort.Rect;
  TopLeft := GetPoint(vFRect.TopLeft);
  BottomRight := GetPoint(vFRect.BottomRight);
  TopRight := GetPoint(MakeFPoint(vFRect.Right, vFRect.Top, 0));
  BottomLeft := GetPoint(MakeFPoint(vFRect.Left, vFRect.Bottom, 0));
  ClipBoundary := TsgDXFViewportAccess(ViewPort).GetClipBoundary(FConverter);
  FPoly.Count := 0;
  if vIsDrawOnBitMap and not FIsIterator then
    AddSelectionMatrix(Sender);
  if ClipBoundary = nil then
  begin
    AddPolyPoint(TopLeft);
    AddPolyPoint(TopRight);
    AddPolyPoint(BottomRight);
    AddPolyPoint(BottomLeft);
    AddPolyPoint(TopLeft);
    FViewPortRegion := CreatePolygonRgn(FPoly.List^, FPoly.Count shr 1, ALTERNATE);
    if ViewPort.VisibleBoundary then
    begin
      if Assigned(FsgExpPolyline) then
      begin
        FsgExpPolyline(FPoly.List^, FPoly.Count shr 1);
      end
      else
      begin
        if vIsDrawOnCanvas then
        begin
          FCanvas.Brush.Style := bsClear;
          Windows.Polyline(FCanvas.Handle, FPoly.List^, FPoly.Count shr 1);
        end;
      end;
    end;
  end
  else
  begin
    if ClipBoundary is TsgDXFRegion then
      CreateHRGNByRegion(TsgDXFRegion(ClipBoundary))
    else//only for classes for which TsgDXFPolyLine is parent
    begin
      for I := 0 to TsgDXFPolyLine(ClipBoundary).PolyPoints.Count - 1 do
        AddPolyPoint(GetPoint(TsgDXFPolyLine(ClipBoundary).PolyPoints[I]));
      if Assigned(FsgExpPolyline) then
        FsgExpPolyline(FPoly.List^, FPoly.Count shr 1);
      FViewPortRegion := CreatePolygonRgn(FPoly.List^, FPoly.Count shr 1, ALTERNATE);
    end;
  end;
  if (FPoly.Count > 0) and (not Assigned(FsgExpPolyline)) and vIsDrawOnBitMap then
  begin
    if SelectionMatrix.ViewPortMode = vmFill then
    begin
      SelectionMatrix.Brush.Style := bsSolid;
      SelectionMatrix.Changed;
      Windows.Polygon(SelectionMatrix.Handle, FPoly.List^, FPoly.Count shr 1);
    end
    else
    begin
      SelectionMatrix.Brush.Style := bsClear;
      SelectionMatrix.Changed;
      Windows.Polyline(SelectionMatrix.Handle, FPoly.List^, FPoly.Count shr 1);
    end;
  end;
  ExpClipRgnInternal(Sender, FViewPortRegion);
end;

procedure TsgCADImage.DrawWipeout(Sender: TObject);
var
  W: TsgCADWipeout absolute Sender;
  Rgn: HRgn;

  P,R: PRgnDataHeader;
  Size: Integer;

begin
  if IsDrawOnCanvas then
  begin
    Rgn := PolyRgn(W);
    DoSetColor(GetBackgroundColor, ctBrush, False);
    if FIsIterator  and Assigned(FsgExpFillRgn) then
    begin
      Size := GetRegionData(Rgn,0,nil);
      GetMem(P,Size);
      try
        if GetRegionData(Rgn, Size, PRgnData(P)) <> 0 then
        begin
          R := P;
          Inc(R);
          FsgExpFillRgn(PRect(R), P.nCount);
        end;
      finally
        FreeMem(P);
      end;
    end
    else
      PaintRgn(FCanvas.Handle, Rgn);
    DeleteObject(Rgn);
  end;
  if not FConverter.HideWipeouts then
    DrawPoly(W);// draws only WIPEOUT boundary (TsgCADBasePolyline) with pen from W
end;

procedure TsgCADImage.DrawImageEnt(Sender: TObject);
var
  Img: TsgDXFImageEnt absolute Sender;
  Rgn,Old: HRgn;
  SaveIndex: Integer;
begin
  if Img.ClipPointsCount < 2 then
    DrawImage(Sender)
  else
  begin
    Rgn := PolyRgn(Img);
    if FIsIterator then
    begin
      SaveIndex := ExpSaveDCInternal(Sender);
      ExpClipRgnInternal(Sender, Rgn);
      DrawImage(Sender);
      ExpRestoreDCInternal(Sender, SaveIndex);
      DeleteObject(Rgn);
      if not FConverter.HideWipeouts then
        DrawPoly(Img);// draws only Wipeout boundary (TsgDXFPolyline) with pen from W
    end
    else
    begin
      sgOffsetRgn(FCanvas,Rgn);
      Old := CreateRectRgn(0, 0, 0, 0);
      if GetClipRgn(FCanvas.Handle, Old) <= 0 then
      begin
        DeleteObject(Old);
        Old := 0;
      end;
      ExtSelectClipRgn(FCanvas.Handle, Rgn, RGN_AND);
      DeleteObject(Rgn);
      DrawImage(Sender);
      SelectClipRgn(FCanvas.Handle, Old);
      if Old <> 0 then
        DeleteObject(Old);
      if Converter.DisplayImageFrame then
        DrawPoly(Img);// draws only IMAGE boundary (TsgCADBasePolyline) with pen from Img
    end;
  end;
end;

procedure TsgCADImage.DrawImageGDI(Sender: TObject;
  const AGraphic: TGraphic; const APoints: array of TPoint);
var
  vImageEnt: TsgDXFImageEntAccess absolute Sender;
  vCurClipRGN: HRGN;

  procedure SelectRgnByMetafile;
  var
    vClipRgn: HRGN;
    OffsetPt: TPoint;
  begin
    vClipRgn := CreateRectRgn(FIRect.Left, FIRect.Top, FIRect.Right, FIRect.Bottom);
    OffsetPt := Point(0, 0);
    LPtoDP(FCanvas.Handle, OffsetPt, 1);
    OffsetRgn(vClipRgn, OffsetPt.X, OffsetPt.Y);
    vCurClipRGN := CreateRectRgn(0, 0, 0, 0);
    if GetClipRgn(FCanvas.Handle, vCurClipRGN) > 0 then
      CombineRgn(vClipRgn, vClipRgn, vCurClipRGN, RGN_AND);
    SelectClipRgn(FCanvas.Handle, vClipRgn);
    DeleteObject(vClipRgn);
  end;
begin
  {$IFNDEF SGFPC}
  if AGraphic is TMetafile then
  begin
    vCurClipRGN := 0;
    try
      SelectRgnByMetafile;
      {$IFNDEF NOGDI}
      ExpImageGDIInternal(Sender, FIRect, AGraphic);
      {$ENDIF}
    finally
      if vCurClipRGN <> 0 then
      begin
       SelectClipRgn(FCanvas.Handle, vCurClipRGN);
       DeleteObject(vCurClipRGN);
      end;
    end;
  end
  {$IFNDEF NOGDI}
  else
    ExpImageGDIInternal(Sender, FIRect, AGraphic)
 {$ENDIF};
 {$ELSE}
 {$IFNDEF NOGDI}
   ExpImageGDIInternal(Sender, FIRect, AGraphic)
  {$ENDIF};
 {$ENDIF}
  if vImageEnt.IsMonoChrome and (GetBackgroundColor = clBlack) then
    PatBlt(FCanvas.Handle, FIRect.Left,FIRect.Top, FIRect.Right-FIRect.Left,
      FIRect.Bottom-FIRect.Top, DSTINVERT);
end;

procedure TsgCADImage.DrawLeader(Sender: TObject);
begin
  if TsgDXFLeader(Sender).IsSpline = False then
    DrawPoly(Sender)
  else
    DrawSpline(Sender);
end;

procedure TsgCADImage.DrawLine(Sender: TObject);
var
  vLine: TsgDXFLine absolute Sender;
  vIsDrawOnBitMap: Boolean;
  I,Cnt, vPtCnt: Integer;
  vLTScale: Single;

  function GetExtruded(const ALine: TsgDXFLine; APoint: TFPoint): TFPoint;
  begin
    Result := APoint;
    DoPreExtrusion(Result, ALine.Extrusion);
    Result.Z := Result.Z + ALine.ZThick;
    DoExtrusion(Result, ALine.Extrusion);
  end;

  procedure DrawLineAndZTick(const APoint1, APoint2: TFPoint);
  var
    vPts: array [0..4] of TPoint;
  begin
    vPts[0] := GetPoint(APoint1);
    vPts[1] := GetPoint(APoint2);
    if not Extruded(vLine.Extrusion) then
    begin
      vPts[2] := GetPoint(MakeFPoint(APoint2.X, APoint2.Y, APoint2.Z + vLine.ZThick));
      vPts[3] := GetPoint(MakeFPoint(APoint1.X, APoint1.Y, APoint1.Z + vLine.ZThick));
    end
    else
    begin
      vPts[2] := GetPoint(GetExtruded(vLine, APoint2));
      vPts[3] := GetPoint(GetExtruded(vLine, APoint1));
    end;
    if IsEqualPoints(vPts[0], vPts[1]) and IsEqualPoints(vPts[1], vPts[2]) then
    begin
      ExpPixelInteger(Sender, vPts[0], FColor);
    end
    else
    begin
      vPts[4] := vPts[0];
      ExpPolylineInteger(Sender, PPoint(@vPts)^, 5);
    end;
  end;

begin
  vIsDrawOnBitMap := IsDrawOnBitMap;
  if vLine.ZThick = 0 then
  begin
    if FReady and FEntityLines.IsSolid then
    begin
      if IsEqualPoints(FIPoints[0], FIPoints[1]) then
      begin
        ExpPixelInteger(Sender, FIPoints[0], FColor);
      end
      else
      begin
        if NeedToAddOnePixel then
        begin
          vPtCnt := 3;
          FIPoints[2] := Point(FIPoints[1].X, FIPoints[1].Y + 1); // (!!!) points changes
        end
        else
          vPtCnt := 2;
        ExpPolylineInteger(Sender, FIPoints, vPtCnt);
      end;
    end
    else
    begin
      if FEntityLines.IsSolid then
        ExpPolylineInteger(Sender, FIPoints, 2)
      else
      begin
        vLTScale := FEntityLines.Scale;
        if InitializeLineType(vLine) then
        begin
          CalcDottedSingPts(vLine, FEntityLines,
            FDraw.ConvertMatrixCurrentIndertToWCS, FDottedSingPts);
          DrawPointsListByPolyPolyline(Sender, FDottedSingPts, False);
        end
        else
        begin
          if NeedToAddOnePixel then
          begin
            vPtCnt := 3;
            FIPoints[2] := Point(FIPoints[1].X, FIPoints[1].Y + 1); // (!!!) points changes
          end
          else
            vPtCnt := 2;
          ExpPolylineInteger(Sender, FIPoints, vPtCnt);
        end;
        FEntityLines.Scale := vLTScale;
      end;
    end;
  end
  else
  begin
    FIntPoints.Count := 0;
    if vIsDrawOnBitMap then
    begin
      AddSelectionMatrix(Sender);
      SelectionMatrix.Changed;
    end;
    if FEntityLines.IsSolid then
      DrawLineAndZTick(vLine.Point, vLine.Point1)
    else
    begin
      begin
        vLTScale := FEntityLines.Scale;
        try
          if InitializeLineType(vLine) then
          begin
            CalcDottedSingPts(vLine, FEntityLines,
              FDraw.ConvertMatrixCurrentIndertToWCS,
              FDottedSingPts);
            I := 0;
            Cnt := (FDottedSingPts.Count shr 1) shl 1;
            while I < Cnt do
            begin
              DrawLineAndZTick(FDottedSingPts[I], FDottedSingPts[I + 1]);
              Inc(I, 2);
            end;
          end;
        finally
          FEntityLines.Scale := vLTScale;
        end;
      end;
    end;
  end;
end;


procedure TsgCADImage.DrawPaperSpace;

  procedure DrawRect(const ABox: TFRect; const AIsFill: Boolean;
    const AColor: TColor; const APenStyle: TPenStyle = psSolid);
  const
    cnstColorType: array[Boolean] of TsgColorType = (ctPen, ctBrush);
  var
    vPlotWindowsArea: array [0..4] of TPoint;
  begin
    DoSetColor(AColor, cnstColorType[AIsFill]);
    DoSetStyle(Integer(APenStyle), ctPen);
    vPlotWindowsArea[0] := GetPoint(ABox.TopLeft);
    vPlotWindowsArea[1] := GetPoint(MakeFPoint(ABox.Right, ABox.Top, ABox.Z1));
    vPlotWindowsArea[2] := GetPoint(ABox.BottomRight);
    vPlotWindowsArea[3] := GetPoint(MakeFPoint(ABox.Left, ABox.Bottom, ABox.Z2));
    vPlotWindowsArea[4] := vPlotWindowsArea[0];
    if AIsFill then
      FCanvas.Polygon(vPlotWindowsArea)
    else
      FCanvas.Polyline(vPlotWindowsArea);
  end;

  function RectInRect(const ASourceRect, ATargetRect: TFRect): Boolean;
  begin
    Result :=
      (ASourceRect.Left > ATargetRect.Left) and
      (ASourceRect.Top > ATargetRect.Top) and
      (ASourceRect.Right < ATargetRect.Right) and
      (ASourceRect.Bottom < ATargetRect.Bottom);
  end;

var
  vPSettings: TsgDXFPlotSettings;
  vShowRect, vPaperArea, vMarginArea: TFRect;
  vMarginColor: TColor;
  vDrawPaperAfterFrame: Boolean;
begin
  if (CurrentLayout.IsModel and FShowPlotForModel) or
     (not CurrentLayout.IsModel) then
  try
    vPSettings := CurrentLayout.PlotSettings;
    vShowRect := vPSettings.PlotFrameArea;
    vPaperArea := vPSettings.PlotPaperArea;
    vMarginArea := vPSettings.PlotMarginsArea;
    vDrawPaperAfterFrame := (vPSettings.PlotType = ptWindowSpecified) and
      RectInRect(vPaperArea, vShowRect);
    DrawRect(vPaperArea, True, GetBackgroundColor, psSolid);
    if (vPSettings.PlotType = ptWindowSpecified) and ShowPlotFrame then
    begin
      DrawRect(vShowRect, True, PlotWindowAreaColor, psClear);
      DrawRect(vShowRect, False, $A0A0A0, psDot);
    end;
    if vDrawPaperAfterFrame then
      DrawRect(vPaperArea, True, GetBackgroundColor, psSolid);
    if ShowPlotMargins then
    begin
      if GetBackgroundColor = clBlack then
        vMarginColor := clWhite
      else
        vMarginColor := clBlack;
      DoSetStyle(Integer(bsClear), ctBrush);
      DrawRect(vMarginArea, False, vMarginColor, psDash);
    end;
  finally
    DoSetStyle(Integer(psSolid), ctPen);
  end;
end;

procedure TsgCADImage.DrawPoint(Sender: TObject);
var
  vPoint: TsgDXFPointAccess absolute Sender;
  I, IE, J, Cnt, vCount: Integer;
  P, P2: TPoint;
  vPt: TFPoint;
  vPointer: Pointer;
begin
  // Draw only null width
  SetPenWidth(FNullWidth);

  FIntPoints.Count := 0;
  if vPoint.Points = nil then
  begin
    vPt := vPoint.Point;
    P := GetPoint(vPt);
    FIntPoints.Add(P.X);
    FIntPoints.Add(P.Y);
    if Abs(vPoint.ZThick) > fAccuracy then
    begin
      vPt := MakeFPoint(0, 0, vPoint.ZThick);
      if Extruded(vPoint.Extrusion) then
        DoExtrusion(vPt, vPoint.Extrusion);
      vPt.X := vPoint.Point.X + vPt.X;
      vPt.Y := vPoint.Point.Y + vPt.Y;
      vPt.Z := vPoint.Point.Z + vPt.Z;
      P2 := GetPoint(vPt);
      FIntPoints.Add(P2.X + Integer(IsEqualPoints(P, P2)));
      FIntPoints.Add(P2.Y);
    end
    else
    begin
      FIntPoints.Add(P.X + 1);
      FIntPoints.Add(P.Y);
    end;
    ExpPolylineInteger(Sender, FIntPoints.List^[0], FIntPoints.Count shr 1);
    FIntPoints.Count := 0;
  end
  else
  begin
    I := 2;
    vCount := vPoint.Points.Count;
    while I < vCount do
    begin
      Cnt := Integer(vPoint.Points[I]);
      Inc(I);
      J := I;
      Inc(I, Cnt);
      while J < I do
      begin
        P := GetPoint(PFPoint(vPoint.Points[J])^);
        FIntPoints.Add(P.X);
        FIntPoints.Add(P.Y);
        Inc(J);
      end;
      if FIntPoints.Count shr 1 = 1 then // point only
      begin
        FIntPoints.Add(Integer(FIntPoints[0]) + 1);
        FIntPoints.Add(FIntPoints[1]);
      end;
      ExpPolylineInteger(Sender, FIntPoints.List^[0], FIntPoints.Count shr 1);
      FIntPoints.Count := 0;
    end;
    if Abs(vPoint.ZThick) > fAccuracy then
    begin
      vCount := (vPoint.Points.Count - 2) shr 1;
      I := 2;
      IE := I + vCount;
      while I < IE do
      begin
        Cnt := Integer(vPoint.Points[I]);
        Inc(I);
        J := I;
        Inc(I, Cnt);
        while J < I do
        begin
          P := GetPoint(PFPoint(vPoint.Points[J])^);
          FIntPoints.Add(P.X);
          FIntPoints.Add(P.Y);
          P := GetPoint(PFPoint(vPoint.Points[J + vCount])^);
          FIntPoints.Add(P.X);
          FIntPoints.Add(P.Y);
          Inc(J);
        end;
      end;

      vCount := FIntPoints.Count shr 2;
      if vCount <> 0 then
      begin
        Cnt := FIntPoints.Count;
        for I := 0 to vCount - 1 do
          FIntPoints.Add(2);
          vPointer := FIntPoints.List;
          Inc(PInteger(vPointer), Cnt);
          ExpPolyPolylineLists(Sender, FIntPoints, vPointer, vCount);
      end;
      FIntPoints.Count := 0;
    end;
  end;
end;

procedure TsgCADImage.DrawPoly(Sender: TObject);
var
  PLine: TsgCADBasePolyLineAccess absolute Sender;
  PL: TsgDXFPolyLine;
  vDx, vDy: Double;

  procedure DrawPolygonMesh(const M, N: Integer; const APointsList: TFPointList;
    const AIsSolid: Boolean);
  var
    I, J, K, C: Integer;
    vMClosed, vNClosed: Boolean;
    P: PInteger;
    Pt: TPoint;
  begin
    vMClosed := PLine.IsMeshMClosed;
    vNClosed := PLine.IsMeshNClosed or (PLine.Closed and PLine.IsPolyZThickness);
    for I := 0 to APointsList.Count - 1 do
    begin
      Pt := GetPoint(APointsList[I]);
      FPoly.Add(Pt.X);
      FPoly.Add(Pt.Y);
      if AIsSolid and ((I + 1) mod N = 0) and vNClosed then
      begin
        FPoly.Add(FPoly[FPoly.Count - (N shl 1)]);
        FPoly.Add(FPoly[FPoly.Count - (N shl 1)]);// count changed
      end;
    end;
    if AIsSolid or (PLine.IsPolygonMesh and not PLine.IsPolyZThickness)then
    begin
      K := FPoly.Count;
      for I := 0 to N - 1 do
      begin
        J := I shl 1;
        while J < K do
        begin
          FPoly.Add(FPoly[J]);
          FPoly.Add(FPoly[J + 1]);
          Inc(J, N shl 1 + 2 * Ord(vNClosed));
        end;
        if vMClosed then
        begin
          J := I shl 1;
          FPoly.Add(FPoly[J]);
          FPoly.Add(FPoly[J + 1]);
        end;
      end;
      J := FPoly.Count;
      for I := 0 to M - 1 do
        FPoly.Add(N + Ord(vNClosed));
      for I := 0 to N - 1 do
        FPoly.Add(M + Ord(vMClosed));
      K := M + N;
    end
    else
    begin
      if vNClosed or PLine.IsPolyZThickness then
      begin
        C := Round(APointsList.Count / M);
        for J := 1 to M - 1 do
          for I := 0 to C - 1 do
          begin
            K := C * J + I;
            Pt := GetPoint(APointsList[K]);
            FPoly.Add(Pt.X);
	          FPoly.Add(Pt.Y);
            Dec(K, C);
            Pt := GetPoint(APointsList[K]);
            FPoly.Add(Pt.X);
            FPoly.Add(Pt.Y);
          end;
      end;
      J := FPoly.Count;
      K := Round(J / 4);
      for I := 1 to K do
        FPoly.Add(2);
    end;
    P := PInteger(FPoly.List);
    Inc(P, J);
    ExpPolyPolylineLists(Sender, FPoly, P, K);
    (*
    if IsDrawOnBitMap then
    begin
      AddSelectionMatrix(Sender);
      SelectionMatrix.Changed;
      PolyPolyline(SelectionMatrix.Handle, FPoly.List^, P^, K);
    end;
    if IsDrawOnCanvas then
      PolyPolyline(FCanvas.Handle, FPoly.List^, P^, K);
    *)
  end;

  procedure DrawPolyFaceMesh;
  var
    I: Integer;
    vPolyPoints: TsgIntegerList;

    procedure CreateWireframeIndexes(vertexNumber: Integer; APLine: TsgDXFPolyline);
    var
      Index, vMaxIndex, vOldIndex, J: Integer;

      function GetVertexIndex(AItemIndex: Integer): Integer;
      begin
        Result := Integer(PL.PolyFaceVertexIndexes.Items[AItemIndex]);
      end;

      procedure AddEdge(AFirst, ALast, AMaxIndex: Integer; APolyLine: TsgDXFPolyline);
      var
        Pt: TPoint;
      begin
        if ((APolyLine <> nil) and (AFirst > 0) and (Alast <> 0)
          and (AFirst <= AMaxIndex) and (Abs(ALast) <= AMaxIndex)) then
        begin
          Pt := GetPoint(APolyLine.Points[AFirst - 1]);
          FPoly.Add(Pt.X);
          FPoly.Add(Pt.Y);
          Pt := GetPoint(APolyLine.Points[Abs(ALast) - 1]);
          FPoly.Add(Pt.X);
          FPoly.Add(Pt.Y);
          vPolyPoints.Add(2);
        end;
      end;
    begin
      vMaxIndex := PL.PolyPoints.Count;
      vOldIndex := GetVertexIndex(vertexNumber);
      if vOldIndex = 0 then
        Exit;
      for J := 1 to 3 do
      begin
        Index := GetVertexIndex(vertexNumber + j);
        if Index = 0 then
          Break
        else
          AddEdge(vOldIndex, Index, vMaxIndex, APLine);
        vOldIndex := Index;
      end;
      AddEdge(vOldIndex, GetVertexIndex(vertexNumber), vMaxIndex, APLine);
    end;
  begin
    vPolyPoints := TsgIntegerList.Create;
    try
      I := 0;
      while I < PL.PolyFaceVertexIndexes.Count do
      begin
        CreateWireframeIndexes(I, PL);
        Inc(I, 4);
      end;

      ExpPolyPolylineLists(Sender, FPoly, PInteger(vPolyPoints.List), vPolyPoints.Count);
      (*
      if IsDrawOnBitMap then
      begin
        AddSelectionMatrix(Sender);
        SelectionMatrix.Changed;
        PolyPolyline(SelectionMatrix.Handle, FPoly.List^, PInteger(vPolyPoints.List)^, vPolyPoints.Count);
      end;
      if IsDrawOnCanvas then
        PolyPolyline(FCanvas.Handle, FPoly.List^, PInteger(vPolyPoints.List)^, vPolyPoints.Count);
      *)
    finally
      vPolyPoints.Free;
    end;
  end;

  function DrawArrows: Boolean;
  var
    I: Integer;
    Pt: TPoint;
    Arrows: TFPointList;
  begin
    Result := False;
    FPoly.Count := 0;
    Arrows := nil;
    if PL <> nil then
      Arrows := PL.Arrows;
    if (Arrows = nil) or (Arrows.Count <= 3) then
      Exit;
    try
      if FPoly.Capacity < Arrows.Capacity * 2 then
      begin
        try
          FPoly.Capacity := Arrows.Capacity * 2;
        except
          SetListsCapacity(True);
          FPoly.Capacity := Arrows.Capacity * 2;
        end;
      end;
      for I := 0 to Arrows.Count - 1 do
      begin
        Pt := GetPoint(Arrows[I]);
        FPoly.Add(Pt.X);
        FPoly.Add(Pt.Y);
      end;
      DoSetColor(FColor, ctBrush);
      ExpArrowsInternal(Sender, FPoly, PL.IsPolyZThickness);
      Result := True;
    finally
      SetListCapacity(FPoly, False);
    end;
  end;

  procedure DrawPolyLineEntities(APolyLine: TsgDXFPolyline);
  var
    I: Integer;
    vEnt: TsgDXFEntity;
  begin
    if APolyLine.PolyLineEntities = nil then
      Exit;
    for I := 0 to APolyLine.PolyLineEntities.Count - 1 do
    begin
      vEnt := TsgDXFEntity(APolyLine.PolyLineEntities[I]);
      if vEnt is TsgDXFArc then
        DrawArc(TsgDXFArc(APolyLine.PolyLineEntities[I]))
      else
    	if vEnt is TsgDXFLine then
    	  DrawLine(TsgDXFLine(APolyLine.PolyLineEntities[I]));
    end;
  end;

  function IsPolyPathClosed: Boolean;
  begin
    Result := PLine.Closed and (PLine.PolyPoints.Count > 2);
  end;

  procedure BeginPolyPath;
  begin
    if not FIsIterator then
    begin
      if IsDrawOnBitMap then
        BeginPath( SelectionMatrix.Handle);
      if IsDrawOnCanvas then
        BeginPath(FCanvas.Handle);
    end;
  end;

  procedure EndPolyPath;
  begin
    if FIsIterator then
    begin
      //  After calling CloseFuger pdf ceases to show the objects.
      //if Assigned(FsgExpCloseFigure) then
      //  FsgExpCloseFigure;
    end
    else
    begin
      if IsDrawOnBitMap then
      begin
        CloseFigure(SelectionMatrix.Handle);
        EndPath(SelectionMatrix.Handle);
        StrokePath(SelectionMatrix.Handle);
      end;
      if IsDrawOnCanvas then
      begin
        CloseFigure(FCanvas.Handle);
        EndPath(FCanvas.Handle);
        StrokePath(FCanvas.Handle);
      end;
    end;
  end;

  procedure DrawPolyLineReady;
  var
    vClosePath: Boolean;
  begin
    vClosePath := IsPolyPathClosed;
    if vClosePath then
      BeginPolyPath
    else
    begin
      if (FIndex > 1) and NeedToAddOnePixel then
      begin
        FIPoints[FIndex] := FIPoints[FIndex - 1];
        Inc(FIPoints[FIndex].Y);
        Inc(FIndex);
      end;
    end;
    ExpPolylineInteger(Sender, FIPoints, FIndex);
    if vClosePath then
      EndPolyPath;
  end;

  procedure DrawPolyLineExt;
  var
    vLTScale: Single;
    vClosePath: Boolean;
  begin
    if FReady and FEntityLines.IsSolid then
      DrawPolyLineReady
    else
      if FEntityLines.IsSolid then
      begin
        vClosePath := IsPolyPathClosed;
        if vClosePath then
          BeginPolyPath;
        DrawPointsListByPolyline(Sender, PLine.PolyPoints, PLine.Closed);
        if vClosePath then
          EndPolyPath;
        DoPolylineArrow(PL, nil, nil);
      end
      else
      begin
        vLTScale := FEntityLines.Scale;
        try
          if InitializeLineType(PLine) then
          begin
            CalcDottedSingPts(TsgDXFEntity(Sender),
              FEntityLines,
              FDraw.ConvertMatrixCurrentIndertToWCS, FDottedSingPts);
            DrawPointsListByPolyPolyline(Sender, FDottedSingPts, PLine.Closed);
          end
          else
          begin
            DrawPointsListByPolyline(Sender, PLine.PolyPoints, PLine.Closed);
            DoPolylineArrow(PL, nil, nil);
          end;
        finally
          FEntityLines.Scale := vLTScale;
        end;
      end;
  end;

begin
  GetPixelSize(1.5, vdX, vdY, True);
  FPoly.Count := 0;
  if not (Sender is TsgDXFPolyLine) then
    PL := nil
  else
    PL := TsgDXFPolyLine(Sender);
  if PLine.IsPolygonMesh and (PL <> nil) then
    DrawPolygonMesh(PL.MeshM, PL.MeshN, PL.PolyPoints, TsgCADBasePolyLineAccess(Sender).IsPolyPointsSolid)
  else
    if PLine.IsPolyZThickness then
    begin
      if not DrawArrows then
        DrawPolygonMesh(2, PLine.PolyPoints.Count shr 1, PLine.PolyPoints, TsgCADBasePolyLineAccess(Sender).IsPolyPointsSolid);
    end
    else
      if (PL <> nil) and PL.IsPolyFaceMesh then
        DrawPolyFaceMesh
      else
      begin
        DrawPolyLineExt;
        DrawArrows;
      end;
end;

procedure TsgCADImage.DrawACISEntity(Sender: TObject);
begin
  // only for correct calling of  Assigned(E.OnDraw)
  // or for changes in future versions
  DrawComplexEntity(Sender);
end;

procedure TsgCADImage.DrawSpline(Sender: TObject);
var
  vSpline: TsgDXFSpline absolute Sender;
  vLTScale: Double;
begin
  FPoly.Count := 0;
  if vSpline.FitCount > vSpline.ControlCount then
  begin
    DrawPoly(vSpline);
    Exit;
  end;
  if FEntityLines.IsSolid then
    DrawPointsListByPolyline(Sender, vSpline.PolyPoints, vSpline.Closed) //evg
  else
  begin
    vLTScale := FEntityLines.Scale;
    try
      if InitializeLineType(vSpline) then
      begin
        FEntityLines.Curve(vSpline.PolyPoints, FDottedSingPts, vSpline.Closed);
        DrawPointsListByPolyPolyline(Sender, FDottedSingPts, vSpline.Closed);
      end
      else
        DrawPointsListByPolyline(Sender, vSpline.PolyPoints, vSpline.Closed);
    finally
      FEntityLines.Scale := vLTScale;
    end;
  end;
end;

procedure TsgCADImage.DrawSolid(Sender: TObject);
var
  vSolid: TsgDXFSolidAccess absolute Sender;
  vHasZTick: Boolean;
  I, vCount, vCount1, vCount2: Integer;
  vSolids, vSolidsZ: array[0..4] of TPoint;
  vPts: TsgPoints4;

  function IsDrawingZ(const ACoodrZ: Double): Boolean;
  var
    vDistanceZ: Double;
    vPlaneXYVect: TFPoint;
  begin
    Result := False;
    if ACoodrZ > fDoubleResolution then
    begin
      vPlaneXYVect := PtXScalar(FDraw.Matrix.EZ, ACoodrZ);
      vDistanceZ := DistanceVector2D(vPlaneXYVect.X, vPlaneXYVect.Y);
      Result := Abs(vDistanceZ) > fAccuracy;
    end;
  end;

  function CalcNormal(const AP1, AP2, AP3: TFPoint{; var ALen: Double}): TFPoint;
  var
    v1, v2: TFPoint;
  begin
    v1 := SubFPoint(AP2, AP1);
    v2 := SubFPoint(AP3, AP1);
    Result := sgFunction.Vector(v1, v2);
    //ALen := DistanceFVector(Result);
  end;

  function IsSolidCollinearToView(const APoints4: TsgPoints4): Boolean;
  var
    //vLen: Double;
    vNormal, vView: TFPoint;
  begin
    vNormal := Ort(CalcNormal(APoints4[0], APoints4[1], APoints4[2]{, vLen}));
    vView := Ort(FDraw.Matrix.EZ);
    Result := IsEqualFPoints(vNormal, vView) or
      IsEqualFPoints(vNormal, Reverse(vView));
  end;

  function GetPoints(var APoints: array of TPoint; ACount: Integer;
    const APoints4: TsgPoints4): Integer;
  var
    P: TPoint;
    I, J: Integer;
  begin
    Result := ACount;
    I := 0;
    P := GetPoint(APoints4[I mod ACount]);
    APoints[I] := P;
    Inc(I);
    J := I;
    repeat
      APoints[J] := GetPoint(APoints4[I mod ACount]);
      if IsEqualPoints(P, APoints[J]) then
        Dec(Result)
      else
      begin
        P := APoints[J];
        Inc(J);
      end;
      Inc(I);
    until I >= ACount;
    APoints[Result] := APoints[0];
    Inc(Result);
  end;

begin
  SetPenWidth(1);
  DoSetColor(FColor, ctBrush);
  if Sender is TsgDXFImageEnt then
    DoSetColor(FColor, ctBrushClear);
  vCount := vSolid.GetPoints(vPts);
//  if FReady then
//    CopyMemory(@vPts, @FIPoints, SizeOf(TPoint) * 4);
  vHasZTick := False;
  if (Abs(vSolid.ZThick) > fAccuracy) or
     IsDrawingZ(Max(Abs(vSolid.ZThick), Abs(vPts[0].Z))) then
    if not IsSolidCollinearToView(vPts) then
    //if IsRotatedFMat(FDraw.Matrix, True) then//change in future version(check only view matrix)
    begin
      vHasZTick := not FIsIterator;//true;
    end;
  if vCount = 4 then
    SwapFPoints(vPts[2], vPts[3]);
  vCount1 := GetPoints(vSolids, vCount, vPts);
  vCount2 := 0;
  if vHasZTick then
  begin
    for I := 0 to vCount - 1 do
      vPts[I].Z := vPts[I].Z + vSolid.ZThick;
    vCount2 := GetPoints(vSolidsZ, vCount, vPts);
  end;
  ExpSolidInternal(Sender, Slice(vSolids, vCount1), Slice(vSolidsZ, vCount2), vHasZTick);
end;

type                              //evg
  PPoints = ^TPoints;
  TPoints = array[0..0] of TPoint;

procedure TsgCADImage.DrawImage(Sender: TObject);
var
  vImageEnt: TsgDXFImageEntAccess absolute Sender;
  vPts: array [0..4] of TPoint;
  vAngle, vAngleY: Double;
  R: Integer;
  vGraphic: TGraphic;

  procedure GetPointAndAngle;
  begin
    vPts[0] := GetPoint(vImageEnt.Point);
    vPts[1] := GetPoint(vImageEnt.Point1);
    vPts[2] := GetPoint(vImageEnt.Point3);
    vPts[3] := GetPoint(vImageEnt.Point2);
    vPts[4] := vPts[0];
    GetAngles(vImageEnt, vAngle, vAngleY);
  end;

begin
  if (vImageEnt.Picture = nil) or (ShowImages = False) then
    Exit;
  GetPointAndAngle;

  if IsDrawOnBitMap and (not vImageEnt.Internal) then
  begin
    AddSelectionMatrix(Sender);
    SelectionMatrix.Brush.Style := bsSolid;
    SelectionMatrix.Changed;
    Polygon(SelectionMatrix.Handle, vPts, 4);
    SelectionMatrix.Brush.Style := bsClear;
  end;
  CheckRastrByFastMode(vImageEnt, vGraphic, vPts);

{$IFDEF SG_USEGDIPLUS}
  if FLibraryGDIPlusExists and bUseGDIPlusForRastImgRotate and
    ( FIsIterator or not CheckOrthoRaster(vAngle) or (vGraphic is TMetafile) or
      vImageEnt.Transparency or (not IsDrawGDI(vAngle, vAngleY))) then
  begin
    DrawImageGDIPlus(vImageEnt, vPts);
  end
  else
{$ENDIF}
  begin
    Inc(FIRect.Right);
    Inc(FIRect.Bottom);
    R := (Round(vAngle) div 90) * 90;
    if R <> 0 then
    begin
      // rotate must be implemented to initialize ... if you need a show GDI
    end;
    if CheckOrthoRaster(vAngle) then
    begin
      DrawImageGDI(vImageEnt, vGraphic, vPts);
    end
    else
      ExpPolylineInteger(nil, PPoints(@vPts)^, High(vPts) + 1);
  end;
end;

{$IFDEF SG_USEGDIPLUS}
procedure TsgCADImage.DrawTilesImage(const AGraphics: TsgGDIPlusGraphics;
   const AImgEnt: TsgDXFImageEnt;
   const APoints: array of TPoint;
   const ImageAttributes: TsgGDIPlusImageAttributes = nil);
var
  vPts: array [0..3] of TPoint;
  vImgEnt: TsgDXFImageEntAccess absolute AImgEnt;
  vDpi: TFPoint;
  I,J, IMax, JMax: Integer;
  vCountParts: TPoint;
  vSmallWidth, vSmallHeight, vSmallWidthCorrect, vSmallHeightCorrect: Integer;
  vRect: TRect;
  vP: TPoint;
  ASmall, ABitmapSmall: TPoint;
  vAngle, vAngleY: Double;
  vPoint, vPoint1, vPoint2, vPoint3, vTempPoint: TPoint;
  vH, vW: Integer;
  vBitmapSmall, vBitmapBig: TBitmap;
  vTransferImage: TsgBitmap;
  vBitmap: TsgBitmapAccess;
  vFGDIPImage: TsgGDIPlusImage;

  function GetCountBlocks(const AWidth, AHeight: Integer;
    const APixelFormat: Graphics.TPixelFormat): Integer;
  const
    cnstBPPs: array[Graphics.TPixelFormat] of Byte = (24,1,4,8,16,16,24,32,0);
    cnstMax = 555;
  begin
    Result := Ceil(MaxI(AWidth, AHeight) / cnstMax);
    if Result = 0 then
      Result := 1;
  end;

begin
  vPts[0] := APoints[0];// GetPoint(AImgEnt.Point);
  vPts[1] := APoints[1];// GetPoint(AImgEnt.Point1);
  vPts[2] := APoints[2];// GetPoint(AImgEnt.Point3);
  vPts[3] := APoints[3];// GetPoint(AImgEnt.Point2);

  vAngle := GetAngleByPoints(GetFPoint(AImgEnt.Point), GetFPoint(AImgEnt.Point1),
    False, fDoubleResolution ,1, -1);
  vAngleY :=  GetAngleByPoints(GetFPoint(AImgEnt.Point), GetFPoint(AImgEnt.Point2),
    False, fDoubleResolution, 1, -1);

  vW := vImgEnt.Picture.Graphic.Width;
  vH := vImgEnt.Picture.Graphic.Height;

  vDpi := MakeFPoint((DistancePoint(vPts[0],vPts[1]) / vW),
                      (DistancePoint(vPts[0],vPts[3]) / vH));

  vP := vPts[0];
  IMax := Ceil(Sqrt(GetCountBlocks(vW, vH, pf8bit)));
  JMax := IMax;

  vCountParts := Point(IMax - 1, JMax - 1);
  vSmallWidth := vW div IMax;
  vSmallHeight := vH div JMax;
  if (vW mod vSmallWidth) > 0 then
    Inc(vCountParts.X);
  if (vH mod vSmallHeight) > 0 then
    Inc(vCountParts.Y);

  vBitmap := TsgBitmapAccess(TsgBitmap.Create);
  try
    vBitmap.Assign(AImgEnt.Picture.Graphic);
    vBitmapBig := TBitmap.Create;
    try
      vBitmapBig.PixelFormat := vBitmap.PixelFormat;
      vBitmapBig.Width := vBitmap.Width;
      vBitmapBig.Height := vBitmap.Height;
      vBitmap.FROP := SRCCOPY;
      vBitmapBig.Canvas.StretchDraw(vBitmapBig.Canvas.ClipRect, vBitmap);

      for I := 0 to vCountParts.X do
      begin
        for J := 0 to vCountParts.Y do
        begin
          vRect.Left := I * vSmallWidth;
          vRect.Top := J * vSmallHeight;
          vRect.Right := vRect.Left + vSmallWidth;
          vRect.Bottom := vRect.Top + vSmallHeight;
          if I = vCountParts.X then
            vRect.Right := vRect.Left + vW - I * vSmallWidth;
          if J = vCountParts.Y then
            vRect.Bottom := vRect.Top + vH - J * vSmallHeight;

          vSmallWidthCorrect := vRect.Right - vRect.Left;
          vSmallHeightCorrect := vRect.Bottom - vRect.Top;



          ASmall :=    Point(vSmallWidth,vSmallHeight);
          ABitmapSmall :=   Point(vSmallWidthCorrect, vSmallHeightCorrect);

          // Find Point2
          vTempPoint := GetPointOnCircleI(vP, I * ASmall.X * vDpi.X, 360 - vAngle);
          vPoint2 := GetPointOnCircleI(vTempPoint, vH* vDpi.Y - J * ASmall.Y * vDpi.Y, 360 - vAngleY);
          vPoint  := GetPointOnCircleI(vPoint2, ABitmapSmall.Y * vDpi.Y, 180 - vAngleY);
          vPoint1 := GetPointOnCircleI(vPoint, ABitmapSmall.X * vDpi.X, 360 - vAngle);
          // Point3
          vPoint3 := GetPointOnCircleI(vPoint2, ABitmapSmall.X * vDpi.X, 360 - vAngle);

          vPts[0] := vPoint2;
          vPts[1] := vPoint3;
          vPts[2] := vPoint;

          vBitmapSmall := TBitmap.Create;
          try
            vBitmapSmall.PixelFormat := vBitmapBig.PixelFormat;
            vBitmapSmall.Width := vSmallWidthCorrect;
            vBitmapSmall.Height := vSmallHeightCorrect;
            BitBlt(vBitmapSmall.Canvas.Handle,
                    0, 0, vBitmapSmall.Width, vBitmapSmall.Height,
                    vBitmapBig.Canvas.Handle, vRect.Left, vRect.Top, SRCCOPY);
            vTransferImage := TsgBitmap.Create;
            try
              vTransferImage.Assign(vBitmapSmall);
              vFGDIPImage := TsgGDIPlusImage(TsgGDIPlusBitmap.Create(vTransferImage.ImageData.Info,
                vTransferImage.ImageData.Data));
              try
                if ImageAttributes = nil then
                begin
                  AGraphics.DrawImage(vFGDIPImage, PsgGPoint(@vPts[0]), 3,
                  0, 0,
                  vSmallWidthCorrect, vSmallHeightCorrect);
                end
                else
                begin
                  AGraphics.DrawImage(vFGDIPImage, PsgGPoint(@vPts[0]), 3,
                  0, 0,
                  vSmallWidthCorrect, vSmallHeightCorrect, ImageAttributes);
                end;
              finally
                vFGDIPImage.Free;
              end;
            finally
              vTransferImage.Free;
            end;
          finally
            vBitmapSmall.Free;
          end;
        end;
      end;
    finally
      vBitmapBig.Free;
    end;
  finally
    vBitmap.Free;
  end;
end;
{$ENDIF}

procedure TsgCADImage.DrawImageGDIPlus(const AImgEnt: TsgDXFImageEnt;
   const APoints: array of TPoint);
{$IFDEF SG_USEGDIPLUS}
var
  vPts: array [0..3] of TPoint;
  vImgEnt: TsgDXFImageEntAccess absolute AImgEnt;
  vGraphics: TsgGDIPlusGraphics;
  vAttr: TsgGDIPlusImageAttributes;
  vH, vW: Integer;
  vTransparentColor: Cardinal;
{$ENDIF}
begin
  if FIsIterator then
  begin
     if Assigned(FsgExpImageUV) then
      FsgExpImageUV(APoints[0], APoints[1], APoints[2], APoints[3], AImgEnt.Picture.Graphic);
  end
  else
  begin
{$IFDEF SG_USEGDIPLUS}
    if vImgEnt.FGDIPImage = nil then
      vImgEnt.GDIPCreate;
    if vImgEnt.FGDIPImage <> nil then
    begin
      vPts[0] := APoints[3];
      vPts[2] := APoints[0];
      vPts[1] := AddPoint(APoints[1], SubPoint(vPts[0], vPts[2]));
      vGraphics := TsgGDIPlusGraphics.Create(FCanvas.Handle);
      try
        vGraphics.InitParams;
        try
          if (vImgEnt.Picture.Graphic is TsgBitMap) and (vImgEnt.Transparency
            or (TsgBitmapAccess(vImgEnt.Picture.Graphic).FROP <> SRCCOPY)) then
          begin
            vAttr := TsgGDIPlusImageAttributes.Create;
            try
              vTransparentColor := ColorRefToARGB(vImgEnt.TransparentColor);
              vAttr.SetColorKey(vTransparentColor, vTransparentColor,
                ColorAdjustTypeBitmap);
              vW := vImgEnt.Picture.Graphic.Width;
              vH := vImgEnt.Picture.Graphic.Height;
              if vGraphics.DrawImage(vImgEnt.FGDIPImage, PsgGPoint(@vPts[0]), 3, 0, 0, vW, vH, vAttr) = OutOfMemory then
              begin
                DrawTilesImage(vGraphics, vImgEnt, APoints, vAttr);
              end;
            finally
              vAttr.Free;
            end;
          end
          else
            begin
              if vGraphics.DrawImage(vImgEnt.FGDIPImage, PsgGPoint(@vPts[0]), 3) = OutOfMemory then
              begin
                DrawTilesImage(vGraphics, vImgEnt, APoints);
              end;
            end;
        except
        end;
      finally
        vGraphics.Free;
      end;
    end
    else
{$ENDIF}
      FCanvas.Polyline(APoints);
  end;
end;

procedure TsgCADImage.FillFromFlat(FP: TsgFlatEntity);
var
  I: Integer;
  P: TPoint;
begin
  if FPoly.Capacity < FP.Points.Count then
    FPoly.Capacity := FP.Points.Count;
  FPoly.Count := 0;
  for I := 0 to FP.PCount-1 do
  begin
    P := GetPoint(FP.XY[I]);
    FPoly.Add(P.X);
    FPoly.Add(P.Y);
  end;
end;

procedure TsgCADImage.DrawFlatPoly(Sender: TObject);
var
  FP: TsgFlatPoly absolute Sender;
  vdX, vdY: Double;

  procedure DrawFlatPolyExt;
  var
    I: Integer;
    P0: PPoint;
  begin
    P0 := PPoint(FPoly.List);
    for I := 0 to FP.Counts.Count-1 do
    begin
      ExpPolylineInteger(Sender, P0^, Integer(FP.Counts[I]));
      Inc(P0, Integer(FP.Counts[I]));
    end;
  end;

  procedure DrawFlatPoly3D;
  var
    I: Integer;
    P: TPoint;
  begin
    for I := 0 to FP.PCount-1 do
    begin
      P := GetPoint(FP.XY[I]);
      FPoly.Add(P.X);
      FPoly.Add(P.Y);
    end;
   DrawFlatPolyExt;
  end;

   {$IFDEF SG_HIDDEN}
      {$INCLUDE HIDDEN3.INC}
   {$ENDIF}

begin
  FCounts.Count := 0;
  FPoly.Count := 0;
  GetPixelSize(1.5, vdX, vdY, True);
  if Sender is TsgFlatPoly3D then
    DrawFlatPoly3D
  else
  begin
  {$IFDEF SG_HIDDEN}
    FillFromFlatExt(FP);
    ExpPolyPolylineLists(Sender, FPoly, FCounts.List, FCounts.Count);
    {$ELSE}
    FillFromFlat(FP);
    DrawFlatPolyExt;
   {$ENDIF}
  end;
end;

procedure TsgCADImage.DrawFlatHatch(Sender: TObject);
var
  FH: TsgFlatHatch absolute Sender;
  procedure DrawHatchExt(const ACanvas: TCanvas);
  var
    PI: PInteger;
    PP: PPoint;
    I, vCounts, vBoundariesCount, vBoundariesPointsCount: Integer;
  begin
    PP := PPoint(FPoly.List);
    PI := PInteger(FH.Counts.List);
    I := 0;
    vCounts := 1;
    while I < FH.Counts.Count do
    begin
      vBoundariesCount := FH.Counts[I];
      Inc(I);
      if vBoundariesCount = 0 then
        Exit;
      Inc(PI, vCounts);
      ExpPolyPolygonInteger(Sender, PP^, PI^, vBoundariesCount);
      Inc(I, vBoundariesCount);
      vBoundariesPointsCount := FH.Counts[I];
      Inc(I);
      Inc(PP, vBoundariesPointsCount);
      vCounts := 2 + vBoundariesCount;
    end;
  end;
begin
  DoSetColor(FColor, ctBrush);
  FillFromFlat(FH);
  DrawHatchExt(FCanvas);
end;

procedure TsgCADImage.DrawShape(Sender: TObject);
begin
  if not IsBadRect(TsgDXFEntity(Sender).Box) then
    DrawText(Sender);
end;

procedure TsgCADImage.DrawText(Sender: TObject);
var
  P: TFPoint;
  S: string;
  vScale: Double;
  vRect: TRect;
  vBox: TFRect;
  vP: TPoint;
  vCounts: TsgIntegerList;
  vIntPoints: TsgIntegerList;
  vMatrix: TFMatrix;
  vSender: TsgDXFText;
  vPrevDraw: TsgCADIterate;
  vIsDrawOnCanvas, vIsDrawOnBitMap: Boolean;

  procedure TxtOut;
  var
    vTextGlyph: TsgTextGlyph;
    vPts: array[0..3] of TFPoint;
    vIntPts: array[0..3] of TPoint;
    vIndex: Integer;
    vUnicodeText: WideString;
    vFillText: Boolean;
//{$IFNDEF SGDEL_6}
    vTextFlags: Integer;
//{$ENDIF}

    procedure DrawTextExt;
    var
      vGlyphBox: TFRect;
      vPtsList: TsgIntegerList;
      vWidth, vDeltaWidth: Double;
      I: Integer;

      procedure InitPts(AIndex: Integer; ABox: PFRect);
      var
        vWidthCur: Integer;
        Pt1, Pt2: TFPoint;
      begin
        Pt1 := FPointXMat(MakeFPoint(ABox.Left, ABox.Bottom, ABox.Z1), vMatrix);
        Pt2 := FPointXMat(ABox.BottomRight, vMatrix);
        vWidth := DistanceFPoint(Pt1, Pt2);
        vWidthCur := Floor(vWidth);
        vDeltaWidth := vDeltaWidth + vWidth - vWidthCur;
        if vDeltaWidth > 0.99 then
        begin
          Inc(vWidthCur);
          vDeltaWidth := vDeltaWidth - 1;
        end;
        vPtsList[AIndex] := vWidthCur;
      end;

    begin
      vRect.TopLeft := GetPoint(vBox.TopLeft);
      vRect.BottomRight := GetPoint(vBox.BottomRight);
      if (Length(vUnicodeText) > 0) and (Integer(vUnicodeText[1]) shr 8 >= $50) then
      begin
        vSender.Font.Height := Abs(Round(vTextGlyph.HKoef * vSender.Height * FHCoef));
        DoSetFont(vSender.Font);
      end;
      DoSetColor(FColor, ctFont);
       // FCanvas.Font.Height := Round(vRect.Top - vRect.Bottom);
      vPtsList := TsgIntegerList.Create;
      try
        vDeltaWidth := 0;
        if Length(vUnicodeText) = 0 then
        begin
          vPtsList.Count := Length(S);
          for I := 1 to vPtsList.Count do
          begin
            vGlyphBox := vTextGlyph.GetBox(S[I], @cnstIdentityMat, nil);
            InitPts(I - 1, @vGlyphBox);
          end;
{$IFDEF UNICODE}
          ExpTextInteger(ttTextOutW, Round(P.X), Round(P.Y), vTextFlags,
            @vRect, PWideChar(S), nil, Length(S), @vPtsList.List[0]);
{$ELSE}
          ExpTextInteger(ttExTextOut, Round(P.X), Round(P.Y), vTextFlags,
            @vRect, nil, PAnsiChar(S), Length(S), @vPtsList.List[0]);
{$ENDIF}
        end
        else
        begin
          vPtsList.Count := Length(vUnicodeText);
          for I := 1 to vPtsList.Count do
          begin
            vGlyphBox := vTextGlyph.GetBoxW('', vUnicodeText[I], @cnstIdentityMat, nil);
            InitPts(I - 1, @vGlyphBox);
          end;
          ExpTextInteger(ttExtTextOutW, Round(P.X), Round(P.Y), vTextFlags,
             @vRect, PWideChar(vUnicodeText), '', Length(vUnicodeText), @vPtsList.List[0]);
        end;
      finally
        vPtsList.Free;
      end;
    end;

  begin
    vTextFlags := 0;
    if Win32Platform = VER_PLATFORM_WIN32_NT then
      vUnicodeText := vSender.UnicodeText
    else
      vUnicodeText := '';
    DoSetColor(FColor, ctBrushClear);
    if not FExportToDXFMode then
      vIndex := ContainerOfTextGlyphs.IndexOf(vSender.Font.Name, TFontStyles(vSender.Font.Style) {FCanvas.Font.Style})
    else // only for export to DXF mode (not for use in future versions)
      vIndex := -1;
    if vIndex > -1 then
    begin
      vTextGlyph := ContainerOfTextGlyphs.TextGlyph[vIndex];
      vMatrix := FMatXMat(vSender.GetMatrix, FDraw.Matrix);
      if not IsIterator and (FCanvas.Font.Height < 2) then
      begin
        if IsBadRect(vBox) then Exit;
        vBox := vTextGlyph.GetBoxW(S, vUnicodeText, @cnstIdentityMat, nil);
        vPts[0] := FPointXMat(vBox.TopLeft, vMatrix);
        vPts[1] := FPointXMat(MakeFPoint(vBox.Right, vBox.Top, 0), vMatrix);
        vPts[2] := FPointXMat(vBox.BottomRight, vMatrix);
        vPts[3] := FPointXMat(MakeFPoint(vBox.Left, vBox.Bottom, 0), vMatrix);
        vIntPts[0] := Point(Round(vPts[0].X), Round(vPts[0].Y));
        vIntPts[1] := Point(Round(vPts[1].X), Round(vPts[1].Y));
        vIntPts[2] := Point(Round(vPts[2].X), Round(vPts[2].Y));
        vIntPts[3] := Point(Round(vPts[3].X), Round(vPts[3].Y));
        if vIsDrawOnBitMap then
          Windows.Polygon(SelectionMatrix.Handle, vIntPts, 4);
        if vIsDrawOnCanvas then
        begin
          DoSetColor(FColor, ctBrush);
          FCanvas.Polygon(vIntPts);
        end;
      end
      else
      begin
        vSender.Font.Height := Abs(Round(vTextGlyph.HKoef * vSender.Height * FHCoef));
        vSender.Font.Width := 0;
        vSender.Font.HandleNeeded;
        DoSetFont(vSender.Font);
        ApplyText;
        DoSetColor(FColor, ctFont);
        if vIsDrawOnBitMap then
        begin
          SelectionMatrix.Pen.Width := 0;
          SelectionMatrix.Brush.Color := SelectionMatrix.Pen.Color;
          SelectionMatrix.Changed;
          vTextGlyph.DrawTextExtW(SelectionMatrix.Handle, vSender.Font.Style, S, vUnicodeText, @vMatrix);
          SelectionMatrix.Brush.Style := bsClear;
        end;
        if vIsDrawOnCanvas then
        begin
          case TTFMode of
            ttfGDI:           DrawTextExt;
            ttfPolyPolyline:
              begin
                vFillText := vTextGlyph.FillText;
                try
                  vTextGlyph.FillText := False;
                  ExpTextInternal(Sender,vTextGlyph, S, vUnicodeText, @vMatrix);
                finally
                  vTextGlyph.FillText := vFillText;
                end;
              end;
            ttfPolyPolygon:
                ExpTextInternal(Sender,vTextGlyph, S, vUnicodeText, @vMatrix)
          else
            if IsRotatedText(vSender, vMatrix) then
              ExpTextInternal(Sender,vTextGlyph, S, vUnicodeText, @vMatrix)
            else
              DrawTextExt;
          end;
          if not FIsIterator then
            FColorBrush := FCanvas.Brush.Color; //evg vTextGlyph.DrawTextExtW changes FCanvas.Brush.Color
        end;
      end;
    end
    else
    begin
      if (vSender.Font.Height < 2) and not FExportToDXFMode and not IsIterator then
      begin
        if IsBadRect(vBox) then Exit;
        vRect.TopLeft := GetPoint(vBox.TopLeft);
        vRect.BottomRight := GetPoint(vBox.BottomRight);
        if vRect.Left > vRect.Right then
          SwapInts(vRect.Left, vRect.Right);
        if vRect.Top > vRect.Bottom then
          SwapInts(vRect.Top, vRect.Bottom);
        vP := Point(Round(P.X), Round(P.Y));
        if vIsDrawOnBitMap then
        begin
          if vSender.Font.Escapement = 0 then
            Rectangle(SelectionMatrix.Handle, vP.X,
              vP.Y, vP.X + (vRect.Right-vRect.Left) , vP.Y + (vRect.Bottom-vRect.Top))
          else
          begin
            MoveToEx(SelectionMatrix.Handle, vP.X, vP.Y, nil);
            LineTo(SelectionMatrix.Handle,
              Round(vP.X + (vRect.Right-vRect.Left)*Cos(vSender.Font.Escapement*0.1)),
              Round(vP.Y - (vRect.Bottom-vRect.Top)*Sin(vSender.Font.Escapement*0.1)));
          end;
        end;
        if vIsDrawOnCanvas then
        begin
          if vSender.Font.Escapement = 0 then
            FCanvas.Rectangle(vP.X, vP.Y, vP.X + (vRect.Right-vRect.Left) , vP.Y + (vRect.Bottom-vRect.Top))
          else
          begin
            FCanvas.MoveTo(vP.X, vP.Y);
            FCanvas.LineTo(Round(vP.X + (vRect.Right-vRect.Left)*Cos(vSender.Font.Escapement*0.1)),
              Round(vP.Y - (vRect.Bottom-vRect.Top)*Sin(vSender.Font.Escapement*0.1)));
          end;
        end;
      end
      else
      begin
        if vIsDrawOnBitMap then
        begin
          if Length(vUnicodeText) = 0 then
            TextOut(SelectionMatrix.Handle, Round(P.X), Round(P.Y), PChar(S), Length(S))
          else
            TextOutW(SelectionMatrix.Handle, Round(P.X), Round(P.Y), PWideChar(vUnicodeText), Length(vUnicodeText));
        end;
        if vIsDrawOnCanvas then
        begin
          DoSetColor(FColor, ctFont);
          if Length(vUnicodeText) = 0 then
{$IFDEF UNICODE}
            ExpTextInteger(ttTextOutW, Round(P.X), Round(P.Y), 0, nil, PWideChar(S), nil, Length(S), nil)
{$ELSE}
            ExpTextInteger(ttTextOut, Round(P.X), Round(P.Y), 0, nil, nil, PAnsiChar(S),  Length(S), nil)
{$ENDIF}
          else
            ExpTextInteger(ttTextOutW, Round(P.X), Round(P.Y),0, nil, PWideChar(vUnicodeText), '', Length(vUnicodeText), nil);
        end;
      end;
    end;
  end;

  procedure TextDrawByPolyPolyline;
  var
    vPts: PInteger;
    I, CntI, Cnt: Integer;
  begin
    CntI := vCounts.Count - 1;
    vPts := PInteger(vIntPoints.List);
    for I := 0 to CntI do
    begin
      Cnt := Integer(vCounts.List[I]);
      if (Cnt = 2) and (vPts^ = PInteger(TsgNativeUInt(vPts) + 8)^) and
        (PInteger(TsgNativeUInt(vPts) + 4)^ = PInteger(TsgNativeUInt(vPts) + 12)^) then
        ExpPixelInteger(Sender, Point(vPts^, PInteger(TsgNativeUInt(vPts) + 4)^), FColor)
      else
        ExpPolylineInteger(vSender, vPts^, Cnt);
      Inc(vPts, Cnt shl 1);
    end;
  end;


begin
  if not FTextVisible then
    Exit;
  vSender := TsgDXFText(Sender);
  vIsDrawOnBitMap := IsDrawOnBitMap;
  vIsDrawOnCanvas := IsDrawOnCanvas;
  if vIsDrawOnBitMap then
  begin
    AddSelectionMatrix(Sender);
    SelectionMatrix.FontColor := SelectionMatrix.Pen.Color;
    SelectionMatrix.Changed;
  end;
  vPrevDraw := FDraw;
  try
    P := FPointXMat(vSender.StartPoint, FDraw.Matrix);
    S := vSender.Text;
    vScale := vSender.Scale;
    vBox := vSender.Box;
    if (vScale = 0) or vSender.IsEmpty then
      Exit;
    DoScale2D(FDraw);
    if FDraw.XScale = 0 then Exit;
    if not FIsIterator then
      vSender.Font.PixelsPerInch := FCanvas.Font.PixelsPerInch;
    vSender.Font.Height :=  Abs(Round(fWinTextHeightFactor * Abs(vSender.Height) * FHCoef));
    vSender.Font.Width := Abs(Round(0.64 * Abs(vSender.Height) * vScale * FHCoef));
    if vSender.Font.Height = 0 then
      vSender.Font.Height := 1;
    if TTFMode = ttfGDI then
      if Sender is TsgDXFAttdef then
        vSender.Font.Escapement := Round(10 * vSender.Rotation)
      else
        vSender.Font.Escapement := Round(10 * (vSender.Rotation - FAngle));

    vSender.Font.HandleNeeded;
//    evg:
    DoSetFont(vSender.Font);
    ApplyText;
    if Converter.UseSHXFonts and (not vSender.WinFont) then
    begin
      //FIntPoints.Count := 0;
      vIntPoints := TsgIntegerList.Create;
      vCounts := TsgIntegerList.Create;
      try
        vSender.GetSHXLinesEx(SHXFontsProc, nil, @FDraw.Matrix, vIntPoints, vCounts, Converter.CodePage);
        if vIntPoints.Count > 0 then
        begin
         DoSetColor(FColor, ctPen);
         TextDrawByPolyPolyline;
        end
        else
          TxtOut;
      finally
        //FIntPoints.Count := 0;
        vIntPoints.Free;
        vCounts.Free;
      end;
    end
    else
      TxtOut;
  finally
    FDraw := vPrevDraw;
    if not FIsIterator then
      FPenWidth := FCanvas.Pen.Width; // evg: text draw in ttf.pas changes pen.width
  end;
end;

procedure TsgCADImage.EndRead(Sender: TObject);
begin
  if not Assigned(OnProgress) then
    Exit;
  DoProgress(psEnding);
  FMsg := sLoadEntities;
end;

procedure TsgCADImage.EnterInsert(Sender: TObject);
var
  Ins: TsgDXFInsert absolute Sender;
begin
  if FOnInsert = Sender then
    FOnInsertMode := False;
  if (Ins is TsgCADClipInsert) then
  begin
    if FIsIterator then
      ExpRestoreDCInternal(nil,0)
    else
    begin
      if IsDrawOnBitMap then
      begin
        SelectClipRgn(SelectionMatrix.Handle, FClipRegion);
        GetclipBox(SelectionMatrix.Handle, FDrawRect);
      end;
      if not FSnapOnlyIterate and IsDrawOnCanvas then
        SetSelectClipRgn(FClipRegion);
    end;
  end;
end;

procedure TsgCADImage.EnterComplexEntity(Sender: TObject);
begin
  if FOnComplexEntity = Sender then
    FOnComplexEntity := nil;
end;

procedure TsgCADImage.EnterViewport(Sender: TObject);
begin
  if not TsgDXFViewport(Sender).IsDraw  then
    Exit;
  if FViewPortCanvasParams <> nil then
  begin
    DeleteObject(FViewPortRegion);
    ExpRestoreDCInternal(Sender, FViewPortCanvasParams^.HDC); //RestoreDC(FCanvas.Handle, FViewPortCanvasParams^.HDC);
    DoSetColor(FViewPortCanvasParams^.CanvasParams.Brush.Color, ctBrush);
    DoSetColor(FViewPortCanvasParams^.CanvasParams.Pen.Color, ctPen);
    DoSetColor(FViewPortCanvasParams^.CanvasParams.Font.Color, ctFont);
    SetPenWidth(1);
    FViewPortCanvasParams^.CanvasParams.Brush.Free;
    FViewPortCanvasParams^.CanvasParams.Font.Free;
    FViewPortCanvasParams^.CanvasParams.Pen.Free;
    Dispose(FViewPortCanvasParams);
    FViewPortCanvasParams := nil;
    if IsDrawOnBitMap then
      SelectionMatrix.RestoreClipRGN;
  end;
end;

procedure TsgCADImage.EnterXRef(Sender: TObject);
begin
  FSHXFontsProc := GetSHXFontsProc;
  FGetSelectionMatrixModeProc := GetSelectionMatrixProc;
  FSetSelectionMatrixModeProc := SetSelectionMatrixProc;
  if FXrefStack.Count > 0 then
    FXrefStack.Delete(FXrefStack.Count - 1);
end;

procedure TsgCADImage.EntityCreated(Sender: TObject);
// Called from Converter after each entity is loaded from DXF
// In the previous versions a drawing procedure was assigned to the entity here
begin
  // SetDraw(TsgDXFEntity(Sender));
end;


procedure TsgCADImage.GetAngles(const AImageEnt: TsgDXFImageEnt; var Angle1,
  Angle2: Double);
var
  vP1, vP2, vP3: TFPoint;
begin
  vP1 := GetFPoint(AImageEnt.Point);
  vP2 := GetFPoint(AImageEnt.Point1);
  vP3 := GetFPoint(AImageEnt.Point2);
  Angle1 := GetAngleByPoints(vP1, vP2, False, fDoubleResolution ,1, -1);
  Angle2 :=  GetAngleByPoints(vP1, vP3, False, fDoubleResolution, 1, -1);
end;

function TsgCADImage.GetBackgroundColor: TColor;
begin
  Result := FBackgroundColor;
end;

function TsgCADImage.GetBlock(Index: Integer): TsgDXFBlock;
begin
  Result := FConverter.Blocks[Index];
end;

function TsgCADImage.GetEntity(Index: Integer): TsgDXFEntity;
begin
  Result := FConverter.Entities[Index];
end;

function TsgCADImage.GetIsLoading: Boolean;
begin
  Result := Loading <> nil;
end;

function TsgCADImage.GetShowLineWeight: Boolean;
begin
  Result := FisShowLineWeight;
end;

function TsgCADImage.GetLayout(Index: Integer): TsgDXFLayout;
begin
  Result := FConverter.Layouts[Index];
end;

function TsgCADImage.GetLayoutsCount: Integer;
begin
  Result := FConverter.LayoutsCount;
end;

function TsgCADImage.GetLineWeightScale: TsgFloat;
begin
  Result := FLineWeightScale;
end;

function TsgCADImage.GetOwnSource: Boolean;
begin
  Result := Converter.OwnSource;
end;

function TsgCADImage.GetRect(const ARect: TFRect): TRect;
  procedure ExpRect(const X, Y, Z: TsgFloat);
  begin
    ExpandRect(Result, GetPoint(MakeFPoint(X, Y, Z)));
  end;
begin
  Result := Classes.Rect(MaxInt, MaxInt, -MaxInt, -MaxInt);
  ExpRect(ARect.Left, ARect.Top, ARect.Z1);
  ExpRect(ARect.Left, ARect.Top, ARect.Z2);
  ExpRect(ARect.Left, ARect.Bottom, ARect.Z1);
  ExpRect(ARect.Left, ARect.Bottom, ARect.Z2);
  ExpRect(ARect.Right, ARect.Top, ARect.Z1);
  ExpRect(ARect.Right, ARect.Top, ARect.Z2);
  ExpRect(ARect.Right, ARect.Bottom, ARect.Z1);
  ExpRect(ARect.Right, ARect.Bottom, ARect.Z2);
end;

procedure TsgCADImage.SetOwnSource(Value: Boolean);
begin
  Converter.OwnSource := Value;
end;

procedure TsgCADImage.Set3DRotDef(const ABox: TFRect; var ANeed2DViewByDefault: Boolean);
begin
  ANeed2DViewByDefault := IsZero(ABox.Z1) and IsZero(ABox.Z2);
  if not ANeed2DViewByDefault then
    RotToView(GetDefSolidRotView);
end;

procedure TsgCADImage.SetBackgroundColor(Value: TColor);
begin
  if FBackgroundColor <> Value then
  begin
    FBackgroundColor := Value;
    FChangeBackgroundColor := GetColorByBackgroud(FBackgroundColor);
    Changed(Self);
  end;
end;

procedure TsgCADImage.SetPlotWindowAreaColor(Value: TColor);
begin
  if FPlotWindowAreaColor <> Value then
  begin
    FPlotWindowAreaColor := Value;
    Changed(Self);
  end;
end;

procedure TsgCADImage.SetPrinting(const AValue: TsgPrintMode);
begin
  FPrinting := AValue;
end;

procedure TsgCADImage.SetDefaultColor(Value: TColor);
begin
  if FDefaultColor <> Value then
  begin
    FDefaultColor := Value;
    Changed(Self);
  end;
end;

procedure TsgCADImage.SetDefaultPlotSettings(const ACheckSize: Boolean = False);
begin
end;

procedure TsgCADImage.DoAfterRotate;
begin
  Dec(FRotCount);
  if FRotCount < 0 then FRotCount := 0;
  if FRotCount = 0 then
  begin
    RefreshCurrentLayout;
    if Assigned(FOnAfterRotate) then
      FOnAfterRotate(Self);
  end;
end;

procedure TsgCADImage.DoBeforeRotate;
begin
  Inc(FRotCount);
  if FRotCount = 1 then
    if Assigned(FOnBeforeRotate) then
      FOnBeforeRotate(Self);
end;

function TsgCADImage.DoDraw(Entity: TsgDXFEntity): Integer;
begin
  Result := 0;
  case Entity.EntType of
    ceLine:              DrawLine(Entity);
    cePoint:             DrawPoint(Entity);
    ceSolid, ceTrace:    DrawSolid(Entity);
    ceCircle:            DrawCircle(Entity);
    ceArc, ceEllipse:    DrawArc(Entity);
    ceLWPolyline,
      cePolyline,
      cePath:            DrawPoly(Entity);
    ceSpline, ceHelix:   DrawSpline(Entity);
    ceLeader:            DrawLeader(Entity);
    ceDimension:         Result := DrawDimension(Entity);
    ceACADTable,
      ceInsert,
      ceMText,
      ceMLine,
      ceTolerance:       Result := DrawInsert(Entity);
    ceText,
      ceAttdef,
      ceAttrib:          DrawText(Entity);
    ceShape:             DrawShape(Entity);
    ce3dFace:            DrawFace(Entity);
    cePolyPolygon,
      ceGradient,
      ceGradientPolygon,
      ceCurvePolygon,
      ceHatch:           DrawHatch(Entity);
    ceMPolygon:          DrawMPolygon(Entity);
    ceImageEnt:          DrawImageEnt(Entity);
    ceViewport:          DrawViewPort(Entity);
    ceIges, ceStep, ceBrep,
    ceRegion,
      ceBody, ce3DSolid: DrawACISEntity(Entity);
    ceOle2Frame:         DrawOle2Frame(Entity);
    ceFlatPoly,
    ceFlatPoly3D:        DrawFlatPoly(Entity);
    ceFlatHatch:         DrawFlatHatch(Entity);
    ceXRef:              DrawXRef(Entity);
    ceWipeout:           DrawWipeout(Entity);
    ceProxy:             DrawComplexEntity(Entity);
{$IFDEF SG_BTI}
    cePolyPolyline2D:   DrawPolyPolyLine2D(Entity);
{$ENDIF}
  end;
end;

{$IFNDEF SGFPC}
procedure TsgCADImage.DoMetafileExport(const MC: TMetafileCanvas;
  const ARect: TRect);
begin
  if Assigned(FOnMetafileExport) then
    FOnMetafileExport(MC, ARect);
end;
{$ENDIF}

procedure TsgCADImage.DoOnProgress(Stage: TProgressStage; Done, Count: Integer);
const
  vRect: TRect = (Left:0; Top:0; Right:0; Bottom:0);
begin
  Progress(Self, Stage, Byte(MulDiv(Done, 100, Count)), False, vRect, '');
end;

function TsgCADImage.DoFinish(Entity: TsgDXFEntity): Integer;
begin
  Result := 0;
  case Entity.EntType of
    ceDimension, ceInsert,
      ceMText:             EnterInsert(Entity);
    ceViewport:            EnterViewport(Entity);
    ceXRef:                EnterXRef(Entity);
    ceProxy:               EnterComplexEntity(Entity);
    ceStep, ceRegion,
      ceBody, ce3DSolid:   EnterComplexEntity(Entity);
  end;
end;

procedure TsgCADImage.DoMatrixChanged;
begin
  if Assigned(FOnMatrixChanged) then
    FOnMatrixChanged(Self);
end;

procedure TsgCADImage.SetDrawingBox(const ABox: TFRect);
begin
  FDrawingBox := ABox;
  if IsBadRect(FDrawingBox) then
  begin
    if FCurrentLayout <> nil then
      SetExtentsParameters(FCurrentLayout.Box, FCurrentLayout.CADSpace <> csUndefined)
    else
    begin
      if Converter.LayoutsCount <= 0 then
        Converter.AddLayout(TsgDXFLayout.Create);
      FCurrentLayout := Converter.Layouts[0];
      SetExtentsParameters(MakeFRect(0,0,0,0,0,0), False);
    end;
  end
  else
    SetExtentsParameters(FDrawingBox, True);
  Changed(Self);
end;

procedure TsgCADImage.SetDrawMatrix(const AMatrix: TFMatrix);
begin
  FDraw.Matrix := AMatrix;
  FDraw.DrawMatrix := AMatrix;
  FDraw.Additional := Ord(IsRotatedFMat(FDraw.Matrix));
  if not FCustomDraw then
  begin
    DoMatrixChanged;
    Changed(Self);
  end;
end;

procedure TsgCADImage.SetDrawMode(Value: TsgDXFDrawMode);
begin
  if Value <> FDrawMode then
  begin
    FDrawMode := Value;
    Changed(Self);
  end;
end;

procedure TsgCADImage.SetIsShowBackground(Value: Boolean);
begin
  if FIsShowBackground <> Value then
    FIsShowBackground := Value;
end;

procedure TsgCADImage.SetShowLineWeight(Value: Boolean);
begin
  if FIsShowLineWeight <> Value then
  begin
    FIsShowLineWeight := Value;
    Changed(Self);
  end;
end;

procedure TsgCADImage.SetIsWithoutBorder(Value: Boolean);
begin
  FIsWithoutBorder := Value;
  if FCurrentLayout <> nil then
    RefreshCurrentLayout;
end;

procedure TsgCADImage.SetStretch(Value: Boolean);
begin
  if Value <> FStretch then
  begin
    FStretch := Value;
    Changed(Self);
  end;
end;

procedure TsgCADImage.SetStretchBltModeInt(const AMode: Integer);
begin
  SetStretchBltMode(FCanvas.Handle, AMode);
end;

function TsgCADImage.GetStretchBltModeInt: Integer;
begin
  Result := GetStretchBltMode(FCanvas.Handle);
end;

procedure TsgCADImage.SetLineWeightScale(const Value: TsgFloat);
begin
  FLineWeightScale := Value;
end;

function TsgCADImage.SetLineWeigth(const AEntity: TsgDXFEntity;
  const ALineWeightScaled: Boolean; AMetric: Double = 1.0): Integer;
var
  vLineWeight: Double;
begin
  Result := 0;
  DoScale2D(FDraw);
  if IsShowLineWeight then
  begin
    if sgIsZero(AMetric) then
      AMetric := 1;
    vLineWeight :=  GetLineWeightFactor * EntLineWeight(AEntity, FDraw.Insert) / AMetric;
    if ALineWeightScaled then
      vLineWeight := vLineWeight * FDraw.XScale;
    Result := Round(LineWeightScale * vLineWeight);
    if Result = 0 then
      Result := 1
    else
      Result := Abs(Result);
  end;
  SetPenWidth(Result);
end;

procedure TsgCADImage.SetListsCapacity(const ASetDefault: Boolean);
begin
  SetListCapacity(FPoly, ASetDefault);
  SetListCapacity(FIntPoints, ASetDefault);
  SetListCapacity(FDottedSingPts, ASetDefault);
end;

procedure TsgCADImage.SetUsePlotSetting(const Value: Boolean);
begin
  FUsePlotSetting := Value;
end;

procedure TsgCADImage.SetShowPlotForModel(const Value: Boolean);
begin
  FShowPlotForModel := Value;
end;

procedure TsgCADImage.SetShowPlotFrame(const Value: Boolean);
begin
  FShowPlotFrame := Value;
end;

procedure TsgCADImage.SetShowPlotMargins(const Value: Boolean);
begin
  FShowPlotMargins := Value;
end;

procedure TsgCADImage.SetShowPlotSetting(const Value: Boolean);
begin
  FShowPlotSetting := Value;
end;

//for internal use
procedure TsgCADImage.SetSHXFontsProc(const AValue: TsgSHXFontsProc);
begin
  FSHXFontsProc := AValue;
end;

procedure TsgCADImage.SetUseWinEllipse(Value: Boolean);
begin
  if Value <> FUseWinEllipse then
  begin
    FUseWinEllipse := Value;
    Changed(Self);
  end;
end;

procedure TsgCADImage.SetShowImages(Value: Boolean);
begin
  if Value <> FShowImages then
  begin
    FShowImages := Value;
    Changed(Self);
  end;
end;

procedure TsgCADImage.SetDimensionsVisible(AVisible: Boolean);
var
  I: Integer;
begin
  if (FDimensionsVisible <> AVisible) then
  begin
    FDimensionsVisible := AVisible;
    if Assigned(Converter) then
      for I := 0 to Converter.XRefs.Count - 1 do
        TsgCADImage(TsgDXFXRef(Converter.XRefs.Items[I]).CADImage).DimensionsVisible := AVisible;
    GetExtents;
  end;
end;

procedure TsgCADImage.SetTextVisible(AVisible: Boolean);
var
  I: Integer;
begin
  if (FTextVisible <> AVisible) then
  begin
    FTextVisible := AVisible;
    if Assigned(Converter) then
      for I := 0 to Converter.XRefs.Count - 1 do
        TsgCADImage(TsgDXFXRef(Converter.XRefs.Items[I]).CADImage).TextVisible := AVisible;
    GetExtents;
  end;
end;

procedure TsgCADImage.StopLoading;
begin
  FConverter.StopLoading;
end;

//
// Call only Iterate functional !!!
//
function TsgCADImage.IsNotScaledLType: Boolean;
begin
  Result := Assigned(FConverter.Params.Insert) and IsAutocadLType;
end;

function TsgCADImage.IsNoWidth: Boolean;
begin
  Result := FPenWidth <= 1; //evg
end;

procedure TsgCADImage.DrawOle2Frame(Sender: TObject);
var
  vRect: TF2DRect;
begin
  if TsgDXFOle2Frame(Sender).OleObject = nil then Exit;
  vRect := cnstBadRectF2D;
  ExpandF2DRect(vRect, MakeF2DPointFromPoint(GetPoint(TsgDXFOle2Frame(Sender).Point)));
  ExpandF2DRect(vRect, MakeF2DPointFromPoint(GetPoint(TsgDXFOle2Frame(Sender).Point1)));
  SwapSGFloats(vRect.Top, vRect.Bottom);
  DoSetColor(FColor, ctBrush);
  ExpOle2FrameInternal(Sender, vRect);
end;

//evg completely changed
procedure TsgCADImage.DrawPointsListByPolyline(const AObj: TObject;
  const DottedSingPts: TFPointList;
  AClosed: Boolean);
var
  I, vCnt: Integer;
  P, P0: TPoint;
  vIsPoint, vIsMissedVertex: Boolean;
  vList: TsgIntegerList;
  vdX, vdY: Double; //evg
  PF: TFPoint;

begin
  if DottedSingPts.Count <= 1 then
    Exit;
  FIntPoints.Count := 0;
  FDotsPoints.Count := 0;
  if DottedSingPts.Count = 2 then
  begin
    P0 := GetPoint(DottedSingPts[0]);;
    P := GetPoint(DottedSingPts[1]);
    vIsPoint := IsEqualPoints(P, P0);
    if vIsPoint then
      ExpPixelInteger(AObj, P, FColor)
    else
    begin
      vList := FIntPoints;
      AddPtToList(vList, P0);
      AddPtToList(vList, P);
      if NeedToAddOnePixel then  // (!!!) points changes
      begin
        P.Y := P.Y + 1;
        AddPtToList(FIntPoints, P);
      end;
      ExpPolylineInteger(AObj, FIntPoints.List[0], FIntPoints.Count div 2);
    end;
  end
  else
  begin
    //evg packing
    GetPixelSize(0.5, vdX, vdY, True);
    if DottedSingPts.Count >0 then
    begin
      PF := DottedSingPts[0];
      P := GetPoint(PF);
      AddPtToList(FIntPoints, P);
    end;
    vIsMissedVertex := False;
    for I := 1 to DottedSingPts.Count - 1 do
    begin
      if (Abs(DottedSingPts[I].X - PF.X) > vdX)
       or (Abs(DottedSingPts[I].Y - PF.Y) > vdY)
       or (Abs(DottedSingPts[I].Z - PF.Z) > vdx) then
      begin
        if vIsMissedVertex then // add last missed point if it is really should be in other pixel than the last added-pixel. the same is in DrawFlatPoly()
        begin
          P0 := GetPoint(DottedSingPts[I - 1]);
          if not IsEqualPoints(P, P0) then
            AddPtToList(FIntPoints, P0);
        end;
        PF := DottedSingPts[I];
        P := GetPoint(PF);
        AddPtToList(FIntPoints, P);
        vIsMissedVertex := False;
      end
      else
        vIsMissedVertex := True;
    end;
    if AClosed then
      AddPtToList(FIntPoints, GetPoint(DottedSingPts[0]))
    else
      if NeedToAddOnePixel then  // (!!!) points changes
      begin
        P.Y := P.Y + 1;
        AddPtToList(FIntPoints, P);
      end;

    vCnt := FIntPoints.Count div 2;
    if vCnt > 1 then
      ExpPolylineInteger(AObj, FIntPoints.List[0], vCnt);
  end;
end;

//evg completely changed
procedure TsgCADImage.DrawPointsListByPolyPolyline(const AObj: TObject;
  const DottedSingPts: TFPointList; AClosed: Boolean = False);

  procedure AddPtsInt(AList: TsgIntegerList; const AP1, AP2: TPoint);
  begin
    AddPtToList(AList, AP1);
    AddPtToList(AList, AP2);
  end;

//  procedure AddPts(AList: TList; const AP1, AP2: TPoint);
//  begin
//    AddPtToList(AList, AP1);
//    AddPtToList(AList, AP2);
//  end;

  procedure Add3Pts(AList: TsgIntegerList; const AP1, AP2, AP3: TPoint);
  begin
    AddPtToList(AList, AP1);
    AddPtToList(AList, AP2);
    AddPtToList(AList, AP3);
  end;

  procedure DrawSegment(const ACountList: TsgIntegerList; const ACount: Integer);
  var
    J, Counter: Integer;
  begin
    Counter := 0;
    for J := 0 to ACount-1 do
    begin
      ExpPolylineInteger(AObj, (@FIntPoints.List[Counter])^, ACountList[J]);
      Inc(Counter, ACountList[J] * 2);
    end;
  end;

  procedure Fill3Counts(AMax: Integer);
  var
    I: Integer;
  begin
    I := F3Counts.Count;
    while I <= AMax do
    begin
      F3Counts.Add(3);
      Inc(I);
    end;
  end;

var
  I, vCnt: Integer;
  {$IFDEF SG_HIDDEN}
  P1, P2: TPoint;
  {$ELSE}
    vPts: array [0..2] of TPoint;
    vCntLines, vCntPoints: Integer;
  {$ENDIF}
  vCounts: TsgIntegerList;
  vdX, vdY, vLTScale: Double;
  vIsPolyline: Boolean;
  vPolyline: TsgCADBasePolyline;
  FP: TFPoint;

    {$IFDEF SG_HIDDEN}
      {$INCLUDE HIDDEN2.INC}
   {$ENDIF}

begin
  FIntPoints.Count := 0;
  FDotsPoints.Count := 0;
  if AObj is TsgCADBasePolyline then
  begin
    vPolyline := TsgCADBasePolyline(AObj);
    GetPixelSize(1.5, vdX, vdY, not IsAutocadLType);
    vIsPolyline := True;

    vCnt := vPolyline.PolyPoints.Count; // Points count must be even
    I := 0;
    vLTScale := FEntityLines.MaxSizeOfPatterns * FEntityLines.Scale;
    if FEntityLines.IsSolid or (vLTScale < vdX) then
    begin
      GetPixelSize(1.5, vdX, vdY, True);
      while I < vCnt - 1 do
      begin
        if Abs(vPolyline.PolyPoints[I].X - vPolyline.PolyPoints[I + 1].X) > vdX then
        begin
          vIsPolyline := False;
          Break;
        end;
        if Abs(vPolyline.PolyPoints[I].Y - vPolyline.PolyPoints[I + 1].Y) > vdY then
        begin
          vIsPolyline := False;
          Break;
        end;
        Inc(I);
      end
    end
    else
      vIsPolyline := False; //for linetypes with big PatternLength
    if vIsPolyline then
    begin
      DrawPointsListByPolyline(AObj, vPolyline.PolyPoints, AClosed);
      Exit;
    end;
  end;
  GetPixelSize(0.5, vdX, vdY, True);
  vCnt := DottedSingPts.Count shr 1 shl 1; // Points count must be even
  I := 0;
  FCounts.Count := 0;
  FIntPoints.Count := 0;
  FP := BadRect.TopLeft;
  {$IFDEF SG_HIDDEN}
  vCounts := TsgIntegerList.Create; //evg??? - all lists to create/destroy!
  while I < vCnt - 1 do
  begin
    if I = 0 then
      AddLine(DottedSingPts[I], DottedSingPts[I + 1])
    else
      if IsInOtherPixel(DottedSingPts[I], vdX, vdY) then // means that new line begins in a new pixel
        AddLine(DottedSingPts[I], DottedSingPts[I + 1])
      else // it is here: PFPoint(DottedSingPts[I])^ approx= FP
        if IsInOtherPixel(DottedSingPts[I + 1], vdX, vdY)  then
          ExtendLine(DottedSingPts[I + 1]);
    Inc(I, 2);
  end;
  AddLastPixelToPoly(FIntPoints, vCounts);
  ExpPolyPolylineLists(AObj, FIntPoints, vCounts.List, vCounts.Count);
  vCounts.Free;
  {$ELSE}
  if IsNoWidth then
  begin
    vCounts := F3Counts;
    Fill3Counts(DottedSingPts.Count);
  end
  else
    vCounts := F2Counts;
  Fill2Counts(DottedSingPts.Count);
  vCntLines := 0;
  vCntPoints := 0;
  while I < vCnt - 1 do
  begin
    vPts[0] := GetPoint(DottedSingPts[I]);
    vPts[1] := GetPoint(DottedSingPts[I + 1]);
    Inc(I, 2);
    if IsEqualPoints(vPts[0], vPts[1]) then
    begin
      vPts[1].Y := vPts[1].Y + 1;
      AddPtsInt(FDotsPoints, vPts[0], vPts[1]);
      Inc(vCntPoints);
    end
    else
    begin
      if IsNoWidth then
      begin
        vPts[2] := Point(vPts[1].X, vPts[1].Y + 1);
        Add3Pts(FIntPoints, vPts[0], vPts[1], vPts[2]);
      end
      else
        AddPtsInt(FIntPoints, vPts[0], vPts[1]);
      Inc(vCntLines);
    end;
  end;
  if IsNoWidth then
    ExpPolyPolylineLists(AObj, FIntPoints, vCounts.List, vCntLines)
  else
    DrawSegment(vCounts, vCntLines);
   ExpPolyPolylineLists(AObj, FDotsPoints, F2Counts.List, vCntPoints);
  {$ENDIF}
end;

procedure TsgCADImage.DrawXRef(Sender: TObject);
begin
  if SelectionMatrix <> nil then
  begin
    AddSelectionMatrix(Sender);
    SelectionMatrix.Changed;
  end;
  if TsgCADImage(TsgDXFXref(Sender).CADImage) <> nil then
  begin
    FSHXFontsProc := TsgCADImage(TsgDXFXref(Sender).CADImage).GetSHXFontsProc;
    FGetSelectionMatrixModeProc := TsgCADImage(TsgDXFXref(Sender).CADImage).GetSelectionMatrixProc;
    FSetSelectionMatrixModeProc := TsgCADImage(TsgDXFXref(Sender).CADImage).SetSelectionMatrixProc;
  end
  else
  begin
    FSHXFontsProc := GetSHXFontsProc;
    FGetSelectionMatrixModeProc := GetSelectionMatrixProc;
    FSetSelectionMatrixModeProc := SetSelectionMatrixProc;
  end;
  FXrefStack.Add(Sender);
end;

procedure TsgCADImage.TransformToUCS(var APoint: TFPoint);
var
  UCS: TFMatrix;

  function FPointXMat(const P: TFPoint; const M: TFMatrix): TFPoint;
    function Part(I: Integer): Extended;
    begin
      Result := P.X * M.M[I,0] + P.Y * M.M[I,1] + P.Z * M.M[I,2] + M.M[3,I];
    end;
  begin
    Result.X := Part(0);
    Result.Y := Part(1);
    Result.Z := Part(2);
  end;

begin
  UCS := FConverter.GetUCS(FCurrentLayout);
  APoint := FPointXMat(APoint, UCS);
end;

procedure TsgCADImage.TransformToWorldCS(var APoint: TFPoint);
var
  UCS: TFMatrix;
begin
  UCS := FConverter.GetUCS(FCurrentLayout);
end;

procedure TsgCADImage.TranslateDrawMatrix(ADx, ADy, ADz: Double);
begin
  SetDrawMatrix(FMatTranslate(DrawMatrix, ADx, ADy, ADz));
end;

function TsgCADImage.InternalToCommonUnits(Pt: TFPoint): TFPoint;
begin
  Result := Pt;
end;

function TsgCADImage.CommonToInternalUnits(Pt: TFPoint): TFPoint;
begin
  Result := Pt;
end;

function TsgCADImage.Measurement: TsgMeasurement;
begin
  case Integer(Converter <> nil) shl 1 + Integer(FConverter.HeadVarStruct.Measurement) of
    2:  Result.DistanceUnits := duInch;
    3:  Result.DistanceUnits := duMM;
  else
    Result.DistanceUnits := duNone;
  end;
  Result.AngularUnits := auNone;
end;

function TsgCADImage.NeedToAddOnePixel: Boolean;
begin
  Result := FAddOnePixel and (FPenWidth < 2) and (not FIsIterator);
end;

procedure TsgCADImage.SetVisibleArea(Data: TPoint);
begin
  if (FVisibleArea.X <> Data.X) and (FVisibleArea.Y <> Data.Y) then
    SetupSnapMatrix;
  FVisibleArea := Data;
end;

procedure TsgCADImage.InitializeVersionData(const AIsTrial: Boolean;
  const AMessage: string);
begin
  if AIsTrial then
    FMessage := AMessage
  else
    FMessage := '';
end;

procedure TsgCADImage.Fill2Counts(AMax: Integer);
var
  I: Integer;
begin
  I := F2Counts.Count;
  while I <= AMax do
  begin
    F2Counts.Add(2);
    Inc(I);
  end;
end;

{$IFDEF SG_BTI}
procedure TsgCADImage.DrawPolyPolyLine2D(Sender: TObject);
var
  vPolyPolyLine: TsgCADPolyPolyline2D absolute Sender;
  I, vPtCnt: Integer;
  vLine: TsgLine;
  vPt1, vPt2: TPoint;
  vList: TList;
  vCounts: TsgIntegerList;
  vDotSingPts: TFPointList;
  P: PFPoint;
begin
  vDotSingPts := vPolyPolyLine.DotSingPts;
  if vDotSingPts = nil then
  begin
    if IsDrawOnCanvas then
    begin
      FIntPoints.Count := 0;
      FDotsPoints.Count := 0;
      vPtCnt := 0;
      vCounts := TsgIntegerList.Create;
      try
        Fill2Counts(vPolyPolyLine.CurvesCount);
        vCounts.Capacity := vPolyPolyLine.CurvesCount;
        for I := 0 to vPolyPolyLine.CurvesCount - 1 do
        begin
          if not vPolyPolyLine.CurveVisible[I] then
            Continue;
          if vPolyPolyLine.IsCurveArc(I) then
          begin
            vPolyPolyLine.GetPointsOfArc(I, nil, FIntPoints, Converter.NumberOfPartsInCircle, GetPoint);
            vCounts.Add(Converter.NumberOfPartsInCircle + 1);
          end
          else
          begin
            vLine := vPolyPolyLine.Lines[I];
            vPt1 := GetPoint(vLine.Point1);
            vPt2 := GetPoint(vLine.Point2);
            if IsEqualPoints(vPt1, vPt2) then
            begin
              vPt2.Y := vPt2.Y + 1;
              AddPtToList(FDotsPoints, vPt1);
              AddPtToList(FDotsPoints, vPt2);
              Inc(vPtCnt);
            end
            else
            begin
              AddPtToList(FIntPoints, vPt1);
              AddPtToList(FIntPoints, vPt2);
              vCounts.Add(2);
            end;
          end;
        end;
        ExpPolyPolylineLists(Sender, FIntPoints, vCounts.List, vCounts.Count, False);
        ExpPolyPolylineLists(Sender, FDotsPoints, F2Counts.List, vPtCnt, False);
      finally
        vCounts.Free;
        FIntPoints.Count := 0;
      end;
    end;
  end
  else
    DrawPointsListByPolyPolyline(Sender, vDotSingPts);
  if (not FIsIterator) and IsDrawOnBitMap then
  begin
    FIntPoints.Count := 0;
    AddSelectionMatrix(Sender);
    if vPolyPolyLine.Boundary = nil then
    begin
      vList := TList.Create;
      try
        vPolyPolyLine.GetBoundary(vList);
        for I := vList.Count - 1 downto 0 do
        begin
          P := vList.List[I];
          vPt1 := GetPoint(P^);
          Dispose(P);
          AddPtToList(FIntPoints, vPt1);
        end;
      finally
        vList.Free;
      end;
    end
    else
      for I := vPolyPolyLine.Boundary.Count - 1 downto 0 do
        AddPtToList(FIntPoints, GetPoint(vPolyPolyLine.Boundary[I]));
   // SelectionMatrix.Brush.Style := bsSolid;
    SelectionMatrix.Changed;
    Windows.Polygon(SelectionMatrix.Handle, FIntPoints.List^, FIntPoints.Count shr 1);
  // SelectionMatrix.Brush.Style := bsClear;
  end;
end;
{$ENDIF}

{ TsgVectorImage }

procedure TsgVectorImage.ApplyLineWeightFactor(var ALineWeight: Double);
begin
end;

constructor TsgVectorImage.Create;
begin
  inherited Create;
  TsgDXFConverterAccess(Converter).FreeEntitiesWithGeneratedHandles;
end;

function TsgVectorImage.GetLineWeightFactor: Double;
begin
  Result := cnstDefaultLineWeightFactor;
end;

procedure TsgVectorImage.SetDefaultPlotSettings(const ACheckSize: Boolean = False);
var
  I: Integer;
  vPlotSettings: TsgDXFPlotSettings;
begin
  for I := 0 to Converter.LayoutsCount - 1 do
  begin
    vPlotSettings := Converter.Layouts[I].PlotSettings;
    if (not ACheckSize) or (vPlotSettings.PlotPaperSize.X * vPlotSettings.PlotPaperSize.Y = 0) then
      vPlotSettings.SetDefaultValueByExtents(Converter.Layouts[I].Box);
  end;
end;

procedure TsgVectorImage.SetDefaultViewModePlotSettings;
begin
  ShowPlotSetting := False;
  ShowPlotForModel := True;
  ShowPlotMargins := True;
end;

{ TsgHandlesImage }

constructor TsgImageWithHandles.Create;
begin
  inherited;
end;

function TsgImageWithHandles.GetConverterParams: TsgConverterParams;
begin
  Result := inherited GetConverterParams;
  Result.CheckHandles := True;
end;

procedure TsgImageWithHandles.SetDefaultViewModePlotSettings;
begin
  ShowPlotSetting := True;
  ShowPlotMargins := True;
  ShowPlotForModel := False;
end;

initialization
  StdLines := TsgLines.Create;
  CreateAcadPal;
  InitGradFill;

finalization
  FreeAndNil(StdLines);
  if Msimg32 <> 0 then FreeLibrary(Msimg32);
  DeleteObject(AcadPal);

end.
