2016-04-22 2 views
0

Я использую библиотеку IGDIPlus от Mitov для Delphi. Я получаю исключение «Общая ошибка» в совершенно невинной ситуации. У меня есть пять перекрывающихся прямоугольников и хотел бы использовать aPath.outline(), чтобы найти контур пути (я запускаю этот пример на Win7, со всеми связанными контурными патчами).gdiplus Path GdipWindingModeOutline troubles

uses 
System.Types, IGDIPlus, VCL.IGDIPlusExt; 


procedure TForm1.FormPaint(Sender: TObject); 
var 
    AGraphics  : IGPGraphics; 
    APath,aPathO : IGPGraphicsPath; 

begin 
    AGraphics := TIGPGraphics.Create(Canvas); 
    AGraphics.SmoothingMode := SmoothingModeAntiAlias; 
    AGraphics.TextRenderingHint := TextRenderingHintAntiAlias; 
    aPath := TIGPGraphicsPath.create() ; 
    // this path gives generic error 
    aPath.addRectangle(73,201,108,96); 
// --------the difference---------- 
    aPath.addRectangle(73,292,58,96); 
// --------the difference---------- 
    aPath.addRectangle(73,383,108,96); 
    aPath.addRectangle(177,201,108,96); 
    aPath.addRectangle(177,383,108,96); 

    try 
    aPathO := apath.clone().Outline(); 
    AGraphics.DrawPath(TIGPPen.Create(aclRed,1), 
     aPathO); 
    except 
    on E: Exception do 
    begin 
     AGraphics.DrawStringF(e.message, 
          TIGPFont.Create('Microsoft Sans Serif', 16, [ fsBold ]), 
          TPointF.Create(23, 23), 
          TIGPSolidBrush.Create(aclRed)) ; 

     AGraphics.DrawPath(TIGPPen.Create(aclRed,1), 
     aPath); 
    end; 
    end; 
    aPath.reset(); 
// this path works fine 
    aPath.addRectangle(373,201,108,96); 
// --------the difference---------- 
    aPath.addRectangle(373,292,108,96);  
// --------the difference---------- 
    aPath.addRectangle(373,383,108,96); 
    aPath.addRectangle(477,201,108,96); 
    aPath.addRectangle(477,383,108,96); 

    try 
    aPathO := apath.clone().Outline(); 
    AGraphics.DrawPath(TIGPPen.Create(aclRed,1), 
     aPathO); 
    AGraphics.DrawStringF('it works', 
          TIGPFont.Create('Microsoft Sans Serif', 16, [ fsBold ]), 
          TPointF.Create(423, 23), 
          TIGPSolidBrush.Create(aclRed)) ; 

    except 
    on E: Exception do 
    begin 
     AGraphics.DrawStringF(e.message, 
          TIGPFont.Create('Microsoft Sans Serif', 16, [ fsBold ]), 
          TPointF.Create(223, 23), 
          TIGPSolidBrush.Create(aclRed)) ; 

     AGraphics.DrawPath(TIGPPen.Create(aclRed,1), 
     aPath); 
    end; 
    end; 
end; 

Любые идеи, предложения приветствуются.

Запуск же пример в C# дает ту же ошибку (используя Outline a path with GDI+ in .Net)



    GraphicsPath aPath = new GraphicsPath(); 
       aPath.AddRectangle(new Rectangle(73, 201, 108, 96)); 
       aPath.AddRectangle(new Rectangle(73, 292, 58, 96)); 
       aPath.AddRectangle(new Rectangle(73, 383, 108, 96)); 
       aPath.AddRectangle(new Rectangle(177, 201, 108, 96)); 
       aPath.AddRectangle(new Rectangle(177, 383, 108, 96)); 

       HandleRef handle = new HandleRef(aPath, (IntPtr)aPath.GetType().GetField("nativePath", BindingFlags.NonPublic | BindingFlags.Instance).GetValue(aPath)); 
       try 
       { 

        int status = GdipWindingModeOutline(handle, IntPtr.Zero, 0.25F); 
        using (Pen outlinePen = new Pen(Color.FromArgb(255, Color.Red), 2)) 
        { 
         g.DrawPath(outlinePen, aPath); 
        } 
       } 

       catch (Exception exp) 
       { ... 
       } 

GdipWindingModeOutline функция возвращает статус = 1 (Общая ошибка)

Потому что мне действительно нужно использовать кривой контур и прямой способ aPath.clone().outline() должен быть gdi + ошибка невозможна, я должен пойти вокруг. Подходящее решение - возможно, не самое лучшее, но работает - может быть:



     procedure TForm1.FormPaint(Sender: TObject); 
     var 
      AGraphics  : IGPGraphics; 
      APath,aPathO : IGPGraphicsPath; 
      aRegion   : IGPRegion; 
      aScan   : TArray; 
      aMatrix   : IGPmatrix; 

     begin 
      AGraphics := TIGPGraphics.Create(Canvas); 
      AGraphics.SmoothingMode := SmoothingModeAntiAlias; 
      AGraphics.TextRenderingHint := TextRenderingHintAntiAlias; 
      aPath := TIGPGraphicsPath.create() ; 
      aRegion := TIGPRegion.create().MakeEmpty(); 
      aRegion.Union( TIGPRect.create(73,201,108,96)); 
      aRegion.Union( TIGPRect.create(73,292,58,96)); 
      aRegion.Union( TIGPRect.create(73,383,108,96)); 
      aRegion.Union( TIGPRect.create(177,201,108,96)); 
      aRegion.Union( TIGPRect.create(177,383,108,96)); 
      aMatrix := TIGPMatrix.Create(); 
      aScan := lRegion.GetRegionScans(aMatrix); 
      for i := 0 to High(aScan) do 
      aPath.addRectangle(GPInflateRect(aScan[i], 1)); 


      aPathO := aPath.Clone().Outline(); 
      AGraphics.DrawPath(TIGPPen.Create(aclRed,1), aPathO); 

     end; 

ответ

0

Ваша линия AGraphics.DrawPath(TIGPPen.Create(aclRed,1), ... опасна в Teh мире Delphi, если вы используете интерфейсы (которые эта библиотека явно делает). У Delphi есть некоторые проблемы, когда дело доходит до подсчета ссылок и создания объектов в функциональных вызовах (я не помню, хотя бы ...). Попробуйте не создавать объект в вызове функции, а скорее определять новую локальную переменную, которая содержит ссылку на интерфейс.

+0

Нет, проблема не в этой строке (код основан на демонстрации Mitov), ​​общая ошибка подсчитывается из строки выше 'aPathO: = apath.clone(). Outline();' Это было бы полезно, если кто-то попытался запустить аналогичный пример на C# или на каком-то другом языке – EvaF