{******************************************************************************
                Copyright (c) PilotLogic Software House
                     
 Package pl_Win_GDI
 This file is part of CodeTyphon Studio (https://www.pilotlogic.com/)      
                                                                               
   ****** BEGIN LICENSE BLOCK *****     
                                                              
   The contents of this file are used with permission, subject to the Mozilla   
   Public License Version 2.0 (the "License"); you may not use this file except 
   in compliance with the License. You may obtain a copy of the License at      
   https://www.mozilla.org/en-US/MPL/2.0/                                     
                                                                               
   Software distributed under the License is distributed on an "AS IS" basis,   
   WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for 
   the specific language governing rights and limitations under the License. 
   
   ****** END LICENSE BLOCK *****  
  
**********************************************************************************}

unit GDIPOBJ;

{$ALIGN ON}
{$MINENUMSIZE 4}

interface
uses
  Windows,
  ActiveX,
  GDICONST,
  GDIPAPI;

  function GetImageDecodersSize(out numDecoders, size: UINT): TStatus;
  function GetImageDecoders(numDecoders, size: UINT; decoders: PImageCodecInfo): TStatus;
  function GetImageEncodersSize(out numEncoders, size: UINT): TStatus;
  function GetImageEncoders(numEncoders, size: UINT; encoders: PImageCodecInfo): TStatus;

(**************************************************************************\
*
*   Private GDI+ header file.
*
\**************************************************************************)

// GDI+ classes for forward reference

type
  TGPGraphics = class;
  TGPPen = class;
  TGPBrush = class;
  TGPMatrix = class;
  TGPBitmap = class;
  TGPMetafile = class;
  TGPFontFamily = class;
  TGPGraphicsPath = class;
  TGPRegion = class;
  TGPImage = class;
  TGPHatchBrush = class;
  TGPSolidBrush = class;
  TGPLinearGradientBrush = class;
  TGPPathGradientBrush = class;
  TGPFont = class;
  TGPFontCollection = class;
  TGPInstalledFontCollection = class;
  TGPPrivateFontCollection = class;
  TGPImageAttributes = class;
  TGPCachedBitmap = class;

  TGPRegion = class(TGdiplusBase)
  protected
    nativeRegion: GpRegion;
    lastResult: TStatus;
    function SetStatus(status: TStatus): TStatus;
    procedure SetNativeRegion(nativeRegion: GpRegion);
    constructor Create(nativeRegion: GpRegion); reintroduce; overload;
  public
    constructor Create; reintroduce; overload;
    constructor Create(rect: TGPRectF); reintroduce; overload;
    constructor Create(rect: TGPRect); reintroduce; overload;
    constructor Create(path: TGPGraphicsPath); reintroduce; overload;
    constructor Create(regionData: PBYTE; size: Integer); reintroduce; overload;
    {$IFNDEF KS_CBUILDER}
    constructor Create(hRgn: HRGN); reintroduce; overload;
    {$ENDIF}
    function FromHRGN(hRgn: HRGN): TGPRegion;
    destructor Destroy; override;
    function Clone: TGPRegion;
    function MakeInfinite: TStatus;
    function MakeEmpty: TStatus;
    function GetDataSize: UINT;
    // buffer     - where to put the data
    // bufferSize - how big the buffer is (should be at least as big as GetDataSize())
    // sizeFilled - if not NULL, this is an OUT param that says how many bytes
    //              of data were written to the buffer.
    function GetData(buffer: PBYTE; bufferSize: UINT;
       sizeFilled: PUINT = nil): TStatus;
    function Intersect(const rect: TGPRect): TStatus; overload;
    function Intersect(const rect: TGPRectF): TStatus; overload;
    function Intersect(path: TGPGraphicsPath): TStatus; overload;
    function Intersect(region: TGPRegion): TStatus; overload;
    function Union(const rect: TGPRect): TStatus; overload;
    function Union(const rect: TGPRectF): TStatus; overload;
    function Union(path: TGPGraphicsPath): TStatus; overload;
    function Union(region: TGPRegion): TStatus; overload;
    function Xor_(const rect: TGPRect): TStatus; overload;
    function Xor_(const rect: TGPRectF): TStatus; overload;
    function Xor_(path: TGPGraphicsPath): TStatus; overload;
    function Xor_(region: TGPRegion): TStatus; overload;
    function Exclude(const rect: TGPRect): TStatus; overload;
    function Exclude(const rect: TGPRectF): TStatus; overload;
    function Exclude(path: TGPGraphicsPath): TStatus; overload;
    function Exclude(region: TGPRegion): TStatus; overload;
    function Complement(const rect: TGPRect): TStatus; overload;
    function Complement(const rect: TGPRectF): TStatus; overload;
    function Complement(path: TGPGraphicsPath): TStatus; overload;
    function Complement(region: TGPRegion): TStatus; overload;
    function Translate(dx, dy: Single): TStatus; overload;
    function Translate(dx, dy: Integer): TStatus; overload;
    function Transform(matrix: TGPMatrix): TStatus;
    function GetBounds(out rect: TGPRect; g: TGPGraphics): TStatus; overload;
    function GetBounds(out rect: TGPRectF; g: TGPGraphics): TStatus; overload;
    function GetHRGN(g: TGPGraphics): HRGN;
    function IsEmpty(g: TGPGraphics): BOOL;
    function IsInfinite(g: TGPGraphics): BOOL ;
    function IsVisible(x, y: Integer; g: TGPGraphics = nil): BOOL; overload;
    function IsVisible(const point: TGPPoint; g: TGPGraphics = nil): BOOL; overload;
    function IsVisible(x, y: Single; g: TGPGraphics = nil): BOOL; overload;
    function IsVisible(const point: TGPPointF; g: TGPGraphics = nil): BOOL; overload;
    function IsVisible(x, y, width, height: Integer; g: TGPGraphics): BOOL; overload;
    function IsVisible(const rect: TGPRect; g: TGPGraphics = nil): BOOL; overload;
    function IsVisible(x, y, width, height: Single; g: TGPGraphics = nil): BOOL; overload;
    function IsVisible(const rect: TGPRectF; g: TGPGraphics = nil): BOOL; overload;
    function Equals(region: TGPRegion; g: TGPGraphics): BOOL;
    function GetRegionScansCount(matrix: TGPMatrix): UINT;
    function GetRegionScans(matrix: TGPMatrix ;rects: PGPRectF; out count: Integer): TStatus; overload;
    function GetRegionScans(matrix: TGPMatrix; rects: PGPRect; out count: Integer): TStatus; overload;
    function GetLastStatus: TStatus;
  end;

//--------------------------------------------------------------------------
// FontFamily
//--------------------------------------------------------------------------

  TGPFontFamily = class(TGdiplusBase)
  protected
    nativeFamily: GpFontFamily;
    lastResult: TStatus;
    function SetStatus(status: TStatus): TStatus;
    constructor Create(nativeOrig: GpFontFamily;
      status: TStatus); reintroduce; overload;
  public
    constructor Create; reintroduce; overload;
    constructor Create(name: WideString; fontCollection: TGPFontCollection = nil); reintroduce; overload;
    destructor Destroy; override;
    class function GenericSansSerif: TGPFontFamily;
    class function GenericSerif: TGPFontFamily;
    class function GenericMonospace: TGPFontFamily;
    function GetFamilyName(out name: String; language: LANGID = 0): TStatus;
    function Clone: TGPFontFamily;
    function IsAvailable: BOOL;
    function IsStyleAvailable(style: Integer): BOOL;
    function GetEmHeight(style: Integer): UINT16;
    function GetCellAscent(style: Integer): UINT16;
    function GetCellDescent(style: Integer): UINT16;
    function GetLineSpacing(style: Integer): UINT16;
    function GetLastStatus: TStatus;
  end;

//--------------------------------------------------------------------------
// Font Collection
//--------------------------------------------------------------------------

  TGPFontCollection = class(TGdiplusBase)
  protected
    nativeFontCollection: GpFontCollection;
    lastResult: TStatus;
    function SetStatus(status: TStatus): TStatus;
  public
    constructor Create;
    destructor Destroy; override;
    function GetFamilyCount: Integer;
    function GetFamilies(numSought: Integer; out gpfamilies: array of TGPFontFamily;
      out numFound: Integer): TStatus;
    function GetLastStatus: TStatus;
  end;

  TGPInstalledFontCollection = class(TGPFontCollection)
  public
    constructor Create; reintroduce;
    destructor Destroy; override;
  end;

  TGPPrivateFontCollection = class(TGPFontCollection)
  public
    constructor Create; reintroduce;
    destructor destroy; override;
    function AddFontFile(filename: WideString): TStatus;
    function AddMemoryFont(memory: Pointer; length: Integer): TStatus;
  end;

//--------------------------------------------------------------------------
// TFont
//--------------------------------------------------------------------------

  TGPFont = class(TGdiplusBase)
  protected
    nativeFont: GpFont;
    lastResult: TStatus;
    procedure SetNativeFont(Font: GpFont);
    function SetStatus(status: TStatus): TStatus;
    constructor Create(font: GpFont; status: TStatus); overload;
  public
    constructor Create(hdc: HDC); reintroduce; overload;
    constructor Create(hdc: HDC; logfont: PLogFontA); reintroduce; overload;
    constructor Create(hdc: HDC; logfont: PLogFontW); reintroduce; overload;
    constructor Create(hdc: HDC; hfont: HFONT); reintroduce; overload;
    constructor Create(family: TGPFontFamily; emSize: Single;
      style: TFontStyle = FontStyleRegular;
      unit_: TUnit = UnitPoint); reintroduce; overload;
    constructor Create(familyName: WideString; emSize: Single;
      style: TFontStyle = FontStyleRegular; unit_: TUnit = UnitPoint;
      fontCollection: TGPFontCollection = nil); reintroduce; overload;
    function GetLogFontA(g: TGPGraphics; out logfontA: TLogFontA): TStatus;
    function GetLogFontW(g: TGPGraphics; out logfontW: TLogFontW): TStatus;
    function Clone: TGPFont;
    destructor Destroy; override;
    function IsAvailable: BOOL;
    function GetStyle: Integer;
    function GetSize: Single;
    function GetUnit: TUnit;
    function GetLastStatus: TStatus;
    function GetHeight(graphics: TGPGraphics): Single; overload;
    function GetHeight(dpi: Single): Single; overload;
    function GetFamily(family: TGPFontFamily): TStatus;
  end;

//--------------------------------------------------------------------------
// Abstract base class for Image and Metafile
//--------------------------------------------------------------------------

  TGPImage = class(TGdiplusBase)
  protected
    nativeImage: GpImage;
    lastResult: TStatus;
    loadStatus: TStatus;
    procedure SetNativeImage(nativeImage: GpImage);
    function SetStatus(status: TStatus): TStatus;
    constructor Create(nativeImage: GpImage; status: TStatus); reintroduce; overload;
  public
    constructor Create(filename: WideString; useEmbeddedColorManagement: BOOL = FALSE); reintroduce; overload;
    constructor Create(stream: IStream; useEmbeddedColorManagement: BOOL  = FALSE); reintroduce; overload;
    function FromFile(filename: WideString; useEmbeddedColorManagement: BOOL = FALSE): TGPImage;
    function FromStream(stream: IStream; useEmbeddedColorManagement: BOOL = FALSE): TGPImage;
    destructor destroy; override;
    function Clone: TGPImage;
    function Save(filename: WideString; const clsidEncoder: TGUID;
      encoderParams: PEncoderParameters = nil): TStatus; overload;
    function Save(stream: IStream; const clsidEncoder: TGUID;
      encoderParams: PEncoderParameters  = nil): TStatus; overload;
    function SaveAdd(encoderParams: PEncoderParameters): TStatus; overload;
    function SaveAdd(newImage: TGPImage; encoderParams: PEncoderParameters): TStatus; overload;
    function GetType: TImageType;
    function GetPhysicalDimension(out size: TGPSizeF): TStatus;
    function GetBounds(out srcRect: TGPRectF; out srcUnit: TUnit): TStatus;
    function GetWidth: UINT;
    function GetHeight: UINT;
    function GetHorizontalResolution: Single;
    function GetVerticalResolution: Single;
    function GetFlags: UINT;
    function GetRawFormat(out format: TGUID): TStatus;
    function GetPixelFormat: TPixelFormat;
    function GetPaletteSize: Integer;
    function GetPalette(palette: PColorPalette; size: Integer): TStatus;
    function SetPalette(palette: PColorPalette): TStatus;
    function GetThumbnailImage(thumbWidth, thumbHeight: UINT;
      callback: GetThumbnailImageAbort = nil; callbackData: pointer = nil): TGPImage;
    function GetFrameDimensionsCount: UINT;
    function GetFrameDimensionsList(dimensionIDs: PGUID; count: UINT): TStatus;
    function GetFrameCount(const dimensionID: TGUID): UINT;
    function SelectActiveFrame(const dimensionID: TGUID; frameIndex: UINT): TStatus;
    function RotateFlip(rotateFlipType: TRotateFlipType): TStatus;
    function GetPropertyCount: UINT;
    function GetPropertyIdList(numOfProperty: UINT; list: PPropID): TStatus;
    function GetPropertyItemSize(propId: PROPID): UINT;
    function GetPropertyItem(propId: PROPID; propSize: UINT; buffer: PPropertyItem): TStatus;
    function GetPropertySize(out totalBufferSize, numProperties : UINT): TStatus;
    function GetAllPropertyItems(totalBufferSize, numProperties: UINT;
      allItems: PPROPERTYITEM): TStatus;
    function RemovePropertyItem(propId: TPROPID): TStatus;
    function SetPropertyItem(const item: TPropertyItem): TStatus;
    function GetEncoderParameterListSize(const clsidEncoder: TGUID): UINT;
    function GetEncoderParameterList(const clsidEncoder: TGUID; size: UINT;
      buffer: PEncoderParameters): TStatus;
    function GetLastStatus: TStatus;
  end;

  TGPBitmap = class(TGPImage)
  protected
    constructor Create(nativeBitmap: GpBitmap);  reintroduce; overload;
  public
    constructor Create(filename: WideString; useEmbeddedColorManagement: BOOL = FALSE); reintroduce; overload;
    constructor Create(stream: IStream; useEmbeddedColorManagement: BOOL = FALSE); reintroduce; overload;
    function FromFile(filename: WideString; useEmbeddedColorManagement: BOOL = FALSE): TGPBitmap;
    function FromStream(stream: IStream; useEmbeddedColorManagement: BOOL = FALSE): TGPBitmap;
    constructor Create(width, height, stride: Integer; format: TPixelFormat; scan0: PBYTE); reintroduce; overload;
    constructor Create(width, height: Integer; format: TPixelFormat = PixelFormat32bppARGB); reintroduce; overload;
    constructor Create(width, height: Integer; target: TGPGraphics); reintroduce; overload;
    function Clone(rect: TGPRect; format: TPixelFormat): TGPBitmap; overload;
    function Clone(x, y, width, height: Integer; format: TPixelFormat): TGPBitmap; overload;
    function Clone(rect: TGPRectF; format: TPixelFormat): TGPBitmap; overload;
    function Clone(x, y, width, height: Single; format: TPixelFormat): TGPBitmap; overload;
    function LockBits(rect: TGPRect; flags: UINT; format: TPixelFormat; out lockedBitmapData: TBitmapData): TStatus;
    function UnlockBits(var lockedBitmapData: TBitmapData): TStatus;
    function GetPixel(x, y: Integer; out color: TGPColor): TStatus;
    function SetPixel(x, y: Integer; color: TGPColor): TStatus;
    function SetResolution(xdpi, ydpi: Single): TStatus;
    constructor Create(var gdiBitmapInfo: TBITMAPINFO; gdiBitmapData: Pointer); reintroduce; overload;
    constructor Create(hbm: HBITMAP; hpal: HPALETTE); reintroduce; overload;
    {$IFNDEF KS_CBUILDER}
    constructor Create(hicon: HICON); reintroduce; overload;
    function FromHICON(hicon: HICON): TGPBitmap;
    {$ENDIF}
    constructor Create(hInstance: HMODULE; bitmapName: WideString); reintroduce; overload;
    function FromBITMAPINFO(var gdiBitmapInfo: TBITMAPINFO; gdiBitmapData: Pointer): TGPBitmap;
    function FromHBITMAP(hbm: HBITMAP; hpal: HPALETTE): TGPBitmap;
    function FromResource(hInstance: HMODULE; bitmapName: WideString): TGPBitmap;
    function GetHBITMAP(colorBackground: TGPColor; out hbmReturn: HBITMAP): TStatus;
    function GetHICON(out hicon: HICON): TStatus;
  end;

  TGPCustomLineCap = class(TGdiplusBase)
  protected
    nativeCap: GpCustomLineCap;
    lastResult: TStatus;
    procedure SetNativeCap(nativeCap: GpCustomLineCap);
    function SetStatus(status: TStatus): TStatus;
    constructor Create(nativeCap: GpCustomLineCap;
      status: TStatus); reintroduce; overload;
  public
    constructor Create; reintroduce; overload;
    constructor Create(fillPath, strokePath: TGPGraphicsPath;
      baseCap: TLineCap = LineCapFlat;
      baseInset: Single = 0); reintroduce; overload;
    destructor Destroy; override;
    function Clone: TGPCustomLineCap;
    function SetStrokeCap(strokeCap: TLineCap): TStatus;
    function SetStrokeCaps(startCap, endCap: TLineCap): TStatus;
    function GetStrokeCaps(out startCap, endCap: TLineCap): TStatus;
    function SetStrokeJoin(lineJoin: TLineJoin): TStatus;
    function GetStrokeJoin: TLineJoin;
    function SetBaseCap(baseCap: TLineCap): TStatus;
    function GetBaseCap: TLineCap;
    function SetBaseInset(inset: Single): TStatus;
    function GetBaseInset: Single;
    function SetWidthScale(widthScale: Single): TStatus;
    function GetWidthScale: Single;
    function GetLastStatus: TStatus;
  end;

  TGPCachedBitmap = class(TGdiplusBase)
  protected
    nativeCachedBitmap: GpCachedBitmap;
    lastResult: TStatus;
  public
    constructor Create(bitmap: TGPBitmap; graphics: TGPGraphics); reintroduce;
    destructor Destroy; override;
    function GetLastStatus: TStatus;
  end;

  TGPImageAttributes = class(TGdiplusBase)
  protected
    nativeImageAttr: GpImageAttributes;
    lastResult: TStatus;
    procedure SetNativeImageAttr(nativeImageAttr: GpImageAttributes);
    function SetStatus(status: TStatus): TStatus;
    constructor Create(imageAttr: GpImageAttributes;
      status: GpStatus); reintroduce; overload;
  public
    constructor Create; reintroduce; overload;
    destructor Destroy; override;
    function Clone: TGPImageAttributes;
    function SetToIdentity(type_: TColorAdjustType = ColorAdjustTypeDefault): TStatus;
    function Reset(type_: TColorAdjustType = ColorAdjustTypeDefault): TStatus;
    function SetColorMatrix(const colorMatrix: TColorMatrix;
      mode: TColorMatrixFlags = ColorMatrixFlagsDefault;
      type_: TColorAdjustType = ColorAdjustTypeDefault): TStatus;
    function ClearColorMatrix(type_: TColorAdjustType = ColorAdjustTypeDefault): TStatus;
    function SetColorMatrices(const colorMatrix: TColorMatrix; const grayMatrix: TColorMatrix;
      mode: TColorMatrixFlags  = ColorMatrixFlagsDefault;
      type_: TColorAdjustType  = ColorAdjustTypeDefault): TStatus;
    function ClearColorMatrices(Type_: TColorAdjustType = ColorAdjustTypeDefault): TStatus;
    function SetThreshold(threshold: Single; type_: TColorAdjustType = ColorAdjustTypeDefault): TStatus;
    function ClearThreshold(type_: TColorAdjustType = ColorAdjustTypeDefault): TStatus;
    function SetGamma(gamma: Single; type_: TColorAdjustType = ColorAdjustTypeDefault): TStatus;
    function ClearGamma( type_: TColorAdjustType = ColorAdjustTypeDefault): TStatus;
    function SetNoOp(type_: TColorAdjustType = ColorAdjustTypeDefault): TStatus;
    function ClearNoOp(Type_: TColorAdjustType = ColorAdjustTypeDefault): TStatus;
    function SetColorKey(colorLow, colorHigh: TGPColor; type_: TColorAdjustType = ColorAdjustTypeDefault): TStatus;
    function ClearColorKey(type_: TColorAdjustType = ColorAdjustTypeDefault): TStatus;
    function SetOutputChannel(channelFlags: TColorChannelFlags; type_: TColorAdjustType = ColorAdjustTypeDefault): TStatus;
    function ClearOutputChannel(type_: TColorAdjustType = ColorAdjustTypeDefault): TStatus;
    function SetOutputChannelColorProfile(colorProfileFilename: WideString;
      type_: TColorAdjustType = ColorAdjustTypeDefault): TStatus;
    function ClearOutputChannelColorProfile(type_: TColorAdjustType = ColorAdjustTypeDefault): TStatus;
    function SetRemapTable(mapSize: Cardinal; map: PColorMap; type_: TColorAdjustType = ColorAdjustTypeDefault): TStatus;
    function ClearRemapTable(type_: TColorAdjustType = ColorAdjustTypeDefault): TStatus;
    function SetBrushRemapTable(mapSize: Cardinal; map: PColorMap): TStatus;
    function ClearBrushRemapTable: TStatus;
    function SetWrapMode(wrap: TWrapMode; color: TGPColor = aclBlack; clamp: BOOL = FALSE): TStatus;
    // The flags of the palette are ignored.
    function GetAdjustedPalette(colorPalette: PColorPalette; colorAdjustType: TColorAdjustType): TStatus;
    function GetLastStatus: TStatus;
  end;

  TMatrixArray = array[0..5] of Single;

  TGPMatrix = class(TGdiplusBase)
  protected
    nativeMatrix: GpMatrix;
    lastResult: GpStatus ;
    procedure SetNativeMatrix(nativeMatrix: GpMatrix);
    function SetStatus(status: GpStatus): TStatus;
    constructor Create(nativeMatrix: GpMatrix); reintroduce; overload;
  public
    // Default constructor is set to identity matrix.
    constructor Create; reintroduce; overload;
    constructor Create(m11, m12, m21, m22, dx, dy: Single); reintroduce; overload;
    constructor Create(const rect: TGPRectF; const dstplg: TGPPointF); reintroduce; overload;
    constructor Create(const rect: TGPRect; const dstplg: TGPPoint); reintroduce; overload;
    destructor Destroy; override;
    function Clone: TGPMatrix;
    function GetElements(const m: TMatrixArray): TStatus;
    function SetElements(m11, m12, m21, m22, dx, dy: Single): TStatus;
    function OffsetX: Single;
    function OffsetY: Single;
    function Reset: TStatus;
    function Multiply(matrix: TGPMatrix; order: TMatrixOrder = MatrixOrderPrepend): TStatus;                // ok
    function Translate(offsetX, offsetY: Single; order: TMatrixOrder = MatrixOrderPrepend): TStatus;      // ok
    function Scale(scaleX, scaleY: Single; order: TMatrixOrder = MatrixOrderPrepend): TStatus;            // ok
    function Rotate(angle: Single; order: TMatrixOrder = MatrixOrderPrepend): TStatus;                    // ok
    function RotateAt(angle: Single; const center: TGPPointF; order: TMatrixOrder = MatrixOrderPrepend): TStatus; // ok
    function Shear(shearX, shearY: Single; order: TMatrixOrder = MatrixOrderPrepend): TStatus;            // ok
    function Invert: TStatus;                                                                             // ok

    function TransformPoints(pts: PGPPointF; count: Integer = 1): TStatus; overload;
    function TransformPoints(pts: PGPPoint; count: Integer = 1): TStatus; overload;

    function TransformVectors(pts: PGPPointF; count: Integer = 1): TStatus; overload;
    function TransformVectors(pts: PGPPoint; count: Integer = 1): TStatus; overload;

    function IsInvertible: BOOL;
    function IsIdentity: BOOL;
    function Equals(matrix: TGPMatrix): BOOL;
    function GetLastStatus: TStatus;
  end;

  //--------------------------------------------------------------------------
  // Abstract base class for various brush types
  //--------------------------------------------------------------------------

  TGPBrush = class(TGdiplusBase)
  protected
    nativeBrush: GpBrush;
    lastResult: TStatus;
    procedure SetNativeBrush(nativeBrush: GpBrush);
    function SetStatus(status: TStatus): TStatus;
    constructor Create(nativeBrush: GpBrush; status: TStatus); overload;
  public
    constructor Create; overload;
    destructor Destroy; override;
    function Clone: TGPBrush; virtual;
    function GetType: TBrushType;
    function GetLastStatus: TStatus;
  end;

  //--------------------------------------------------------------------------
  // Solid Fill Brush Object
  //--------------------------------------------------------------------------

  TGPSolidBrush = class(TGPBrush)
  public
    constructor Create(color: TGPColor); reintroduce; overload;
    constructor Create; reintroduce; overload;
    function GetColor(out color: TGPColor): TStatus;
    function SetColor(color: TGPColor): TStatus;
  end;

  //--------------------------------------------------------------------------
  // Texture Brush Fill Object
  //--------------------------------------------------------------------------

  TGPTextureBrush = class(TGPBrush)
  public
    constructor Create(image: TGPImage; wrapMode: TWrapMode = WrapModeTile); reintroduce; overload;
    constructor Create(image: TGPImage; wrapMode: TWrapMode; dstRect: TGPRectF); reintroduce; overload;
    constructor Create(image: TGPImage; dstRect: TGPRectF; imageAttributes: TGPImageAttributes = nil); reintroduce; overload;
    constructor Create(image: TGPImage; dstRect: TGPRect; imageAttributes: TGPImageAttributes = nil); reintroduce; overload;
    constructor Create(image: TGPImage; wrapMode: TWrapMode; dstRect: TGPRect); reintroduce; overload;
    constructor Create(image: TGPImage; wrapMode: TWrapMode; dstX, dstY, dstWidth,
      dstHeight: Single); reintroduce; overload;
    constructor Create(image: TGPImage; wrapMode: TWrapMode; dstX, dstY, dstWidth,
      dstHeight: Integer); reintroduce; overload;
    constructor Create; reintroduce; overload;
    function SetTransform(matrix: TGPMatrix): TStatus;
    function GetTransform(matrix: TGPMatrix): TStatus;
    function ResetTransform: TStatus;
    function MultiplyTransform(matrix: TGPMatrix; order: TMatrixOrder = MatrixOrderPrepend): TStatus;
    function TranslateTransform(dx, dy: Single; order: MatrixOrder = MatrixOrderPrepend): TStatus;
    function ScaleTransform(sx, sy: Single; order: TMatrixOrder = MatrixOrderPrepend): TStatus;
    function RotateTransform(angle: Single; order: TMatrixOrder = MatrixOrderPrepend): TStatus;
    function SetWrapMode(wrapMode: TWrapMode): TStatus;
    function GetWrapMode: TWrapMode;
    function GetImage: TGPImage;
  end;

  //--------------------------------------------------------------------------
  // Linear Gradient Brush Object
  //--------------------------------------------------------------------------

  TGPLinearGradientBrush = class(TGPBrush)
  public
    constructor Create; reintroduce; overload;
    constructor Create(const point1, point2: TGPPointF; color1,
      color2: TGPColor); reintroduce; overload;
    constructor Create(const point1, point2: TGPPoint; color1,
      color2: TGPColor); reintroduce; overload;
    constructor Create(rect: TGPRectF; color1, color2: TGPColor;
      mode: TLinearGradientMode); reintroduce; overload;
    constructor Create(rect: TGPRect; color1, color2: TGPColor;
      mode: TLinearGradientMode); reintroduce; overload;
    constructor Create(rect: TGPRectF; color1, color2: TGPColor; angle: Single;
      isAngleScalable: BOOL = FALSE); overload;
    constructor Create(rect: TGPRect; color1, color2: TGPColor; angle: Single;
      isAngleScalable: BOOL = FALSE); overload;
    function SetLinearColors(color1, color2: TGPColor): TStatus;
    function GetLinearColors(out color1, color2: TGPColor): TStatus;
    function GetRectangle(out rect: TGPRectF): TStatus; overload;
    function GetRectangle(out rect: TGPRect): TStatus; overload;
    function SetGammaCorrection(useGammaCorrection: BOOL): TStatus;
    function GetGammaCorrection: BOOL;
    function GetBlendCount: Integer;
    function SetBlend(blendFactors, blendPositions: PSingle; count: Integer): TStatus;
    function GetBlend(blendFactors, blendPositions: PSingle; count: Integer): TStatus;
    function GetInterpolationColorCount: Integer;
    function SetInterpolationColors(presetColors: PGPColor; blendPositions: PSingle; count: Integer): TStatus;
    function GetInterpolationColors(presetColors: PGPColor; blendPositions: PSingle; count: Integer): TStatus;
    function SetBlendBellShape(focus: Single; scale: Single = 1.0): TStatus;
    function SetBlendTriangularShape(focus: Single; scale: Single = 1.0): TStatus;
    function SetTransform(matrix: TGPMatrix): TStatus;
    function GetTransform(matrix: TGPMatrix): TStatus;
    function ResetTransform: TStatus;
    function MultiplyTransform(matrix: TGPMatrix; order: TMatrixOrder = MatrixOrderPrepend): TStatus;
    function TranslateTransform(dx, dy: Single; order: TMatrixOrder = MatrixOrderPrepend): TStatus;
    function ScaleTransform(sx, sy: Single; order: TMatrixOrder = MatrixOrderPrepend): TStatus;
    function RotateTransform(angle: Single; order: TMatrixOrder = MatrixOrderPrepend): TStatus;
    function SetWrapMode(wrapMode: TWrapMode): TStatus;
    function GetWrapMode: TWrapMode;
  end;

  //--------------------------------------------------------------------------
  // Hatch Brush Object
  //--------------------------------------------------------------------------

  TGPHatchBrush = class(TGPBrush)
  public
    constructor Create; reintroduce; overload;
    constructor Create(hatchStyle: THatchStyle; foreColor: TGPColor; backColor: TGPColor = aclBlack); reintroduce; overload; // ok
    function GetHatchStyle: THatchStyle;
    function GetForegroundColor(out color: TGPColor): TStatus;
    function GetBackgroundColor(out color: TGPColor): TStatus;
  end;

//--------------------------------------------------------------------------
// Pen class
//--------------------------------------------------------------------------

  TGPPen = class(TGdiplusBase)
  protected
    nativePen: GpPen;
    lastResult: TStatus;
    procedure SetNativePen(nativePen: GpPen);
    function SetStatus(status: TStatus): TStatus;
    constructor Create(nativePen: GpPen; status: TStatus); reintroduce; overload;
  public
    constructor Create(color: TGPColor; width: Single = 1.0); reintroduce; overload;
    constructor Create(brush: TGPBrush; width: Single = 1.0); reintroduce; overload;
    destructor Destroy; override;
    function Clone: TGPPen;
    function SetWidth(width: Single): TStatus;
    function GetWidth: Single;
    // Set/get line caps: start, end, and dash
    // Line cap and join APIs by using LineCap and LineJoin enums.
    function SetLineCap(startCap, endCap: TLineCap; dashCap: TDashCap): TStatus;
    function SetStartCap(startCap: TLineCap): TStatus;
    function SetEndCap(endCap: TLineCap): TStatus;
    function SetDashCap(dashCap: TDashCap): TStatus;
    function GetStartCap: TLineCap;
    function GetEndCap: TLineCap;
    function GetDashCap: TDashCap;
    function SetLineJoin(lineJoin: TLineJoin): TStatus;
    function GetLineJoin: TLineJoin;
    function SetCustomStartCap(customCap: TGPCustomLineCap): TStatus;
    function GetCustomStartCap(customCap: TGPCustomLineCap): TStatus;
    function SetCustomEndCap(customCap: TGPCustomLineCap): TStatus;
    function GetCustomEndCap(customCap: TGPCustomLineCap): TStatus;
    function SetMiterLimit(miterLimit: Single): TStatus;
    function GetMiterLimit: Single;
    function SetAlignment(penAlignment: TPenAlignment): TStatus;
    function GetAlignment: TPenAlignment;
    function SetTransform(matrix: TGPMatrix): TStatus;
    function GetTransform(matrix: TGPMatrix): TStatus;
    function ResetTransform: TStatus;
    function MultiplyTransform(matrix: TGPMatrix; order: TMatrixOrder = MatrixOrderPrepend): TStatus;
    function TranslateTransform(dx, dy: Single; order: TMatrixOrder = MatrixOrderPrepend): TStatus;
    function ScaleTransform(sx, sy: Single; order: TMatrixOrder = MatrixOrderPrepend): TStatus;
    function RotateTransform(angle: Single; order: TMatrixOrder = MatrixOrderPrepend): TStatus;
    function GetPenType: TPenType;
    function SetColor(color: TGPColor): TStatus;
    function SetBrush(brush: TGPBrush): TStatus;
    function GetColor(out Color: TGPColor): TStatus;
    function GetBrush: TGPBrush;
    function GetDashStyle: TDashStyle;
    function SetDashStyle(dashStyle: TDashStyle): TStatus;
    function GetDashOffset: Single;
    function SetDashOffset(dashOffset: Single): TStatus;
    function SetDashPattern(dashArray: PSingle; count: Integer): TStatus;
    function GetDashPatternCount: Integer;
    function GetDashPattern(dashArray: PSingle; count: Integer): TStatus;
    function SetCompoundArray(compoundArray: PSingle; count: Integer): TStatus;
    function GetCompoundArrayCount: Integer;
    function GetCompoundArray(compoundArray: PSingle; count: Integer): TStatus;
    function GetLastStatus: TStatus;
  end;

  TGPStringFormat = class(TGdiplusBase)
  protected
    nativeFormat: GpStringFormat;
    lastError: TStatus;
    function SetStatus(newStatus: GpStatus): TStatus;
    procedure Assign(source: TGPStringFormat);
    constructor Create(clonedStringFormat: GpStringFormat; status: TStatus); reintroduce; overload;
  public
    constructor Create(formatFlags: Integer = 0; language: LANGID = LANG_NEUTRAL); reintroduce; overload;
    constructor Create(format: TGPStringFormat); reintroduce; overload;
    destructor Destroy; override;
    class function GenericDefault: TGPStringFormat;
    class function GenericTypographic: TGPStringFormat;
    function Clone: TGPStringFormat;
    function SetFormatFlags(flags: Integer): TStatus;
    function GetFormatFlags: Integer;
    function SetAlignment(align: TStringAlignment): TStatus;
    function GetAlignment: TStringAlignment;
    function SetLineAlignment(align: TStringAlignment): TStatus;
    function GetLineAlignment: TStringAlignment;
    function SetHotkeyPrefix(hotkeyPrefix: THotkeyPrefix): TStatus;
    function GetHotkeyPrefix: THotkeyPrefix;
    function SetTabStops(firstTabOffset: Single; count: Integer; tabStops: PSingle): TStatus;
    function GetTabStopCount: Integer;
    function GetTabStops(count: Integer; firstTabOffset, tabStops: PSingle): TStatus;
    function SetDigitSubstitution(language: LANGID; substitute: TStringDigitSubstitute): TStatus;
    function GetDigitSubstitutionLanguage: LANGID;
    function GetDigitSubstitutionMethod: TStringDigitSubstitute;
    function SetTrimming(trimming: TStringTrimming): TStatus;
    function GetTrimming: TStringTrimming;
    function SetMeasurableCharacterRanges(rangeCount: Integer; ranges: PCharacterRange): TStatus;
    function GetMeasurableCharacterRangeCount: Integer;
    function GetLastStatus: TStatus;
  end;

  TGPGraphicsPath = class(TGdiplusBase)
  protected
    nativePath: GpPath;
    lastResult: TStatus;
    procedure SetNativePath(nativePath: GpPath);
    function SetStatus(status: TStatus): TStatus;
    constructor Create(nativePath: GpPath); reintroduce; overload;
  public
    constructor Create(path: TGPGraphicsPath); reintroduce; overload;
    constructor Create(fillMode: TFillMode = FillModeAlternate); reintroduce; overload;
    constructor Create(points: PGPPointF; types: PBYTE; count: Integer;
      fillMode: TFillMode = FillModeAlternate); reintroduce; overload;
    constructor Create(points: PGPPoint; types: PBYTE; count: Integer;
      fillMode: TFillMode = FillModeAlternate); reintroduce; overload;
    destructor destroy; override;
    function Clone: TGPGraphicsPath;
    // Reset the path object to empty (and fill mode to FillModeAlternate)
    function Reset: TStatus;
    function GetFillMode: TFillMode;
    function SetFillMode(fillmode: TFillMode): TStatus;
    function GetPathData(pathData: TPathData): TStatus;
    function StartFigure: TStatus;
    function CloseFigure: TStatus;
    function CloseAllFigures: TStatus;
    function SetMarker: TStatus;
    function ClearMarkers: TStatus;
    function Reverse: TStatus;
    function GetLastPoint(out lastPoint: TGPPointF): TStatus;

    function AddLine(const pt1, pt2: TGPPointF): TStatus; overload;
    function AddLine(x1, y1, x2, y2: Single): TStatus; overload;
    function AddLines(points: PGPPointF; count: Integer): TStatus; overload;
    function AddLine(const pt1, pt2: TGPPoint): TStatus; overload;
    function AddLine(x1, y1, x2, y2: Integer): TStatus; overload;
    function AddLines(points: PGPPoint; count: Integer): TStatus; overload;

    function AddArc(rect: TGPRectF; startAngle, sweepAngle: Single): TStatus; overload;
    function AddArc(x, y, width, height, startAngle, sweepAngle: Single): TStatus; overload;
    function AddArc(rect: TGPRect; startAngle, sweepAngle: Single): TStatus; overload;
    function AddArc(x, y, width, height: Integer; startAngle, sweepAngle: Single): TStatus; overload;

    function AddBezier(pt1, pt2, pt3, pt4: TGPPointF): TStatus; overload;
    function AddBezier(x1, y1, x2, y2, x3, y3, x4, y4: Single): TStatus; overload;
    function AddBeziers(points: PGPPointF; count: Integer): TStatus; overload;
    function AddBezier(pt1, pt2, pt3, pt4: TGPPoint): TStatus; overload;
    function AddBezier(x1, y1, x2, y2, x3, y3, x4, y4: Integer): TStatus; overload;
    function AddBeziers(points: PGPPoint; count: Integer): TStatus; overload;

    function AddCurve(points: PGPPointF; count: Integer): TStatus; overload;
    function AddCurve(points: PGPPointF; count: Integer; tension: Single): TStatus; overload;
    function AddCurve(points: PGPPointF; count, offset, numberOfSegments: Integer; tension: Single): TStatus; overload;
    function AddCurve(points: PGPPoint; count: Integer): TStatus; overload;
    function AddCurve(points: PGPPoint; count: Integer; tension: Single): TStatus; overload;
    function AddCurve(points: PGPPoint; count, offset, numberOfSegments: Integer; tension: Single): TStatus; overload;

    function AddClosedCurve(points: PGPPointF; count: Integer): TStatus; overload;
    function AddClosedCurve(points: PGPPointF; count: Integer; tension: Single): TStatus; overload;
    function AddClosedCurve(points: PGPPoint; count: Integer): TStatus; overload;
    function AddClosedCurve(points: PGPPoint; count: Integer; tension: Single): TStatus; overload;

    function AddRectangle(rect: TGPRectF): TStatus; overload;
    function AddRectangles(rects: PGPRectF; count: Integer): TStatus; overload;
    function AddRectangle(rect: TGPRect): TStatus; overload;
    function AddRectangles(rects: PGPRect; count: Integer): TStatus; overload;

    function AddEllipse(rect: TGPRectF): TStatus; overload;
    function AddEllipse(x, y, width, height: Single): TStatus; overload;
    function AddEllipse(rect: TGPRect): TStatus; overload;
    function AddEllipse(x, y, width, height: Integer): TStatus; overload;

    function AddPie(rect: TGPRectF; startAngle, sweepAngle: Single): TStatus; overload;
    function AddPie(x, y, width, height, startAngle, sweepAngle: Single): TStatus; overload;
    function AddPie(rect: TGPRect; startAngle, sweepAngle: Single): TStatus; overload;
    function AddPie(x, y, width, height: Integer; startAngle, sweepAngle: Single): TStatus; overload;

    function AddPolygon(points: PGPPointF; count: Integer): TStatus; overload;
    function AddPolygon(points: PGPPoint; count: Integer): TStatus; overload;

    function AddPath(addingPath: TGPGraphicsPath; connect: Bool): TStatus;

    function AddString(string_: WideString; length: Integer; family : TGPFontFamily;
      style  : Integer; emSize : Single; origin : TGPPointF; format : TGPStringFormat): TStatus; overload;
    function AddString(string_: WideString; length : Integer; family : TGPFontFamily;
      style  : Integer; emSize : Single; layoutRect: TGPRectF; format : TGPStringFormat): TStatus; overload;
    function AddString(string_: WideString; length : Integer; family : TGPFontFamily;
      style  : Integer; emSize : Single; origin : TGPPoint; format : TGPStringFormat): TStatus; overload;
    function AddString(string_: WideString; length : Integer; family : TGPFontFamily;
      style  : Integer; emSize : Single; layoutRect: TGPRect; format : TGPStringFormat): TStatus; overload;

    function Transform(matrix: TGPMatrix): TStatus;

    // This is not always the tightest bounds.
    function GetBounds(out bounds: TGPRectF; matrix: TGPMatrix = nil; pen: TGPPen = nil): TStatus; overload;
    function GetBounds(out bounds: TGPRect; matrix: TGPMatrix = nil; pen: TGPPen = nil): TStatus;  overload;
    // Once flattened, the resultant path is made of line segments and
    // the original path information is lost.  When matrix is NULL the
    // identity matrix is assumed.
    function Flatten(matrix: TGPMatrix = nil; flatness: Single = FlatnessDefault): TStatus;
    function Widen(pen: TGPPen; matrix: TGPMatrix = nil; flatness: Single = FlatnessDefault): TStatus;
    function Outline(matrix: TGPMatrix = nil; flatness: Single = FlatnessDefault): TStatus;
    // Once this is called, the resultant path is made of line segments and
    // the original path information is lost.  When matrix is NULL, the
    // identity matrix is assumed.
    function Warp(destPoints: PGPPointF; count: Integer; srcRect: TGPRectF;
      matrix: TGPMatrix = nil; warpMode: TWarpMode = WarpModePerspective;
      flatness: Single = FlatnessDefault): TStatus;
    function GetPointCount: Int64;
    function GetPathTypes(types: PBYTE; count: Integer): TStatus;
    function GetPathPoints(points: PGPPointF; count: Integer): TStatus; overload;
    function GetPathPoints(points: PGPPoint; count: Integer): TStatus; overload;
    function GetLastStatus: TStatus;

    function IsVisible(point: TGPPointF; g: TGPGraphics = nil): BOOL; overload;
    function IsVisible(x, y: Single; g: TGPGraphics = nil): BOOL; overload;
    function IsVisible(point: TGPPoint; g : TGPGraphics = nil): BOOL; overload;
    function IsVisible(x, y: Integer; g: TGPGraphics = nil): BOOL; overload;

    function IsOutlineVisible(point: TGPPointF; pen: TGPPen; g: TGPGraphics = nil): BOOL; overload;
    function IsOutlineVisible(x, y: Single; pen: TGPPen; g: TGPGraphics = nil): BOOL; overload;
    function IsOutlineVisible(point: TGPPoint; pen: TGPPen; g: TGPGraphics = nil): BOOL; overload;
    function IsOutlineVisible(x, y: Integer; pen: TGPPen; g: TGPGraphics = nil): BOOL; overload;
  end;

//--------------------------------------------------------------------------
// GraphisPathIterator class
//--------------------------------------------------------------------------

  TGPGraphicsPathIterator = class(TGdiplusBase)
  protected
    nativeIterator: GpPathIterator;
    lastResult    : TStatus;
    procedure SetNativeIterator(nativeIterator: GpPathIterator);
    function SetStatus(status: TStatus): TStatus;
  public
    constructor Create(path: TGPGraphicsPath); reintroduce;
    destructor Destroy; override;
    function NextSubpath(out startIndex, endIndex: Integer; out isClosed: bool): Integer; overload;
    function NextSubpath(path: TGPGraphicsPath; out isClosed: BOOL): Integer; overload;
    function NextPathType(out pathType: TPathPointType; out startIndex, endIndex: Integer): Integer;
    function NextMarker(out startIndex, endIndex: Integer): Integer; overload;
    function NextMarker(path: TGPGraphicsPath): Integer; overload;
    function GetCount: Integer;
    function GetSubpathCount: Integer;
    function HasCurve: BOOL;
    procedure Rewind;
    function Enumerate(points: PGPPointF; types: PBYTE; count: Integer): Integer;
    function CopyData(points: PGPPointF; types: PBYTE; startIndex, endIndex: Integer): Integer;
    function GetLastStatus: TStatus;
  end;

//--------------------------------------------------------------------------
// Path Gradient Brush
//--------------------------------------------------------------------------

  TGPPathGradientBrush = class(TGPBrush)
  public
    constructor Create(points: PGPPointF; count: Integer;
      wrapMode: TWrapMode = WrapModeClamp); reintroduce; overload;
    constructor Create(points: PGPPoint; count: Integer;
      wrapMode: TWrapMode = WrapModeClamp); reintroduce; overload;
    constructor Create(path: TGPGraphicsPath); reintroduce; overload;
    constructor Create; reintroduce; overload;
    function GetCenterColor(out Color: TGPColor): TStatus;
    function SetCenterColor(color: TGPColor): TStatus;
    function GetPointCount: Integer;
    function GetSurroundColorCount: Integer;
    function GetSurroundColors(colors: PARGB; var count: Integer): TStatus;
    function SetSurroundColors(colors: PARGB; var count: Integer): TStatus;
    function GetGraphicsPath(path: TGPGraphicsPath): TStatus;
    function SetGraphicsPath(path: TGPGraphicsPath): TStatus;
    function GetCenterPoint(out point: TGPPointF): TStatus; overload;
    function GetCenterPoint(out point: TGPPoint): TStatus; overload;
    function SetCenterPoint(point: TGPPointF): TStatus; overload;
    function SetCenterPoint(point: TGPPoint): TStatus; overload;
    function GetRectangle(out rect: TGPRectF): TStatus; overload;
    function GetRectangle(out rect: TGPRect): TStatus; overload;
    function SetGammaCorrection(useGammaCorrection: BOOL): TStatus; overload;
    function GetGammaCorrection: BOOL; overload;
    function GetBlendCount: Integer;
    function GetBlend(blendFactors, blendPositions: PSingle; count: Integer): TStatus;
    function SetBlend(blendFactors, blendPositions: PSingle; count: Integer): TStatus;
    function GetInterpolationColorCount: Integer;
    function SetInterpolationColors(presetColors: PARGB; blendPositions: PSingle;
      count: Integer): TStatus;
    function GetInterpolationColors(presetColors: PARGB;
      blendPositions: PSingle; count: Integer): TStatus;
    function SetBlendBellShape(focus: Single; scale: Single = 1.0): TStatus;
    function SetBlendTriangularShape(focus: Single; scale: Single = 1.0): TStatus;
    function GetTransform(matrix: TGPMatrix): TStatus;
    function SetTransform(matrix: TGPMatrix): TStatus;
    function ResetTransform: TStatus;
    function MultiplyTransform(matrix: TGPMatrix;
      order: TMatrixOrder = MatrixOrderPrepend): TStatus;
    function TranslateTransform(dx, dy: Single;
      order: TMatrixOrder = MatrixOrderPrepend): TStatus;
    function ScaleTransform(sx, sy: Single;
      order: TMatrixOrder = MatrixOrderPrepend): TStatus;
    function RotateTransform(angle: Single;
      order: TMatrixOrder = MatrixOrderPrepend): TStatus;
    function GetFocusScales(out xScale, yScale: Single): TStatus;
    function SetFocusScales(xScale, yScale: Single): TStatus;
    function GetWrapMode: TWrapMode;
    function SetWrapMode(wrapMode: TWrapMode): TStatus;
  end;

  TGPGraphics = class(TGdiplusBase)
  protected
    nativeGraphics: GpGraphics;
    lastResult: TStatus;
    procedure SetNativeGraphics(graphics: GpGraphics);
    function SetStatus(status: TStatus): TStatus;
    function GetNativeGraphics: GpGraphics;
    function GetNativePen(pen: TGPPen): GpPen;
    constructor Create(graphics: GpGraphics); reintroduce; overload;
  public
    function FromHDC(hdc: HDC): TGPGraphics; overload;
    function FromHDC(hdc: HDC; hdevice: THANDLE): TGPGraphics; overload;
    function FromHWND(hwnd: HWND; icm: BOOL = FALSE): TGPGraphics;
    function FromImage(image: TGPImage): TGPGraphics;
    constructor Create(hdc: HDC; NotUses1: integer = 0; NotUses2: integer = 0); reintroduce; overload;
    constructor Create(hdc: HDC; hdevice: THANDLE); reintroduce; overload;
    constructor Create(hwnd: HWND; icm: BOOL{ = FALSE}); reintroduce; overload;
    constructor Create(image: TGPImage); reintroduce; overload;
    destructor destroy; override;
    procedure Flush(intention: TFlushIntention = FlushIntentionFlush);
    //------------------------------------------------------------------------
    // GDI Interop methods
    //------------------------------------------------------------------------
    // Locks the graphics until ReleaseDC is called
    function GetHDC: HDC;
    procedure ReleaseHDC(hdc: HDC);
    //------------------------------------------------------------------------
    // Rendering modes
    //------------------------------------------------------------------------
    function SetRenderingOrigin(x, y: Integer): TStatus;
    function GetRenderingOrigin(out x, y: Integer): TStatus;
    function SetCompositingMode(compositingMode: TCompositingMode): TStatus;
    function GetCompositingMode: TCompositingMode;
    function SetCompositingQuality(compositingQuality: TCompositingQuality): TStatus;
    function GetCompositingQuality: TCompositingQuality;
    function SetTextRenderingHint(newMode: TTextRenderingHint): TStatus;
    function GetTextRenderingHint: TTextRenderingHint;
    function SetTextContrast(contrast: UINT): TStatus; // 0..12
    function GetTextContrast: UINT;
    function GetInterpolationMode: TInterpolationMode;
    function SetInterpolationMode(interpolationMode: TInterpolationMode): TStatus;
    function GetSmoothingMode: TSmoothingMode;
    function SetSmoothingMode(smoothingMode: TSmoothingMode): TStatus;
    function GetPixelOffsetMode: TPixelOffsetMode;
    function SetPixelOffsetMode(pixelOffsetMode: TPixelOffsetMode): TStatus;
    //------------------------------------------------------------------------
    // Manipulate current world transform
    //------------------------------------------------------------------------
    function SetTransform(matrix: TGPMatrix): TStatus;
    function ResetTransform: TStatus;
    function MultiplyTransform(matrix: TGPMatrix; order: TMatrixOrder = MatrixOrderPrepend): TStatus;
    function TranslateTransform(dx, dy: Single; order: TMatrixOrder = MatrixOrderPrepend): TStatus;
    function ScaleTransform(sx, sy: Single; order: TMatrixOrder = MatrixOrderPrepend): TStatus;
    function RotateTransform(angle: Single; order: TMatrixOrder = MatrixOrderPrepend): TStatus;
    function GetTransform(matrix: TGPMatrix): TStatus;
    function SetPageUnit(unit_: TUnit): TStatus;
    function SetPageScale(scale: Single): TStatus;
    function GetPageUnit: TUnit;
    function GetPageScale: Single;
    function GetDpiX: Single;
    function GetDpiY: Single;
    function TransformPoints(destSpace: TCoordinateSpace; srcSpace: TCoordinateSpace;
      pts: PGPPointF; count: Integer): TStatus; overload;
    function TransformPoints(destSpace: TCoordinateSpace; srcSpace: TCoordinateSpace;
      pts: PGPPoint; count: Integer): TStatus; overload;
    //------------------------------------------------------------------------
    // GetNearestColor (for <= 8bpp surfaces).  Note: Alpha is ignored.
    //------------------------------------------------------------------------
    function GetNearestColor(var color: TGPColor): TStatus;

    // DrawLine(s)
    function DrawLine(pen: TGPPen; x1, y1, x2, y2: Single): TStatus; overload;
    function DrawLine(pen: TGPPen; const pt1, pt2: TGPPointF): TStatus; overload;
    function DrawLines(pen: TGPPen; points: PGPPointF; count: Integer): TStatus; overload;
    function DrawLine(pen: TGPPen; x1, y1, x2, y2: Integer): TStatus; overload;
    function DrawLine(pen: TGPPen; const pt1, pt2: TGPPoint): TStatus; overload;
    function DrawLines(pen: TGPPen; points: PGPPoint; count: Integer): TStatus; overload;

    // DrawArc
    function DrawArc(pen: TGPPen; x, y, width, height, startAngle, sweepAngle: Single): TStatus; overload;
    function DrawArc(pen: TGPPen; const rect: TGPRectF; startAngle, sweepAngle: Single): TStatus; overload;
    function DrawArc(pen: TGPPen; x, y, width, height: Integer; startAngle, sweepAngle: Single): TStatus; overload;
    function DrawArc(pen: TGPPen; const rect: TGPRect; startAngle, sweepAngle: Single): TStatus; overload;

    // DrawBezier(s)
    function DrawBezier(pen: TGPPen; x1, y1, x2, y2, x3, y3, x4, y4: Single): TStatus; overload;
    function DrawBezier(pen: TGPPen; const pt1, pt2, pt3, pt4: TGPPointF): TStatus; overload;
    function DrawBeziers(pen: TGPPen; points: PGPPointF; count: Integer): TStatus; overload;
    function DrawBezier(pen: TGPPen; x1, y1, x2, y2, x3, y3, x4, y4: Integer): TStatus; overload;
    function DrawBezier(pen: TGPPen; const pt1, pt2, pt3, pt4: TGPPoint): TStatus; overload;
    function DrawBeziers(pen: TGPPen; points: PGPPoint; count: Integer): TStatus; overload;

    // DrawRectangle(s)
    function DrawRectangle(pen: TGPPen; const rect: TGPRectF): TStatus; overload;
    function DrawRectangle(pen: TGPPen; x, y, width, height: Single): TStatus; overload;
    function DrawRectangles(pen: TGPPen; rects: PGPRectF; count: Integer): TStatus; overload;
    function DrawRectangle(pen: TGPPen; const rect: TGPRect): TStatus; overload;
    function DrawRectangle(pen: TGPPen; x, y, width, height: Integer): TStatus; overload;
    function DrawRectangles(pen: TGPPen; rects: PGPRect; count: Integer): TStatus; overload;

    // DrawEllipse
    function DrawEllipse(pen: TGPPen; const rect: TGPRectF): TStatus; overload;
    function DrawEllipse(pen: TGPPen; x, y, width, height: Single): TStatus; overload;
    function DrawEllipse(pen: TGPPen; const rect: TGPRect): TStatus; overload;
    function DrawEllipse(pen: TGPPen; x, y, width, height: Integer): TStatus; overload;

    // DrawPie
    function DrawPie(pen: TGPPen; const rect: TGPRectF; startAngle, sweepAngle: Single): TStatus; overload;
    function DrawPie(pen: TGPPen; x, y, width, height, startAngle, sweepAngle: Single): TStatus; overload;
    function DrawPie(pen: TGPPen; const rect: TGPRect; startAngle, sweepAngle: Single): TStatus; overload;
    function DrawPie(pen: TGPPen; x, y, width, height: Integer; startAngle, sweepAngle: Single): TStatus; overload;

    // DrawPolygon
    function DrawPolygon(pen: TGPPen; points: PGPPointF; count: Integer): TStatus; overload;
    function DrawPolygon(pen: TGPPen; points: PGPPoint; count: Integer): TStatus; overload;

    // DrawPath
    function DrawPath(pen: TGPPen; path: TGPGraphicsPath): TStatus;

    // DrawCurve
    function DrawCurve(pen: TGPPen; points: PGPPointF; count: Integer): TStatus; overload;
    function DrawCurve(pen: TGPPen; points: PGPPointF; count: Integer; tension: Single): TStatus; overload;
    function DrawCurve(pen: TGPPen; points: PGPPointF; count, offset,
      numberOfSegments: Integer; tension: Single = 0.5): TStatus; overload;
    function DrawCurve(pen: TGPPen; points: PGPPoint; count: Integer): TStatus; overload;
    function DrawCurve(pen: TGPPen; points: PGPPoint; count: Integer; tension: Single): TStatus; overload;
    function DrawCurve(pen: TGPPen; points: PGPPoint; count, offset, numberOfSegments: Integer;
      tension: Single = 0.5): TStatus; overload;

    // DrawClosedCurve
    function DrawClosedCurve(pen: TGPPen; points: PGPPointF; count: Integer): TStatus; overload;
    function DrawClosedCurve(pen: TGPPen; points: PGPPointF; count: Integer; tension: Single): TStatus; overload;
    function DrawClosedCurve(pen: TGPPen; points: PGPPoint;  count: Integer): TStatus; overload;
    function DrawClosedCurve(pen: TGPPen; points: PGPPoint; count: Integer; tension: Single): TStatus; overload;

    // Clear
    function Clear(color: TGPColor): TStatus;

    // FillRectangle(s)
    function FillRectangle(brush: TGPBrush; const rect: TGPRectF): TStatus; overload;
    function FillRectangle(brush: TGPBrush; x, y, width, height: Single): TStatus; overload;
    function FillRectangles(brush: TGPBrush; rects: PGPRectF; count: Integer): TStatus; overload;
    function FillRectangle(brush: TGPBrush; const rect: TGPRect): TStatus; overload;
    function FillRectangle(brush: TGPBrush; x, y, width, height: Integer): TStatus; overload;
    function FillRectangles(brush: TGPBrush; rects: PGPRect; count: Integer): TStatus; overload;

    // FillPolygon
    function FillPolygon(brush: TGPBrush; points: PGPPointF; count: Integer): TStatus; overload;
    function FillPolygon(brush: TGPBrush; points: PGPPointF; count: Integer; fillMode: TFillMode): TStatus; overload;
    function FillPolygon(brush: TGPBrush; points: PGPPoint; count: Integer): TStatus; overload;
    function FillPolygon(brush: TGPBrush; points: PGPPoint; count: Integer; fillMode: TFillMode): TStatus; overload;

    // FillEllipse
    function FillEllipse(brush: TGPBrush; const rect: TGPRectF): TStatus; overload;
    function FillEllipse(brush: TGPBrush; x, y, width, height: Single): TStatus; overload;
    function FillEllipse(brush: TGPBrush; const rect: TGPRect): TStatus; overload;
    function FillEllipse(brush: TGPBrush; x, y, width, height: Integer): TStatus; overload;

    // FillPie
    function FillPie(brush: TGPBrush; const rect: TGPRectF; startAngle, sweepAngle: Single): TStatus; overload;
    function FillPie(brush: TGPBrush; x, y, width, height, startAngle, sweepAngle: Single): TStatus; overload;
    function FillPie(brush: TGPBrush; const rect: TGPRect; startAngle, sweepAngle: Single): TStatus; overload;
    function FillPie(brush: TGPBrush; x, y, width, height: Integer; startAngle, sweepAngle: Single): TStatus; overload;

    // FillPath
    function FillPath(brush: TGPBrush; path: TGPGraphicsPath): TStatus;

    // FillClosedCurve
    function FillClosedCurve(brush: TGPBrush; points: PGPPointF; count: Integer): TStatus; overload;
    function FillClosedCurve(brush: TGPBrush; points: PGPPointF; count: Integer;
      fillMode: TFillMode; tension: Single = 0.5 ): TStatus; overload;
    function FillClosedCurve(brush: TGPBrush; points: PGPPoint; count: Integer): TStatus; overload;
    function FillClosedCurve(brush: TGPBrush; points: PGPPoint; count: Integer;
      fillMode: TFillMode; tension: Single = 0.5): TStatus; overload;

    // FillRegion
    function FillRegion(brush: TGPBrush; region: TGPRegion): TStatus;

    // DrawString
    function DrawString(string_: WideString; length: Integer; font: TGPFont;
      const layoutRect: TGPRectF; stringFormat: TGPStringFormat; brush: TGPBrush): TStatus; overload;
    function DrawString(string_: WideString; length: Integer; font: TGPFont;
      const origin: TGPPointF; brush: TGPBrush): TStatus; overload;
    function DrawString(string_: WideString; length: Integer; font: TGPFont;
      const origin: TGPPointF; stringFormat: TGPStringFormat; brush: TGPBrush): TStatus; overload;

    // MeasureString
    function MeasureString(string_: WideString; length: Integer; font: TGPFont;
      const layoutRect: TGPRectF; stringFormat: TGPStringFormat; out boundingBox: TGPRectF;
      codepointsFitted: PInteger = nil; linesFilled: PInteger = nil): TStatus; overload;
    function MeasureString(string_: WideString; length: Integer; font: TGPFont;
      const layoutRectSize: TGPSizeF; stringFormat: TGPStringFormat; out size: TGPSizeF;
      codepointsFitted: PInteger = nil; linesFilled: PInteger = nil): TStatus; overload;
    function MeasureString(string_: WideString ; length: Integer; font: TGPFont;
      const origin: TGPPointF; stringFormat: TGPStringFormat;
      out boundingBox: TGPRectF): TStatus; overload;
    function MeasureString(string_: WideString; length: Integer; font: TGPFont;
      const layoutRect: TGPRectF; out boundingBox: TGPRectF): TStatus; overload;
    function MeasureString(string_: WideString; length: Integer; font: TGPFont;
      const origin: TGPPointF; out boundingBox: TGPRectF): TStatus; overload;

    // MeasureCharacterRanges
    function MeasureCharacterRanges(string_: WideString; length: Integer; font: TGPFont;
      const layoutRect: TGPRectF; stringFormat: TGPStringFormat; regionCount: Integer;
      const regions: array of TGPRegion): TStatus; overload;

    // DrawDriverString
    function DrawDriverString(text: PUINT16; length: Integer; font: TGPFont;
      brush: TGPBrush; positions: PGPPointF; flags: Integer; matrix: TGPMatrix): TStatus;

    // MeasureDriverString
    function MeasureDriverString(text: PUINT16; length: Integer; font: TGPFont;
       positions: PGPPointF; flags: Integer; matrix: TGPMatrix;
       out boundingBox: TGPRectF): TStatus;

    // Draw a cached bitmap on this graphics destination offset by
    // x, y. Note this will fail with WrongState if the CachedBitmap
    // native format differs from this Graphics.
    function DrawCachedBitmap(cb: TGPCachedBitmap;  x, y: Integer): TStatus;
    function DrawImage(image: TGPImage; const point: TGPPointF): TStatus; overload;
    function DrawImage(image: TGPImage; x, y: Single): TStatus; overload;
    function DrawImage(image: TGPImage; const rect: TGPRectF): TStatus; overload;
    function DrawImage(image: TGPImage; x, y, width, height: Single): TStatus; overload;
    function DrawImage(image: TGPImage; const point: TGPPoint): TStatus; overload;
    function DrawImage(image: TGPImage; x, y: Integer): TStatus; overload;
    function DrawImage(image: TGPImage; const rect: TGPRect): TStatus; overload;
    function DrawImage(image: TGPImage; x, y, width, height: Integer): TStatus; overload;

    // Affine Draw Image
    // destPoints.length = 3: rect => parallelogram
    //     destPoints[0] <=> top-left corner of the source rectangle
    //     destPoints[1] <=> top-right corner
    //     destPoints[2] <=> bottom-left corner
    // destPoints.length = 4: rect => quad
    //     destPoints[3] <=> bottom-right corner
    function DrawImage(image: TGPImage; destPoints: PGPPointF; count: Integer): TStatus; overload;
    function DrawImage(image: TGPImage; destPoints: PGPPoint; count: Integer): TStatus; overload;
    function DrawImage(image: TGPImage; x, y, srcx, srcy, srcwidth, srcheight: Single; srcUnit: TUnit): TStatus; overload;
    function DrawImage(image: TGPImage; const destRect: TGPRectF; srcx, srcy,
      srcwidth, srcheight: Single; srcUnit: TUnit;
      imageAttributes: TGPImageAttributes = nil; callback: DrawImageAbort = nil;
      callbackData: Pointer = nil): TStatus; overload;
    function DrawImage(image: TGPImage; destPoints: PGPPointF; count: Integer;
      srcx, srcy, srcwidth, srcheight: Single; srcUnit: TUnit;
      imageAttributes: TGPImageAttributes = nil; callback: DrawImageAbort = nil;
      callbackData: Pointer = nil): TStatus; overload;
    function DrawImage(image: TGPImage; x, y, srcx, srcy, srcwidth,
      srcheight: Integer; srcUnit: TUnit): TStatus; overload;
    function DrawImage(image: TGPImage; const destRect: TGPRect; srcx, srcy,
      srcwidth, srcheight: Integer; srcUnit: TUnit;
      imageAttributes: TGPImageAttributes = nil; callback: DrawImageAbort = nil;
      callbackData: Pointer = nil): TStatus; overload;
    function DrawImage(image: TGPImage; destPoints: PGPPoint;
      count, srcx, srcy, srcwidth, srcheight: Integer; srcUnit: TUnit;
      imageAttributes: TGPImageAttributes = nil; callback: DrawImageAbort = nil;
      callbackData: Pointer = nil): TStatus; overload;

    // The following methods are for playing an EMF+ to a graphics
    // via the enumeration interface.  Each record of the EMF+ is
    // sent to the callback (along with the callbackData).  Then
    // the callback can invoke the Metafile::PlayRecord method
    // to play the particular record.
    function EnumerateMetafile(metafile: TGPMetafile; const destPoint: TGPPointF;
      callback: EnumerateMetafileProc; callbackData: Pointer = nil;
      imageAttributes: TGPImageAttributes = nil): TStatus; overload;
    function EnumerateMetafile(metafile: TGPMetafile; const destPoint: TGPPoint;
       callback: EnumerateMetafileProc; callbackData: pointer = nil;
       imageAttributes: TGPImageAttributes = nil): TStatus; overload;
    function EnumerateMetafile(metafile: TGPMetafile; const destRect: TGPRectF;
       callback: EnumerateMetafileProc; callbackData: Pointer = nil;
       imageAttributes: TGPImageAttributes = nil): TStatus; overload;
    function EnumerateMetafile(metafile: TGPMetafile; const destRect: TGPRect;
       callback: EnumerateMetafileProc; callbackData: Pointer = nil;
       imageAttributes: TGPImageAttributes = nil): TStatus; overload;
    function EnumerateMetafile(metafile: TGPMetafile; destPoints: PGPPointF;
       count: Integer; callback: EnumerateMetafileProc; callbackData: Pointer = nil;
       imageAttributes: TGPImageAttributes = nil): TStatus; overload;
    function EnumerateMetafile(metafile: TGPMetafile; destPoints: PGPPoint;
       count: Integer; callback: EnumerateMetafileProc; callbackData: Pointer = nil;
       imageAttributes: TGPImageAttributes = nil): TStatus; overload;
    function EnumerateMetafile(metafile: TGPMetafile; const destPoint: TGPPointF;
       const srcRect: TGPRectF; srcUnit: TUnit; callback: EnumerateMetafileProc;
       callbackData: pointer = nil; imageAttributes: TGPImageAttributes = nil
       ): TStatus; overload;
    function EnumerateMetafile(metafile : TGPMetafile; const destPoint : TGPPoint;
       const srcRect : TGPRect; srcUnit : TUnit; callback : EnumerateMetafileProc;
       callbackData : Pointer = nil; imageAttributes : TGPImageAttributes = nil
       ): TStatus; overload;
    function EnumerateMetafile(metafile: TGPMetafile; const destRect: TGPRectF;
       const srcRect: TGPRectF; srcUnit: TUnit; callback: EnumerateMetafileProc;
       callbackData: Pointer = nil; imageAttributes: TGPImageAttributes = nil): TStatus; overload;
    function EnumerateMetafile(metafile : TGPMetafile; const destRect, srcRect: TGPRect;
       srcUnit : TUnit; callback : EnumerateMetafileProc; callbackData : Pointer = nil;
       imageAttributes : TGPImageAttributes = nil): TStatus; overload;
    function EnumerateMetafile( metafile: TGPMetafile; destPoints: PGPPointF;
        count: Integer; const srcRect: TGPRectF; srcUnit: TUnit; callback: EnumerateMetafileProc;
        callbackData: Pointer = nil; imageAttributes: TGPImageAttributes = nil): TStatus; overload;
    function EnumerateMetafile(metafile: TGPMetafile; destPoints: PGPPoint;
        count: Integer; const srcRect: TGPRect; srcUnit: TUnit; callback: EnumerateMetafileProc;
        callbackData: Pointer = nil; imageAttributes: TGPImageAttributes = nil): TStatus; overload;

    // SetClip
    function SetClip(g: TGPGraphics; combineMode: TCombineMode = CombineModeReplace): TStatus; overload;
    function SetClip(rect: TGPRectF; combineMode: TCombineMode = CombineModeReplace): TStatus; overload;
    function SetClip(rect: TGPRect; combineMode: TCombineMode = CombineModeReplace): TStatus; overload;
    function SetClip(path: TGPGraphicsPath; combineMode: TCombineMode = CombineModeReplace): TStatus; overload;
    function SetClip(region: TGPRegion; combineMode: TCombineMode = CombineModeReplace): TStatus; overload;
    // This is different than the other SetClip methods because it assumes
    // that the HRGN is already in device units, so it doesn't transform
    // the coordinates in the HRGN.
    function SetClip(hRgn: HRGN; combineMode: TCombineMode = CombineModeReplace): TStatus; overload;

    // IntersectClip
    function IntersectClip(const rect: TGPRectF): TStatus; overload;
    function IntersectClip(const rect: TGPRect): TStatus; overload;
    function IntersectClip(region: TGPRegion): TStatus; overload;
    // ExcludeClip
    function ExcludeClip(const rect: TGPRectF): TStatus; overload;
    function ExcludeClip(const rect: TGPRect): TStatus; overload;
    function ExcludeClip(region: TGPRegion): TStatus; overload;

    function ResetClip: TStatus;

    function TranslateClip(dx, dy: Single): TStatus; overload;
    function TranslateClip(dx, dy: Integer): TStatus; overload;

    function GetClip(region: TGPRegion): TStatus;

    function GetClipBounds(out rect: TGPRectF): TStatus; overload;
    function GetClipBounds(out rect: TGPRect): TStatus; overload;

    function IsClipEmpty: Bool;

    function GetVisibleClipBounds(out rect: TGPRectF): TStatus; overload;
    function GetVisibleClipBounds(out rect: TGPRect): TStatus; overload;

    function IsVisibleClipEmpty: BOOL;

    function IsVisible(x, y: Integer): BOOL; overload;
    function IsVisible(const point: TGPPoint): BOOL; overload;
    function IsVisible(x, y, width, height: Integer): BOOL; overload;
    function IsVisible(const rect: TGPRect): BOOL; overload;
    function IsVisible(x, y: Single): BOOL; overload;
    function IsVisible(const point: TGPPointF): BOOL; overload;
    function IsVisible(x, y, width, height: Single): BOOL; overload;
    function IsVisible(const rect: TGPRectF): BOOL; overload;

    function Save: GraphicsState;
    function Restore(gstate: GraphicsState): TStatus;

    function BeginContainer(const dstrect,srcrect: TGPRectF; unit_: TUnit): GraphicsContainer; overload;
    function BeginContainer(const dstrect, srcrect: TGPRect; unit_: TUnit): GraphicsContainer; overload;
    function BeginContainer: GraphicsContainer; overload;
    function EndContainer(state: GraphicsContainer): TStatus;

    // Only valid when recording metafiles.
    function AddMetafileComment(data: PBYTE; sizeData: UINT): TStatus;

    function GetHalftonePalette: HPALETTE;
    function GetLastStatus: TStatus;
  end;


  TGPAdjustableArrowCap = class(TGPCustomLineCap)
  public
    constructor Create(height, width: Single; isFilled: Bool = TRUE);
    function SetHeight(height: Single): TStatus;
    function GetHeight: Single;
    function SetWidth(width: Single): TStatus;
    function GetWidth: Single;
    function SetMiddleInset(middleInset: Single): TStatus;
    function GetMiddleInset: Single;
    function SetFillState(isFilled: Bool): TStatus;
    function IsFilled: BOOL;
  end;

  TGPMetafile = class(TGPImage)
  public
    constructor Create(hWmf: HMETAFILE; var wmfPlaceableFileHeader: TWmfPlaceableFileHeader;
      deleteWmf: BOOL = FALSE); overload;
    constructor Create(hEmf: HENHMETAFILE; deleteEmf: BOOL = FALSE); overload;
    constructor Create(filename: WideString); overload;
    constructor Create(filename: WideString; var wmfPlaceableFileHeader: TWmfPlaceableFileHeader); overload;
    constructor Create(stream: IStream); overload;
    constructor Create(referenceHdc: HDC; type_: TEmfType = EmfTypeEmfPlusDual;
      description: PWCHAR = nil); overload;
    constructor Create(referenceHdc: HDC; frameRect: TGPRectF;
      frameUnit: TMetafileFrameUnit = MetafileFrameUnitGdi;
      type_: TEmfType = EmfTypeEmfPlusDual; description: PWCHAR = nil); overload;
    constructor Create(referenceHdc: HDC; frameRect: TGPRect;
      frameUnit: TMetafileFrameUnit = MetafileFrameUnitGdi;
      type_: TEmfType = EmfTypeEmfPlusDual; description: PWCHAR = nil); overload;
    constructor Create(fileName: WideString;referenceHdc: HDC;
      type_: TEmfType = EmfTypeEmfPlusDual; description: PWCHAR = nil); overload;
    constructor Create(fileName: WideString; referenceHdc: HDC; frameRect: TGPRectF;
      frameUnit: TMetafileFrameUnit = MetafileFrameUnitGdi;
      type_: TEmfType = EmfTypeEmfPlusDual; description: PWCHAR = nil); overload;
    constructor Create( fileName: WideString; referenceHdc: HDC; frameRect: TGPRect;
      frameUnit: TMetafileFrameUnit = MetafileFrameUnitGdi;
      type_: TEmfType = EmfTypeEmfPlusDual; description: PWCHAR = nil); overload;
    constructor Create(stream: IStream; referenceHdc: HDC;
      type_: TEmfType = EmfTypeEmfPlusDual; description: PWCHAR = nil); overload;
    constructor Create(stream: IStream; referenceHdc: HDC; frameRect: TGPRectF;
      frameUnit: TMetafileFrameUnit = MetafileFrameUnitGdi;
      type_: TEmfType = EmfTypeEmfPlusDual; description: PWCHAR = nil); overload;
    constructor Create(stream : IStream; referenceHdc : HDC; frameRect : TGPRect;
     frameUnit : TMetafileFrameUnit = MetafileFrameUnitGdi;
     type_ : TEmfType = EmfTypeEmfPlusDual; description : PWCHAR = nil); overload;
    constructor Create; reintroduce; overload;
    function GetMetafileHeader(hWmf: HMETAFILE; var wmfPlaceableFileHeader: TWmfPlaceableFileHeader;
      header: TMetafileHeader): TStatus; overload;
    function GetMetafileHeader(hEmf: HENHMETAFILE; header: TMetafileHeader): TStatus; overload;   // ok
    function GetMetafileHeader(filename: WideString; header: TMetafileHeader): TStatus; overload; // ok
    function GetMetafileHeader(stream: IStream; header: TMetafileHeader): TStatus; overload;      // ok
    function GetMetafileHeader(header: TMetafileHeader): TStatus; overload;                       // ok
    function GetHENHMETAFILE: HENHMETAFILE;
    function PlayRecord(recordType: TEmfPlusRecordType; flags, dataSize: UINT; data: PBYTE): TStatus;
    function SetDownLevelRasterizationLimit(metafileRasterizationLimitDpi: UINT): TStatus;
    function GetDownLevelRasterizationLimit: UINT;
    function EmfToWmfBits(hemf: HENHMETAFILE; cbData16: UINT; pData16: PBYTE;
      iMapMode: Integer = MM_ANISOTROPIC; eFlags: TEmfToWmfBitsFlags = EmfToWmfBitsFlagsDefault): UINT;
  end;

////////////////////////////////////////////////////////////////////////////////

////////////////////////////////////////////////////////////////////////////////

var
   GenericSansSerifFontFamily : TGPFontFamily = nil;
   GenericSerifFontFamily     : TGPFontFamily = nil;
   GenericMonospaceFontFamily : TGPFontFamily = nil;

   GenericTypographicStringFormatBuffer: TGPStringFormat = nil;
   GenericDefaultStringFormatBuffer    : TGPStringFormat = nil;

   StartupInput: TGDIPlusStartupInput;
   gdiplusToken: ULONG;

////////////////////////////////////////////////////////////////////////////////

implementation

  constructor TGPImageAttributes.Create;
  begin
    nativeImageAttr := nil;
    lastResult := GdipCreateImageAttributes(nativeImageAttr);
  end;

  destructor TGPImageAttributes.Destroy;
  begin
    GdipDisposeImageAttributes(nativeImageAttr);
    inherited Destroy;
  end;

  function TGPImageAttributes.Clone: TGPImageAttributes;
  var clone: GpImageAttributes;
  begin
    SetStatus(GdipCloneImageAttributes(nativeImageAttr, clone));
    result := TGPImageAttributes.Create(clone, lastResult);
  end;

  function TGPImageAttributes.SetToIdentity(type_: TColorAdjustType = ColorAdjustTypeDefault): TStatus;
  begin
    result := SetStatus(GdipSetImageAttributesToIdentity(nativeImageAttr, type_));
  end;

  function TGPImageAttributes.Reset(type_: TColorAdjustType = ColorAdjustTypeDefault): TStatus;
  begin
    result := SetStatus(GdipResetImageAttributes(nativeImageAttr, type_));
  end;

  function TGPImageAttributes.SetColorMatrix(const colorMatrix: TColorMatrix;
    mode: TColorMatrixFlags = ColorMatrixFlagsDefault;
    type_: TColorAdjustType = ColorAdjustTypeDefault): TStatus;
  begin
    result := SetStatus(GdipSetImageAttributesColorMatrix(nativeImageAttr,
      type_, TRUE, @colorMatrix, nil, mode));
  end;

  function TGPImageAttributes.ClearColorMatrix(type_: TColorAdjustType = ColorAdjustTypeDefault): TStatus;
  begin
    result := SetStatus(GdipSetImageAttributesColorMatrix(nativeImageAttr, type_,
      FALSE, nil, nil, ColorMatrixFlagsDefault));
  end;


  function TGPImageAttributes.SetColorMatrices(const colorMatrix: TColorMatrix;
    const grayMatrix: TColorMatrix; mode: TColorMatrixFlags  = ColorMatrixFlagsDefault;
    type_: TColorAdjustType  = ColorAdjustTypeDefault): TStatus;
  begin
    result := SetStatus(GdipSetImageAttributesColorMatrix(nativeImageAttr, type_,
      TRUE, @colorMatrix, @grayMatrix, mode));
  end;

  function TGPImageAttributes.ClearColorMatrices(Type_: TColorAdjustType = ColorAdjustTypeDefault): TStatus;
  begin
    result := SetStatus(GdipSetImageAttributesColorMatrix( nativeImageAttr,
      type_, FALSE, nil, nil, ColorMatrixFlagsDefault));
  end;

  function TGPImageAttributes.SetThreshold(threshold: Single; type_: TColorAdjustType = ColorAdjustTypeDefault): TStatus;
  begin
    result := SetStatus(GdipSetImageAttributesThreshold( nativeImageAttr, type_,
      TRUE, threshold));
  end;

  function TGPImageAttributes.ClearThreshold(type_: TColorAdjustType = ColorAdjustTypeDefault): TStatus;
  begin
    result := SetStatus(GdipSetImageAttributesThreshold(nativeImageAttr, type_,
      FALSE, 0.0));
  end;

  function TGPImageAttributes.SetGamma(gamma: Single; type_: TColorAdjustType = ColorAdjustTypeDefault): TStatus;
  begin
    result := SetStatus(GdipSetImageAttributesGamma(nativeImageAttr, type_, TRUE, gamma));
  end;

  function TGPImageAttributes.ClearGamma(type_: TColorAdjustType = ColorAdjustTypeDefault): TStatus;
  begin
    result := SetStatus(GdipSetImageAttributesGamma(nativeImageAttr, type_, FALSE, 0.0));
  end;

  function TGPImageAttributes.SetNoOp(type_: TColorAdjustType = ColorAdjustTypeDefault): TStatus;
  begin
    result := SetStatus(GdipSetImageAttributesNoOp(nativeImageAttr, type_, TRUE));
  end;

  function TGPImageAttributes.ClearNoOp(Type_: TColorAdjustType = ColorAdjustTypeDefault): TStatus;
  begin
    result := SetStatus(GdipSetImageAttributesNoOp( nativeImageAttr, type_, FALSE));
  end;

  function TGPImageAttributes.SetColorKey(colorLow, colorHigh: TGPColor;
    type_: TColorAdjustType = ColorAdjustTypeDefault): TStatus;
  begin
    result := SetStatus(GdipSetImageAttributesColorKeys(nativeImageAttr, type_,
      TRUE, colorLow, colorHigh));
  end;

  function TGPImageAttributes.ClearColorKey(type_: TColorAdjustType = ColorAdjustTypeDefault): TStatus;
  begin
    result := SetStatus(GdipSetImageAttributesColorKeys(nativeImageAttr, type_,
      FALSE, 0, 0));
  end;

  function TGPImageAttributes.SetOutputChannel(channelFlags: TColorChannelFlags;
        type_: TColorAdjustType = ColorAdjustTypeDefault): TStatus;
  begin
    result := SetStatus(GdipSetImageAttributesOutputChannel(nativeImageAttr,
      type_, TRUE, channelFlags));
  end;

  function TGPImageAttributes.ClearOutputChannel(type_: TColorAdjustType = ColorAdjustTypeDefault): TStatus;
  begin
    result := SetStatus(GdipSetImageAttributesOutputChannel(nativeImageAttr,
      type_, FALSE, ColorChannelFlagsLast));
  end;

  function TGPImageAttributes.SetOutputChannelColorProfile(colorProfileFilename: WideString;
    type_: TColorAdjustType = ColorAdjustTypeDefault): TStatus;
  begin
    result := SetStatus(GdipSetImageAttributesOutputChannelColorProfile(nativeImageAttr,
      type_, TRUE, PWideChar(colorProfileFilename)));
  end;

  function TGPImageAttributes.ClearOutputChannelColorProfile(type_: TColorAdjustType = ColorAdjustTypeDefault): TStatus;
  begin
    result := SetStatus(GdipSetImageAttributesOutputChannelColorProfile(nativeImageAttr,
      type_, FALSE, nil));
  end;

  function TGPImageAttributes.SetRemapTable(mapSize: Cardinal; map: PColorMap;
    type_: TColorAdjustType = ColorAdjustTypeDefault): TStatus;
  begin
    result := SetStatus(GdipSetImageAttributesRemapTable(nativeImageAttr, type_,
      TRUE, mapSize, map));
  end;

  function TGPImageAttributes.ClearRemapTable(type_: TColorAdjustType = ColorAdjustTypeDefault): TStatus;
  begin
    result := SetStatus(GdipSetImageAttributesRemapTable(nativeImageAttr, type_,
      FALSE, 0, nil));
  end;

  function TGPImageAttributes.SetBrushRemapTable(mapSize: Cardinal; map: PColorMap): TStatus;
  begin
    result := SetRemapTable(mapSize, map, ColorAdjustTypeBrush);
  end;

  function TGPImageAttributes.ClearBrushRemapTable: TStatus;
  begin
    result := ClearRemapTable(ColorAdjustTypeBrush);
  end;

  function TGPImageAttributes.SetWrapMode(wrap: TWrapMode; color: TGPColor = aclBlack;
    clamp: BOOL = FALSE): TStatus;
  begin
    result := SetStatus(GdipSetImageAttributesWrapMode(nativeImageAttr, wrap, color, clamp));
  end;

  // The flags of the palette are ignored.

  function TGPImageAttributes.GetAdjustedPalette(colorPalette: PColorPalette;
    colorAdjustType: TColorAdjustType): TStatus;
  begin
    result := SetStatus(GdipGetImageAttributesAdjustedPalette(nativeImageAttr,
      colorPalette, colorAdjustType));
  end;

  function TGPImageAttributes.GetLastStatus: TStatus;
  begin
    result := lastResult;
    lastResult := Ok;
  end;

  constructor TGPImageAttributes.Create(imageAttr: GpImageAttributes; status: TStatus);
  begin
    SetNativeImageAttr(imageAttr);
    lastResult := status;
  end;

  procedure TGPImageAttributes.SetNativeImageAttr(nativeImageAttr: GpImageAttributes);
  begin
    self.nativeImageAttr := nativeImageAttr;
  end;

  function TGPImageAttributes.SetStatus(status: TStatus): TStatus;
  begin
    if (status <> Ok) then lastResult := status;
    result := status;
  end;

(**************************************************************************\
*
*   GDI+ Matrix class
*
\**************************************************************************)

  // Default constructor is set to identity matrix.
  constructor TGPMatrix.Create;
  var matrix: GpMatrix;
  begin
    matrix := nil;
    lastResult := GdipCreateMatrix(matrix);
    SetNativeMatrix(matrix);
  end;

  constructor TGPMatrix.Create(m11, m12, m21, m22, dx, dy: Single);
  var matrix: GpMatrix;
  begin
    matrix := nil;
    lastResult := GdipCreateMatrix2(m11, m12, m21, m22, dx, dy, matrix);
    SetNativeMatrix(matrix);
  end;

  constructor TGPMatrix.Create(const rect: TGPRectF; const dstplg: TGPPointF);
  var matrix: GpMatrix;
  begin
    matrix := nil;
    lastResult := GdipCreateMatrix3(@rect, @dstplg, matrix);
    SetNativeMatrix(matrix);
  end;

  constructor TGPMatrix.Create(const rect: TGPRect; const dstplg: TGPPoint);
  var matrix: GpMatrix;
  begin
    matrix := nil;
    lastResult := GdipCreateMatrix3I(@rect, @dstplg, matrix);
    SetNativeMatrix(matrix);
  end;

  destructor TGPMatrix.Destroy;
  begin
    GdipDeleteMatrix(nativeMatrix);
  end;

  function TGPMatrix.Clone: TGPMatrix;
  var cloneMatrix: GpMatrix;
  begin
    cloneMatrix := nil;
    SetStatus(GdipCloneMatrix(nativeMatrix, cloneMatrix));
    if (lastResult <> Ok) then
    begin
      result := nil;
      exit;
    end;
    result := TGPMatrix.Create(cloneMatrix);
  end;

  function TGPMatrix.GetElements(const m: TMatrixArray): TStatus;
  begin
    result := SetStatus(GdipGetMatrixElements(nativeMatrix, @m));
  end;

  function TGPMatrix.SetElements(m11, m12, m21, m22, dx, dy: Single): TStatus;
  begin
        result := SetStatus(GdipSetMatrixElements(nativeMatrix,
                            m11, m12, m21, m22, dx, dy));
  end;

  function TGPMatrix.OffsetX: Single;
  var elements: TMatrixArray;
  begin
    if (GetElements(elements) = Ok) then
      result := elements[4]
    else
      result := 0.0;
  end;

  function TGPMatrix.OffsetY: Single;
  var elements: TMatrixArray;
  begin
    if (GetElements(elements) = Ok) then result := elements[5]
                                        else result := 0.0;
  end;

  function TGPMatrix.Reset: TStatus;
  begin
    // set identity matrix elements
    result := SetStatus(GdipSetMatrixElements(nativeMatrix, 1.0, 0.0, 0.0, 1.0,
                0.0, 0.0));
  end;

  function TGPMatrix.Multiply(matrix: TGPMatrix; order: TMatrixOrder = MatrixOrderPrepend): TStatus;
  begin
    result := SetStatus(GdipMultiplyMatrix(nativeMatrix, matrix.nativeMatrix, order));
  end;

  function TGPMatrix.Translate(offsetX, offsetY: Single; order: TMatrixOrder = MatrixOrderPrepend): TStatus;
  begin
    result := SetStatus(GdipTranslateMatrix(nativeMatrix, offsetX, offsetY, order));
  end;

  function TGPMatrix.Scale(scaleX, scaleY: Single; order: TMatrixOrder = MatrixOrderPrepend): TStatus;
  begin
    result := SetStatus(GdipScaleMatrix(nativeMatrix, scaleX, scaleY, order));
  end;

  function TGPMatrix.Rotate(angle: Single; order: TMatrixOrder = MatrixOrderPrepend): TStatus;
  begin
    result := SetStatus(GdipRotateMatrix(nativeMatrix, angle, order));
  end;

  function TGPMatrix.RotateAt(angle: Single; const center: TGPPointF; order: TMatrixOrder = MatrixOrderPrepend): TStatus;
  begin
    if(order = MatrixOrderPrepend) then
    begin
      SetStatus(GdipTranslateMatrix(nativeMatrix, center.X, center.Y, order));
      SetStatus(GdipRotateMatrix(nativeMatrix, angle, order));
      result := SetStatus(GdipTranslateMatrix(nativeMatrix, -center.X, -center.Y,
                  order));
    end
    else
    begin
      SetStatus(GdipTranslateMatrix(nativeMatrix, - center.X, - center.Y, order));
      SetStatus(GdipRotateMatrix(nativeMatrix, angle, order));
      result := SetStatus(GdipTranslateMatrix(nativeMatrix, center.X, center.Y,
                  order));
    end;
  end;

  function TGPMatrix.Shear(shearX, shearY: Single; order: TMatrixOrder = MatrixOrderPrepend): TStatus;
  begin
    result := SetStatus(GdipShearMatrix(nativeMatrix, shearX, shearY, order));
  end;

  function TGPMatrix.Invert: TStatus;
  begin
    result := SetStatus(GdipInvertMatrix(nativeMatrix));
  end;

  // float version
  function TGPMatrix.TransformPoints(pts: PGPPointF; count: Integer = 1): TStatus;
  begin
    result := SetStatus(GdipTransformMatrixPoints(nativeMatrix, pts, count));
  end;

  function TGPMatrix.TransformPoints(pts: PGPPoint; count: Integer = 1): TStatus;
  begin
    result := SetStatus(GdipTransformMatrixPointsI(nativeMatrix, pts, count));
  end;

  function TGPMatrix.TransformVectors(pts: PGPPointF; count: Integer = 1): TStatus;
  begin
    result := SetStatus(GdipVectorTransformMatrixPoints( nativeMatrix, pts, count));
  end;

  function TGPMatrix.TransformVectors(pts: PGPPoint; count: Integer = 1): TStatus;
  begin
    result := SetStatus(GdipVectorTransformMatrixPointsI(nativeMatrix, pts, count));
  end;

  function TGPMatrix.IsInvertible: BOOL;
  begin
    result := FALSE;
    SetStatus(GdipIsMatrixInvertible(nativeMatrix, result));
  end;

  function TGPMatrix.IsIdentity: BOOL;
  begin
    result := False;
    SetStatus(GdipIsMatrixIdentity(nativeMatrix, result));
  end;

  function TGPMatrix.Equals(matrix: TGPMatrix): BOOL;
  begin
    result := FALSE;
    SetStatus(GdipIsMatrixEqual(nativeMatrix, matrix.nativeMatrix, result));
  end;

  function TGPMatrix.GetLastStatus: TStatus;
  begin
    result := lastResult;
    lastResult := Ok;
  end;

  constructor TGPMatrix.Create(nativeMatrix: GpMatrix);
  begin
    lastResult := Ok;
    SetNativeMatrix(nativeMatrix);
  end;

  procedure TGPMatrix.SetNativeMatrix(nativeMatrix: GpMatrix);
  begin
    self.nativeMatrix := nativeMatrix;
  end;

  function TGPMatrix.SetStatus(status: TStatus): TStatus;
  begin
    if (status <> Ok) then lastResult := status;
    result := status;
  end;


(**************************************************************************\
*
*   GDI+ StringFormat class
*
\**************************************************************************)

  constructor TGPStringFormat.Create(formatFlags: Integer = 0; language: LANGID = LANG_NEUTRAL);
  begin
    nativeFormat := nil;
    lastError := GdipCreateStringFormat(formatFlags, language, nativeFormat);
  end;

  class function TGPStringFormat.GenericDefault: TGPStringFormat;
  begin
    if not assigned(GenericDefaultStringFormatBuffer) then
    begin
      GenericDefaultStringFormatBuffer := TGPStringFormat.Create;
      GenericDefaultStringFormatBuffer.lastError :=
        GdipStringFormatGetGenericDefault(GenericDefaultStringFormatBuffer.nativeFormat);
    end;
    result := GenericDefaultStringFormatBuffer;
  end;

  class function TGPStringFormat.GenericTypographic: TGPStringFormat;
  begin
    if not assigned(GenericTypographicStringFormatBuffer) then
    begin
      GenericTypographicStringFormatBuffer := TGPStringFormat.Create;
      GenericTypographicStringFormatBuffer.lastError :=
        GdipStringFormatGetGenericTypographic(GenericTypographicStringFormatBuffer.nativeFormat);
    end;
    result := GenericTypographicStringFormatBuffer;
  end;

  constructor TGPStringFormat.Create(format: TGPStringFormat);
  var gpstf: GPSTRINGFORMAT;
  begin
    nativeFormat := nil;
    if assigned(format) then gpstf := format.nativeFormat
                        else gpstf := nil;
    lastError := GdipCloneStringFormat(gpstf, nativeFormat);
  end;

  function TGPStringFormat.Clone: TGPStringFormat;
  var
    clonedStringFormat: GpStringFormat;
  begin
    clonedStringFormat := nil;
    lastError := GdipCloneStringFormat(nativeFormat, clonedStringFormat);
    if (lastError = Ok) then
      result := TGPStringFormat.Create(clonedStringFormat, lastError)
    else
      result := nil;
  end;

  destructor TGPStringFormat.Destroy;
  begin
    GdipDeleteStringFormat(nativeFormat);
  end;

  function TGPStringFormat.SetFormatFlags(flags: Integer): TStatus;
  begin
    result := SetStatus(GdipSetStringFormatFlags(nativeFormat, flags));
  end;

  function TGPStringFormat.GetFormatFlags: Integer;
  begin
    SetStatus(GdipGetStringFormatFlags(nativeFormat, result));
  end;

  function TGPStringFormat.SetAlignment(align: TStringAlignment): TStatus;
  begin
    result := SetStatus(GdipSetStringFormatAlign(nativeFormat, align));
  end;

  function TGPStringFormat.GetAlignment: TStringAlignment;
  begin
    SetStatus(GdipGetStringFormatAlign(nativeFormat, result));
  end;

  function TGPStringFormat.SetLineAlignment(align: TStringAlignment): TStatus;
  begin
    result := SetStatus(GdipSetStringFormatLineAlign(nativeFormat, align));
  end;

  function TGPStringFormat.GetLineAlignment: TStringAlignment;
  begin
    SetStatus(GdipGetStringFormatLineAlign(nativeFormat, result));
  end;

  function TGPStringFormat.SetHotkeyPrefix(hotkeyPrefix: THotkeyPrefix): TStatus;
  begin
    result := SetStatus(GdipSetStringFormatHotkeyPrefix(nativeFormat, Integer(hotkeyPrefix)));
  end;

  function TGPStringFormat.GetHotkeyPrefix: THotkeyPrefix;
  var HotkeyPrefix: Integer;
  begin
    SetStatus(GdipGetStringFormatHotkeyPrefix(nativeFormat, HotkeyPrefix));
    result := THotkeyPrefix(HotkeyPrefix);
  end;

  function TGPStringFormat.SetTabStops(firstTabOffset: Single; count: Integer; tabStops: PSingle): TStatus;
  begin
    result := SetStatus(GdipSetStringFormatTabStops(nativeFormat, firstTabOffset, count, tabStops));
  end;

  function TGPStringFormat.GetTabStopCount: Integer;
  begin
    SetStatus(GdipGetStringFormatTabStopCount(nativeFormat, result));
  end;

  function TGPStringFormat.GetTabStops(count: Integer; firstTabOffset, tabStops: PSingle): TStatus;
  begin
    result := SetStatus(GdipGetStringFormatTabStops(nativeFormat, count, firstTabOffset, tabStops));
  end;

  function TGPStringFormat.SetDigitSubstitution(language: LANGID; substitute: TStringDigitSubstitute): TStatus;
  begin
    result := SetStatus(GdipSetStringFormatDigitSubstitution(nativeFormat, language, substitute));
  end;

  function TGPStringFormat.GetDigitSubstitutionLanguage: LANGID;
  begin
    SetStatus(GdipGetStringFormatDigitSubstitution(nativeFormat, @result, nil));
  end;

  function TGPStringFormat.GetDigitSubstitutionMethod: TStringDigitSubstitute;
  begin
    SetStatus(GdipGetStringFormatDigitSubstitution(nativeFormat, nil, @result));
  end;

  function TGPStringFormat.SetTrimming(trimming: TStringTrimming): TStatus;
  begin
    result := SetStatus(GdipSetStringFormatTrimming(nativeFormat, trimming));
  end;

  function TGPStringFormat.GetTrimming: TStringTrimming;
  begin
    SetStatus(GdipGetStringFormatTrimming(nativeFormat, result));
  end;

  function TGPStringFormat.SetMeasurableCharacterRanges(rangeCount: Integer;
    ranges: PCharacterRange): TStatus;
  begin
    result := SetStatus(GdipSetStringFormatMeasurableCharacterRanges(nativeFormat,
      rangeCount, ranges));
  end;

  function TGPStringFormat.GetMeasurableCharacterRangeCount: Integer;
  begin
    SetStatus(GdipGetStringFormatMeasurableCharacterRangeCount(nativeFormat, result));
  end;

  function TGPStringFormat.GetLastStatus: TStatus;
  begin
    result := lastError;
    lastError := Ok;
  end;

  function TGPStringFormat.SetStatus(newStatus: GpStatus): TStatus;
  begin
    if (newStatus <> Ok) then lastError := newStatus;
    result := newStatus;
  end;

  // operator =
  procedure TGPStringFormat.Assign(source: TGPStringFormat);
  begin
    assert(assigned(source));
    GdipDeleteStringFormat(nativeFormat);
    lastError := GdipCloneStringFormat(source.nativeFormat, nativeFormat);
  end;

  constructor TGPStringFormat.Create(clonedStringFormat: GpStringFormat; status: TStatus);
  begin
    lastError := status;
    nativeFormat := clonedStringFormat;
  end;



  // ---------------------------------------------------------------------------
  //  TAdjustableArrowCap
  // ---------------------------------------------------------------------------

  constructor TGPAdjustableArrowCap.Create(height, width: Single; isFilled: Bool = TRUE);
  var cap: GpAdjustableArrowCap;
  begin
    cap := nil;
    lastResult := GdipCreateAdjustableArrowCap(height, width, isFilled, cap);
    SetNativeCap(cap);
  end;

  function TGPAdjustableArrowCap.SetHeight(height: Single): TStatus;
  begin
    result := SetStatus(GdipSetAdjustableArrowCapHeight(GpAdjustableArrowCap(nativeCap), height));
  end;

  function TGPAdjustableArrowCap.GetHeight: Single;
  begin
    SetStatus(GdipGetAdjustableArrowCapHeight(GpAdjustableArrowCap(nativeCap), result));
  end;

  function TGPAdjustableArrowCap.SetWidth(width: Single): TStatus;
  begin
    result := SetStatus(GdipSetAdjustableArrowCapWidth(GpAdjustableArrowCap(nativeCap), width));
  end;

  function TGPAdjustableArrowCap.GetWidth: Single;
  begin
    SetStatus(GdipGetAdjustableArrowCapWidth(GpAdjustableArrowCap(nativeCap), result));
  end;

  function TGPAdjustableArrowCap.SetMiddleInset(middleInset: Single): TStatus;
  begin
    result := SetStatus(GdipSetAdjustableArrowCapMiddleInset(GpAdjustableArrowCap(nativeCap), middleInset));
  end;

  function TGPAdjustableArrowCap.GetMiddleInset: Single;
  begin
    SetStatus(GdipGetAdjustableArrowCapMiddleInset(
      GpAdjustableArrowCap(nativeCap), result));
  end;

  function TGPAdjustableArrowCap.SetFillState(isFilled: Bool): TStatus;
  begin
    result := SetStatus(GdipSetAdjustableArrowCapFillState(
      GpAdjustableArrowCap(nativeCap), isFilled));
  end;

  function TGPAdjustableArrowCap.IsFilled: BOOL;
  begin
    SetStatus(GdipGetAdjustableArrowCapFillState(
      GpAdjustableArrowCap(nativeCap), result));
  end;

(**************************************************************************\
*
*   GDI+ Metafile class
*
\**************************************************************************)

    // Playback a metafile from a HMETAFILE
    // If deleteWmf is TRUE, then when the metafile is deleted,
    // the hWmf will also be deleted.  Otherwise, it won't be.

  constructor TGPMetafile.Create(hWmf: HMETAFILE;
    var wmfPlaceableFileHeader: TWmfPlaceableFileHeader; deleteWmf: BOOL = FALSE);
  var
    metafile: GpMetafile;
  begin
    metafile := nil;
    lastResult := GdipCreateMetafileFromWmf(hWmf, deleteWmf, @wmfPlaceableFileHeader, metafile);
    SetNativeImage(metafile);
  end;

    // Playback a metafile from a HENHMETAFILE
    // If deleteEmf is TRUE, then when the metafile is deleted,
    // the hEmf will also be deleted.  Otherwise, it won't be.

  constructor TGPMetafile.Create(hEmf: HENHMETAFILE; deleteEmf: BOOL = FALSE);
  var
    metafile: GpMetafile;
  begin
    metafile := nil;
    lastResult := GdipCreateMetafileFromEmf(hEmf, deleteEmf, metafile);
    SetNativeImage(metafile);
  end;

  constructor TGPMetafile.Create(filename: WideString);
  var
    metafile: GpMetafile;
  begin
    metafile := nil;
    lastResult := GdipCreateMetafileFromFile(PWideChar(filename), metafile);
    SetNativeImage(metafile);
  end;

    // Playback a WMF metafile from a file.

  constructor TGPMetafile.Create(filename: Widestring; var wmfPlaceableFileHeader: TWmfPlaceableFileHeader);
  var
    metafile: GpMetafile;
  begin
    metafile := nil;
    lastResult := GdipCreateMetafileFromWmfFile(PWideChar(filename), @wmfPlaceableFileHeader, metafile);
    SetNativeImage(metafile);
  end;

  constructor TGPMetafile.Create(stream: IStream);
  var
    metafile: GpMetafile;
  begin
    metafile := nil;
    lastResult := GdipCreateMetafileFromStream(stream, metafile);
    SetNativeImage(metafile);
  end;

    // Record a metafile to memory.

  constructor TGPMetafile.Create(referenceHdc: HDC; type_: TEmfType = EmfTypeEmfPlusDual;
    description: PWCHAR = nil);
  var
    metafile: GpMetafile;
  begin
    metafile := nil;
    lastResult := GdipRecordMetafile(referenceHdc, type_, nil, MetafileFrameUnitGdi,
       description, metafile);
    SetNativeImage(metafile);
  end;

    // Record a metafile to memory.

  constructor TGPMetafile.Create(referenceHdc: HDC; frameRect: TGPRectF;
     frameUnit: TMetafileFrameUnit = MetafileFrameUnitGdi;
     type_: TEmfType = EmfTypeEmfPlusDual; description: PWCHAR = nil);
  var metafile: GpMetafile;
  begin
    metafile := nil;
    lastResult := GdipRecordMetafile(referenceHdc, type_, @frameRect, frameUnit,
      description, metafile);
    SetNativeImage(metafile);
  end;

    // Record a metafile to memory.

  constructor TGPMetafile.Create(referenceHdc: HDC; frameRect: TGPRect;
    frameUnit: TMetafileFrameUnit = MetafileFrameUnitGdi;
    type_: TEmfType = EmfTypeEmfPlusDual; description: PWCHAR = nil);
  var
    metafile: GpMetafile;
  begin
    metafile := nil;
    lastResult := GdipRecordMetafileI(referenceHdc, type_, @frameRect, frameUnit,
      description, metafile);
    SetNativeImage(metafile);
  end;

  constructor TGPMetafile.Create(fileName: WideString; referenceHdc: HDC;
    type_: TEmfType = EmfTypeEmfPlusDual; description: PWCHAR = nil);
  var
    metafile: GpMetafile;
  begin
    metafile := nil;
    lastResult := GdipRecordMetafileFileName(PWideChar(fileName),
      referenceHdc, type_, nil, MetafileFrameUnitGdi, description, metafile);
    SetNativeImage(metafile);
  end;

  constructor TGPMetafile.Create(fileName: WideString; referenceHdc: HDC; frameRect: TGPRectF;
    frameUnit: TMetafileFrameUnit = MetafileFrameUnitGdi; type_: TEmfType = EmfTypeEmfPlusDual;
    description: PWCHAR = nil);
  var
    metafile: GpMetafile;
  begin
    metafile := nil;
    lastResult := GdipRecordMetafileFileName(PWideChar(fileName), referenceHdc,
      type_, @frameRect, frameUnit, description, metafile);
    SetNativeImage(metafile);
  end;

  constructor TGPMetafile.Create(fileName: WideString; referenceHdc: HDC; frameRect: TGPRect;
    frameUnit: TMetafileFrameUnit = MetafileFrameUnitGdi; type_: TEmfType = EmfTypeEmfPlusDual;
    description: PWCHAR = nil);
  var
    metafile: GpMetafile;
  begin
    metafile := nil;
    lastResult := GdipRecordMetafileFileNameI(PWideChar(fileName),
      referenceHdc, type_, @frameRect, frameUnit, description, metafile);
    SetNativeImage(metafile);
  end;

  constructor TGPMetafile.Create(stream: IStream; referenceHdc: HDC;
    type_: TEmfType = EmfTypeEmfPlusDual; description: PWCHAR = nil);
  var
    metafile: GpMetafile;
  begin
    metafile := nil;
    lastResult := GdipRecordMetafileStream(stream, referenceHdc, type_, nil,
      MetafileFrameUnitGdi, description, metafile);
    SetNativeImage(metafile);
  end;

  constructor TGPMetafile.Create(stream: IStream; referenceHdc: HDC; frameRect: TGPRectF;
    frameUnit: TMetafileFrameUnit = MetafileFrameUnitGdi; type_: TEmfType = EmfTypeEmfPlusDual;
    description: PWCHAR = nil);
  var
    metafile: GpMetafile;
  begin
    metafile := nil;
    lastResult := GdipRecordMetafileStream(stream, referenceHdc, type_,
      @frameRect, frameUnit, description, metafile);
    SetNativeImage(metafile);
  end;

  constructor TGPMetafile.Create(stream : IStream; referenceHdc : HDC; frameRect : TGPRect;
    frameUnit : TMetafileFrameUnit = MetafileFrameUnitGdi; type_ : TEmfType = EmfTypeEmfPlusDual;
    description : PWCHAR = nil);
  var
    metafile: GpMetafile;
  begin
    metafile := nil;
    lastResult := GdipRecordMetafileStreamI(stream, referenceHdc, type_,
      @frameRect, frameUnit, description, metafile);
    SetNativeImage(metafile);
  end;

  function TGPMetafile.GetMetafileHeader(hWmf: HMETAFILE;
    var wmfPlaceableFileHeader: TWmfPlaceableFileHeader; header: TMetafileHeader): TStatus;
  begin
    result := GdipGetMetafileHeaderFromWmf(hWmf, @wmfPlaceableFileHeader, @header.Type_);
  end;

  function TGPMetafile.GetMetafileHeader(hEmf: HENHMETAFILE; header: TMetafileHeader): TStatus;
  begin
    result := GdipGetMetafileHeaderFromEmf(hEmf, @header.Type_);
  end;

  function TGPMetafile.GetMetafileHeader(filename: WideString; header: TMetafileHeader): TStatus;
  begin
    result := GdipGetMetafileHeaderFromFile(PWideChar(filename), @header.Type_);
  end;

  function TGPMetafile.GetMetafileHeader(stream: IStream; header: TMetafileHeader): TStatus;
  begin
    result := GdipGetMetafileHeaderFromStream(stream, @header.Type_);
  end;

  function TGPMetafile.GetMetafileHeader(header: TMetafileHeader): TStatus;
  begin
    result := SetStatus(GdipGetMetafileHeaderFromMetafile(GpMetafile(nativeImage),
      @header.Type_));
  end;

  function TGPMetafile.GetHENHMETAFILE: HENHMETAFILE;
  begin
    SetStatus(GdipGetHemfFromMetafile(GpMetafile(nativeImage), result));
  end;

  function TGPMetafile.PlayRecord(recordType: TEmfPlusRecordType; flags, dataSize: UINT;
    data: PBYTE): TStatus;
  begin
    result := SetStatus(GdipPlayMetafileRecord(GpMetafile(nativeImage),
      recordType, flags, dataSize, data));
  end;

  function TGPMetafile.SetDownLevelRasterizationLimit(metafileRasterizationLimitDpi: UINT): TStatus;
  begin
    result := SetStatus(GdipSetMetafileDownLevelRasterizationLimit(
      GpMetafile(nativeImage), metafileRasterizationLimitDpi));
  end;

  function TGPMetafile.GetDownLevelRasterizationLimit: UINT;
  var metafileRasterizationLimitDpi: UINT;
  begin
    metafileRasterizationLimitDpi := 0;
    SetStatus(GdipGetMetafileDownLevelRasterizationLimit(
      GpMetafile(nativeImage), metafileRasterizationLimitDpi));
    result := metafileRasterizationLimitDpi;
  end;

  function TGPMetafile.EmfToWmfBits(hemf: HENHMETAFILE; cbData16: UINT; pData16: PBYTE;
    iMapMode: Integer = MM_ANISOTROPIC; eFlags: TEmfToWmfBitsFlags = EmfToWmfBitsFlagsDefault): UINT;
  begin
    result := GdipEmfToWmfBits(hemf, cbData16, pData16, iMapMode, Integer(eFlags));
  end;

  constructor TGPMetafile.Create;
  begin
    SetNativeImage(nil);
    lastResult := Ok;
  end;

//--------------------------------------------------------------------------
// Codec Management APIs
//--------------------------------------------------------------------------

  function GetImageDecodersSize(out numDecoders, size: UINT): TStatus;
  begin
    result := GdipGetImageDecodersSize(numDecoders, size);
  end;

  function GetImageDecoders(numDecoders, size: UINT;
     decoders: PImageCodecInfo): TStatus;
  begin
    result := GdipGetImageDecoders(numDecoders, size, decoders);
  end;


  function GetImageEncodersSize(out numEncoders, size: UINT): TStatus;
  begin
    result := GdipGetImageEncodersSize(numEncoders, size);
  end;

  function GetImageEncoders(numEncoders, size: UINT;
     encoders: PImageCodecInfo): TStatus;
  begin
    result := GdipGetImageEncoders(numEncoders, size, encoders);
  end;

  constructor TGPRegion.Create;
  var
    region: GpRegion;
  begin
    region := nil;
    lastResult := GdipCreateRegion(region);
    SetNativeRegion(region);
  end;

  constructor TGPRegion.Create(rect: TGPRectF);
  var
    region: GpRegion;
  begin
    region := nil;
    lastResult := GdipCreateRegionRect(@rect, region);
    SetNativeRegion(region);
  end;

  constructor TGPRegion.Create(rect: TGPRect);
  var
    region: GpRegion;
  begin
    region := nil;
    lastResult := GdipCreateRegionRectI(@rect, region);
    SetNativeRegion(region);
  end;

  constructor TGPRegion.Create(path: TGPGraphicsPath);
  var
    region: GpRegion;
  begin
    region := nil;
    lastResult := GdipCreateRegionPath(path.nativePath, region);
    SetNativeRegion(region);
  end;

  constructor TGPRegion.Create(regionData: PBYTE; size: Integer);
  var
    region: GpRegion;
  begin
    region := nil;
    lastResult := GdipCreateRegionRgnData(regionData, size, region);
    SetNativeRegion(region);
  end;

  {$IFNDEF KS_CBUILDER}
  constructor TGPRegion.Create(hRgn: HRGN);
  var
    region: GpRegion;
  begin
    region := nil;
    lastResult := GdipCreateRegionHrgn(hRgn, region);
    SetNativeRegion(region);
  end;
  {$ENDIF}

  function TGPRegion.FromHRGN(hRgn: HRGN): TGPRegion;
  var
    region: GpRegion;
  begin
    region := nil;
    if (GdipCreateRegionHrgn(hRgn, region) = Ok) then
    begin
        result := TGPRegion.Create(region);
        if (result = nil) then
            GdipDeleteRegion(region);
        exit;
    end
    else
      result := nil;
  end;

  destructor TGPRegion.Destroy;
  begin
    GdipDeleteRegion(nativeRegion);
  end;

  function TGPRegion.Clone: TGPRegion;
  var region: GpRegion;
  begin
    region := nil;
    SetStatus(GdipCloneRegion(nativeRegion, region));
    result := TGPRegion.Create(region);
  end;

  function TGPRegion.MakeInfinite: TStatus;
  begin
    result := SetStatus(GdipSetInfinite(nativeRegion));
  end;

  function TGPRegion.MakeEmpty: TStatus;
  begin
    result := SetStatus(GdipSetEmpty(nativeRegion));
  end;

  function TGPRegion.GetDataSize: UINT;
  var bufferSize: UINT;
  begin
    bufferSize := 0;
    SetStatus(GdipGetRegionDataSize(nativeRegion, bufferSize));
    result := bufferSize;
  end;

  function TGPRegion.GetData(buffer: PBYTE; bufferSize: UINT; sizeFilled: PUINT = nil): TStatus;
  begin
    result := SetStatus(GdipGetRegionData(nativeRegion, buffer, bufferSize, sizeFilled));
  end;

  function TGPRegion.Intersect(const rect: TGPRect): TStatus;
  begin
    result := SetStatus(GdipCombineRegionRectI(nativeRegion, @rect, CombineModeIntersect));
  end;

  function TGPRegion.Intersect(const rect: TGPRectF): TStatus;
  begin
    result := SetStatus(GdipCombineRegionRect(nativeRegion, @rect, CombineModeIntersect));
  end;

  function TGPRegion.Intersect(path: TGPGraphicsPath): TStatus;
  begin
    result := SetStatus(GdipCombineRegionPath(nativeRegion, path.nativePath,
      CombineModeIntersect));
  end;

  function TGPRegion.Intersect(region: TGPRegion): TStatus;
  begin
    result := SetStatus(GdipCombineRegionRegion(nativeRegion, region.nativeRegion,
      CombineModeIntersect));
  end;

  function TGPRegion.Union(const rect: TGPRect): TStatus;
  begin
    result := SetStatus(GdipCombineRegionRectI(nativeRegion, @rect, CombineModeUnion));
  end;

  function TGPRegion.Union(const rect: TGPRectF): TStatus;
  begin
    result := SetStatus(GdipCombineRegionRect(nativeRegion, @rect, CombineModeUnion));
  end;

  function TGPRegion.Union(path: TGPGraphicsPath): TStatus;
  begin
    result := SetStatus(GdipCombineRegionPath(nativeRegion, path.nativePath, CombineModeUnion));
  end;

  function TGPRegion.Union(region: TGPRegion): TStatus;
  begin
    result := SetStatus(GdipCombineRegionRegion(nativeRegion, region.nativeRegion,
      CombineModeUnion));
  end;

  function TGPRegion.Xor_(const rect: TGPRect): TStatus;
  begin
    result := SetStatus(GdipCombineRegionRectI(nativeRegion, @rect, CombineModeXor));
  end;

  function TGPRegion.Xor_(const rect: TGPRectF): TStatus;
  begin
    result := SetStatus(GdipCombineRegionRect(nativeRegion, @rect, CombineModeXor));
  end;

  function TGPRegion.Xor_(path: TGPGraphicsPath): TStatus;
  begin
    result := SetStatus(GdipCombineRegionPath(nativeRegion, path.nativePath, CombineModeXor));
  end;

  function TGPRegion.Xor_(region: TGPRegion): TStatus;
  begin
    result := SetStatus(GdipCombineRegionRegion(nativeRegion, region.nativeRegion,
      CombineModeXor));
  end;

  function TGPRegion.Exclude(const rect: TGPRect): TStatus;
  begin
     result := SetStatus(GdipCombineRegionRectI(nativeRegion, @rect, CombineModeExclude));
  end;

  function TGPRegion.Exclude(const rect: TGPRectF): TStatus;
  begin
    result := SetStatus(GdipCombineRegionRect(nativeRegion, @rect, CombineModeExclude));
  end;

  function TGPRegion.Exclude(path: TGPGraphicsPath): TStatus;
  begin
    result := SetStatus(GdipCombineRegionPath(nativeRegion, path.nativePath, CombineModeExclude));
  end;

  function TGPRegion.Exclude(region: TGPRegion): TStatus;
  begin
    result := SetStatus(GdipCombineRegionRegion(nativeRegion,
                                               region.nativeRegion,
                                                         CombineModeExclude));
  end;

  function TGPRegion.Complement(const rect: TGPRect): TStatus;
  begin
    result := SetStatus(GdipCombineRegionRectI(nativeRegion, @rect,
                                                        CombineModeComplement));
  end;

  function TGPRegion.Complement(const rect: TGPRectF): TStatus;
  begin
    result := SetStatus(GdipCombineRegionRect(nativeRegion, @rect,
                                                       CombineModeComplement));
  end;

  function TGPRegion.Complement(path: TGPGraphicsPath): TStatus;
  begin
    result := SetStatus(GdipCombineRegionPath(nativeRegion,
                                                path.nativePath,
                                                CombineModeComplement));
  end;

  function TGPRegion.Complement(region: TGPRegion): TStatus;
  begin
    result := SetStatus(GdipCombineRegionRegion(nativeRegion,
                                                  region.nativeRegion,
                                                         CombineModeComplement));
  end;

  function TGPRegion.Translate(dx, dy: Single): TStatus;
  begin
    result := SetStatus(GdipTranslateRegion(nativeRegion, dx, dy));
  end;

  function TGPRegion.Translate(dx, dy: Integer): TStatus;
  begin
    result := SetStatus(GdipTranslateRegionI(nativeRegion, dx, dy));
  end;

  function TGPRegion.Transform(matrix: TGPMatrix): TStatus;
  begin
    result := SetStatus(GdipTransformRegion(nativeRegion,
                                                     matrix.nativeMatrix));
  end;

  function TGPRegion.GetBounds(out rect: TGPRect; g: TGPGraphics): TStatus;
  begin
    result := SetStatus(GdipGetRegionBoundsI(nativeRegion,
                                                g.nativeGraphics,
                                                @rect));
  end;

  function TGPRegion.GetBounds(out rect: TGPRectF; g: TGPGraphics): TStatus;
  begin
    result := SetStatus(GdipGetRegionBounds(nativeRegion,
                                                g.nativeGraphics,
                                                @rect));
  end;

  function TGPRegion.GetHRGN(g: TGPGraphics): HRGN;
  begin
    SetStatus(GdipGetRegionHRgn(nativeRegion, g.nativeGraphics, result));
  end;

  function TGPRegion.IsEmpty(g: TGPGraphics): BOOL;
  var booln: BOOL;
  begin
    booln := FALSE;
    SetStatus(GdipIsEmptyRegion(nativeRegion, g.nativeGraphics, booln));
    result := booln;
  end;

  function TGPRegion.IsInfinite(g: TGPGraphics): BOOL ;
  var booln: BOOL;
  begin
    booln := FALSE;
    SetStatus(GdipIsInfiniteRegion(nativeRegion, g.nativeGraphics, booln));
    result := booln;
  end;

  function TGPRegion.IsVisible(x, y: Integer; g: TGPGraphics = nil): BOOL;
  var
    booln: BOOL;
    GPX: GpGraphics;
  begin
    booln := FALSE;
    if assigned(g) then gpx := g.nativeGraphics else gpx := nil;
    SetStatus(GdipIsVisibleRegionPointI(nativeRegion, X, Y, gpx, booln));
    result := booln;
  end;

  function TGPRegion.IsVisible(const point: TGPPoint; g: TGPGraphics = nil): BOOL;
  var
    booln: BOOL;
    GPX: GpGraphics;
  begin
    booln := FALSE;
    if assigned(g) then gpx := g.nativeGraphics else gpx := nil;
    SetStatus(GdipIsVisibleRegionPointI(nativeRegion, point.X, point.Y, gpx, booln));
    result := booln;
  end;

  function TGPRegion.IsVisible(x, y: Single; g: TGPGraphics = nil): BOOL;
  var
    booln: BOOL;
    GPX: GpGraphics;
  begin
    booln := FALSE;
    if assigned(g) then gpx := g.nativeGraphics else gpx := nil;
    SetStatus(GdipIsVisibleRegionPoint(nativeRegion, X, Y, gpx, booln));
    result := booln;
  end;

  function TGPRegion.IsVisible(const point: TGPPointF; g: TGPGraphics = nil): BOOL;
  var
    booln: BOOL;
    GPX: GpGraphics;
  begin
    booln := FALSE;
    if assigned(g) then gpx := g.nativeGraphics else gpx := nil;
    SetStatus(GdipIsVisibleRegionPoint(nativeRegion, point.X, point.Y, gpx, booln));
    result := booln;
  end;

  function TGPRegion.IsVisible(x, y, width, height: Integer; g: TGPGraphics): BOOL;
  var
    booln: BOOL;
    GPX: GpGraphics;
  begin
    booln := FALSE;
    if assigned(g) then gpx := g.nativeGraphics else gpx := nil;
    SetStatus(GdipIsVisibleRegionRectI(nativeRegion,
                                                  X,
                                                  Y,
                                                  Width,
                                                  Height,
                                                  gpx,
                                                  booln));
    result := booln;
  end;

  function TGPRegion.IsVisible(const rect: TGPRect; g: TGPGraphics = nil): BOOL;
  var
    booln: BOOL;
    GPX: GpGraphics;
  begin
    booln := FALSE;
    if assigned(g) then gpx := g.nativeGraphics else gpx := nil;
    SetStatus(GdipIsVisibleRegionRectI(nativeRegion,
                                                  rect.X,
                                                  rect.Y,
                                                  rect.Width,
                                                  rect.Height,
                                                  gpx,
                                                  booln));
    result := booln;
  end;

  function TGPRegion.IsVisible(x, y, width, height: Single; g: TGPGraphics = nil): BOOL;
  var
    booln: BOOL;
    GPX: GpGraphics;
  begin
    booln := FALSE;
    if assigned(g) then gpx := g.nativeGraphics else gpx := nil;
    SetStatus(GdipIsVisibleRegionRect(nativeRegion, X,
                                                    Y, Width,
                                                    Height,
                                                    gpx,
                                                    booln));
    result := booln;
  end;

  function TGPRegion.IsVisible(const rect: TGPRectF; g: TGPGraphics = nil): BOOL;
  var
    booln: BOOL;
    GPX: GpGraphics;
  begin
    booln := FALSE;
    if assigned(g) then gpx := g.nativeGraphics else gpx := nil;
    SetStatus(GdipIsVisibleRegionRect(nativeRegion, rect.X,
                                                    rect.Y, rect.Width,
                                                    rect.Height,
                                                    gpx,
                                                    booln));
    result := booln;
  end;

  function TGPRegion.Equals(region: TGPRegion; g: TGPGraphics): BOOL;
  var
    booln: BOOL;
  begin
    booln := FALSE;
    SetStatus(GdipIsEqualRegion(nativeRegion,
                                              region.nativeRegion,
                                              g.nativeGraphics,
                                              booln));
    result := booln;
  end;

  function TGPRegion.GetRegionScansCount(matrix: TGPMatrix): UINT;
  var Count: UINT;
  begin
    count := 0;
    SetStatus(GdipGetRegionScansCount(nativeRegion, count, matrix.nativeMatrix));
    result := count;
  end;

  function TGPRegion.GetRegionScans(matrix: TGPMatrix; rects: PGPRectF; out count: Integer): TStatus;
  begin
    result := SetStatus(GdipGetRegionScans(nativeRegion,
                                          rects,
                                          count,
                                          matrix.nativeMatrix));
  end;

  function TGPRegion.GetRegionScans(matrix: TGPMatrix; rects: PGPRect; out count: Integer): TStatus;
  begin
    result := SetStatus(GdipGetRegionScansI(nativeRegion,
                                          rects,
                                          count,
                                          matrix.nativeMatrix));
  end;

  function TGPRegion.GetLastStatus: TStatus;
  begin
    result := lastResult;
    lastResult := Ok;
  end;

  function TGPRegion.SetStatus(status: TStatus): TStatus;
  begin
    if (status <> Ok) then lastResult := status;
    result := status;
  end;

  constructor TGPRegion.Create(nativeRegion: GpRegion);
  begin
    SetNativeRegion(nativeRegion);
  end;

  procedure TGPRegion.SetNativeRegion(nativeRegion: GpRegion);
  begin
    self.nativeRegion := nativeRegion;
  end;

  constructor TGPCustomLineCap.Create(fillPath, strokePath: TGPGraphicsPath;
                  baseCap: TLineCap = LineCapFlat; baseInset: Single = 0);
  var nativeFillPath, nativeStrokePath: GpPath;
  begin
    nativeCap := nil;
    nativeFillPath := nil;
    nativeStrokePath := nil;

    if assigned(fillPath) then nativeFillPath := fillPath.nativePath;
    if assigned(strokePath) then nativeStrokePath := strokePath.nativePath;

    lastResult := GdipCreateCustomLineCap(nativeFillPath, nativeStrokePath,
                    baseCap, baseInset, nativeCap);
  end;

  destructor TGPCustomLineCap.Destroy;
  begin
    GdipDeleteCustomLineCap(nativeCap);
  end;

  function TGPCustomLineCap.Clone: TGPCustomLineCap;
  var newNativeLineCap: GpCustomLineCap;
  begin
    newNativeLineCap := nil;
    SetStatus(GdipCloneCustomLineCap(nativeCap, newNativeLineCap));
    if (lastResult = Ok) then
    begin
      result := TGPCustomLineCap.Create(newNativeLineCap, lastResult);
      if (result = nil) then
         SetStatus(GdipDeleteCustomLineCap(newNativeLineCap));
    end
    else
      result := nil;
  end;

  // This changes both the start and end cap.
  function TGPCustomLineCap.SetStrokeCap(strokeCap: TLineCap): TStatus;
  begin
    result := SetStrokeCaps(strokeCap, strokeCap);
  end;

  function TGPCustomLineCap.SetStrokeCaps(startCap, endCap: TLineCap): TStatus;
  begin
    result := SetStatus(GdipSetCustomLineCapStrokeCaps(nativeCap, startCap, endCap));
  end;

  function TGPCustomLineCap.GetStrokeCaps(out startCap, endCap: TLineCap): TStatus;
  begin
    result := SetStatus(GdipGetCustomLineCapStrokeCaps(nativeCap, startCap, endCap));
  end;

  function TGPCustomLineCap.SetStrokeJoin(lineJoin: TLineJoin): TStatus;
  begin
    result := SetStatus(GdipSetCustomLineCapStrokeJoin(nativeCap, lineJoin));
  end;

  function TGPCustomLineCap.GetStrokeJoin: TLineJoin;
  begin
    SetStatus(GdipGetCustomLineCapStrokeJoin(nativeCap, result));
  end;

  function TGPCustomLineCap.SetBaseCap(baseCap: TLineCap): TStatus;
  begin
    result := SetStatus(GdipSetCustomLineCapBaseCap(nativeCap, baseCap));
  end;

  function TGPCustomLineCap.GetBaseCap: TLineCap;
  begin
    SetStatus(GdipGetCustomLineCapBaseCap(nativeCap, result));
  end;

  function TGPCustomLineCap.SetBaseInset(inset: Single): TStatus;
  begin
    result := SetStatus(GdipSetCustomLineCapBaseInset(nativeCap, inset));
  end;

  function TGPCustomLineCap.GetBaseInset: Single;
  begin
    SetStatus(GdipGetCustomLineCapBaseInset(nativeCap, result));
  end;

  function TGPCustomLineCap.SetWidthScale(widthScale: Single): TStatus;
  begin
    result := SetStatus(GdipSetCustomLineCapWidthScale(nativeCap, widthScale));
  end;

  function TGPCustomLineCap.GetWidthScale: Single;
  begin
    SetStatus(GdipGetCustomLineCapWidthScale(nativeCap, result));
  end;

  function TGPCustomLineCap.GetLastStatus: TStatus;
  begin
    result := lastResult;
    lastResult := Ok;
  end;

  constructor TGPCustomLineCap.Create;
  begin
    nativeCap := nil;
    lastResult := Ok;
  end;

  constructor TGPCustomLineCap.Create(nativeCap: GpCustomLineCap; status: TStatus);
  begin
    lastResult := status;
    SetNativeCap(nativeCap);
  end;

  procedure TGPCustomLineCap.SetNativeCap(nativeCap: GpCustomLineCap);
  begin
    self.nativeCap := nativeCap;
  end;

  function TGPCustomLineCap.SetStatus(status: TStatus): TStatus;
  begin
    if (status <> Ok) then lastResult := status;
    result := status;
  end;

  constructor TGPCachedBitmap.Create(bitmap: TGPBitmap; graphics: TGPGraphics);
  begin
    nativeCachedBitmap := nil;
    lastResult := GdipCreateCachedBitmap(
        GpBitmap(bitmap.nativeImage),
        graphics.nativeGraphics,
        nativeCachedBitmap);
  end;

  destructor TGPCachedBitmap.Destroy;
  begin
    GdipDeleteCachedBitmap(nativeCachedBitmap);
  end;

  function TGPCachedBitmap.GetLastStatus: TStatus;
  begin
    result := lastResult;
    lastResult := Ok;
  end;

  //--------------------------------------------------------------------------
  // Pen class
  //--------------------------------------------------------------------------

  constructor TGPPen.Create(color: TGPColor; width: Single = 1.0);
  var unit_: TUnit;
  begin
    unit_ := UnitWorld;
    nativePen := nil;
    lastResult := GdipCreatePen1(color, width, unit_, nativePen);
  end;

  constructor TGPPen.Create(brush: TGPBrush; width: Single = 1.0);
  var unit_: TUnit;
  begin
    unit_ := UnitWorld;
    nativePen := nil;
    lastResult := GdipCreatePen2(brush.nativeBrush, width, unit_, nativePen);
  end;

  destructor TGPPen.Destroy;
  begin
    GdipDeletePen(nativePen);
  end;

  function TGPPen.Clone: TGPPen;
  var clonePen: GpPen;
  begin
    clonePen := nil;
    lastResult := GdipClonePen(nativePen, clonePen);
    result := TGPPen.Create(clonePen, lastResult);
  end;

  function TGPPen.SetWidth(width: Single): TStatus;
  begin
    result := SetStatus(GdipSetPenWidth(nativePen, width));
  end;

  function TGPPen.GetWidth: Single;
  begin
    SetStatus(GdipGetPenWidth(nativePen, result));
  end;

  // Set/get line caps: start, end, and dash
  // Line cap and join APIs by using LineCap and LineJoin enums.

  function TGPPen.SetLineCap(startCap, endCap: TLineCap; dashCap: TDashCap): TStatus;
  begin
    result := SetStatus(GdipSetPenLineCap197819(nativePen, startCap, endCap, dashCap));
  end;

  function TGPPen.SetStartCap(startCap: TLineCap): TStatus;
  begin
    result := SetStatus(GdipSetPenStartCap(nativePen, startCap));
  end;

  function TGPPen.SetEndCap(endCap: TLineCap): TStatus;
  begin
    result := SetStatus(GdipSetPenEndCap(nativePen, endCap));
  end;

  function TGPPen.SetDashCap(dashCap: TDashCap): TStatus;
  begin
    result := SetStatus(GdipSetPenDashCap197819(nativePen, dashCap));
  end;

  function TGPPen.GetStartCap: TLineCap;
  begin
    SetStatus(GdipGetPenStartCap(nativePen, result));
  end;

  function TGPPen.GetEndCap: TLineCap;
  begin
    SetStatus(GdipGetPenEndCap(nativePen, result));
  end;

  function TGPPen.GetDashCap: TDashCap;
  begin
    SetStatus(GdipGetPenDashCap197819(nativePen, result));
  end;

  function TGPPen.SetLineJoin(lineJoin: TLineJoin): TStatus;
  begin
    result := SetStatus(GdipSetPenLineJoin(nativePen, lineJoin));
  end;

  function TGPPen.GetLineJoin: TLineJoin;
  begin
    SetStatus(GdipGetPenLineJoin(nativePen, result));
  end;

  function TGPPen.SetCustomStartCap(customCap: TGPCustomLineCap): TStatus;
  var nativeCap: GpCustomLineCap;
  begin
    nativeCap := nil;
    if assigned(customCap) then nativeCap := customCap.nativeCap;
    result := SetStatus(GdipSetPenCustomStartCap(nativePen, nativeCap));
  end;

  function TGPPen.GetCustomStartCap(customCap: TGPCustomLineCap): TStatus;
  begin
    if(customCap = nil) then
      result := SetStatus(InvalidParameter)
    else
      result := SetStatus(GdipGetPenCustomStartCap(nativePen, customCap.nativeCap));
  end;

  function TGPPen.SetCustomEndCap(customCap: TGPCustomLineCap): TStatus;
  var nativeCap: GpCustomLineCap;
  begin
    nativeCap := nil;
    if assigned(customCap) then nativeCap := customCap.nativeCap;
    result := SetStatus(GdipSetPenCustomEndCap(nativePen, nativeCap));
  end;

  function TGPPen.GetCustomEndCap(customCap: TGPCustomLineCap): TStatus;
  begin
    if(customCap = nil) then
      result := SetStatus(InvalidParameter)
    else
      result := SetStatus(GdipGetPenCustomEndCap(nativePen, customCap.nativeCap));
  end;

  function TGPPen.SetMiterLimit(miterLimit: Single): TStatus;
  begin
    result := SetStatus(GdipSetPenMiterLimit(nativePen, miterLimit));
  end;

  function TGPPen.GetMiterLimit: Single;
  begin
    SetStatus(GdipGetPenMiterLimit(nativePen, result));
  end;

  function TGPPen.SetAlignment(penAlignment: TPenAlignment): TStatus;
  begin
    result := SetStatus(GdipSetPenMode(nativePen, penAlignment));
  end;

  function TGPPen.GetAlignment: TPenAlignment;
  begin
    SetStatus(GdipGetPenMode(nativePen, result));
  end;

  function TGPPen.SetTransform(matrix: TGPMatrix): TStatus;
  begin
    result := SetStatus(GdipSetPenTransform(nativePen, matrix.nativeMatrix));
  end;

  function TGPPen.GetTransform(matrix: TGPMatrix): TStatus;
  begin
    result := SetStatus(GdipGetPenTransform(nativePen, matrix.nativeMatrix));
  end;

  function TGPPen.ResetTransform: TStatus;
  begin
    result := SetStatus(GdipResetPenTransform(nativePen));
  end;

  function TGPPen.MultiplyTransform(matrix: TGPMatrix; order: TMatrixOrder = MatrixOrderPrepend): TStatus;
  begin
    result := SetStatus(GdipMultiplyPenTransform(nativePen, matrix.nativeMatrix, order));
  end;

  function TGPPen.TranslateTransform(dx, dy: Single; order: TMatrixOrder = MatrixOrderPrepend): TStatus;
  begin
    result := SetStatus(GdipTranslatePenTransform(nativePen, dx, dy, order));
  end;

  function TGPPen.ScaleTransform(sx, sy: Single; order: TMatrixOrder = MatrixOrderPrepend): TStatus;
  begin
    result := SetStatus(GdipScalePenTransform(nativePen, sx, sy, order));
  end;

  function TGPPen.RotateTransform(angle: Single; order: TMatrixOrder = MatrixOrderPrepend): TStatus;
  begin
    result := SetStatus(GdipRotatePenTransform(nativePen, angle, order));
  end;

  function TGPPen.GetPenType: TPenType;
  begin
    SetStatus(GdipGetPenFillType(nativePen, result));
  end;

  function TGPPen.SetColor(color: TGPColor): TStatus;
  begin
    result := SetStatus(GdipSetPenColor(nativePen, color));
  end;

  function TGPPen.SetBrush(brush: TGPBrush): TStatus;
  begin
    result := SetStatus(GdipSetPenBrushFill(nativePen, brush.nativeBrush));
  end;

  function TGPPen.GetColor(out Color: TGPColor): TStatus;
  var
    type_: TPenType;
    argb: DWORD;
  begin
    type_ := GetPenType;

    if (type_ <> PenTypeSolidColor) then
    begin
      result := WrongState;
      exit;
    end;

    SetStatus(GdipGetPenColor(nativePen, argb));
    if (lastResult = Ok) then color := argb;
    result := lastResult;
  end;

  function TGPPen.GetBrush: TGPBrush;
  var
    type_: TPenType;
    Brush: TGPBrush;
    nativeBrush: GpBrush;
  begin
    type_ := GetPenType;
    brush := nil;

    case type_ of
       PenTypeSolidColor     : brush := TGPSolidBrush.Create;
       PenTypeHatchFill      : brush := TGPHatchBrush.Create;
       PenTypeTextureFill    : brush := TGPTextureBrush.Create;
       PenTypePathGradient   : brush := TGPBrush.Create;
       PenTypeLinearGradient : brush := TGPLinearGradientBrush.Create;
     end;

     if (brush <> nil) then
     begin
       SetStatus(GdipGetPenBrushFill(nativePen, nativeBrush));
       brush.SetNativeBrush(nativeBrush);
     end;

     result := brush;
  end;

  function TGPPen.GetDashStyle: TDashStyle;
  begin
    SetStatus(GdipGetPenDashStyle(nativePen, result));
  end;

  function TGPPen.SetDashStyle(dashStyle: TDashStyle): TStatus;
  begin
    result := SetStatus(GdipSetPenDashStyle(nativePen, dashStyle));
  end;

  function TGPPen.GetDashOffset: Single;
  begin
    SetStatus(GdipGetPenDashOffset(nativePen, result));
  end;

  function TGPPen.SetDashOffset(dashOffset: Single): TStatus;
  begin
    result := SetStatus(GdipSetPenDashOffset(nativePen, dashOffset));
  end;

  function TGPPen.SetDashPattern(dashArray: PSingle; count: Integer): TStatus;
  begin
    result := SetStatus(GdipSetPenDashArray(nativePen, dashArray, count));
  end;

  function TGPPen.GetDashPatternCount: Integer;
  begin
    SetStatus(GdipGetPenDashCount(nativePen, result));
  end;

  function TGPPen.GetDashPattern(dashArray: PSingle; count: Integer): TStatus;
  begin
    result := SetStatus(GdipGetPenDashArray(nativePen, dashArray, count));
  end;

  function TGPPen.SetCompoundArray(compoundArray: PSingle; count: Integer): TStatus;
  begin
    result := SetStatus(GdipSetPenCompoundArray(nativePen, compoundArray, count));
  end;

  function TGPPen.GetCompoundArrayCount: Integer;
  begin
    SetStatus(GdipGetPenCompoundCount(nativePen, result));
  end;

  function TGPPen.GetCompoundArray(compoundArray: PSingle; count: Integer): TStatus;
  begin
    if (count <= 0) then
      result := SetStatus(InvalidParameter)
    else
      result := SetStatus(GdipGetPenCompoundArray(nativePen, compoundArray, count));
  end;

  function TGPPen.GetLastStatus: TStatus;
  begin
    result := lastResult;
    lastResult := Ok;
  end;

  constructor TGPPen.Create(nativePen: GpPen; status: TStatus);
  begin
    lastResult := status;
    SetNativePen(nativePen);
  end;

  procedure TGPPen.SetNativePen(nativePen: GpPen);
  begin
    self.nativePen := nativePen;
  end;

  function TGPPen.SetStatus(status: TStatus): TStatus;
  begin
    if (status <> Ok) then lastResult := status;
    result := status;
  end;

//--------------------------------------------------------------------------
// Abstract base class for various brush types
//--------------------------------------------------------------------------

  destructor TGPBrush.Destroy;
  begin
    GdipDeleteBrush(nativeBrush);
  end;

  function TGPBrush.Clone: TGPBrush;
  var
    brush: GpBrush;
    newBrush: TGPBrush;
  begin
    brush := nil;
    SetStatus(GdipCloneBrush(nativeBrush, brush));
    newBrush := TGPBrush.Create(brush, lastResult);
    if (newBrush = nil) then
      GdipDeleteBrush(brush);
    result := newBrush;
  end;

  function TGPBrush.GetType: TBrushType;
  var type_: TBrushType;
  begin
    type_ := TBrushType(-1);
    SetStatus(GdipGetBrushType(nativeBrush, type_));
    result := type_;
  end;

  function TGPBrush.GetLastStatus: TStatus;
  begin
    result := lastResult;
    lastResult := Ok;
  end;

  constructor TGPBrush.Create;
  begin
    SetStatus(NotImplemented);
  end;

  constructor TGPBrush.Create(nativeBrush: GpBrush; status: TStatus);
  begin
    lastResult := status;
    SetNativeBrush(nativeBrush);
  end;

  procedure TGPBrush.SetNativeBrush(nativeBrush: GpBrush);
  begin
    self.nativeBrush := nativeBrush;
  end;

  function TGPBrush.SetStatus(status: TStatus): TStatus;
  begin
    if (status <> Ok) then lastResult := status;
    result := status;
  end;

//--------------------------------------------------------------------------
// Solid Fill Brush Object
//--------------------------------------------------------------------------

  constructor TGPSolidBrush.Create(color: TGPColor);
  var
    brush: GpSolidFill;
  begin
    brush := nil;
    lastResult := GdipCreateSolidFill(color, brush);
    SetNativeBrush(brush);
  end;

  function TGPSolidBrush.GetColor(out color: TGPColor): TStatus;
  begin
    SetStatus(GdipGetSolidFillColor(GPSOLIDFILL(nativeBrush), color));
    result := lastResult;
  end;

  function TGPSolidBrush.SetColor(color: TGPColor): TStatus;
  begin
    result := SetStatus(GdipSetSolidFillColor(GpSolidFill(nativeBrush),
                color));
  end;

  constructor TGPSolidBrush.Create;
  begin
    // hide parent function
  end;

//--------------------------------------------------------------------------
// Texture Brush Fill Object
//--------------------------------------------------------------------------

  constructor TGPTextureBrush.Create(image: TGPImage; wrapMode: TWrapMode = WrapModeTile);
  var texture: GpTexture;
  begin
    //texture := nil;
    lastResult := GdipCreateTexture(image.nativeImage, wrapMode, texture);
    SetNativeBrush(texture);
  end;

  constructor TGPTextureBrush.Create(image: TGPImage; wrapMode: TWrapMode; dstRect: TGPRectF);
  var texture: GpTexture;
  begin
    texture := nil;
    lastResult := GdipCreateTexture2(image.nativeImage, wrapMode, dstRect.X,
                    dstRect.Y, dstRect.Width, dstRect.Height, texture);
    SetNativeBrush(texture);
  end;

  constructor TGPTextureBrush.Create(image: TGPImage; dstRect: TGPRectF; imageAttributes: TGPImageAttributes = nil);
  var texture: GpTexture;
      ImgAtt: GpImageAttributes;
  begin
    texture := nil;
    if assigned(imageAttributes) then ImgAtt := imageAttributes.nativeImageAttr
                                 else ImgAtt := nil;

    lastResult := GdipCreateTextureIA(image.nativeImage, ImgAtt, dstRect.X,
                    dstRect.Y, dstRect.Width, dstRect.Height, texture);
    SetNativeBrush(texture);
  end;

  constructor TGPTextureBrush.Create(image: TGPImage; dstRect: TGPRect; imageAttributes: TGPImageAttributes = nil);
  var texture: GpTexture;
      ImgAtt: GpImageAttributes;
  begin
    texture := nil;
    if assigned(imageAttributes) then ImgAtt := imageAttributes.nativeImageAttr
                                 else ImgAtt := nil;
    lastResult := GdipCreateTextureIAI(image.nativeImage, ImgAtt, dstRect.X,
                    dstRect.Y, dstRect.Width, dstRect.Height, texture);
     SetNativeBrush(texture);
  end;

  constructor TGPTextureBrush.Create(image: TGPImage; wrapMode: TWrapMode; dstRect: TGPRect);
  var texture: GpTexture;
  begin
    texture := nil;
    lastResult := GdipCreateTexture2I(image.nativeImage, wrapMode, dstRect.X,
                    dstRect.Y, dstRect.Width, dstRect.Height, texture);
    SetNativeBrush(texture);
  end;

  constructor TGPTextureBrush.Create(image: TGPImage; wrapMode: TWrapMode; dstX, dstY, dstWidth, dstHeight: Single);
  var texture: GpTexture;
  begin
    texture := nil;
    lastResult := GdipCreateTexture2(image.nativeImage, wrapMode, dstX, dstY,
                    dstWidth, dstHeight, texture);
    SetNativeBrush(texture);
  end;

  constructor TGPTextureBrush.Create(image: TGPImage; wrapMode: TWrapMode; dstX, dstY, dstWidth, dstHeight: Integer);
  var texture: GpTexture;
  begin
    texture := nil;
    lastResult := GdipCreateTexture2I(image.nativeImage, wrapMode, dstX, dstY,
                    dstWidth, dstHeight, texture);
    SetNativeBrush(texture);
  end;

  function TGPTextureBrush.SetTransform(matrix: TGPMatrix): TStatus;
  begin
    result := SetStatus(GdipSetTextureTransform(GpTexture(nativeBrush),
                matrix.nativeMatrix));
  end;

  function TGPTextureBrush.GetTransform(matrix: TGPMatrix): TStatus;
  begin
    result := SetStatus(GdipGetTextureTransform(GpTexture(nativeBrush),
                matrix.nativeMatrix));
  end;

  function TGPTextureBrush.ResetTransform: TStatus;
  begin
    result := SetStatus(GdipResetTextureTransform(GpTexture(nativeBrush)));
  end;

  function TGPTextureBrush.MultiplyTransform(matrix: TGPMatrix; order: TMatrixOrder = MatrixOrderPrepend): TStatus;
  begin
    result := SetStatus(GdipMultiplyTextureTransform(GpTexture(nativeBrush),
                matrix.nativeMatrix, order));
  end;

  function TGPTextureBrush.TranslateTransform(dx, dy: Single; order: MatrixOrder = MatrixOrderPrepend): TStatus;
  begin
    result := SetStatus(GdipTranslateTextureTransform(GpTexture(nativeBrush),
                dx, dy, order));
  end;

  function TGPTextureBrush.ScaleTransform(sx, sy: Single; order: TMatrixOrder = MatrixOrderPrepend): TStatus;
  begin
    result := SetStatus(GdipScaleTextureTransform(GpTexture(nativeBrush),
                 sx, sy, order));
  end;

  function TGPTextureBrush.RotateTransform(angle: Single; order: TMatrixOrder = MatrixOrderPrepend): TStatus;
  begin
    result := SetStatus(GdipRotateTextureTransform(GpTexture(nativeBrush),
                                                              angle, order));
  end;

  function TGPTextureBrush.SetWrapMode(wrapMode: TWrapMode): TStatus;
  begin
    result := SetStatus(GdipSetTextureWrapMode(GpTexture(nativeBrush), wrapMode));
  end;

  function TGPTextureBrush.GetWrapMode: TWrapMode;
  begin
    SetStatus(GdipGetTextureWrapMode(GpTexture(nativeBrush), result));
  end;

  function TGPTextureBrush.GetImage: TGPImage;
  var image: GpImage;
  begin
    SetStatus(GdipGetTextureImage(GpTexture(nativeBrush), image));
    result := TGPImage.Create(image, lastResult);
    if (result = nil) then
      GdipDisposeImage(image);
  end;

  constructor TGPTextureBrush.Create;
  begin
    // hide parent function
  end;

//--------------------------------------------------------------------------
// Linear Gradient Brush Object
//--------------------------------------------------------------------------

  constructor TGPLinearGradientBrush.Create(const point1, point2: TGPPointF; color1, color2: TGPColor);
  var brush: GpLineGradient;
  begin
    brush := nil;
    lastResult := GdipCreateLineBrush(@point1, @point2, color1, color2, WrapModeTile, brush);
    SetNativeBrush(brush);
  end;

  constructor TGPLinearGradientBrush.Create(const point1, point2: TGPPoint; color1, color2: TGPColor);
  var brush: GpLineGradient;
  begin
    brush := nil;
    lastResult := GdipCreateLineBrushI(@point1, @point2, color1,
                    color2, WrapModeTile, brush);
    SetNativeBrush(brush);
  end;

  constructor TGPLinearGradientBrush.Create(rect: TGPRectF; color1, color2: TGPColor; mode: TLinearGradientMode);
  var brush: GpLineGradient;
  begin
    brush := nil;
    lastResult := GdipCreateLineBrushFromRect(@rect, color1,
                    color2, mode, WrapModeTile, brush);
    SetNativeBrush(brush);
  end;

  constructor TGPLinearGradientBrush.Create(rect: TGPRect; color1, color2: TGPColor; mode: TLinearGradientMode);
  var brush: GpLineGradient;
  begin
    brush := nil;
    lastResult := GdipCreateLineBrushFromRectI(@rect, color1,
                    color2, mode, WrapModeTile, brush);
    SetNativeBrush(brush);
  end;

  constructor TGPLinearGradientBrush.Create(rect: TGPRectF; color1, color2: TGPColor; angle: Single; isAngleScalable: BOOL = FALSE);
  var brush: GpLineGradient;
  begin
    brush := nil;
    lastResult := GdipCreateLineBrushFromRectWithAngle(@rect, color1,
                    color2, angle, isAngleScalable, WrapModeTile, brush);
    SetNativeBrush(brush);
  end;

  constructor TGPLinearGradientBrush.Create(rect: TGPRect; color1, color2: TGPColor; angle: Single; isAngleScalable: BOOL = FALSE);
  var brush: GpLineGradient;
  begin
    brush := nil;
    lastResult := GdipCreateLineBrushFromRectWithAngleI(@rect, color1,
                    color2, angle, isAngleScalable, WrapModeTile, brush);
    SetNativeBrush(brush);
  end;

  function TGPLinearGradientBrush.SetLinearColors(color1, color2: TGPColor): TStatus;
  begin
    result := SetStatus(GdipSetLineColors(GpLineGradient(nativeBrush),
                color1, color2));
  end;

  function TGPLinearGradientBrush.GetLinearColors(out color1, color2: TGPColor): TStatus;
  var colors: array[0..1] of TGPColor;
  begin
    SetStatus(GdipGetLineColors(GpLineGradient(nativeBrush), @colors));
    if (lastResult = Ok) then
    begin
      color1 := colors[0];
      color2 := colors[1];
    end;
    result := lastResult;
  end;

  function TGPLinearGradientBrush.GetRectangle(out rect: TGPRectF): TStatus;
  begin
    result := SetStatus(GdipGetLineRect(GpLineGradient(nativeBrush), @rect));
  end;

  function TGPLinearGradientBrush.GetRectangle(out rect: TGPRect): TStatus;
  begin
    result := SetStatus(GdipGetLineRectI(GpLineGradient(nativeBrush), @rect));
  end;

  function TGPLinearGradientBrush.SetGammaCorrection(useGammaCorrection: BOOL): TStatus;
  begin
    result := SetStatus(GdipSetLineGammaCorrection(GpLineGradient(nativeBrush),
                useGammaCorrection));
  end;

  function TGPLinearGradientBrush.GetGammaCorrection: BOOL;
  var useGammaCorrection: BOOL;
  begin
    SetStatus(GdipGetLineGammaCorrection(GpLineGradient(nativeBrush),
                useGammaCorrection));
    result := useGammaCorrection;
  end;

  function TGPLinearGradientBrush.GetBlendCount: Integer;
  var count: Integer;
  begin
    count := 0;
    SetStatus(GdipGetLineBlendCount(GpLineGradient(nativeBrush), count));
    result := count;
  end;

  function TGPLinearGradientBrush.SetBlend(blendFactors, blendPositions: PSingle; count: Integer): TStatus;
  begin
    result := SetStatus(GdipSetLineBlend(GpLineGradient(nativeBrush),
                          blendFactors, blendPositions, count));
  end;

  function TGPLinearGradientBrush.GetBlend(blendFactors, blendPositions: PSingle; count: Integer): TStatus;
  begin
    if ((count <= 0) or (blendFactors = nil) or (blendPositions = nil)) then
      result := SetStatus(InvalidParameter)
    else
      result := SetStatus(GdipGetLineBlend(GpLineGradient(nativeBrush), blendFactors,
        blendPositions, count));
  end;

  function TGPLinearGradientBrush.GetInterpolationColorCount: Integer;
  var count: Integer;
  begin
    count := 0;
    SetStatus(GdipGetLinePresetBlendCount(GpLineGradient(nativeBrush), count));
    result := count;
  end;

  function TGPLinearGradientBrush.SetInterpolationColors(presetColors: PGPColor;
    blendPositions: PSingle; count: Integer): TStatus;
  begin
    if (count <= 0)  then
      result := SetStatus(InvalidParameter)
    else
      result := SetStatus(GdipSetLinePresetBlend(GpLineGradient(nativeBrush),
        PARGB(presetColors), blendPositions, count));
  end;

  function TGPLinearGradientBrush.GetInterpolationColors(presetColors: PGPColor; blendPositions: PSingle; count: Integer): TStatus;
  begin
    if (count <= 0) then
      result := SetStatus(InvalidParameter)
    else
      result := SetStatus(GdipGetLinePresetBlend(GpLineGradient(nativeBrush),
                          PARGB(presetColors), blendPositions, count));
  end;

  function TGPLinearGradientBrush.SetBlendBellShape(focus: Single; scale: Single = 1.0): TStatus;
  begin
    result := SetStatus(GdipSetLineSigmaBlend(GpLineGradient(nativeBrush), focus, scale));
  end;

  function TGPLinearGradientBrush.SetBlendTriangularShape(focus: Single; scale: Single = 1.0): TStatus;
  begin
    result := SetStatus(GdipSetLineLinearBlend(GpLineGradient(nativeBrush), focus, scale));
  end;

  function TGPLinearGradientBrush.SetTransform(matrix: TGPMatrix): TStatus;
  begin
    result := SetStatus(GdipSetLineTransform(GpLineGradient(nativeBrush),
                                                          matrix.nativeMatrix));
  end;

  function TGPLinearGradientBrush.GetTransform(matrix: TGPMatrix): TStatus;
  begin
    result := SetStatus(GdipGetLineTransform(GpLineGradient(nativeBrush),
                                                     matrix.nativeMatrix));
  end;

  function TGPLinearGradientBrush.ResetTransform: TStatus;
  begin
    result := SetStatus(GdipResetLineTransform(GpLineGradient(nativeBrush)));
  end;

  function TGPLinearGradientBrush.MultiplyTransform(matrix: TGPMatrix; order: TMatrixOrder = MatrixOrderPrepend): TStatus;
  begin
    result := SetStatus(GdipMultiplyLineTransform(GpLineGradient(nativeBrush),
                                                                matrix.nativeMatrix,
                                                                order));
  end;

  function TGPLinearGradientBrush.TranslateTransform(dx, dy: Single; order: TMatrixOrder = MatrixOrderPrepend): TStatus;
  begin
    result := SetStatus(GdipTranslateLineTransform(GpLineGradient(nativeBrush),
                                                               dx, dy, order));
  end;

  function TGPLinearGradientBrush.ScaleTransform(sx, sy: Single; order: TMatrixOrder = MatrixOrderPrepend): TStatus;
  begin
    result := SetStatus(GdipScaleLineTransform(GpLineGradient(nativeBrush),
                                                             sx, sy, order));
  end;

  function TGPLinearGradientBrush.RotateTransform(angle: Single; order: TMatrixOrder = MatrixOrderPrepend): TStatus;
  begin
    result := SetStatus(GdipRotateLineTransform(GpLineGradient(nativeBrush),
                                                              angle, order));
  end;

  function TGPLinearGradientBrush.SetWrapMode(wrapMode: TWrapMode): TStatus;
  begin
    result := SetStatus(GdipSetLineWrapMode(GpLineGradient(nativeBrush), wrapMode));
  end;

  function TGPLinearGradientBrush.GetWrapMode: TWrapMode;
  begin
     SetStatus(GdipGetLineWrapMode(GpLineGradient(nativeBrush), result));
  end;

  constructor TGPLinearGradientBrush.Create;
  begin
    // hide parent function
  end;

//--------------------------------------------------------------------------
// Hatch Brush Object
//--------------------------------------------------------------------------

  constructor TGPHatchBrush.Create(hatchStyle: THatchStyle; foreColor: TGPColor; backColor: TGPColor = aclBlack);
  var
    brush: GpHatch;
  begin
    brush := nil;
    lastResult := GdipCreateHatchBrush(Integer(hatchStyle), foreColor, backColor, brush);
    SetNativeBrush(brush);
  end;

  function TGPHatchBrush.GetHatchStyle: THatchStyle;
  begin
    SetStatus(GdipGetHatchStyle(GpHatch(nativeBrush), result));
  end;

  function TGPHatchBrush.GetForegroundColor(out color: TGPColor): TStatus;
  begin
    result := SetStatus(GdipGetHatchForegroundColor(GpHatch(nativeBrush), color));
  end;

  function TGPHatchBrush.GetBackgroundColor(out color: TGPColor): TStatus;
  begin
    result := SetStatus(GdipGetHatchBackgroundColor(GpHatch(nativeBrush), color));
  end;

  constructor TGPHatchBrush.Create;
  begin
  end;

  constructor TGPImage.Create(filename: WideString;
                  useEmbeddedColorManagement: BOOL = FALSE);
  begin
    nativeImage := nil;
    if(useEmbeddedColorManagement) then
    begin
        lastResult := GdipLoadImageFromFileICM(
            PWideChar(filename),
            nativeImage
        );
    end
    else
    begin
        lastResult := GdipLoadImageFromFile(
            PWideChar(filename),
            nativeImage
        );
    end;
  end;

  constructor TGPImage.Create(stream: IStream;
                  useEmbeddedColorManagement: BOOL  = FALSE);
  begin
    nativeImage := nil;
    if(useEmbeddedColorManagement) then
         lastResult := GdipLoadImageFromStreamICM(stream, nativeImage)
    else lastResult := GdipLoadImageFromStream(stream, nativeImage);
  end;

  function TGPImage.FromFile(filename: WideString;
               useEmbeddedColorManagement: BOOL = FALSE): TGPImage;
  begin
    result := TGPImage.Create(
        PWideChar(filename),
        useEmbeddedColorManagement
    );
  end;

  function TGPImage.FromStream(stream: IStream;
               useEmbeddedColorManagement: BOOL = FALSE): TGPImage;
  begin
    result := TGPImage.Create(
        stream,
        useEmbeddedColorManagement
    );
  end;

  destructor TGPImage.destroy;
  begin
    GdipDisposeImage(nativeImage);
  end;

  function TGPImage.Clone: TGPImage;
  var cloneimage: GpImage;
  begin
    cloneimage := nil;
    SetStatus(GdipCloneImage(nativeImage, cloneimage));
    result := TGPImage.Create(cloneimage, lastResult);
  end;

  function TGPImage.Save(filename: WideString; const clsidEncoder: TGUID;
               encoderParams: PEncoderParameters = nil): TStatus;
  begin
    result := SetStatus(GdipSaveImageToFile(nativeImage,
                                                     PWideChar(filename),
                                                     @clsidEncoder,
                                                     encoderParams));
  end;

  function TGPImage.Save(stream: IStream; const clsidEncoder: TGUID;
               encoderParams: PEncoderParameters  = nil): TStatus;
  begin
    result := SetStatus(GdipSaveImageToStream(nativeImage,
                                                       stream,
                                                       @clsidEncoder,
                                                       encoderParams));
  end;

  function TGPImage.SaveAdd(encoderParams: PEncoderParameters): TStatus;
  begin
    result := SetStatus(GdipSaveAdd(nativeImage,
                                             encoderParams));
  end;

  function TGPImage.SaveAdd(newImage: TGPImage;
               encoderParams: PEncoderParameters): TStatus;
  begin
    if (newImage = nil) then
    begin
      result := SetStatus(InvalidParameter);
      exit;
    end;
    result := SetStatus(GdipSaveAddImage(nativeImage,
                                                  newImage.nativeImage,
                                                  encoderParams));
  end;

  function TGPImage.GetType: TImageType;
  begin
    SetStatus(GdipGetImageType(nativeImage, result));
  end;

  function TGPImage.GetPhysicalDimension(out size: TGPSizeF): TStatus;
  var
    width, height: Single;
    status: TStatus;
  begin
    status := SetStatus(GdipGetImageDimension(nativeImage, width, height));
    size.Width  := width;
    size.Height := height;
    result := status;
  end;

  function TGPImage.GetBounds(out srcRect: TGPRectF; out srcUnit: TUnit): TStatus;
  begin
    result := SetStatus(GdipGetImageBounds(nativeImage, @srcRect, srcUnit));
  end;

  function TGPImage.GetWidth: UINT;
  var width: UINT;
  begin
    width := 0;
    SetStatus(GdipGetImageWidth(nativeImage, width));
    result := width;
  end;

  function TGPImage.GetHeight: UINT;
  var height: UINT;
  begin
    height := 0;
    SetStatus(GdipGetImageHeight(nativeImage, height));
    result := height;
  end;

  function TGPImage.GetHorizontalResolution: Single;
  var resolution: Single;
  begin
    resolution := 0.0;
    SetStatus(GdipGetImageHorizontalResolution(nativeImage, resolution));
    result := resolution;
  end;

  function TGPImage.GetVerticalResolution: Single;
  var resolution: Single;
  begin
    resolution := 0.0;
    SetStatus(GdipGetImageVerticalResolution(nativeImage, resolution));
    result := resolution;
  end;

  function TGPImage.GetFlags: UINT;
  var flags: UINT;
  begin
    flags := 0;
    SetStatus(GdipGetImageFlags(nativeImage, flags));
    result := flags;
  end;

  function TGPImage.GetRawFormat(out format: TGUID): TStatus;
  begin
    result := SetStatus(GdipGetImageRawFormat(nativeImage, @format));
  end;

  function TGPImage.GetPixelFormat: TPixelFormat;
  begin
    SetStatus(GdipGetImagePixelFormat(nativeImage, result));
  end;

  function TGPImage.GetPaletteSize: Integer;
  var size: Integer;
  begin
    size := 0;
    SetStatus(GdipGetImagePaletteSize(nativeImage, size));
    result := size;
  end;

  function TGPImage.GetPalette(palette: PColorPalette; size: Integer): TStatus;
  begin
    result := SetStatus(GdipGetImagePalette(nativeImage, palette, size));
  end;

  function TGPImage.SetPalette(palette: PColorPalette): TStatus;
  begin
    result := SetStatus(GdipSetImagePalette(nativeImage, palette));
  end;

  function TGPImage.GetThumbnailImage(thumbWidth, thumbHeight: UINT;
                callback: GetThumbnailImageAbort = nil;
                callbackData: pointer = nil): TGPImage;
  var
    thumbimage: GpImage;
    newImage: TGPImage;
  begin
    thumbimage := nil;
    SetStatus(GdipGetImageThumbnail(nativeImage,
                                                thumbWidth, thumbHeight,
                                                thumbimage,
                                                callback, callbackData));

    newImage := TGPImage.Create(thumbimage, lastResult);
    if (newImage = nil) then
        GdipDisposeImage(thumbimage);

    result := newImage;
  end;

  function TGPImage.GetFrameDimensionsCount: UINT;
  var count: UINT;
  begin
    count := 0;
    SetStatus(GdipImageGetFrameDimensionsCount(nativeImage, count));
    result := count;
  end;

  function TGPImage.GetFrameDimensionsList(dimensionIDs: PGUID; count: UINT): TStatus;
  begin
    result := SetStatus(GdipImageGetFrameDimensionsList(nativeImage, dimensionIDs, count));
  end;

  function TGPImage.GetFrameCount(const dimensionID: TGUID): UINT;
  var count: UINT;
  begin
    count := 0;
    SetStatus(GdipImageGetFrameCount(nativeImage, @dimensionID, count));
    result := count;
  end;

  function TGPImage.SelectActiveFrame(const dimensionID: TGUID; frameIndex: UINT): TStatus;
  begin
    result := SetStatus(GdipImageSelectActiveFrame(nativeImage,
                                                            @dimensionID,
                                                            frameIndex));
  end;

  function TGPImage.RotateFlip(rotateFlipType: TRotateFlipType): TStatus;
  begin
    result := SetStatus(GdipImageRotateFlip(nativeImage,
                                                     rotateFlipType));
  end;

  function TGPImage.GetPropertyCount: UINT;
  var numProperty: UINT;
  begin
    numProperty := 0;
    SetStatus(GdipGetPropertyCount(nativeImage, numProperty));
    result := numProperty;
  end;

  function TGPImage.GetPropertyIdList(numOfProperty: UINT; list: PPropID): TStatus;
  begin
    result := SetStatus(GdipGetPropertyIdList(nativeImage, numOfProperty, list));
  end;

  function TGPImage.GetPropertyItemSize(propId: PROPID): UINT;
  var size: UINT;
  begin
    size := 0;
    SetStatus(GdipGetPropertyItemSize(nativeImage, propId, size));
    result := size;
  end;

  function TGPImage.GetPropertyItem(propId: PROPID; propSize: UINT;
               buffer: PPropertyItem): TStatus;
  begin
    result := SetStatus(GdipGetPropertyItem(nativeImage,
                                                     propId, propSize, buffer));
  end;

  function TGPImage.GetPropertySize(out totalBufferSize, numProperties : UINT): TStatus;
  begin
    result := SetStatus(GdipGetPropertySize(nativeImage,
                                                     totalBufferSize,
                                                     numProperties));
  end;

  function TGPImage.GetAllPropertyItems(totalBufferSize, numProperties: UINT;
               allItems: PPROPERTYITEM): TStatus;
  begin
    result := SetStatus(GdipGetAllPropertyItems(nativeImage,
                                                         totalBufferSize,
                                                         numProperties,
                                                         allItems));
  end;

  function TGPImage.RemovePropertyItem(propId: TPROPID): TStatus;
  begin
    result := SetStatus(GdipRemovePropertyItem(nativeImage, propId));
  end;

  function TGPImage.SetPropertyItem(const item: TPropertyItem): TStatus;
  begin
    result := SetStatus(GdipSetPropertyItem(nativeImage, @item));
  end;

  function TGPImage.GetEncoderParameterListSize(const clsidEncoder: TGUID): UINT;
  var size: UINT;
  begin
    size := 0;
    SetStatus(GdipGetEncoderParameterListSize(nativeImage, @clsidEncoder, size));
    result := size;
  end;

  function TGPImage.GetEncoderParameterList(const clsidEncoder: TGUID; size: UINT;
               buffer: PEncoderParameters): TStatus;
  begin
    result := SetStatus(GdipGetEncoderParameterList(nativeImage,
                                                             @clsidEncoder,
                                                             size,
                                                             buffer));
  end;

  function TGPImage.GetLastStatus: TStatus;
  begin
    result := lastResult;
    lastResult := Ok;
  end;

  constructor TGPImage.Create(nativeImage: GpImage; status: TStatus);
  begin
    SetNativeImage(nativeImage);
    lastResult := status;
  end;

  procedure TGPImage.SetNativeImage(nativeImage: GpImage);
  begin
    self.nativeImage := nativeImage;
  end;

  function TGPImage.SetStatus(status: TStatus): TStatus;
  begin
    if (status <> Ok) then lastResult := status;
    result := status;
  end;

  // TGPBitmap

  constructor TGPBitmap.Create(filename: WideString; useEmbeddedColorManagement: BOOL = FALSE);
  var bitmap: GpBitmap;
  begin
    bitmap := nil;
    if(useEmbeddedColorManagement) then
      lastResult := GdipCreateBitmapFromFileICM(PWideChar(filename), bitmap)
    else
        lastResult := GdipCreateBitmapFromFile(PWideChar(filename), bitmap);
    SetNativeImage(bitmap);
  end;

  constructor TGPBitmap.Create(stream: IStream; useEmbeddedColorManagement: BOOL = FALSE);
  var bitmap: GpBitmap;
  begin
    bitmap := nil;
    if(useEmbeddedColorManagement) then
      lastResult := GdipCreateBitmapFromStreamICM(stream, bitmap)
    else
        lastResult := GdipCreateBitmapFromStream(stream, bitmap);
    SetNativeImage(bitmap);
  end;

  function TGPBitmap.FromFile(filename: WideString; useEmbeddedColorManagement: BOOL = FALSE): TGPBitmap;
  begin
    result := TGPBitmap.Create(
        PWideChar(filename),
        useEmbeddedColorManagement
    );
  end;

  function TGPBitmap.FromStream(stream: IStream; useEmbeddedColorManagement: BOOL = FALSE): TGPBitmap;
  begin
    result := TGPBitmap.Create(
        stream,
        useEmbeddedColorManagement
    );
  end;

  constructor TGPBitmap.Create(width, height, stride: Integer; format: TPixelFormat; scan0: PBYTE);
  var bitmap: GpBitmap;
  begin
    bitmap := nil;
    lastResult := GdipCreateBitmapFromScan0(width,
                                                       height,
                                                       stride,
                                                       format,
                                                       scan0,
                                                       bitmap);

    SetNativeImage(bitmap);
  end;

  constructor TGPBitmap.Create(width, height: Integer; format: TPixelFormat = PixelFormat32bppARGB);
  var bitmap: GpBitmap;
  begin
    bitmap := nil;
    lastResult := GdipCreateBitmapFromScan0(width,
                                                       height,
                                                       0,
                                                       format,
                                                       nil,
                                                       bitmap);

    SetNativeImage(bitmap);
  end;

  constructor TGPBitmap.Create(width, height: Integer; target: TGPGraphics);
  var bitmap: GpBitmap;
  begin
    bitmap := nil;
    lastResult := GdipCreateBitmapFromGraphics(width,
                                                          height,
                                                          target.nativeGraphics,
                                                          bitmap);

    SetNativeImage(bitmap);
  end;

  function TGPBitmap.Clone(rect: TGPRect; format: TPixelFormat): TGPBitmap;
  begin
    result := Clone(rect.X, rect.Y, rect.Width, rect.Height, format);
  end;

  function TGPBitmap.Clone(x, y, width, height: Integer; format: TPixelFormat): TGPBitmap;
  var
    bitmap: TGPBitmap;
    gpdstBitmap: GpBitmap;
  begin
    gpdstBitmap := nil;
    lastResult := GdipCloneBitmapAreaI(
                               x,
                               y,
                               width,
                               height,
                               format,
                               GpBitmap(nativeImage),
                               gpdstBitmap);

    if (lastResult = Ok) then
    begin
       bitmap := TGPBitmap.Create(gpdstBitmap);
       if (bitmap = nil) then
         GdipDisposeImage(gpdstBitmap);
       result := bitmap;
       exit;
    end
    else
       result := nil;
  end;

  function TGPBitmap.Clone(rect: TGPRectF; format: TPixelFormat): TGPBitmap;
  begin
    result := Clone(rect.X, rect.Y, rect.Width, rect.Height, format);
  end;

  function TGPBitmap.Clone(x, y, width, height: Single; format: TPixelFormat): TGPBitmap;
  var
    bitmap: TGPBitmap;
    gpdstBitmap: GpBitmap;
  begin
    gpdstBitmap := nil;
    SetStatus(GdipCloneBitmapArea(
                               x,
                               y,
                               width,
                               height,
                               format,
                               GpBitmap(nativeImage),
                               gpdstBitmap));

   if (lastResult = Ok) then
   begin
     bitmap := TGPBitmap.Create(gpdstBitmap);
     if (bitmap = nil) then
       GdipDisposeImage(gpdstBitmap);
       result := bitmap;
   end
   else
       result := nil;
  end;

  function TGPBitmap.LockBits(rect: TGPRect; flags: UINT; format: TPixelFormat;
               out lockedBitmapData: TBitmapData): TStatus;
  begin
    result := SetStatus(GdipBitmapLockBits(
                                    GpBitmap(nativeImage),
                                    @rect,
                                    flags,
                                    format,
                                    @lockedBitmapData));
  end;

  function TGPBitmap.UnlockBits(var lockedBitmapData: TBitmapData): TStatus;
  begin
    result := SetStatus(GdipBitmapUnlockBits(
                                    GpBitmap(nativeImage),
                                    @lockedBitmapData));
  end;

  function TGPBitmap.GetPixel(x, y: Integer; out color: TGPColor): TStatus;
  begin
    result := SetStatus(GdipBitmapGetPixel(GpBitmap(nativeImage), x, y, color));
  end;

  function TGPBitmap.SetPixel(x, y: Integer; color: TGPColor): TStatus;
  begin
    result := SetStatus(GdipBitmapSetPixel(
        GpBitmap(nativeImage),
        x, y,
        color));
  end;

  function TGPBitmap.SetResolution(xdpi, ydpi: Single): TStatus;
  begin
    result := SetStatus(GdipBitmapSetResolution(
        GpBitmap(nativeImage),
        xdpi, ydpi));
  end;

  constructor TGPBitmap.Create(var gdiBitmapInfo: TBITMAPINFO; gdiBitmapData: Pointer);
  var bitmap: GpBitmap;
  begin
    bitmap := nil;
    lastResult := GdipCreateBitmapFromGdiDib(@gdiBitmapInfo, gdiBitmapData, bitmap);
    SetNativeImage(bitmap);
  end;

  constructor TGPBitmap.Create(hbm: HBITMAP; hpal: HPALETTE);
  var bitmap: GpBitmap;
  begin
    bitmap := nil;
    lastResult := GdipCreateBitmapFromHBITMAP(hbm, hpal, bitmap);
    SetNativeImage(bitmap);
  end;

  {$IFNDEF KS_CBUILDER}
  constructor TGPBitmap.Create(hicon: HICON);
  var bitmap: GpBitmap;
  begin
    bitmap := nil;
    lastResult := GdipCreateBitmapFromHICON(hicon, bitmap);
    SetNativeImage(bitmap);
  end;

  function TGPBitmap.FromHICON(hicon: HICON): TGPBitmap;
  begin
    result := TGPBitmap.Create(hicon);
  end;
  {$ENDIF}

  constructor TGPBitmap.Create(hInstance: HMODULE; bitmapName: WideString);
  var bitmap: GpBitmap;
  begin
    bitmap := nil;
    lastResult := GdipCreateBitmapFromResource(hInstance, PWideChar(bitmapName), bitmap);
    SetNativeImage(bitmap);
  end;

  function TGPBitmap.FromBITMAPINFO(var gdiBitmapInfo: TBITMAPINFO; gdiBitmapData: Pointer): TGPBitmap;
  begin
    result := TGPBitmap.Create(gdiBitmapInfo, gdiBitmapData);
  end;

  function TGPBitmap.FromHBITMAP(hbm: HBITMAP; hpal: HPALETTE): TGPBitmap;
  begin
    result := TGPBitmap.Create(hbm, hpal);
  end;

  function TGPBitmap.FromResource(hInstance: HMODULE; bitmapName: WideString): TGPBitmap;
  begin
    result := TGPBitmap.Create(hInstance, PWideChar(bitmapName));
  end;

  function TGPBitmap.GetHBITMAP(colorBackground: TGPColor; out hbmreturn: HBITMAP): TStatus;
  begin
    result := SetStatus(GdipCreateHBITMAPFromBitmap(
                                        GpBitmap(nativeImage),
                                        hbmreturn,
                                        colorBackground));
  end;

  function TGPBitmap.GetHICON(out hicon: HICON): TStatus;
  begin
    result := SetStatus(GdipCreateHICONFromBitmap(
                                        GpBitmap(nativeImage),
                                        hicon));
  end;

  constructor TGPBitmap.Create(nativeBitmap: GpBitmap);
  begin
    lastResult := Ok;
    SetNativeImage(nativeBitmap);
  end;

(**************************************************************************\
*
*   GDI+ Graphics Object
*
\**************************************************************************)

  function TGPGraphics.FromHDC(hdc: HDC): TGPGraphics;
  begin
    result := TGPGraphics.Create(hdc, 0, 0);
  end;

  function TGPGraphics.FromHDC(hdc: HDC; hdevice: THANDLE): TGPGraphics;
  begin
    result := TGPGraphics.Create(hdc, hdevice);
  end;

  function TGPGraphics.FromHWND(hwnd: HWND; icm: BOOL = FALSE): TGPGraphics;
  begin
    result := TGPGraphics.Create(hwnd, icm);
  end;

  function TGPGraphics.FromImage(image: TGPImage): TGPGraphics;
  begin
    result := TGPGraphics.Create(image);
  end;

  constructor TGPGraphics.Create(hdc: HDC; NotUses1, NotUses2: integer);
  var graphics: GpGraphics;
  begin
    graphics:= nil;
    lastResult := GdipCreateFromHDC(hdc, graphics);
    SetNativeGraphics(graphics);
  end;

  constructor TGPGraphics.Create(hdc: HDC; hdevice: THANDLE);
  var graphics: GpGraphics;
  begin
    graphics:= nil;
    lastResult := GdipCreateFromHDC2(hdc, hdevice, graphics);
    SetNativeGraphics(graphics);
  end;

  constructor TGPGraphics.Create(hwnd: HWND; icm: BOOL{ = FALSE});
  var graphics: GpGraphics;
  begin
    graphics:= nil;
    if icm then lastResult := GdipCreateFromHWNDICM(hwnd, graphics)
           else lastResult := GdipCreateFromHWND(hwnd, graphics);
    SetNativeGraphics(graphics);
  end;

  constructor TGPGraphics.Create(image: TGPImage);
  var graphics: GpGraphics;
  begin
    graphics:= nil;
    if (image <> nil) then
      lastResult := GdipGetImageGraphicsContext(image.nativeImage, graphics);
    SetNativeGraphics(graphics);
  end;

  destructor TGPGraphics.destroy;
  begin
    GdipDeleteGraphics(nativeGraphics);
  end;

  procedure TGPGraphics.Flush(intention: TFlushIntention = FlushIntentionFlush);
  begin
    GdipFlush(nativeGraphics, intention);
  end;

    //------------------------------------------------------------------------
    // GDI Interop methods
    //------------------------------------------------------------------------

    // Locks the graphics until ReleaseDC is called

  function TGPGraphics.GetHDC: HDC;
  begin
    SetStatus(GdipGetDC(nativeGraphics, result));
  end;

  procedure TGPGraphics.ReleaseHDC(hdc: HDC);
  begin
    SetStatus(GdipReleaseDC(nativeGraphics, hdc));
  end;

    //------------------------------------------------------------------------
    // Rendering modes
    //------------------------------------------------------------------------

  function TGPGraphics.SetRenderingOrigin(x, y: Integer): TStatus;
  begin
    result := SetStatus(GdipSetRenderingOrigin(nativeGraphics, x, y));
  end;

  function TGPGraphics.GetRenderingOrigin(out x, y: Integer): TStatus;
  begin
    result := SetStatus(GdipGetRenderingOrigin(nativeGraphics, x, y));
  end;

  function TGPGraphics.SetCompositingMode(compositingMode: TCompositingMode): TStatus;
  begin
    result := SetStatus(GdipSetCompositingMode(nativeGraphics,
                                compositingMode));
  end;

  function TGPGraphics.GetCompositingMode: TCompositingMode;
  begin
    SetStatus(GdipGetCompositingMode(nativeGraphics, result));
  end;

  function TGPGraphics.SetCompositingQuality(compositingQuality: TCompositingQuality): TStatus;
  begin
    result := SetStatus(GdipSetCompositingQuality( nativeGraphics, compositingQuality));
  end;

  function TGPGraphics.GetCompositingQuality: TCompositingQuality;
  begin
    SetStatus(GdipGetCompositingQuality(nativeGraphics, result));
  end;

  function TGPGraphics.SetTextRenderingHint(newMode: TTextRenderingHint): TStatus;
  begin
    result := SetStatus(GdipSetTextRenderingHint(nativeGraphics, newMode));
  end;

  function TGPGraphics.GetTextRenderingHint: TTextRenderingHint;
  begin
    SetStatus(GdipGetTextRenderingHint(nativeGraphics, result));
  end;

  function TGPGraphics.SetTextContrast(contrast: UINT): TStatus;
  begin
    result := SetStatus(GdipSetTextContrast(nativeGraphics, contrast));
  end;

  function TGPGraphics.GetTextContrast: UINT;
  begin
    SetStatus(GdipGetTextContrast(nativeGraphics, result));
  end;

  function TGPGraphics.GetInterpolationMode: TInterpolationMode;
  var mode: TInterpolationMode;
  begin
    mode := InterpolationModeInvalid;
    SetStatus(GdipGetInterpolationMode(nativeGraphics, mode));
    result := mode;
  end;

  function TGPGraphics.SetInterpolationMode(interpolationMode: TInterpolationMode): TStatus;
  begin
    result := SetStatus(GdipSetInterpolationMode(nativeGraphics,
                               interpolationMode));
  end;

  function TGPGraphics.GetSmoothingMode: TSmoothingMode;
  var smoothingMode: TSmoothingMode;
  begin
    smoothingMode := SmoothingModeInvalid;
    SetStatus(GdipGetSmoothingMode(nativeGraphics,  smoothingMode));
    result := smoothingMode;
  end;

  function TGPGraphics.SetSmoothingMode(smoothingMode: TSmoothingMode): TStatus;
  begin
    result := SetStatus(GdipSetSmoothingMode(nativeGraphics, smoothingMode));
  end;

  function TGPGraphics.GetPixelOffsetMode: TPixelOffsetMode;
  var pixelOffsetMode: TPixelOffsetMode;
  begin
    pixelOffsetMode := PixelOffsetModeInvalid;
    SetStatus(GdipGetPixelOffsetMode(nativeGraphics, pixelOffsetMode));
    result := pixelOffsetMode;
  end;

  function TGPGraphics.SetPixelOffsetMode(pixelOffsetMode: TPixelOffsetMode): TStatus;
  begin
    result := SetStatus(GdipSetPixelOffsetMode(nativeGraphics, pixelOffsetMode));
  end;

    //------------------------------------------------------------------------
    // Manipulate current world transform
    //------------------------------------------------------------------------

  function TGPGraphics.SetTransform(matrix: TGPMatrix): TStatus;
  begin
    result := SetStatus(GdipSetWorldTransform(nativeGraphics, matrix.nativeMatrix));
  end;

  function TGPGraphics.ResetTransform: TStatus;
  begin
    result := SetStatus(GdipResetWorldTransform(nativeGraphics));
  end;

  function TGPGraphics.MultiplyTransform(matrix: TGPMatrix; order: TMatrixOrder = MatrixOrderPrepend): TStatus;
  begin
    result := SetStatus(GdipMultiplyWorldTransform(nativeGraphics,
                                matrix.nativeMatrix,
                                order));
  end;

  function TGPGraphics.TranslateTransform(dx, dy: Single; order: TMatrixOrder = MatrixOrderPrepend): TStatus;
  begin
    result := SetStatus(GdipTranslateWorldTransform(nativeGraphics,
                                   dx, dy, order));
  end;

  function TGPGraphics.ScaleTransform(sx, sy: Single; order: TMatrixOrder = MatrixOrderPrepend): TStatus;
  begin
    result := SetStatus(GdipScaleWorldTransform(nativeGraphics,
                                 sx, sy, order));
  end;

  function TGPGraphics.RotateTransform(angle: Single; order: TMatrixOrder = MatrixOrderPrepend): TStatus;
  begin
    result := SetStatus(GdipRotateWorldTransform(nativeGraphics,
                                  angle, order));
  end;

  function TGPGraphics.GetTransform(matrix: TGPMatrix): TStatus;
  begin
    result := SetStatus(GdipGetWorldTransform(nativeGraphics,
                               matrix.nativeMatrix));
  end;

  function TGPGraphics.SetPageUnit(unit_: TUnit): TStatus;
  begin
    result := SetStatus(GdipSetPageUnit(nativeGraphics,
                             unit_));
  end;

  function TGPGraphics.SetPageScale(scale: Single): TStatus;
  begin
    result := SetStatus(GdipSetPageScale(nativeGraphics,
                              scale));
  end;

  function TGPGraphics.GetPageUnit: TUnit;
  begin
    SetStatus(GdipGetPageUnit(nativeGraphics, result));
  end;

  function TGPGraphics.GetPageScale: Single;
  begin
    SetStatus(GdipGetPageScale(nativeGraphics, result));
  end;

  function TGPGraphics.GetDpiX: Single;
  begin
    SetStatus(GdipGetDpiX(nativeGraphics, result));
  end;

  function TGPGraphics.GetDpiY: Single;
  begin
    SetStatus(GdipGetDpiY(nativeGraphics, result));
  end;

  function TGPGraphics.TransformPoints(destSpace: TCoordinateSpace;
               srcSpace: TCoordinateSpace;
               pts: PGPPointF;
               count: Integer): TStatus;
  begin
    result := SetStatus(GdipTransformPoints(nativeGraphics,
                             destSpace,
                             srcSpace,
                             pts,
                             count));
  end;

  function TGPGraphics.TransformPoints(destSpace: TCoordinateSpace;
               srcSpace: TCoordinateSpace;
               pts: PGPPoint;
               count: Integer): TStatus;
  begin

    result := SetStatus(GdipTransformPointsI(nativeGraphics,
                              destSpace,
                              srcSpace,
                              pts,
                              count));
  end;

    //------------------------------------------------------------------------
    // GetNearestColor (for <= 8bpp surfaces).  Note: Alpha is ignored.
    //------------------------------------------------------------------------

  function TGPGraphics.GetNearestColor(var color: TGPColor): TStatus;
  begin
    result := SetStatus(GdipGetNearestColor(nativeGraphics, @color));
  end;

  function TGPGraphics.DrawLine(pen: TGPPen; x1, y1, x2, y2: Single): TStatus;
  begin
    result := SetStatus(GdipDrawLine(nativeGraphics,
                          pen.nativePen, x1, y1, x2,
                          y2));
  end;

  function TGPGraphics.DrawLine(pen: TGPPen; const pt1, pt2: TGPPointF): TStatus;
  begin
    result := DrawLine(pen, pt1.X, pt1.Y, pt2.X, pt2.Y);
  end;

  function TGPGraphics.DrawLines(pen: TGPPen; points: PGPPointF; count: Integer): TStatus;
  begin
    result := SetStatus(GdipDrawLines(nativeGraphics,
                           pen.nativePen,
                           points, count));
  end;

  function TGPGraphics.DrawLine(pen: TGPPen; x1, y1, x2, y2: Integer): TStatus;
  begin
    result := SetStatus(GdipDrawLineI(nativeGraphics,
                           pen.nativePen,
                           x1,
                           y1,
                           x2,
                           y2));
  end;

  function TGPGraphics.DrawLine(pen: TGPPen; const pt1, pt2: TGPPoint): TStatus;
  begin
    result := DrawLine(pen,
            pt1.X,
            pt1.Y,
            pt2.X,
            pt2.Y);
  end;

  function TGPGraphics.DrawLines(pen: TGPPen; points: PGPPoint; count: Integer): TStatus;
  begin
    result := SetStatus(GdipDrawLinesI(nativeGraphics,
                            pen.nativePen,
                            points,
                            count));
  end;

  function TGPGraphics.DrawArc(pen: TGPPen; x, y, width, height, startAngle, sweepAngle: Single): TStatus;
  begin
    result := SetStatus(GdipDrawArc(nativeGraphics,
                         pen.nativePen,
                         x,
                         y,
                         width,
                         height,
                         startAngle,
                         sweepAngle));
  end;

  function TGPGraphics.DrawArc(pen: TGPPen; const rect: TGPRectF; startAngle, sweepAngle: Single): TStatus;
  begin
    result := DrawArc(pen, rect.X, rect.Y, rect.Width, rect.Height,
               startAngle, sweepAngle);
  end;

  function TGPGraphics.DrawArc(pen: TGPPen; x, y, width, height: Integer; startAngle,
           sweepAngle: Single): TStatus;
  begin
    result := SetStatus(GdipDrawArcI(nativeGraphics,
                          pen.nativePen,
                          x,
                          y,
                          width,
                          height,
                          startAngle,
                          sweepAngle));
  end;


  function TGPGraphics.DrawArc(pen: TGPPen; const rect: TGPRect; startAngle, sweepAngle: Single): TStatus;
  begin
    result := DrawArc(pen,
               rect.X,
               rect.Y,
               rect.Width,
               rect.Height,
               startAngle,
               sweepAngle);
  end;

  function TGPGraphics.DrawBezier(pen: TGPPen; x1, y1, x2, y2, x3, y3, x4, y4: Single): TStatus;
  begin
    result := SetStatus(GdipDrawBezier(nativeGraphics,
                            pen.nativePen, x1, y1,
                            x2, y2, x3, y3, x4, y4));
  end;

  function TGPGraphics.DrawBezier(pen: TGPPen; const pt1, pt2, pt3, pt4: TGPPointF): TStatus;
  begin
    result := DrawBezier(pen,
              pt1.X,
              pt1.Y,
              pt2.X,
              pt2.Y,
              pt3.X,
              pt3.Y,
              pt4.X,
              pt4.Y);
  end;

  function TGPGraphics.DrawBeziers(pen: TGPPen; points: PGPPointF; count: Integer): TStatus;
  begin
    result := SetStatus(GdipDrawBeziers(nativeGraphics,
                             pen.nativePen,
                             points,
                             count));
  end;

  function TGPGraphics.DrawBezier(pen: TGPPen; x1, y1, x2, y2, x3, y3, x4, y4: Integer): TStatus;
  begin
    result := SetStatus(GdipDrawBezierI(nativeGraphics,
                             pen.nativePen,
                             x1,
                             y1,
                             x2,
                             y2,
                             x3,
                             y3,
                             x4,
                             y4));
  end;

  function TGPGraphics.DrawBezier(pen: TGPPen; const pt1, pt2, pt3, pt4: TGPPoint): TStatus;
  begin
    result := DrawBezier(pen,
              pt1.X,
              pt1.Y,
              pt2.X,
              pt2.Y,
              pt3.X,
              pt3.Y,
              pt4.X,
              pt4.Y);
  end;

  function TGPGraphics.DrawBeziers(pen: TGPPen; points: PGPPoint; count: Integer): TStatus;
  begin
    result := SetStatus(GdipDrawBeziersI(nativeGraphics,
                              pen.nativePen,
                              points,
                              count));
  end;

  function TGPGraphics.DrawRectangle(pen: TGPPen; const rect: TGPRectF): TStatus;
  begin
    result := DrawRectangle(pen, rect.X, rect.Y, rect.Width, rect.Height);
  end;

  function TGPGraphics.DrawRectangle(pen: TGPPen; x, y, width, height: Single): TStatus;
  begin
    result := SetStatus(GdipDrawRectangle(nativeGraphics,
                               pen.nativePen, x, y,
                               width, height));
  end;

  function TGPGraphics.DrawRectangles(pen: TGPPen;  rects: PGPRectF; count: Integer): TStatus;
  begin
    result := SetStatus(GdipDrawRectangles(nativeGraphics,
                            pen.nativePen,
                            rects, count));
  end;

  function TGPGraphics.DrawRectangle(pen: TGPPen; const rect: TGPRect): TStatus;
  begin
    result := DrawRectangle(pen,
                 rect.X,
                 rect.Y,
                 rect.Width,
                 rect.Height);
  end;

  function TGPGraphics.DrawRectangle(pen: TGPPen; x, y, width, height: Integer): TStatus;
  begin
    result := SetStatus(GdipDrawRectangleI(nativeGraphics,
                            pen.nativePen,
                            x,
                            y,
                            width,
                            height));
  end;

  function TGPGraphics.DrawRectangles(pen: TGPPen; rects: PGPRect; count: Integer): TStatus;
  begin
    result := SetStatus(GdipDrawRectanglesI(nativeGraphics,
                             pen.nativePen,
                             rects,
                             count));
  end;

  function TGPGraphics.DrawEllipse(pen: TGPPen; const rect: TGPRectF): TStatus;
  begin
    result := DrawEllipse(pen, rect.X, rect.Y, rect.Width, rect.Height);
  end;

  function TGPGraphics.DrawEllipse(pen: TGPPen; x, y, width, height: Single): TStatus;
  begin
    result := SetStatus(GdipDrawEllipse(nativeGraphics,
                             pen.nativePen,
                             x,
                             y,
                             width,
                             height));
  end;

  function TGPGraphics.DrawEllipse(pen: TGPPen; const rect: TGPRect): TStatus;
  begin
    result := DrawEllipse(pen,
               rect.X,
               rect.Y,
               rect.Width,
               rect.Height);
  end;

  function TGPGraphics.DrawEllipse(pen: TGPPen; x, y, width, height: Integer): TStatus;
  begin
    result := SetStatus(GdipDrawEllipseI(nativeGraphics,
                              pen.nativePen,
                              x,
                              y,
                              width,
                              height));
  end;

  function TGPGraphics.DrawPie(pen: TGPPen; const rect: TGPRectF; startAngle, sweepAngle: Single): TStatus;
  begin
    result := DrawPie(pen,
               rect.X,
               rect.Y,
               rect.Width,
               rect.Height,
               startAngle,
               sweepAngle);
  end;

  function TGPGraphics.DrawPie(pen: TGPPen; x, y, width, height, startAngle, sweepAngle: Single): TStatus;
  begin
    result := SetStatus(GdipDrawPie(nativeGraphics,
                         pen.nativePen,
                         x,
                         y,
                         width,
                         height,
                         startAngle,
                         sweepAngle));
  end;

  function TGPGraphics.DrawPie(pen: TGPPen; const rect: TGPRect; startAngle, sweepAngle: Single): TStatus;
  begin
    result := DrawPie(pen,
               rect.X,
               rect.Y,
               rect.Width,
               rect.Height,
               startAngle,
               sweepAngle);
  end;

  function TGPGraphics.DrawPie(pen: TGPPen; x, y, width, height: Integer;
                 startAngle, sweepAngle: Single): TStatus;
  begin
    result := SetStatus(GdipDrawPieI(nativeGraphics,
                          pen.nativePen,
                          x,
                          y,
                          width,
                          height,
                          startAngle,
                          sweepAngle));
  end;

  function TGPGraphics.DrawPolygon(pen: TGPPen; points: PGPPointF; count: Integer): TStatus;
  begin
    result := SetStatus(GdipDrawPolygon(nativeGraphics,
                             pen.nativePen,
                             points,
                             count));
  end;

  function TGPGraphics.DrawPolygon(pen: TGPPen; points: PGPPoint; count: Integer): TStatus;
  begin
    result := SetStatus(GdipDrawPolygonI(nativeGraphics,
                              pen.nativePen,
                              points,
                              count));
  end;

  function TGPGraphics.DrawPath(pen: TGPPen; path: TGPGraphicsPath): TStatus;
  var
    nPen: GpPen;
    nPath: GpPath;
  begin
    if assigned(pen) then nPen := pen.nativePen else nPen  := nil;
    if assigned(path) then nPath := path.nativePath else nPath := nil;
    result := SetStatus(GdipDrawPath(nativeGraphics, nPen, nPath));
  end;

  function TGPGraphics.DrawCurve(pen: TGPPen; points: PGPPointF; count: Integer): TStatus;
  begin
    result := SetStatus(GdipDrawCurve(nativeGraphics,
                           pen.nativePen, points,
                           count));
  end;

  function TGPGraphics.DrawCurve(pen: TGPPen; points: PGPPointF; count: Integer; tension: Single): TStatus;
  begin
    result := SetStatus(GdipDrawCurve2(nativeGraphics,
                            pen.nativePen, points,
                            count, tension));
  end;

  function TGPGraphics.DrawCurve(pen: TGPPen; points: PGPPointF; count, offset,
           numberOfSegments: Integer; tension: Single = 0.5): TStatus;
  begin
    result := SetStatus(GdipDrawCurve3(nativeGraphics,
                            pen.nativePen, points,
                            count, offset,
                            numberOfSegments, tension));
  end;

  function TGPGraphics.DrawCurve(pen: TGPPen; points: PGPPoint; count: Integer): TStatus;
  begin
    result := SetStatus(GdipDrawCurveI(nativeGraphics,
                            pen.nativePen,
                            points,
                            count));
  end;

  function TGPGraphics.DrawCurve(pen: TGPPen; points: PGPPoint; count: Integer; tension: Single): TStatus;
  begin
    result := SetStatus(GdipDrawCurve2I(nativeGraphics,
                             pen.nativePen,
                             points,
                             count,
                             tension));
  end;

  function TGPGraphics.DrawCurve(pen: TGPPen; points: PGPPoint; count, offset,
           numberOfSegments: Integer; tension: Single = 0.5): TStatus;
  begin
    result := SetStatus(GdipDrawCurve3I(nativeGraphics,
                             pen.nativePen,
                             points,
                             count,
                             offset,
                             numberOfSegments,
                             tension));
  end;

  function TGPGraphics.DrawClosedCurve(pen: TGPPen; points: PGPPointF; count: Integer): TStatus;
  begin
    result := SetStatus(GdipDrawClosedCurve(nativeGraphics,
                             pen.nativePen,
                             points, count));
  end;

  function TGPGraphics.DrawClosedCurve(pen: TGPPen; points: PGPPointF; count: Integer;
           tension: Single): TStatus;
  begin
    result := SetStatus(GdipDrawClosedCurve2(nativeGraphics,
                              pen.nativePen,
                              points, count,
                              tension));
  end;

  function TGPGraphics.DrawClosedCurve(pen: TGPPen; points: PGPPoint; count: Integer): TStatus;
  begin
    result := SetStatus(GdipDrawClosedCurveI(nativeGraphics,
                              pen.nativePen,
                              points,
                              count));
  end;

  function TGPGraphics.DrawClosedCurve(pen: TGPPen; points: PGPPoint;
           count: Integer; tension: Single): TStatus;
  begin
    result := SetStatus(GdipDrawClosedCurve2I(nativeGraphics,
                               pen.nativePen,
                               points,
                               count,
                               tension));
  end;

  function TGPGraphics.Clear(color: TGPColor): TStatus;
  begin
    result := SetStatus(GdipGraphicsClear(
        nativeGraphics,
        color));
  end;

  function TGPGraphics.FillRectangle(brush: TGPBrush; const rect: TGPRectF): TStatus;
  begin
    result := FillRectangle(brush, rect.X, rect.Y, rect.Width, rect.Height);
  end;

  function TGPGraphics.FillRectangle(brush: TGPBrush; x, y, width, height: Single): TStatus;
  begin
    result := SetStatus(GdipFillRectangle(nativeGraphics,
                               brush.nativeBrush, x, y,
                               width, height));
  end;

  function TGPGraphics.FillRectangles(brush: TGPBrush; rects: PGPRectF; count: Integer): TStatus;
  begin
    result := SetStatus(GdipFillRectangles(nativeGraphics,
                            brush.nativeBrush,
                            rects, count));
  end;

  function TGPGraphics.FillRectangle(brush: TGPBrush; const rect: TGPRect): TStatus;
  begin
    result := FillRectangle(brush,
                 rect.X,
                 rect.Y,
                 rect.Width,
                 rect.Height);
  end;

  function TGPGraphics.FillRectangle(brush: TGPBrush; x, y, width, height: Integer): TStatus;
  begin
    result := SetStatus(GdipFillRectangleI(nativeGraphics,
                            brush.nativeBrush,
                            x,
                            y,
                            width,
                            height));
  end;

  function TGPGraphics.FillRectangles(brush: TGPBrush; rects: PGPRect; count: Integer): TStatus;
  begin
    result := SetStatus(GdipFillRectanglesI(nativeGraphics,
                             brush.nativeBrush,
                             rects,
                             count));
  end;

  function TGPGraphics.FillPolygon(brush: TGPBrush; points: PGPPointF; count: Integer): TStatus;
  begin
    result := FillPolygon(brush, points, count, FillModeAlternate);
  end;

  function TGPGraphics.FillPolygon(brush: TGPBrush; points: PGPPointF; count: Integer;
               fillMode: TFillMode): TStatus;
  begin
    result := SetStatus(GdipFillPolygon(nativeGraphics,
                             brush.nativeBrush,
                             points, count, fillMode));
  end;

  function TGPGraphics.FillPolygon(brush: TGPBrush; points: PGPPoint; count: Integer): TStatus;
  begin
    result := FillPolygon(brush, points, count, FillModeAlternate);
  end;

  function TGPGraphics.FillPolygon(brush: TGPBrush; points: PGPPoint; count: Integer;
               fillMode: TFillMode): TStatus;
  begin
    result := SetStatus(GdipFillPolygonI(nativeGraphics,
                              brush.nativeBrush,
                              points, count,
                              fillMode));
  end;

  function TGPGraphics.FillEllipse(brush: TGPBrush; const rect: TGPRectF): TStatus;
  begin
    result := FillEllipse(brush, rect.X, rect.Y, rect.Width, rect.Height);
  end;

  function TGPGraphics.FillEllipse(brush: TGPBrush; x, y, width, height: Single): TStatus;
  begin
    result := SetStatus(GdipFillEllipse(nativeGraphics,
                             brush.nativeBrush, x, y,
                             width, height));
  end;

  function TGPGraphics.FillEllipse(brush: TGPBrush; const rect: TGPRect): TStatus;
  begin
    result := FillEllipse(brush, rect.X, rect.Y, rect.Width, rect.Height);
  end;

  function TGPGraphics.FillEllipse(brush: TGPBrush; x, y, width, height: Integer): TStatus;
  begin
    result := SetStatus(GdipFillEllipseI(nativeGraphics,
                              brush.nativeBrush,
                              x,
                              y,
                              width,
                              height));
  end;

  function TGPGraphics.FillPie(brush: TGPBrush; const rect: TGPRectF; startAngle, sweepAngle: Single): TStatus;
  begin
    result := FillPie(brush, rect.X, rect.Y, rect.Width, rect.Height,
               startAngle, sweepAngle);
  end;

  function TGPGraphics.FillPie(brush: TGPBrush; x, y, width, height, startAngle, sweepAngle: Single): TStatus;
  begin
    result := SetStatus(GdipFillPie(nativeGraphics,
                         brush.nativeBrush, x, y,
                         width, height, startAngle,
                         sweepAngle));
  end;

  function TGPGraphics.FillPie(brush: TGPBrush; const rect: TGPRect; startAngle, sweepAngle: Single): TStatus;
  begin
    result := FillPie(brush, rect.X, rect.Y, rect.Width, rect.Height,
               startAngle, sweepAngle);
  end;

  function TGPGraphics.FillPie(brush: TGPBrush; x, y, width, height: Integer; startAngle,
           sweepAngle: Single): TStatus;
  begin
    result := SetStatus(GdipFillPieI(nativeGraphics,
                          brush.nativeBrush,
                          x,
                          y,
                          width,
                          height,
                          startAngle,
                          sweepAngle));
  end;

  function TGPGraphics.FillPath(brush: TGPBrush; path: TGPGraphicsPath): TStatus;
  begin
    result := SetStatus(GdipFillPath(nativeGraphics,
                          brush.nativeBrush,
                          path.nativePath));
  end;

  function TGPGraphics.FillClosedCurve(brush: TGPBrush; points: PGPPointF; count: Integer): TStatus;
  begin
    result := SetStatus(GdipFillClosedCurve(nativeGraphics,
                             brush.nativeBrush,
                             points, count));

  end;

  function TGPGraphics.FillClosedCurve(brush: TGPBrush; points: PGPPointF; count: Integer;
               fillMode: TFillMode; tension: Single = 0.5): TStatus;
  begin
    result := SetStatus(GdipFillClosedCurve2(nativeGraphics,
                              brush.nativeBrush,
                              points, count,
                              tension, fillMode));
  end;

  function TGPGraphics.FillClosedCurve(brush: TGPBrush; points:  PGPPoint; count: Integer): TStatus;
  begin
    result := SetStatus(GdipFillClosedCurveI(nativeGraphics,
                              brush.nativeBrush,
                              points,
                              count));
  end;

  function TGPGraphics.FillClosedCurve(brush: TGPBrush; points: PGPPoint;
           count: Integer; fillMode: TFillMode; tension: Single = 0.5): TStatus;
  begin
    result := SetStatus(GdipFillClosedCurve2I(nativeGraphics,
                               brush.nativeBrush,
                               points, count,
                               tension, fillMode));
  end;

  function TGPGraphics.FillRegion(brush: TGPBrush; region: TGPRegion): TStatus;
  begin
    result := SetStatus(GdipFillRegion(nativeGraphics,
                            brush.nativeBrush,
                            region.nativeRegion));
  end;


  function TGPGraphics.DrawString( string_: WideString; length: Integer; font: TGPFont;
     const layoutRect: TGPRectF; stringFormat: TGPStringFormat; brush: TGPBrush): TStatus;
  var
    nFont: GpFont;
    nStringFormat: GpStringFormat;
    nBrush: GpBrush;
  begin
    if assigned(font) then nfont := font.nativeFont else nfont := nil;
    if assigned(stringFormat) then nstringFormat := stringFormat.nativeFormat else nstringFormat := nil;
    if assigned(brush) then nbrush := brush.nativeBrush else nbrush := nil;
    result := SetStatus(GdipDrawString(
        nativeGraphics,
        PWideChar(string_),
        length,
        nfont,
        @layoutRect,
        nstringFormat,
        nbrush));
  end;

  function TGPGraphics.DrawString(string_: WideString; length: Integer; font: TGPFont;
           const origin: TGPPointF; brush: TGPBrush): TStatus;
  var
    rect: TGPRectF;
    nfont: Gpfont;
    nBrush: GpBrush;
  begin
    rect.X := origin.X;
    rect.Y := origin.Y;
    rect.Width := 0.0;
    rect.Height := 0.0;
    if assigned(font) then nfont := font.nativeFont else nfont := nil;
    if assigned(Brush) then nBrush := Brush.nativeBrush else nBrush := nil;
    result := SetStatus(GdipDrawString(
        nativeGraphics,
        PWideChar(string_),
        length,
        nfont,
        @rect,
        nil,
        nbrush));
  end;

  function TGPGraphics.DrawString(string_: WideString; length: Integer; font: TGPFont;
      const origin: TGPPointF; stringFormat: TGPStringFormat; brush: TGPBrush): TStatus;
  var
    rect: TGPRectF;
    nFont: GpFont;
    nStringFormat: GpStringFormat;
    nBrush: GpBrush;
  begin
    rect.X := origin.X;
    rect.Y := origin.Y;
    rect.Width := 0.0;
    rect.Height := 0.0;
    if assigned(font) then nfont := font.nativeFont else nfont := nil;
    if assigned(stringFormat) then nstringFormat := stringFormat.nativeFormat else nstringFormat := nil;
    if assigned(brush) then nbrush := brush.nativeBrush else nbrush := nil;
    result := SetStatus(GdipDrawString(
        nativeGraphics,
        PWideChar(string_),
        length,
        nfont,
        @rect,
        nstringFormat,
        nbrush));
  end;


  function TGPGraphics.MeasureString(string_: WideString; length: Integer; font: TGPFont;
       const layoutRect: TGPRectF; stringFormat: TGPStringFormat; out boundingBox: TGPRectF;
       codepointsFitted: PInteger = nil; linesFilled: PInteger = nil): TStatus;
  var
    nFont: GpFont;
    nStringFormat: GpStringFormat;
  begin
    if assigned(font) then nfont := font.nativeFont else nfont := nil;
    if assigned(stringFormat) then nstringFormat := stringFormat.nativeFormat else nstringFormat := nil;
    result := SetStatus(GdipMeasureString(
        nativeGraphics,
        PWideChar(string_),
        length,
        nfont,
        @layoutRect,
        nstringFormat,
        @boundingBox,
        codepointsFitted,
        linesFilled
    ));
  end;


  function TGPGraphics.MeasureString(string_: WideString; length: Integer; font: TGPFont;
       const layoutRectSize: TGPSizeF; stringFormat: TGPStringFormat; out size: TGPSizeF;
       codepointsFitted: PInteger = nil; linesFilled: PInteger = nil): TStatus;
  var
    layoutRect, boundingBox: TGPRectF;
    status: TStatus;
    nFont: GpFont;
    nStringFormat: GpStringFormat;
  begin
    layoutRect.X := 0;
    layoutRect.Y := 0;
    layoutRect.Width := layoutRectSize.Width;
    layoutRect.Height := layoutRectSize.Height;

    if assigned(font) then nfont := font.nativeFont else nfont := nil;
    if assigned(stringFormat) then nstringFormat := stringFormat.nativeFormat else nstringFormat := nil;

    status := SetStatus(GdipMeasureString(
        nativeGraphics,
        PWideChar(string_),
        length,
        nfont,
        @layoutRect,
        nstringFormat,
        @boundingBox,
        codepointsFitted,
        linesFilled
    ));

    if (status = Ok) then
    begin
      size.Width  := boundingBox.Width;
      size.Height := boundingBox.Height;
    end;
    result := status;
  end;


  function TGPGraphics.MeasureString(string_: WideString ; length: Integer; font: TGPFont;
       const origin: TGPPointF; stringFormat: TGPStringFormat; out boundingBox: TGPRectF): TStatus;
  var
    rect: TGPRectF;
    nFont: GpFont;
    nstringFormat: GpstringFormat;
  begin
    rect.X := origin.X;
    rect.Y := origin.Y;
    rect.Width := 0.0;
    rect.Height := 0.0;

    if assigned(font) then nfont := font.nativeFont else nfont := nil;
    if assigned(stringFormat) then nstringFormat := stringFormat.nativeFormat else nstringFormat := nil;

    result := SetStatus(GdipMeasureString(
        nativeGraphics,
        PWideChar(string_),
        length,
        nfont,
        @rect,
        nstringFormat,
        @boundingBox,
        nil,
        nil
    ));
  end;


  function TGPGraphics.MeasureString(string_: WideString; length: Integer; font: TGPFont;
       const layoutRect: TGPRectF; out boundingBox: TGPRectF): TStatus;
  var
    nFont: GpFont;
  begin
    if assigned(font) then nfont := font.nativeFont else nfont := nil;
    result := SetStatus(GdipMeasureString(
        nativeGraphics,
        PWideChar(string_),
        length,
        nfont,
        @layoutRect,
        nil,
        @boundingBox,
        nil,
        nil
    ));
  end;


  function TGPGraphics.MeasureString(string_: WideString; length: Integer; font: TGPFont;
       const origin: TGPPointF; out boundingBox: TGPRectF): TStatus;
  var
    nFont: GpFont;
    rect: TGPRectF;
  begin
    if assigned(font) then nfont := font.nativeFont else nfont := nil;
    rect.X := origin.X;
    rect.Y := origin.Y;
    rect.Width := 0.0;
    rect.Height := 0.0;

    result := SetStatus(GdipMeasureString(
        nativeGraphics,
        PWideChar(string_),
        length,
        nfont,
        @rect,
        nil,
        @boundingBox,
        nil,
        nil
    ));
  end;



  function TGPGraphics.MeasureCharacterRanges(string_: WideString; length: Integer; font: TGPFont;
       const layoutRect: TGPRectF; stringFormat: TGPStringFormat; regionCount: Integer;
       const regions: array of TGPRegion): TStatus;
  var
    nativeRegions: Pointer;
    i: Integer;
    Status: TStatus;
    nFont: GpFont;
    nstringFormat: GpstringFormat;
  type
    TArrayGpRegion = array of GpRegion;
  begin
    if assigned(font) then nfont := font.nativeFont else nfont := nil;
    if assigned(stringFormat) then nstringFormat := stringFormat.nativeFormat else nstringFormat := nil;

    if (regionCount <= 0) then
    begin
      result := InvalidParameter;
      exit;
    end;

    getmem(nativeRegions, Sizeof(GpRegion)* regionCount);

    for i := 0 to regionCount - 1 do
      TArrayGpRegion(nativeRegions)[i] := regions[i].nativeRegion;

    status := SetStatus(GdipMeasureCharacterRanges(
        nativeGraphics,
        PWideChar(string_),
        length,
        nfont,
        @layoutRect,
        nstringFormat,
        regionCount,
        nativeRegions
    ));

    freemem(nativeRegions, Sizeof(GpRegion)* regionCount);
    result := status;
  end;

  function TGPGraphics.DrawDriverString(text: PUINT16; length: Integer; font: TGPFont
       ; brush: TGPBrush; positions: PGPPointF; flags: Integer
       ; matrix: TGPMatrix): TStatus;
  var
    nfont: Gpfont;
    nbrush: Gpbrush;
    nmatrix: Gpmatrix;
  begin
    if assigned(font) then nfont := font.nativeFont else nfont := nil;
    if assigned(brush) then nbrush := brush.nativeBrush else nbrush := nil;
    if assigned(matrix) then nmatrix := matrix.nativeMatrix else nmatrix := nil;

    result := SetStatus(GdipDrawDriverString(
        nativeGraphics,
        text,
        length,
        nfont,
        nbrush,
        positions,
        flags,
        nmatrix));
  end;

  function TGPGraphics.MeasureDriverString(text: PUINT16; length: Integer; font: TGPFont;
       positions: PGPPointF; flags: Integer; matrix: TGPMatrix;
       out boundingBox: TGPRectF): TStatus;
  var
    nfont: Gpfont;
    nmatrix: Gpmatrix;
  begin
    if assigned(font) then nfont := font.nativeFont else nfont := nil;
    if assigned(matrix) then nmatrix := matrix.nativeMatrix else nmatrix := nil;

    result := SetStatus(GdipMeasureDriverString(
        nativeGraphics,
        text,
        length,
        nfont,
        positions,
        flags,
        nmatrix,
        @boundingBox
    ));
  end;

    // Draw a cached bitmap on this graphics destination offset by
    // x, y. Note this will fail with WrongState if the CachedBitmap
    // native format differs from this Graphics.

  function TGPGraphics.DrawCachedBitmap(cb: TGPCachedBitmap;  x, y: Integer): TStatus;
  begin
    result := SetStatus(GdipDrawCachedBitmap(
        nativeGraphics,
        cb.nativeCachedBitmap,
        x, y
    ));
  end;

  function TGPGraphics.DrawImage(image: TGPImage; const point: TGPPointF): TStatus;
  begin
    result := DrawImage(image, point.X, point.Y);
  end;

  function TGPGraphics.DrawImage(image: TGPImage; x, y: Single): TStatus;
  var
   nImage: GpImage;
  begin
    if assigned(Image) then nImage := Image.nativeImage else nImage := nil;
    result := SetStatus(GdipDrawImage(nativeGraphics, nImage, x, y));
  end;

  function TGPGraphics.DrawImage(image: TGPImage; const rect: TGPRectF): TStatus;
  begin
    result := DrawImage(image, rect.X, rect.Y, rect.Width, rect.Height);
  end;

  function TGPGraphics.DrawImage(image: TGPImage; x, y, width, height: Single): TStatus;
  var
   nImage: GpImage;
  begin
    if assigned(Image) then nImage := Image.nativeImage else nImage := nil;
    result := SetStatus(GdipDrawImageRect(nativeGraphics,
                               nimage,
                               x,
                               y,
                               width,
                               height));
  end;

  function TGPGraphics.DrawImage(image: TGPImage; const point: TGPPoint): TStatus;
  begin
    result := DrawImage(image, point.X, point.Y);
  end;

  function TGPGraphics.DrawImage(image: TGPImage; x, y: Integer): TStatus;
  var
   nImage: GpImage;
  begin
    if assigned(Image) then nImage := Image.nativeImage else nImage := nil;
    result := SetStatus(GdipDrawImageI(nativeGraphics,
                            nimage,
                            x,
                            y));
  end;

  function TGPGraphics.DrawImage(image: TGPImage; const rect: TGPRect): TStatus;
  begin
    result := DrawImage(image,
             rect.X,
             rect.Y,
             rect.Width,
             rect.Height);
  end;

  function TGPGraphics.DrawImage(image: TGPImage; x, y, width, height: Integer): TStatus;
  var
   nImage: GpImage;
  begin
    if assigned(Image) then nImage := Image.nativeImage else nImage := nil;
    result := SetStatus(GdipDrawImageRectI(nativeGraphics,
                            nimage,
                            x,
                            y,
                            width,
                            height));
  end;


  function TGPGraphics.DrawImage(image: TGPImage; destPoints: PGPPointF; count: Integer): TStatus;
  var
   nImage: GpImage;
  begin
    if (((count <> 3) and (count <> 4)) or (destPoints = nil)) then
    begin
      result := SetStatus(InvalidParameter);
      exit;
    end;
    if assigned(Image) then nImage := Image.nativeImage else nImage := nil;
    result := SetStatus(GdipDrawImagePoints(nativeGraphics,
                             nimage,
                             destPoints, count));
  end;

  function TGPGraphics.DrawImage(image: TGPImage; destPoints: PGPPoint; count: Integer): TStatus;
  var
   nImage: GpImage;
  begin
    if (((count <> 3) and (count <> 4))or (destPoints = nil)) then
    begin
      result := SetStatus(InvalidParameter);
      exit;
    end;

    if assigned(Image) then nImage := Image.nativeImage else nImage := nil;
    result := SetStatus(GdipDrawImagePointsI(nativeGraphics,
                              nimage,
                              destPoints,
                              count));
  end;

  function TGPGraphics.DrawImage(image: TGPImage; x, y, srcx, srcy, srcwidth, srcheight: Single;
        srcUnit: TUnit): TStatus;
  var
    nImage: GpImage;
  begin
    if assigned(Image) then nImage := Image.nativeImage else nImage := nil;
    result := SetStatus(GdipDrawImagePointRect(nativeGraphics,
                                nimage,
                                x, y,
                                srcx, srcy,
                                srcwidth, srcheight, srcUnit));
  end;

  function TGPGraphics.DrawImage(image: TGPImage; const destRect: TGPRectF; srcx, srcy, srcwidth, srcheight: Single;
       srcUnit: TUnit; imageAttributes: TGPImageAttributes = nil; callback: DrawImageAbort = nil;
       callbackData: Pointer = nil): TStatus;
  var
    nImage: GpImage;
    nimageAttributes: GpimageAttributes;
  begin
    if assigned(Image) then nImage := Image.nativeImage else nImage := nil;
    if assigned(imageAttributes) then nimageAttributes := imageAttributes.nativeImageAttr else nimageAttributes := nil;
    result := SetStatus(GdipDrawImageRectRect(nativeGraphics,
                               nimage,
                               destRect.X,
                               destRect.Y,
                               destRect.Width,
                               destRect.Height,
                               srcx, srcy,
                               srcwidth, srcheight,
                               srcUnit,
                               nimageAttributes,
                               callback,
                               callbackData));
  end;

  function TGPGraphics.DrawImage(image: TGPImage; destPoints: PGPPointF; count: Integer;
       srcx, srcy, srcwidth, srcheight: Single; srcUnit: TUnit;
       imageAttributes: TGPImageAttributes = nil; callback: DrawImageAbort = nil;
       callbackData: Pointer = nil): TStatus;
  var
    nImage: GpImage;
    nimageAttributes: GpimageAttributes;
  begin
    if assigned(Image) then nImage := Image.nativeImage else nImage := nil;
    if assigned(imageAttributes) then nimageAttributes := imageAttributes.nativeImageAttr else nimageAttributes := nil;
    result := SetStatus(GdipDrawImagePointsRect(nativeGraphics,
                                 nimage,
                                 destPoints, count,
                                 srcx, srcy,
                                 srcwidth,
                                 srcheight,
                                 srcUnit,
                                 nimageAttributes,
                                 callback,
                                 callbackData));
  end;

  function TGPGraphics.DrawImage(image: TGPImage; x, y, srcx, srcy, srcwidth, srcheight: Integer;
       srcUnit: TUnit): TStatus;
  var
    nImage: GpImage;
  begin
    if assigned(Image) then nImage := Image.nativeImage else nImage := nil;
    result := SetStatus(GdipDrawImagePointRectI(nativeGraphics,
                                 nimage,
                                 x,
                                 y,
                                 srcx,
                                 srcy,
                                 srcwidth,
                                 srcheight,
                                 srcUnit));
  end;

  function TGPGraphics.DrawImage(image: TGPImage; const destRect: TGPRect; srcx, srcy, srcwidth,
       srcheight: Integer; srcUnit: TUnit; imageAttributes: TGPImageAttributes = nil;
       callback: DrawImageAbort = nil; callbackData: Pointer = nil): TStatus;
  var
    nImage: GpImage;
    nimageAttributes: GpimageAttributes;
  begin
    if assigned(Image) then nImage := Image.nativeImage else nImage := nil;
    if assigned(imageAttributes) then nimageAttributes := imageAttributes.nativeImageAttr else nimageAttributes := nil;
    result := SetStatus(GdipDrawImageRectRectI(nativeGraphics,
                                nimage,
                                destRect.X,
                                destRect.Y,
                                destRect.Width,
                                destRect.Height,
                                srcx,
                                srcy,
                                srcwidth,
                                srcheight,
                                srcUnit,
                                nimageAttributes,
                                callback,
                                callbackData));
  end;

  function TGPGraphics.DrawImage(image: TGPImage; destPoints: PGPPoint;
       count, srcx, srcy, srcwidth, srcheight: Integer; srcUnit: TUnit;
       imageAttributes: TGPImageAttributes = nil; callback: DrawImageAbort = nil;
       callbackData: Pointer = nil): TStatus;
  var
    nImage: GpImage;
    nimageAttributes: GpimageAttributes;
  begin
    if assigned(Image) then nImage := Image.nativeImage else nImage := nil;
    if assigned(imageAttributes) then nimageAttributes := imageAttributes.nativeImageAttr else nimageAttributes := nil;

    result := SetStatus(GdipDrawImagePointsRectI(nativeGraphics,
                                  nimage,
                                  destPoints,
                                  count,
                                  srcx,
                                  srcy,
                                  srcwidth,
                                  srcheight,
                                  srcUnit,
                                  nimageAttributes,
                                  callback,
                                  callbackData));
  end;


  function TGPGraphics.EnumerateMetafile(metafile: TGPMetafile; const destPoint: TGPPointF;
      callback: EnumerateMetafileProc; callbackData: Pointer = nil;
      imageAttributes: TGPImageAttributes = nil): TStatus;
  var
    nMetafile: GpMetafile;
    nimageAttributes: GpimageAttributes;
  begin
    if assigned(Metafile) then nMetafile := GpMetafile(Metafile.nativeImage) else nMetafile := nil;
    if assigned(imageAttributes) then nimageAttributes := imageAttributes.nativeImageAttr else nimageAttributes := nil;
    result := SetStatus(GdipEnumerateMetafileDestPoint(
            nativeGraphics,
            nmetafile,
            @destPoint,
            callback,
            callbackData,
            nimageAttributes));
  end;


  function TGPGraphics.EnumerateMetafile(metafile: TGPMetafile; const destPoint: TGPPoint;
       callback: EnumerateMetafileProc; callbackData: pointer = nil;
       imageAttributes: TGPImageAttributes = nil): TStatus;
  var
    nMetafile: GpMetafile;
    nimageAttributes: GpimageAttributes;
  begin
    if assigned(Metafile) then nMetafile := GpMetafile(Metafile.nativeImage) else nMetafile := nil;
    if assigned(imageAttributes) then nimageAttributes := imageAttributes.nativeImageAttr else nimageAttributes := nil;
    result := SetStatus(GdipEnumerateMetafileDestPointI(
            nativeGraphics,
            nmetafile,
            @destPoint,
            callback,
            callbackData,
            nimageAttributes));
  end;


  function TGPGraphics.EnumerateMetafile(metafile: TGPMetafile; const destRect: TGPRectF;
       callback: EnumerateMetafileProc; callbackData: Pointer = nil;
       imageAttributes: TGPImageAttributes = nil): TStatus;
  var
    nMetafile: GpMetafile;
    nimageAttributes: GpimageAttributes;
  begin
    if assigned(Metafile) then nMetafile := GpMetafile(Metafile.nativeImage) else nMetafile := nil;
    if assigned(imageAttributes) then nimageAttributes := imageAttributes.nativeImageAttr else nimageAttributes := nil;
    result := SetStatus(GdipEnumerateMetafileDestRect(
            nativeGraphics,
            nmetafile,
            @destRect,
            callback,
            callbackData,
            nimageAttributes));
  end;


  function TGPGraphics.EnumerateMetafile(metafile: TGPMetafile; const destRect: TGPRect;
       callback: EnumerateMetafileProc; callbackData: Pointer = nil;
       imageAttributes: TGPImageAttributes = nil): TStatus;
  var
    nMetafile: GpMetafile;
    nimageAttributes: GpimageAttributes;
  begin
    if assigned(Metafile) then nMetafile := GpMetafile(Metafile.nativeImage) else nMetafile := nil;
    if assigned(imageAttributes) then nimageAttributes := imageAttributes.nativeImageAttr else nimageAttributes := nil;
    result := SetStatus(GdipEnumerateMetafileDestRectI(
            nativeGraphics,
            nmetafile,
            @destRect,
            callback,
            callbackData,
            nimageAttributes));
  end;


  function TGPGraphics.EnumerateMetafile(metafile: TGPMetafile; destPoints: PGPPointF;
       count: Integer; callback: EnumerateMetafileProc; callbackData: Pointer = nil;
       imageAttributes: TGPImageAttributes = nil): TStatus;
  var
    nMetafile: GpMetafile;
    nimageAttributes: GpimageAttributes;
  begin
    if assigned(Metafile) then nMetafile := GpMetafile(Metafile.nativeImage) else nMetafile := nil;
    if assigned(imageAttributes) then nimageAttributes := imageAttributes.nativeImageAttr else nimageAttributes := nil;
    result := SetStatus(GdipEnumerateMetafileDestPoints(
            nativeGraphics,
            nmetafile,
            destPoints,
            count,
            callback,
            callbackData,
            nimageAttributes));
  end;


  function TGPGraphics.EnumerateMetafile(metafile: TGPMetafile; destPoints: PGPPoint;
       count: Integer; callback: EnumerateMetafileProc; callbackData: Pointer = nil;
       imageAttributes: TGPImageAttributes = nil): TStatus;
  var
    nMetafile: GpMetafile;
    nimageAttributes: GpimageAttributes;
  begin
    if assigned(Metafile) then nMetafile := GpMetafile(Metafile.nativeImage) else nMetafile := nil;
    if assigned(imageAttributes) then nimageAttributes := imageAttributes.nativeImageAttr else nimageAttributes := nil;
    result := SetStatus(GdipEnumerateMetafileDestPointsI(
            nativeGraphics,
            nmetafile,
            destPoints,
            count,
            callback,
            callbackData,
            nimageAttributes));
  end;


  function TGPGraphics.EnumerateMetafile(metafile: TGPMetafile; const destPoint: TGPPointF;
       const srcRect: TGPRectF; srcUnit: TUnit; callback: EnumerateMetafileProc;
       callbackData: pointer = nil; imageAttributes: TGPImageAttributes = nil): TStatus;
  var
    nMetafile: GpMetafile;
    nimageAttributes: GpimageAttributes;
  begin
    if assigned(Metafile) then nMetafile := GpMetafile(Metafile.nativeImage) else nMetafile := nil;
    if assigned(imageAttributes) then nimageAttributes := imageAttributes.nativeImageAttr else nimageAttributes := nil;
    result := SetStatus(GdipEnumerateMetafileSrcRectDestPoint(
            nativeGraphics,
            nmetafile,
            @destPoint,
            @srcRect,
            srcUnit,
            callback,
            callbackData,
            nimageAttributes));
  end;


  function TGPGraphics.EnumerateMetafile(metafile : TGPMetafile; const destPoint : TGPPoint;
       const srcRect : TGPRect; srcUnit : TUnit; callback : EnumerateMetafileProc;
       callbackData : Pointer = nil; imageAttributes : TGPImageAttributes = nil): TStatus;
  var
    nMetafile: GpMetafile;
    nimageAttributes: GpimageAttributes;
  begin
    if assigned(Metafile) then nMetafile := GpMetafile(Metafile.nativeImage) else nMetafile := nil;
    if assigned(imageAttributes) then nimageAttributes := imageAttributes.nativeImageAttr else nimageAttributes := nil;
    result := SetStatus(GdipEnumerateMetafileSrcRectDestPointI(
            nativeGraphics,
            nmetafile,
            @destPoint,
            @srcRect,
            srcUnit,
            callback,
            callbackData,
            nimageAttributes));
  end;


  function TGPGraphics.EnumerateMetafile(metafile: TGPMetafile; const destRect: TGPRectF;
       const srcRect: TGPRectF; srcUnit: TUnit; callback: EnumerateMetafileProc;
       callbackData: Pointer = nil; imageAttributes: TGPImageAttributes = nil): TStatus;
  var
    nMetafile: GpMetafile;
    nimageAttributes: GpimageAttributes;
  begin
    if assigned(Metafile) then nMetafile := GpMetafile(Metafile.nativeImage) else nMetafile := nil;
    if assigned(imageAttributes) then nimageAttributes := imageAttributes.nativeImageAttr else nimageAttributes := nil;
    result := SetStatus(GdipEnumerateMetafileSrcRectDestRect(
            nativeGraphics,
            nmetafile,
            @destRect,
            @srcRect,
            srcUnit,
            callback,
            callbackData,
            nimageAttributes));
  end;


  function TGPGraphics.EnumerateMetafile(metafile : TGPMetafile; const destRect, srcRect: TGPRect;
       srcUnit : TUnit; callback : EnumerateMetafileProc; callbackData : Pointer = nil;
       imageAttributes : TGPImageAttributes = nil): TStatus;
  var
    nMetafile: GpMetafile;
    nimageAttributes: GpimageAttributes;
  begin
    if assigned(Metafile) then nMetafile := GpMetafile(Metafile.nativeImage) else nMetafile := nil;
    if assigned(imageAttributes) then nimageAttributes := imageAttributes.nativeImageAttr else nimageAttributes := nil;
    result := SetStatus(GdipEnumerateMetafileSrcRectDestRectI(
            nativeGraphics,
            nmetafile,
            @destRect,
            @srcRect,
            srcUnit,
            callback,
            callbackData,
            nimageAttributes));
  end;


  function TGPGraphics.EnumerateMetafile( metafile: TGPMetafile; destPoints: PGPPointF;
    count: Integer; const srcRect: TGPRectF; srcUnit: TUnit; callback: EnumerateMetafileProc;
    callbackData: Pointer = nil; imageAttributes: TGPImageAttributes = nil): TStatus;
  var
    nMetafile: GpMetafile;
    nimageAttributes: GpimageAttributes;
  begin
    if assigned(Metafile) then nMetafile := GpMetafile(Metafile.nativeImage) else nMetafile := nil;
    if assigned(imageAttributes) then nimageAttributes := imageAttributes.nativeImageAttr else nimageAttributes := nil;
    result := SetStatus(GdipEnumerateMetafileSrcRectDestPoints(
            nativeGraphics,
            nmetafile,
            destPoints,
            count,
            @srcRect,
            srcUnit,
            callback,
            callbackData,
            nimageAttributes));
  end;


  function TGPGraphics.EnumerateMetafile(metafile: TGPMetafile; destPoints: PGPPoint;
    count: Integer; const srcRect: TGPRect; srcUnit: TUnit; callback: EnumerateMetafileProc;
    callbackData: Pointer = nil; imageAttributes: TGPImageAttributes = nil): TStatus;
  var
    nMetafile: GpMetafile;
    nimageAttributes: GpimageAttributes;
  begin
    if assigned(Metafile) then nMetafile := GpMetafile(Metafile.nativeImage) else nMetafile := nil;
    if assigned(imageAttributes) then nimageAttributes := imageAttributes.nativeImageAttr else nimageAttributes := nil;
    result := SetStatus(GdipEnumerateMetafileSrcRectDestPointsI(
            nativeGraphics,
            nmetafile,
            destPoints,
            count,
            @srcRect,
            srcUnit,
            callback,
            callbackData,
            nimageAttributes));
  end;

  function TGPGraphics.SetClip(g: TGPGraphics; combineMode: TCombineMode = CombineModeReplace): TStatus;
  begin
    result := SetStatus(GdipSetClipGraphics(nativeGraphics,
                             g.nativeGraphics,
                             combineMode));
  end;

  function TGPGraphics.SetClip(rect: TGPRectF; combineMode: TCombineMode = CombineModeReplace): TStatus;
  begin
    result := SetStatus(GdipSetClipRect(nativeGraphics,
                             rect.X, rect.Y,
                             rect.Width, rect.Height,
                             combineMode));
  end;

  function TGPGraphics.SetClip(rect: TGPRect; combineMode: TCombineMode = CombineModeReplace): TStatus;
  begin
    result := SetStatus(GdipSetClipRectI(nativeGraphics,
                              rect.X, rect.Y,
                              rect.Width, rect.Height,
                              combineMode));
  end;

  function TGPGraphics.SetClip(path: TGPGraphicsPath; combineMode: TCombineMode = CombineModeReplace): TStatus;
  begin
    result := SetStatus(GdipSetClipPath(nativeGraphics,
                             path.nativePath,
                             combineMode));
  end;

  function TGPGraphics.SetClip(region: TGPRegion; combineMode: TCombineMode = CombineModeReplace): TStatus;
  begin
    result := SetStatus(GdipSetClipRegion(nativeGraphics,
                               region.nativeRegion,
                               combineMode));
  end;

  function TGPGraphics.SetClip(hRgn: HRGN; combineMode: TCombineMode = CombineModeReplace): TStatus;
  begin
    result := SetStatus(GdipSetClipHrgn(nativeGraphics, hRgn,
                             combineMode));
  end;

  function TGPGraphics.IntersectClip(const rect: TGPRectF): TStatus;
  begin
    result := SetStatus(GdipSetClipRect(nativeGraphics,
                             rect.X, rect.Y,
                             rect.Width, rect.Height,
                             CombineModeIntersect));
  end;

  function TGPGraphics.IntersectClip(const rect: TGPRect): TStatus;
  begin
    result := SetStatus(GdipSetClipRectI(nativeGraphics,
                              rect.X, rect.Y,
                              rect.Width, rect.Height,
                              CombineModeIntersect));
  end;

  function TGPGraphics.IntersectClip(region: TGPRegion): TStatus;
  begin
    result := SetStatus(GdipSetClipRegion(nativeGraphics,
                               region.nativeRegion,
                               CombineModeIntersect));
  end;

  function TGPGraphics.ExcludeClip(const rect: TGPRectF): TStatus;
  begin
    result := SetStatus(GdipSetClipRect(nativeGraphics,
                             rect.X, rect.Y,
                             rect.Width, rect.Height,
                             CombineModeExclude));
  end;

  function TGPGraphics.ExcludeClip(const rect: TGPRect): TStatus;
  begin
    result := SetStatus(GdipSetClipRectI(nativeGraphics,
                              rect.X, rect.Y,
                              rect.Width, rect.Height,
                              CombineModeExclude));
  end;

  function TGPGraphics.ExcludeClip(region: TGPRegion): TStatus;
  begin
    result := SetStatus(GdipSetClipRegion(nativeGraphics,
                               region.nativeRegion,
                               CombineModeExclude));
  end;

  function TGPGraphics.ResetClip: TStatus;
  begin
    result := SetStatus(GdipResetClip(nativeGraphics));
  end;

  function TGPGraphics.TranslateClip(dx, dy: Single): TStatus;
  begin
    result := SetStatus(GdipTranslateClip(nativeGraphics, dx, dy));
  end;

  function TGPGraphics.TranslateClip(dx, dy: Integer): TStatus;
  begin
    result := SetStatus(GdipTranslateClipI(nativeGraphics,
                            dx, dy));
  end;

  function TGPGraphics.GetClip(region: TGPRegion): TStatus;
  begin
    result := SetStatus(GdipGetClip(nativeGraphics,
                         region.nativeRegion));
  end;

  function TGPGraphics.GetClipBounds(out rect: TGPRectF): TStatus;
  begin
    result := SetStatus(GdipGetClipBounds(nativeGraphics, @rect));
  end;

  function TGPGraphics.GetClipBounds(out rect: TGPRect): TStatus;
  begin
    result := SetStatus(GdipGetClipBoundsI(nativeGraphics, @rect));
  end;

  function TGPGraphics.IsClipEmpty: Bool;
  var booln: BOOL;
  begin
    booln := FALSE;
    SetStatus(GdipIsClipEmpty(nativeGraphics, @booln));
    result := booln;
  end;

  function TGPGraphics.GetVisibleClipBounds(out rect: TGPRectF): TStatus;
  begin
    result := SetStatus(GdipGetVisibleClipBounds(nativeGraphics, @rect));
  end;

  function TGPGraphics.GetVisibleClipBounds(out rect: TGPRect): TStatus;
  begin
    result := SetStatus(GdipGetVisibleClipBoundsI(nativeGraphics, @rect));
  end;

  function TGPGraphics.IsVisibleClipEmpty: BOOL;
  var booln: BOOL;
  begin
    booln := FALSE;
    SetStatus(GdipIsVisibleClipEmpty(nativeGraphics, booln));
    result := booln;
  end;

  function TGPGraphics.IsVisible(x, y: Integer): BOOL;
  var pt: TGPPoint;
  begin
    pt.X := x; pt.Y := y;
    result := IsVisible(pt);
  end;

  function TGPGraphics.IsVisible(const point: TGPPoint): BOOL;
  var booln: BOOL;
  begin
    booln := FALSE;
    SetStatus(GdipIsVisiblePointI(nativeGraphics,
                          point.X,
                          point.Y,
                          booln));
    result := booln;
  end;

  function TGPGraphics.IsVisible(x, y, width, height: Integer): BOOL;
  var booln: BOOL;
  begin
    booln := TRUE;
    SetStatus(GdipIsVisibleRectI(nativeGraphics,
                         X,
                         Y,
                         Width,
                         Height,
                         booln));
    result := booln;
  end;

  function TGPGraphics.IsVisible(const rect: TGPRect): BOOL;
  var booln: BOOL;
  begin
    booln := TRUE;
    SetStatus(GdipIsVisibleRectI(nativeGraphics,
                         rect.X,
                         rect.Y,
                         rect.Width,
                         rect.Height,
                         booln));
    result := booln;
  end;

  function TGPGraphics.IsVisible(x, y: Single): BOOL;
  var booln: BOOL;
  begin
    booln := FALSE;
    SetStatus(GdipIsVisiblePoint(nativeGraphics,
                         X,
                         Y,
                         booln));

    result := booln;
  end;

  function TGPGraphics.IsVisible(const point: TGPPointF): BOOL;
  var booln: BOOL;
  begin
    booln := FALSE;
    SetStatus(GdipIsVisiblePoint(nativeGraphics,
                         point.X,
                         point.Y,
                         booln));

    result := booln;
  end;

  function TGPGraphics.IsVisible(x, y, width, height: Single): BOOL;
  var booln: BOOL;
  begin
    booln := TRUE;
    SetStatus(GdipIsVisibleRect(nativeGraphics,
                        X,
                        Y,
                        Width,
                        Height,
                        booln));
    result := booln;
  end;

  function TGPGraphics.IsVisible(const rect: TGPRectF): BOOL;
  var booln: BOOL;
  begin
    booln := TRUE;
    SetStatus(GdipIsVisibleRect(nativeGraphics,
                        rect.X,
                        rect.Y,
                        rect.Width,
                        rect.Height,
                        booln));
    result := booln;
  end;

  function TGPGraphics.Save: GraphicsState;
  begin
    SetStatus(GdipSaveGraphics(nativeGraphics, result));
  end;

  function TGPGraphics.Restore(gstate: GraphicsState): TStatus;
  begin
    result := SetStatus(GdipRestoreGraphics(nativeGraphics,
                             gstate));
  end;

  function TGPGraphics.BeginContainer(const dstrect,srcrect: TGPRectF; unit_: TUnit): GraphicsContainer;
  begin
    SetStatus(GdipBeginContainer(nativeGraphics, @dstrect,
                         @srcrect, unit_, result));
  end;

  function TGPGraphics.BeginContainer(const dstrect, srcrect: TGPRect; unit_: TUnit): GraphicsContainer;
  begin
    SetStatus(GdipBeginContainerI(nativeGraphics, @dstrect,
                          @srcrect, unit_, result));
  end;

  function TGPGraphics.BeginContainer: GraphicsContainer;
  begin
    SetStatus(GdipBeginContainer2(nativeGraphics, result));
  end;

  function TGPGraphics.EndContainer(state: GraphicsContainer): TStatus;
  begin
    result := SetStatus(GdipEndContainer(nativeGraphics, state));
  end;

  function TGPGraphics.AddMetafileComment(data: PBYTE; sizeData: UINT): TStatus;
  begin
    result := SetStatus(GdipComment(nativeGraphics, sizeData, data));
  end;

  function TGPGraphics.GetHalftonePalette: HPALETTE;
  begin
    result := GdipCreateHalftonePalette;
  end;

  function TGPGraphics.GetLastStatus: TStatus;
  begin
    result := lastResult;
    lastResult := Ok;
  end;

  constructor TGPGraphics.Create(graphics: GpGraphics);
  begin
    lastResult := Ok;
    SetNativeGraphics(graphics);
  end;

  procedure TGPGraphics.SetNativeGraphics(graphics: GpGraphics);
  begin
    self.nativeGraphics := graphics;
  end;

  function TGPGraphics.SetStatus(status: TStatus): TStatus;
  begin
    if (status <> Ok) then lastResult := status;
    result := status;
  end;

  function TGPGraphics.GetNativeGraphics: GpGraphics;
  begin
    result := self.nativeGraphics;
  end;

  function TGPGraphics.GetNativePen(pen: TGPPen): GpPen;
  begin
    result := pen.nativePen;
  end;

  constructor TGPFontFamily.Create;
  begin
    nativeFamily := nil;
    lastResult   := Ok;
  end;

  constructor TGPFontFamily.Create(name: WideString; fontCollection: TGPFontCollection = nil);
  var nfontCollection: GpfontCollection;
  begin
    nativeFamily := nil;
    if assigned(fontCollection) then nfontCollection := fontCollection.nativeFontCollection else nfontCollection := nil;
    lastResult := GdipCreateFontFamilyFromName(PWideChar(name), nfontCollection, nativeFamily);
  end;

  destructor TGPFontFamily.Destroy;
  begin
    GdipDeleteFontFamily (nativeFamily);
  end;

  class function TGPFontFamily.GenericSansSerif: TGPFontFamily;
  var
    nFontFamily: GpFontFamily;
  begin
    if (GenericSansSerifFontFamily <> nil) then
    begin
      result := GenericSansSerifFontFamily;
      exit;
    end;
    GenericSansSerifFontFamily := TGPFontFamily.Create;
    GenericSansSerifFontFamily.lastResult := GdipGetGenericFontFamilySansSerif(nFontFamily);
    GenericSansSerifFontFamily.nativeFamily := nFontFamily;
    result := GenericSansSerifFontFamily;
  end;

  class function TGPFontFamily.GenericSerif: TGPFontFamily;
  var nFontFamily: GpFontFamily;
  begin
    if (GenericSerifFontFamily <> nil) then
    begin
      result := GenericSerifFontFamily;
      exit;
    end;

    GenericSerifFontFamily := TGPFontFamily.Create;// (GenericSerifFontFamilyBuffer);
    GenericSerifFontFamily.lastResult := GdipGetGenericFontFamilySerif(nFontFamily);
    GenericSerifFontFamily.nativeFamily := nFontFamily;
    result := GenericSerifFontFamily;
  end;

  class function TGPFontFamily.GenericMonospace: TGPFontFamily;
  var nFontFamily: GpFontFamily;
  begin
    if (GenericMonospaceFontFamily <> nil) then
    begin
      result := GenericMonospaceFontFamily;
      exit;
    end;
    GenericMonospaceFontFamily := TGPFontFamily.Create;// (GenericMonospaceFontFamilyBuffer);
    GenericMonospaceFontFamily.lastResult := GdipGetGenericFontFamilyMonospace(nFontFamily);
    GenericMonospaceFontFamily.nativeFamily := nFontFamily;
    result := GenericMonospaceFontFamily;
  end;

  function TGPFontFamily.GetFamilyName(out name: string; language: LANGID = 0): TStatus;
  var str: array[0..LF_FACESIZE - 1] of WideChar;
  begin
    result := SetStatus(GdipGetFamilyName(nativeFamily, @str, language));
    name := str;
  end;

  function TGPFontFamily.Clone: TGPFontFamily;
  var
    clonedFamily: GpFontFamily;
  begin
    clonedFamily := nil;
    SetStatus(GdipCloneFontFamily (nativeFamily, clonedFamily));
    result := TGPFontFamily.Create(clonedFamily, lastResult);
  end;

  function TGPFontFamily.IsAvailable: BOOL;
  begin
    result := (nativeFamily <> nil);
  end;

  function TGPFontFamily.IsStyleAvailable(style: Integer): BOOL;
  var
    StyleAvailable: BOOL;
    status: TStatus;
  begin
    status := SetStatus(GdipIsStyleAvailable(nativeFamily, style, StyleAvailable));
    if (status <> Ok) then StyleAvailable := FALSE;
    result := StyleAvailable;
  end;

  function TGPFontFamily.GetEmHeight(style: Integer): UINT16;
  begin
    SetStatus(GdipGetEmHeight(nativeFamily, style, result));
  end;

  function TGPFontFamily.GetCellAscent(style: Integer): UINT16;
  begin
    SetStatus(GdipGetCellAscent(nativeFamily, style, result));
  end;

  function TGPFontFamily.GetCellDescent(style: Integer): UINT16;
  begin
    SetStatus(GdipGetCellDescent(nativeFamily, style, result));
  end;

  function TGPFontFamily.GetLineSpacing(style: Integer): UINT16;
  begin
    SetStatus(GdipGetLineSpacing(nativeFamily, style, result));
  end;

  function TGPFontFamily.GetLastStatus: TStatus;
  begin
    result := lastResult;
    lastResult := Ok;
  end;

  function TGPFontFamily.SetStatus(status: TStatus): TStatus;
  begin
    if (status <> Ok) then lastResult := status;
    result := status;
  end;

  constructor TGPFontFamily.Create(nativeOrig: GpFontFamily; status: TStatus);
  begin
    lastResult  := status;
    nativeFamily := nativeOrig;
  end;

(**************************************************************************\
*
*   GDI+ Font class
*
\**************************************************************************)

  constructor TGPFont.Create(hdc: HDC);
  var font: GpFont;
  begin
    font := nil;
    lastResult := GdipCreateFontFromDC(hdc, font);
    SetNativeFont(font);
  end;

  constructor TGPFont.Create(hdc: HDC; logfont: PLogFontA);
  var font: GpFont;
  begin
    font := nil;
    if assigned(logfont) then
      lastResult := GdipCreateFontFromLogfontA(hdc, logfont, font)
    else
      lastResult := GdipCreateFontFromDC(hdc, font);
    SetNativeFont(font);
  end;

  constructor TGPFont.Create(hdc: HDC; logfont: PLogFontW);
  var font: GpFont;
  begin
    font := nil;
    if assigned(logfont) then
      lastResult := GdipCreateFontFromLogfontW(hdc, logfont, font)
    else
      lastResult := GdipCreateFontFromDC(hdc, font);
    SetNativeFont(font);
  end;

  constructor TGPFont.Create(hdc: HDC; hfont: HFONT);
  var
    font: GpFont;
    {$IFNDEF FPC}
    lf: LOGFONTA;
    {$ENDIF}
  begin
    font := nil;
    {$IFNDEF FPC}
    if BOOL(hfont) then
    begin
      if( BOOL(GetObjectA(hfont, sizeof(LOGFONTA), @lf))) then
            lastResult := GdipCreateFontFromLogfontA(hdc, @lf, font)
        else
            lastResult := GdipCreateFontFromDC(hdc, font);
    end
    else
      lastResult := GdipCreateFontFromDC(hdc, font);
    SetNativeFont(font);
    {$ENDIF}
  end;

  constructor TGPFont.Create(family: TGPFontFamily; emSize: Single;
      style: TFontStyle = FontStyleRegular; unit_: TUnit = UnitPoint);
  var
    font: GpFont;
    nFontFamily: GpFontFamily;
  begin
    font := nil;
    if assigned(Family) then nFontFamily := Family.nativeFamily else nFontFamily := nil;
    lastResult := GdipCreateFont(nFontFamily, emSize, Integer(style), Integer(unit_), font);
    SetNativeFont(font);
  end;

  constructor TGPFont.Create(familyName: WideString; emSize: Single;
      style: TFontStyle = FontStyleRegular; unit_: TUnit = UnitPoint;
      fontCollection: TGPFontCollection = nil);
  var
    family: TGPFontFamily;
    nativeFamily: GpFontFamily;
  begin
    nativeFont := nil;
    family := TGPFontFamily.Create(familyName, fontCollection);
    nativeFamily := family.nativeFamily;
    lastResult := family.GetLastStatus;
    if (lastResult <> Ok) then
    begin
      nativeFamily := TGPFontFamily.GenericSansSerif.nativeFamily;
      lastResult := TGPFontFamily.GenericSansSerif.lastResult;
      if (lastResult <> Ok) then
      begin
        family.Free;
        exit;
      end;
    end;

    lastResult := GdipCreateFont(nativeFamily,
                            emSize,
                            integer(style),
                            integer(unit_),
                            nativeFont);

    if (lastResult <> Ok) then
      begin
        nativeFamily := TGPFontFamily.GenericSansSerif.nativeFamily;
        lastResult := TGPFontFamily.GenericSansSerif.lastResult;
        if (lastResult <> Ok) then
        begin
          family.Free;
          exit;
        end;

        lastResult := GdipCreateFont(
            nativeFamily,
            emSize,
            Integer(style),
            Integer(unit_),
            nativeFont);
      end;
      family.Free;
  end;

  function TGPFont.GetLogFontA(g: TGPGraphics; out logfontA: TLogFontA): TStatus;
  var nGraphics: GpGraphics;
  begin
    if assigned(g) then nGraphics := g.nativeGraphics else nGraphics := nil;
    {$IFNDEF FPC}
    result := SetStatus(GdipGetLogFontA(nativeFont, nGraphics, logfontA));
    {$ENDIF}
  end;

  function TGPFont.GetLogFontW(g: TGPGraphics; out logfontW: TLogFontW): TStatus;
  var nGraphics: GpGraphics;
  begin
    if assigned(g) then nGraphics := g.nativeGraphics else nGraphics := nil;
    result := SetStatus(GdipGetLogFontW(nativeFont, nGraphics, logfontW));
  end;

  function TGPFont.Clone: TGPFont;
  var cloneFont: GpFont;
  begin
    cloneFont := nil;
    SetStatus(GdipCloneFont(nativeFont, cloneFont));
    result := TGPFont.Create(cloneFont, lastResult);
  end;

  destructor TGPFont.Destroy;
  begin
    GdipDeleteFont(nativeFont);
  end;

  function TGPFont.IsAvailable: BOOL;
  begin
    result := (nativeFont <> nil);
  end;

  function TGPFont.GetStyle: Integer;
  begin
    SetStatus(GdipGetFontStyle(nativeFont, result));
  end;

  function TGPFont.GetSize: Single;
  begin
    SetStatus(GdipGetFontSize(nativeFont, result));
  end;

  function TGPFont.GetUnit: TUnit;
  begin
    SetStatus(GdipGetFontUnit(nativeFont, result));
  end;

  function TGPFont.GetLastStatus: TStatus;
  begin
    result := lastResult;
  end;

  function TGPFont.GetHeight(graphics: TGPGraphics): Single;
  var ngraphics: Gpgraphics;
  begin
    if assigned(graphics) then ngraphics := graphics.nativeGraphics else ngraphics := nil;
    SetStatus(GdipGetFontHeight(nativeFont, ngraphics, result));
  end;

  function TGPFont.GetHeight(dpi: Single): Single;
  begin
    SetStatus(GdipGetFontHeightGivenDPI(nativeFont, dpi, result));
  end;

  function TGPFont.GetFamily(family: TGPFontFamily): TStatus;
  var
    status: TStatus;
    nFamily: GpFontFamily;
  begin
    if (family = nil) then
    begin
      result := SetStatus(InvalidParameter);
      exit;
    end;

    status := GdipGetFamily(nativeFont, nFamily);
    family.nativeFamily := nFamily;
    family.SetStatus(status);
    result := SetStatus(status);
  end;

  constructor TGPFont.Create(font: GpFont; status: TStatus);
  begin
    lastResult := status;
    SetNativeFont(font);
  end;

  procedure TGPFont.SetNativeFont(Font: GpFont);
  begin
    nativeFont := Font;
  end;

  function TGPFont.SetStatus(status: TStatus): TStatus;
  begin
    if (status <> Ok) then lastResult := status;
    result := status;
  end;

(**************************************************************************\
*
*   Font collections (Installed and Private)
*
\**************************************************************************)

  constructor TGPFontCollection.Create;
  begin
    nativeFontCollection := nil;
  end;

  destructor TGPFontCollection.Destroy;
  begin
    inherited Destroy;
  end;

  function TGPFontCollection.GetFamilyCount: Integer;
  var
    numFound: Integer;
  begin
    numFound := 0;
    lastResult := GdipGetFontCollectionFamilyCount(nativeFontCollection, numFound);
    result := numFound;
  end;

  function TGPFontCollection.GetFamilies(numSought: Integer; out gpfamilies: array of TGPFontFamily;
      out numFound: Integer): TStatus;
  var
    nativeFamilyList: Pointer;
    Status: TStatus;
    i: Integer;
  type
    ArrGpFontFamily = array of GpFontFamily;
  begin
    if ((numSought <= 0) or (length(gpfamilies) = 0)) then
    begin
      result := SetStatus(InvalidParameter);
      exit;
    end;
    numFound := 0;

    getMem(nativeFamilyList, numSought * SizeOf(GpFontFamily));
    if nativeFamilyList = nil then
    begin
      result := SetStatus(OutOfMemory);
      exit;
    end;

    status := SetStatus(GdipGetFontCollectionFamilyList(
        nativeFontCollection,
        numSought,
        nativeFamilyList,
        numFound
    ));

    if (status = Ok) then
      for i := 0 to numFound - 1 do
         GdipCloneFontFamily(ArrGpFontFamily(nativeFamilyList)[i], gpfamilies[i].nativeFamily);
    Freemem(nativeFamilyList, numSought * SizeOf(GpFontFamily));
    result := status;
  end;

  function TGPFontCollection.GetLastStatus: TStatus;
  begin
    result := lastResult;
  end;

  function TGPFontCollection.SetStatus(status: TStatus): TStatus;
  begin
    lastResult := status;
    result := lastResult;
  end;


  constructor TGPInstalledFontCollection.Create;
  begin
    nativeFontCollection := nil;
    lastResult := GdipNewInstalledFontCollection(nativeFontCollection);
  end;

  destructor TGPInstalledFontCollection.Destroy;
  begin
    inherited Destroy;
  end;

  constructor TGPPrivateFontCollection.Create;
  begin
    nativeFontCollection := nil;
    lastResult := GdipNewPrivateFontCollection(nativeFontCollection);
  end;

  destructor TGPPrivateFontCollection.destroy;
  begin
    GdipDeletePrivateFontCollection(nativeFontCollection);
    inherited Destroy;
  end;

  function TGPPrivateFontCollection.AddFontFile(filename: WideString): TStatus;
  begin
    result := SetStatus(GdipPrivateAddFontFile(nativeFontCollection, PWideChar(filename)));
  end;

  function TGPPrivateFontCollection.AddMemoryFont(memory: Pointer; length: Integer): TStatus;
  begin
    result := SetStatus(GdipPrivateAddMemoryFont(
        nativeFontCollection,
        memory,
        length));
  end;

  constructor TGPGraphicsPath.Create(fillMode: TFillMode = FillModeAlternate);
  begin
    nativePath := nil;
    lastResult := GdipCreatePath(fillMode, nativePath);
  end;

  constructor TGPGraphicsPath.Create(points: PGPPointF; types: PBYTE; count: Integer;
              fillMode: TFillMode = FillModeAlternate);
  begin
    nativePath := nil;
    lastResult := GdipCreatePath2(points, types, count, fillMode, nativePath);
  end;

  constructor TGPGraphicsPath.Create(points: PGPPoint; types: PBYTE; count: Integer;
              fillMode: TFillMode = FillModeAlternate);
  begin
      nativePath := nil;
      lastResult := GdipCreatePath2I(points, types, count, fillMode, nativePath);
  end;

  destructor TGPGraphicsPath.destroy;
  begin
    GdipDeletePath(nativePath);
  end;

  function TGPGraphicsPath.Clone: TGPGraphicsPath;
  var
    clonepath: GpPath;
  begin
    clonepath := nil;
    SetStatus(GdipClonePath(nativePath, clonepath));
    result := TGPGraphicsPath.Create(clonepath);
  end;

  function TGPGraphicsPath.Reset: TStatus;
  begin
    result := SetStatus(GdipResetPath(nativePath));
  end;

  function TGPGraphicsPath.GetFillMode: TFillMode;
  var FMode: TFillMode;
  begin
    FMode := FillModeAlternate;
    SetStatus(GdipGetPathFillMode(nativePath, result));
    result := FMode;
  end;

  function TGPGraphicsPath.SetFillMode(fillmode: TFillMode): TStatus;
  begin
    result := SetStatus(GdipSetPathFillMode(nativePath, fillmode));
  end;

  function TGPGraphicsPath.GetPathData(pathData: TPathData): TStatus;
  var
    count: Int64;
  begin
    count := GetPointCount;
    if ((count <= 0) or ((pathData.Count > 0) and (pathData.Count < Count))) then
    begin
      pathData.Count := 0;
      if assigned(pathData.Points) then
      begin
        FreeMem(pathData.Points);
        pathData.Points := nil;
      end;
      if assigned(pathData.Types) then
      begin
        freemem(pathData.Types);
        pathData.Types := nil;
      end;
      if (count <= 0) then
      begin
        result := lastResult;
        exit;
      end;
    end;

    if (pathData.Count = 0) then
    begin
      getmem(pathData.Points, SizeOf(TGPPointF) * count);
      if (pathData.Points = nil) then
      begin
        result := SetStatus(OutOfMemory);
        exit;
      end;
      Getmem(pathData.Types, count);
      if (pathData.Types = nil) then
      begin
        freemem(pathData.Points);
        pathData.Points := nil;
        result := SetStatus(OutOfMemory);
        exit;
      end;
      pathData.Count := count;
    end;

    result := SetStatus(GdipGetPathData(nativePath, @pathData.Count));
  end;

  function TGPGraphicsPath.StartFigure: TStatus;
  begin
    result := SetStatus(GdipStartPathFigure(nativePath));
  end;

  function TGPGraphicsPath.CloseFigure: TStatus;
  begin
    result := SetStatus(GdipClosePathFigure(nativePath));
  end;

  function TGPGraphicsPath.CloseAllFigures: TStatus;
  begin
    result := SetStatus(GdipClosePathFigures(nativePath));
  end;

  function TGPGraphicsPath.SetMarker: TStatus;
  begin
    result := SetStatus(GdipSetPathMarker(nativePath));
  end;

  function TGPGraphicsPath.ClearMarkers: TStatus;
  begin
    result := SetStatus(GdipClearPathMarkers(nativePath));
  end;

  function TGPGraphicsPath.Reverse: TStatus;
  begin
    result := SetStatus(GdipReversePath(nativePath));
  end;

  function TGPGraphicsPath.GetLastPoint(out lastPoint: TGPPointF): TStatus;
  begin
    result := SetStatus(GdipGetPathLastPoint(nativePath,
                                            @lastPoint));
  end;

  function TGPGraphicsPath.AddLine(const pt1, pt2: TGPPointF): TStatus;
  begin
    result := AddLine(pt1.X, pt1.Y, pt2.X, pt2.Y);
  end;

  function TGPGraphicsPath.AddLine(x1, y1, x2, y2: Single): TStatus;
  begin
    result := SetStatus(GdipAddPathLine(nativePath, x1, y1,
                                         x2, y2));
  end;

  function TGPGraphicsPath.AddLines(points: PGPPointF; count: Integer): TStatus;
  begin
    result := SetStatus(GdipAddPathLine2(nativePath, points, count));
  end;

  function TGPGraphicsPath.AddLine(const pt1, pt2: TGPPoint): TStatus;
  begin
    result := AddLine(pt1.X, pt1.Y, pt2.X, pt2.Y);
  end;

  function TGPGraphicsPath.AddLine(x1, y1, x2, y2: Integer): TStatus;
  begin
    result := SetStatus(GdipAddPathLineI(nativePath, x1, y1, x2, y2));
  end;

  function TGPGraphicsPath.AddLines(points: PGPPoint; count: Integer): TStatus;
  begin
    result := SetStatus(GdipAddPathLine2I(nativePath, points, count));
  end;

  function TGPGraphicsPath.AddArc(rect: TGPRectF; startAngle, sweepAngle: Single): TStatus;
  begin
    result := AddArc(rect.X, rect.Y, rect.Width, rect.Height,
                  startAngle, sweepAngle);
  end;

  function TGPGraphicsPath.AddArc(x, y, width, height, startAngle, sweepAngle: Single): TStatus;
  begin
    result := SetStatus(GdipAddPathArc(nativePath, x, y, width, height, startAngle, sweepAngle));
  end;

  function TGPGraphicsPath.AddArc(rect: TGPRect; startAngle, sweepAngle: Single): TStatus;
  begin
    result := AddArc(rect.X, rect.Y, rect.Width, rect.Height, startAngle, sweepAngle);
  end;

  function TGPGraphicsPath.AddArc(x, y, width, height: Integer; startAngle, sweepAngle: Single): TStatus;
  begin
    result := SetStatus(GdipAddPathArcI(nativePath, x, y, width, height, startAngle, sweepAngle));
  end;

  function TGPGraphicsPath.AddBezier(pt1, pt2, pt3, pt4: TGPPointF): TStatus;
  begin
    result := AddBezier(pt1.X, pt1.Y, pt2.X, pt2.Y, pt3.X, pt3.Y, pt4.X, pt4.Y);
  end;

  function TGPGraphicsPath.AddBezier(x1, y1, x2, y2, x3, y3, x4, y4: Single): TStatus;
  begin
    result := SetStatus(GdipAddPathBezier(nativePath, x1, y1, x2, y2, x3, y3, x4, y4));
  end;

  function TGPGraphicsPath.AddBeziers(points: PGPPointF; count: Integer): TStatus;
  begin
    result := SetStatus(GdipAddPathBeziers(nativePath, points, count));
  end;

  function TGPGraphicsPath.AddBezier(pt1, pt2, pt3, pt4: TGPPoint): TStatus;
  begin
    result := AddBezier(pt1.X, pt1.Y, pt2.X, pt2.Y, pt3.X, pt3.Y, pt4.X, pt4.Y);
  end;

  function TGPGraphicsPath.AddBezier(x1, y1, x2, y2, x3, y3, x4, y4: Integer): TStatus;
  begin
       result := SetStatus(GdipAddPathBezierI(nativePath, x1, y1, x2, y2, x3, y3, x4, y4));
  end;

  function TGPGraphicsPath.AddBeziers(points: PGPPoint; count: Integer): TStatus;
  begin
       result := SetStatus(GdipAddPathBeziersI(nativePath, points, count));
  end;

  function TGPGraphicsPath.AddCurve(points: PGPPointF; count: Integer): TStatus;
  begin
    result := SetStatus(GdipAddPathCurve(nativePath, points, count));
  end;

  function TGPGraphicsPath.AddCurve(points: PGPPointF; count: Integer;
    tension: Single): TStatus;
  begin
    result := SetStatus(GdipAddPathCurve2(nativePath, points, count, tension));
  end;

  function TGPGraphicsPath.AddCurve(points: PGPPointF; count, offset,
    numberOfSegments: Integer; tension: Single): TStatus;
  begin
    result := SetStatus(GdipAddPathCurve3(nativePath, points, count, offset,
                          numberOfSegments, tension));
  end;

  function TGPGraphicsPath.AddCurve(points: PGPPoint; count: Integer): TStatus;
  begin
    result := SetStatus(GdipAddPathCurveI(nativePath, points, count));
  end;

  function TGPGraphicsPath.AddCurve(points: PGPPoint; count: Integer; tension: Single): TStatus;
  begin
    result := SetStatus(GdipAddPathCurve2I(nativePath, points, count, tension));
  end;

  function TGPGraphicsPath.AddCurve(points: PGPPoint; count, offset,
    numberOfSegments: Integer; tension: Single): TStatus;
  begin
    result := SetStatus(GdipAddPathCurve3I(nativePath, points, count, offset,
     numberOfSegments, tension));
  end;

  function TGPGraphicsPath.AddClosedCurve(points: PGPPointF; count: Integer): TStatus;
  begin
    result := SetStatus(GdipAddPathClosedCurve(nativePath, points, count));
  end;

  function TGPGraphicsPath.AddClosedCurve(points: PGPPointF; count: Integer; tension: Single): TStatus;
  begin
    result := SetStatus(GdipAddPathClosedCurve2(nativePath, points, count, tension));
  end;

  function TGPGraphicsPath.AddClosedCurve(points: PGPPoint; count: Integer): TStatus;
  begin
    result := SetStatus(GdipAddPathClosedCurveI(nativePath, points, count));
  end;


  function TGPGraphicsPath.AddClosedCurve(points: PGPPoint; count: Integer; tension: Single): TStatus;
  begin
       result := SetStatus(GdipAddPathClosedCurve2I(nativePath, points, count, tension));
  end;

  function TGPGraphicsPath.AddRectangle(rect: TGPRectF): TStatus;
  begin
    result := SetStatus(GdipAddPathRectangle(nativePath,
                                            rect.X,
                                            rect.Y,
                                            rect.Width,
                                            rect.Height));
  end;

  function TGPGraphicsPath.AddRectangles(rects: PGPRectF; count: Integer): TStatus;
  begin
    result := SetStatus(GdipAddPathRectangles(nativePath,
                                             rects,
                                             count));
  end;

  function TGPGraphicsPath.AddRectangle(rect: TGPRect): TStatus;
  begin
    result := SetStatus(GdipAddPathRectangleI(nativePath,
                                            rect.X,
                                            rect.Y,
                                            rect.Width,
                                            rect.Height));
  end;

  function TGPGraphicsPath.AddRectangles(rects: PGPRect; count: Integer): TStatus;
  begin
    result := SetStatus(GdipAddPathRectanglesI(nativePath,
                                             rects,
                                             count));
  end;

  function TGPGraphicsPath.AddEllipse(rect: TGPRectF): TStatus;
  begin
    result := AddEllipse(rect.X, rect.Y, rect.Width, rect.Height);
  end;

  function TGPGraphicsPath.AddEllipse(x, y, width, height: Single): TStatus;
  begin
    result := SetStatus(GdipAddPathEllipse(nativePath,
                                          x,
                                          y,
                                          width,
                                          height));
  end;

  function TGPGraphicsPath.AddEllipse(rect: TGPRect): TStatus;
  begin
    result := AddEllipse(rect.X, rect.Y, rect.Width, rect.Height);
  end;

  function TGPGraphicsPath.AddEllipse(x, y, width, height: Integer): TStatus;
  begin
    result := SetStatus(GdipAddPathEllipseI(nativePath,
                                          x,
                                          y,
                                          width,
                                          height));
  end;

  function TGPGraphicsPath.AddPie(rect: TGPRectF; startAngle, sweepAngle: Single): TStatus;
  begin
    result := AddPie(rect.X, rect.Y, rect.Width, rect.Height, startAngle,
                  sweepAngle);
  end;

  function TGPGraphicsPath.AddPie(x, y, width, height, startAngle, sweepAngle: Single): TStatus;
  begin
    result := SetStatus(GdipAddPathPie(nativePath, x, y, width,
                                        height, startAngle,
                                        sweepAngle));
  end;

  function TGPGraphicsPath.AddPie(rect: TGPRect; startAngle, sweepAngle: Single): TStatus;
  begin
    result := AddPie(rect.X,
                  rect.Y,
                  rect.Width,
                  rect.Height,
                  startAngle,
                  sweepAngle);
  end;

  function TGPGraphicsPath.AddPie(x, y, width, height: Integer; startAngle, sweepAngle: Single): TStatus;
  begin
    result := SetStatus(GdipAddPathPieI(nativePath,
                                        x,
                                        y,
                                        width,
                                        height,
                                        startAngle,
                                        sweepAngle));
  end;

  function TGPGraphicsPath.AddPolygon(points: PGPPointF; count: Integer): TStatus;
  begin
    result := SetStatus(GdipAddPathPolygon(nativePath, points, count));
  end;

  function TGPGraphicsPath.AddPolygon(points: PGPPoint; count: Integer): TStatus;
  begin
       result := SetStatus(GdipAddPathPolygonI(nativePath, points,
                                          count));
  end;

  function TGPGraphicsPath.AddPath(addingPath: TGPGraphicsPath; connect: Bool): TStatus;
  var
    nativePath2: GpPath;
  begin
    nativePath2 := nil;
    if assigned(addingPath) then nativePath2 := addingPath.nativePath;
    result := SetStatus(GdipAddPathPath(nativePath, nativePath2, connect));
  end;

  function TGPGraphicsPath.AddString(
      string_: WideString; length: Integer;
      family : TGPFontFamily;
      style  : Integer;
      emSize : Single;  // World units
      origin : TGPPointF;
      format : TGPStringFormat): TStatus;
  var
    rect : TGPRectF;
    gpff : GPFONTFAMILY;
    gpsf : GPSTRINGFORMAT;
  begin
    rect.X := origin.X;
    rect.Y := origin.Y;
    rect.Width := 0.0;
    rect.Height := 0.0;

    gpff := nil;
    gpsf := nil;
    if assigned(family) then gpff := family.nativeFamily;
    if assigned(format) then gpsf := format.nativeFormat;
    result := SetStatus(GdipAddPathString(nativePath, PWideChar(string_), length, gpff,
          style, emSize, @rect, gpsf));
  end;

  function TGPGraphicsPath.AddString(
      string_: WideString;
      length : Integer;
      family : TGPFontFamily;
      style  : Integer;
      emSize : Single;  // World units
      layoutRect: TGPRectF;
      format : TGPStringFormat): TStatus;
  var
    gpff : GPFONTFAMILY;
    gpsf : GPSTRINGFORMAT;
  begin
    gpff := nil;
    gpsf := nil;
    if assigned(family) then gpff := family.nativeFamily;
    if assigned(format) then gpsf := format.nativeFormat;
    result := SetStatus(GdipAddPathString( nativePath, PWideChar(string_), length, gpff,
          style, emSize, @layoutRect, gpsf));
  end;

  function TGPGraphicsPath.AddString(
      string_: WideString;
      length : Integer;
      family : TGPFontFamily;
      style  : Integer;
      emSize : Single;  // World units
      origin : TGPPoint;
      format : TGPStringFormat): TStatus;
  var
    rect : TGPRect;
    gpff : GPFONTFAMILY;
    gpsf : GPSTRINGFORMAT;
  begin
    rect.X := origin.X;
    rect.Y := origin.Y;
    rect.Width := 0;
    rect.Height := 0;
    gpff := nil;
    gpsf := nil;
    if assigned(family) then gpff := family.nativeFamily;
    if assigned(format) then gpsf := format.nativeFormat;
    result := SetStatus(GdipAddPathStringI(nativePath, PWideChar(string_), length, gpff,
          style, emSize, @rect, gpsf));
  end;

  function TGPGraphicsPath.AddString(
      string_: WideString;
      length : Integer;
      family : TGPFontFamily;
      style  : Integer;
      emSize : Single;  // World units
      layoutRect: TGPRect;
      format : TGPStringFormat): TStatus;
  var
    gpff : GPFONTFAMILY;
    gpsf : GPSTRINGFORMAT;
  begin
    gpff := nil;
    gpsf := nil;
    if assigned(family) then gpff := family.nativeFamily;
    if assigned(format) then gpsf := format.nativeFormat;
    result := SetStatus(GdipAddPathStringI( nativePath, PWideChar(string_), length, gpff,
          style, emSize, @layoutRect, gpsf));
  end;

  function TGPGraphicsPath.Transform(matrix: TGPMatrix): TStatus;
  begin
      if assigned(matrix) then
        result := SetStatus(GdipTransformPath(nativePath, matrix.nativeMatrix))
      else
        result := Ok;
  end;

  function TGPGraphicsPath.GetBounds(out bounds: TGPRectF; matrix: TGPMatrix = nil; pen: TGPPen = nil): TStatus;
  var
    nativeMatrix: GpMatrix;
    nativePen: GpPen;
  begin
    nativeMatrix := nil;
    nativePen    := nil;
    if assigned(matrix) then nativeMatrix := matrix.nativeMatrix;
    if assigned(pen) then nativePen := pen.nativePen;

    result := SetStatus(GdipGetPathWorldBounds(nativePath, @bounds, nativeMatrix, nativePen));
  end;

  function TGPGraphicsPath.GetBounds(out bounds: TGPRect; matrix: TGPMatrix = nil; pen: TGPPen = nil): TStatus;
  var
    nativeMatrix: GpMatrix;
    nativePen: GpPen;
  begin
    nativeMatrix := nil;
    nativePen    := nil;
    if assigned(matrix) then nativeMatrix := matrix.nativeMatrix;
    if assigned(pen) then nativePen := pen.nativePen;

    result := SetStatus(GdipGetPathWorldBoundsI(nativePath, @bounds, nativeMatrix, nativePen));
  end;

  function TGPGraphicsPath.Flatten(matrix: TGPMatrix = nil; flatness: Single = FlatnessDefault): TStatus;
  var nativeMatrix: GpMatrix;
  begin
    nativeMatrix := nil;
    if assigned(matrix) then nativeMatrix := matrix.nativeMatrix;
    result := SetStatus(GdipFlattenPath(nativePath, nativeMatrix, flatness));
  end;

  function TGPGraphicsPath.Widen(pen: TGPPen; matrix: TGPMatrix = nil; flatness: Single = FlatnessDefault): TStatus;
  var nativeMatrix: GpMatrix;
  begin
    nativeMatrix := nil;
    if assigned(matrix) then nativeMatrix := matrix.nativeMatrix;
    result := SetStatus(GdipWidenPath(nativePath, pen.nativePen, nativeMatrix, flatness));
  end;

  function TGPGraphicsPath.Outline(matrix: TGPMatrix = nil; flatness: Single = FlatnessDefault): TStatus;
  var nativeMatrix: GpMatrix;
  begin
    nativeMatrix := nil;
    if assigned(matrix) then nativeMatrix := matrix.nativeMatrix;
    result := SetStatus(GdipWindingModeOutline(nativePath, nativeMatrix, flatness));
  end;

    // Once this is called, the resultant path is made of line segments and
    // the original path information is lost.  When matrix is nil, the
    // identity matrix is assumed.

  function TGPGraphicsPath.Warp(destPoints: PGPPointF; count: Integer; srcRect: TGPRectF;
            matrix: TGPMatrix = nil; warpMode: TWarpMode = WarpModePerspective;
            flatness: Single = FlatnessDefault): TStatus;
  var nativeMatrix: GpMatrix;
  begin
    nativeMatrix := nil;
    if assigned(matrix) then nativeMatrix := matrix.nativeMatrix;
    result := SetStatus(GdipWarpPath(nativePath, nativeMatrix, destPoints,
                count, srcRect.X, srcRect.Y, srcRect.Width, srcRect.Height,
                warpMode, flatness));
  end;

  function TGPGraphicsPath.GetPointCount: Int64;
  var count: Int64;
  begin
    count := 0;
    SetStatus(GdipGetPointCount(nativePath, count));
    result := count;
  end;

  function TGPGraphicsPath.GetPathTypes(types: PBYTE; count: Integer): TStatus;
  begin
    result := SetStatus(GdipGetPathTypes(nativePath, types, count));
  end;

  function TGPGraphicsPath.GetPathPoints(points: PGPPointF; count: Integer): TStatus;
  begin
    result := SetStatus(GdipGetPathPoints(nativePath, points, count));
  end;

  function TGPGraphicsPath.GetPathPoints(points: PGPPoint; count: Integer): TStatus;
  begin
    result := SetStatus(GdipGetPathPointsI(nativePath, points, count));
  end;

  function TGPGraphicsPath.GetLastStatus: TStatus;
  begin
    result := lastResult;
    lastResult := Ok;
  end;

  function TGPGraphicsPath.IsVisible(point: TGPPointF; g: TGPGraphics = nil): BOOL;
  begin
    result := IsVisible(point.X, point.Y, g);
  end;

  function TGPGraphicsPath.IsVisible(x, y: Single; g: TGPGraphics = nil): BOOL;
  var
    booln: BOOL;
    nativeGraphics: GpGraphics;
  begin
    booln := FALSE;
    nativeGraphics := nil;
    if assigned(g) then nativeGraphics := g.nativeGraphics;
    SetStatus(GdipIsVisiblePathPoint(nativePath, x, y, nativeGraphics, booln));
    result := booln;
  end;

  function TGPGraphicsPath.IsVisible(point: TGPPoint; g : TGPGraphics = nil): BOOL;
  begin
    result := IsVisible(point.X, point.Y, g);
  end;

  function TGPGraphicsPath.IsVisible(x, y: Integer; g: TGPGraphics = nil): BOOL;
  var
    booln: BOOL;
    nativeGraphics: GpGraphics;
  begin
    booln := FALSE;
    nativeGraphics := nil;
    if assigned(g) then nativeGraphics := g.nativeGraphics;
    SetStatus(GdipIsVisiblePathPointI(nativePath, x, y, nativeGraphics, booln));
    result := booln;
  end;

  function TGPGraphicsPath.IsOutlineVisible(point: TGPPointF; pen: TGPPen; g: TGPGraphics = nil): BOOL;
  begin
    result := IsOutlineVisible(point.X, point.Y, pen, g);
  end;

  function TGPGraphicsPath.IsOutlineVisible(x, y: Single; pen: TGPPen; g: TGPGraphics = nil): BOOL;
  var
    booln: BOOL;
    nativeGraphics: GpGraphics;
    nativePen: GpPen;
  begin
    booln := FALSE;
    nativeGraphics := nil;
    nativePen := nil;
    if assigned(g) then nativeGraphics := g.nativeGraphics;
    if assigned(pen) then nativePen := pen.nativePen;
    SetStatus(GdipIsOutlineVisiblePathPoint(nativePath, x, y, nativePen,
        nativeGraphics, booln));
    result := booln;
  end;

  function TGPGraphicsPath.IsOutlineVisible(point: TGPPoint; pen: TGPPen; g: TGPGraphics = nil): BOOL;
  begin
    result := IsOutlineVisible(point.X, point.Y, pen, g);
  end;

  function TGPGraphicsPath.IsOutlineVisible(x, y: Integer; pen: TGPPen; g: TGPGraphics = nil): BOOL;
  var
    booln: BOOL;
    nativeGraphics: GpGraphics;
    nativePen: GpPen;
  begin
    booln := FALSE;
    nativeGraphics := nil;
    nativePen := nil;
    if assigned(g) then nativeGraphics := g.nativeGraphics;
    if assigned(pen) then nativePen := pen.nativePen;
    SetStatus(GdipIsOutlineVisiblePathPointI(nativePath, x, y, nativePen,
       nativeGraphics, booln));
    result := booln;
  end;

  constructor TGPGraphicsPath.Create(path: TGPGraphicsPath);
  var clonepath: GpPath;
  begin
    clonepath := nil;
    SetStatus(GdipClonePath(path.nativePath, clonepath));
    SetNativePath(clonepath);
  end;

  constructor TGPGraphicsPath.Create(nativePath: GpPath);
  begin
    lastResult := Ok;
    SetNativePath(nativePath);
  end;

  procedure TGPGraphicsPath.SetNativePath(nativePath: GpPath);
  begin
    self.nativePath := nativePath;
  end;

  function TGPGraphicsPath.SetStatus(status: TStatus): TStatus;
  begin
    if (status <> Ok) then LastResult := status;
    result := status;
  end;

//--------------------------------------------------------------------------
// GraphisPathIterator class
//--------------------------------------------------------------------------

  constructor TGPGraphicsPathIterator.Create(path: TGPGraphicsPath);
  var
    nativePath: GpPath;
    iter: GpPathIterator;
  begin
    nativePath := nil;
    if assigned(path) then nativePath := path.nativePath;
    iter := nil;
    lastResult := GdipCreatePathIter(iter, nativePath);
    SetNativeIterator(iter);
  end;

  destructor TGPGraphicsPathIterator.Destroy;
  begin
    GdipDeletePathIter(nativeIterator);
  end;


  function TGPGraphicsPathIterator.NextSubpath(out startIndex, endIndex: Integer; out isClosed: bool): Integer;
  begin
    SetStatus(GdipPathIterNextSubpath(nativeIterator, result, startIndex, endIndex, isClosed));
  end;

  function TGPGraphicsPathIterator.NextSubpath(path: TGPGraphicsPath; out isClosed: BOOL): Integer;
  var
    nativePath: GpPath;
    resultCount: Integer;
  begin
    nativePath := nil;
    if assigned(path) then nativePath := path.nativePath;
    SetStatus(GdipPathIterNextSubpathPath(nativeIterator, resultCount,
      nativePath, isClosed));
    result := resultCount;
  end;

  function TGPGraphicsPathIterator.NextPathType(out pathType: TPathPointType; out startIndex, endIndex: Integer): Integer;
  var
    resultCount: Integer;
  begin
    SetStatus(GdipPathIterNextPathType(nativeIterator, resultCount, @pathType,
       startIndex, endIndex));
    result := resultCount;
  end;

  function TGPGraphicsPathIterator.NextMarker(out startIndex, endIndex: Integer): Integer;
  begin
    SetStatus(GdipPathIterNextMarker(nativeIterator, result, startIndex, endIndex));
  end;

  function TGPGraphicsPathIterator.NextMarker(path: TGPGraphicsPath): Integer;
  var nativePath: GpPath;
  begin
    nativePath := nil;
    if assigned(path) then nativePath := path.nativePath;
    SetStatus(GdipPathIterNextMarkerPath(nativeIterator, result, nativePath));
  end;

  function TGPGraphicsPathIterator.GetCount: Integer;
  begin
    SetStatus(GdipPathIterGetCount(nativeIterator, result));
  end;

  function TGPGraphicsPathIterator.GetSubpathCount: Integer;
  begin
    SetStatus(GdipPathIterGetSubpathCount(nativeIterator, result));
  end;

  function TGPGraphicsPathIterator.HasCurve: BOOL;
  begin
    SetStatus(GdipPathIterHasCurve(nativeIterator, result));
  end;

  procedure TGPGraphicsPathIterator.Rewind;
  begin
    SetStatus(GdipPathIterRewind(nativeIterator));
  end;

  function TGPGraphicsPathIterator.Enumerate(points: PGPPointF; types: PBYTE;
    count: Integer): Integer;
  begin
    SetStatus(GdipPathIterEnumerate(nativeIterator, result, points, types, count));
  end;

  function TGPGraphicsPathIterator.CopyData(points: PGPPointF; types: PBYTE;
    startIndex, endIndex: Integer): Integer;
  begin
    SetStatus(GdipPathIterCopyData(nativeIterator, result, points, types,
      startIndex, endIndex));
  end;

  function TGPGraphicsPathIterator.GetLastStatus: TStatus;
  begin
    result := lastResult;
    lastResult := Ok;
  end;

  procedure TGPGraphicsPathIterator.SetNativeIterator(nativeIterator: GpPathIterator);
  begin
    self.nativeIterator := nativeIterator;
  end;

  function TGPGraphicsPathIterator.SetStatus(status: TStatus): TStatus;
  begin
    if (status <> Ok) then lastResult := status;
    result := status;
  end;

//--------------------------------------------------------------------------
// Path Gradient Brush
//--------------------------------------------------------------------------

  constructor TGPPathGradientBrush.Create(points: PGPPointF; count: Integer; wrapMode: TWrapMode = WrapModeClamp);
  var brush: GpPathGradient;
  begin
    brush := nil;
    lastResult := GdipCreatePathGradient(points, count, wrapMode, brush);
    SetNativeBrush(brush);
  end;

  constructor TGPPathGradientBrush.Create(points: PGPPoint; count: Integer; wrapMode: TWrapMode = WrapModeClamp);
  var brush: GpPathGradient;
  begin
    brush := nil;
    lastResult := GdipCreatePathGradientI(points, count, wrapMode, brush);
    SetNativeBrush(brush);
  end;

  constructor TGPPathGradientBrush.Create(path: TGPGraphicsPath);
  var brush: GpPathGradient;
  begin
    brush := nil;
    lastResult := GdipCreatePathGradientFromPath(path.nativePath, brush);
    SetNativeBrush(brush);
  end;

  function TGPPathGradientBrush.GetCenterColor(out Color: TGPColor): TStatus;
  begin
    SetStatus(GdipGetPathGradientCenterColor(GpPathGradient(nativeBrush), Color));
    result := lastResult;
  end;

  function TGPPathGradientBrush.SetCenterColor(color: TGPColor): TStatus;
  begin
    SetStatus(GdipSetPathGradientCenterColor(GpPathGradient(nativeBrush),color));
    result := lastResult;
  end;

  function TGPPathGradientBrush.GetPointCount: Integer;
  begin
    SetStatus(GdipGetPathGradientPointCount(GpPathGradient(nativeBrush), result));
  end;

  function TGPPathGradientBrush.GetSurroundColorCount: Integer;
  begin
    SetStatus(GdipGetPathGradientSurroundColorCount(GpPathGradient(nativeBrush), result));
  end;

  function TGPPathGradientBrush.GetSurroundColors(colors: PARGB; var count: Integer): TStatus;
  var
    count1: Integer;
  begin
    if not assigned(colors) then
    begin
      result := SetStatus(InvalidParameter);
      exit;
    end;

    SetStatus(GdipGetPathGradientSurroundColorCount(GpPathGradient(nativeBrush), count1));

    if(lastResult <> Ok) then
    begin
      result := lastResult;
      exit;
    end;

    if((count < count1) or (count1 <= 0)) then
    begin
      result := SetStatus(InsufficientBuffer);
      exit;
    end;

    SetStatus(GdipGetPathGradientSurroundColorsWithCount(GpPathGradient(nativeBrush), colors, count1));
    if(lastResult = Ok) then
      count := count1;

    result := lastResult;
  end;

  function TGPPathGradientBrush.SetSurroundColors(colors: PARGB; var count: Integer): TStatus;
  var
    count1: Integer;
  type
    TDynArrDWORD = array of DWORD;
  begin
    if (colors = nil) then
    begin
      result := SetStatus(InvalidParameter);
      exit;
    end;

    count1 := GetPointCount;

    if((count > count1) or (count1 <= 0)) then
    begin
      result := SetStatus(InvalidParameter);
      exit;
    end;

    count1 := count;

    SetStatus(GdipSetPathGradientSurroundColorsWithCount(
                GpPathGradient(nativeBrush), colors, count1));

    if(lastResult = Ok) then count := count1;
    result := lastResult;
  end;

  function TGPPathGradientBrush.GetGraphicsPath(path: TGPGraphicsPath): TStatus;
  begin
    if(path = nil) then
    begin
      result := SetStatus(InvalidParameter);
      exit;
    end;
    result := SetStatus(GdipGetPathGradientPath(GpPathGradient(nativeBrush), path.nativePath));
  end;

  function TGPPathGradientBrush.SetGraphicsPath(path: TGPGraphicsPath): TStatus;
  begin
    if(path = nil) then
    begin
      result := SetStatus(InvalidParameter);
      exit;
    end;
    result := SetStatus(GdipSetPathGradientPath(GpPathGradient(nativeBrush), path.nativePath));
  end;

  function TGPPathGradientBrush.GetCenterPoint(out point: TGPPointF): TStatus;
  begin
    result := SetStatus(GdipGetPathGradientCenterPoint(GpPathGradient(nativeBrush), @point));
  end;

  function TGPPathGradientBrush.GetCenterPoint(out point: TGPPoint): TStatus;
  begin
    result := SetStatus(GdipGetPathGradientCenterPointI(GpPathGradient(nativeBrush), @point));
  end;

  function TGPPathGradientBrush.SetCenterPoint(point: TGPPointF): TStatus;
  begin
    result := SetStatus(GdipSetPathGradientCenterPoint(GpPathGradient(nativeBrush), @point));
  end;

  function TGPPathGradientBrush.SetCenterPoint(point: TGPPoint): TStatus;
  begin
    result := SetStatus(GdipSetPathGradientCenterPointI(GpPathGradient(nativeBrush), @point));
  end;

  function TGPPathGradientBrush.GetRectangle(out rect: TGPRectF): TStatus;
  begin
    result := SetStatus(GdipGetPathGradientRect(GpPathGradient(nativeBrush), @rect));
  end;

  function TGPPathGradientBrush.GetRectangle(out rect: TGPRect): TStatus;
  begin
    result := SetStatus(GdipGetPathGradientRectI(GpPathGradient(nativeBrush), @rect));
  end;

  function TGPPathGradientBrush.SetGammaCorrection(useGammaCorrection: BOOL): TStatus;
  begin
    result := SetStatus(GdipSetPathGradientGammaCorrection(GpPathGradient(nativeBrush),
      useGammaCorrection));
  end;

  function TGPPathGradientBrush.GetGammaCorrection: BOOL;
  begin
    SetStatus(GdipGetPathGradientGammaCorrection(GpPathGradient(nativeBrush), result));
  end;

  function TGPPathGradientBrush.GetBlendCount: Integer;
  var count: Integer;
  begin
    count := 0;
    SetStatus(GdipGetPathGradientBlendCount(GpPathGradient(nativeBrush), count));
    result := count;
  end;

  function TGPPathGradientBrush.GetBlend(blendFactors, blendPositions:PSingle; count: Integer): TStatus;
  begin
    result := SetStatus(GdipGetPathGradientBlend(
                      GpPathGradient(nativeBrush),
                      blendFactors, blendPositions, count));
  end;

  function TGPPathGradientBrush.SetBlend(blendFactors, blendPositions: PSingle; count: Integer): TStatus;
  begin
    result := SetStatus(GdipSetPathGradientBlend(
                      GpPathGradient(nativeBrush),
                      blendFactors, blendPositions, count));
  end;

  function TGPPathGradientBrush.GetInterpolationColorCount: Integer;
  var count: Integer;
  begin
    count := 0;
    SetStatus(GdipGetPathGradientPresetBlendCount(GpPathGradient(nativeBrush), count));
    result := count;
  end;

  function TGPPathGradientBrush.SetInterpolationColors(presetColors: PARGB;
    blendPositions: PSingle; count: Integer): TStatus;
  var
    status: TStatus;
  begin
    if ((count <= 0) or (presetColors = nil)) then
    begin
      result := SetStatus(InvalidParameter);
      exit;
    end;

    status := SetStatus(GdipSetPathGradientPresetBlend(GpPathGradient(nativeBrush),
                          presetColors, blendPositions, count));
    result := status;
  end;

  function TGPPathGradientBrush.GetInterpolationColors(presetColors: PARGB;
    blendPositions: PSingle; count: Integer): TStatus;
  var
    status: GpStatus;
    i: Integer;
    argbs: PARGB;
  begin
        if ((count <= 0) or (presetColors = nil)) then
        begin
          result := SetStatus(InvalidParameter);
          exit;
        end;
        getmem(argbs, count*SizeOf(ARGB));
        if (argbs = nil) then
        begin
          result := SetStatus(OutOfMemory);
          exit;
        end;

        status := SetStatus(GdipGetPathGradientPresetBlend(nativeBrush, argbs,
                     blendPositions, count));

        for i := 0 to count - 1 do
          TColorDynArray(presetColors)[i] := TColorDynArray(argbs)[i];

        freemem(argbs);

        result := status;
  end;

  function TGPPathGradientBrush.SetBlendBellShape(focus: Single; scale: Single = 1.0): TStatus;
  begin
    result := SetStatus(GdipSetPathGradientSigmaBlend(GpPathGradient(nativeBrush), focus, scale));
  end;

  function TGPPathGradientBrush.SetBlendTriangularShape(focus: Single; scale: Single = 1.0): TStatus;
  begin
    result := SetStatus(GdipSetPathGradientLinearBlend(GpPathGradient(nativeBrush), focus, scale));
  end;

  function TGPPathGradientBrush.GetTransform(matrix: TGPMatrix): TStatus;
  begin
    result := SetStatus(GdipGetPathGradientTransform(GpPathGradient(nativeBrush),
                      matrix.nativeMatrix));
  end;

  function TGPPathGradientBrush.SetTransform(matrix: TGPMatrix): TStatus;
  begin
    result := SetStatus(GdipSetPathGradientTransform(
                      GpPathGradient(nativeBrush),
                      matrix.nativeMatrix));
  end;

  function TGPPathGradientBrush.ResetTransform: TStatus;
  begin
    result := SetStatus(GdipResetPathGradientTransform(
                      GpPathGradient(nativeBrush)));
  end;

  function TGPPathGradientBrush.MultiplyTransform(matrix: TGPMatrix; order: TMatrixOrder = MatrixOrderPrepend): TStatus;
  begin
    result := SetStatus(GdipMultiplyPathGradientTransform(
                      GpPathGradient(nativeBrush),
                      matrix.nativeMatrix,
                      order));
  end;

  function TGPPathGradientBrush.TranslateTransform(dx, dy: Single; order: TMatrixOrder = MatrixOrderPrepend): TStatus;
  begin
    result := SetStatus(GdipTranslatePathGradientTransform(
                      GpPathGradient(nativeBrush),
                      dx, dy, order));
  end;

  function TGPPathGradientBrush.ScaleTransform(sx, sy: Single; order: TMatrixOrder = MatrixOrderPrepend): TStatus;
  begin
    result := SetStatus(GdipScalePathGradientTransform(
                      GpPathGradient(nativeBrush),
                      sx, sy, order));
  end;

  function TGPPathGradientBrush.RotateTransform(angle: Single; order: TMatrixOrder = MatrixOrderPrepend): TStatus;
  begin
    result := SetStatus(GdipRotatePathGradientTransform(
                      GpPathGradient(nativeBrush),
                      angle, order));
  end;

  function TGPPathGradientBrush.GetFocusScales(out xScale, yScale: Single): TStatus;
  begin
    result := SetStatus(GdipGetPathGradientFocusScales(
                      GpPathGradient(nativeBrush), xScale, yScale));
  end;

  function TGPPathGradientBrush.SetFocusScales(xScale, yScale: Single): TStatus;
  begin
    result := SetStatus(GdipSetPathGradientFocusScales(
                      GpPathGradient(nativeBrush), xScale, yScale));
  end;

  function TGPPathGradientBrush.GetWrapMode: TWrapMode;
  begin
    SetStatus(GdipGetPathGradientWrapMode(GpPathGradient(nativeBrush), result));
  end;

  function TGPPathGradientBrush.SetWrapMode(wrapMode: TWrapMode): TStatus;
  begin
    result := SetStatus(GdipSetPathGradientWrapMode(
                      GpPathGradient(nativeBrush), wrapMode));
  end;

  constructor TGPPathGradientBrush.Create;
  begin
  end;


end.
