TGPGraphics.GetVisibleClipBounds
We use the TGPGraphics.GetVisibleClipBounds
function to get the current clipping zone, store it and restore later. But this function seems to give a wrong result in Linux and MacOS:
procedure TForm1.FormPaint(Sender: TObject);
var GPGraphics: TGPGraphics;
tmpR: TGPRectF;
begin
GPGraphics:=TGPGraphics.Create(Canvas.Handle);
GPGraphics.GetVisibleClipBounds(tmpR);
Caption:='Width: ' + FormatFloat('#,##0.00#', tmpR.Width) + ', Height: ' + FormatFloat('#,##0.00#', tmpR.Height);
end;
Comments (7)
-
repo owner -
reporter Our TChart component fails to draw the Legend under some circumstances and I suspect there's something wrong with the clipping. However, at this moment I'm not sure the problem is at
TGPGraphics.GetVisibleClipBounds
function. Sorry for the confusion.
Here is the result in Linux:And in MacOS:
However, in 3D the Legend is drawn both for Linux and MacOS.
In Linux:And in MacOS:
Of course in Windows the Legend is drawn both in 2D and 3D.
At this moment I believe the problem is at how we callTGPGraphics.IntersectClip
function.
For 2D Charts we use thisClipRectangle
function:procedure TGDIPlusCanvas.ClipRectangle(Const Rect:TRect); var tmpR : TRect; begin tmpR:=TeeRect(Rect.Left,Rect.Top-1,Rect.Right,Rect.Bottom+1); FGraphics.IntersectClip(MakeRect(tmpR)); end;
For 3D Charts we use this
ClipPolygon
function:Procedure TGDIPlusCanvas.ClipPolygon(const Points:Array of TPoint; NumPoints:Integer; DiffRegion:Boolean=False); var Region : HRgn; r : TGPRegion; begin Region:=CreatePolygonRgn(Points,NumPoints,ALTERNATE); r:=TGPRegion.Create(Region); try PushClipRect; if DiffRegion then FGraphics.SetClip(r,CombineModeExclude) else FGraphics.IntersectClip(r); finally DeleteObject(Region); r.Free; end; //DONT: inherited; end;
Now I'm testing this new
ClipRectangle
function, which seems to work fine everywhere:procedure TGDIPlusCanvas.ClipRectangle(Const Rect:TRect); var tmpR : TRect; {$IFNDEF MSWINDOWS} tmpP : TFourPoints; Region : HRgn; r : TGPRegion; {$ENDIF} begin PushClipRect; tmpR:=TeeRect(Rect.Left,Rect.Top-1,Rect.Right,Rect.Bottom+1); {$IFDEF MSWINDOWS} FGraphics.IntersectClip(MakeRect(tmpR)); {$ELSE} try RectToFourPoints(tmpR, 0, tmpP); Region:=CreatePolygonRgn(tmpP,4,ALTERNATE); r:=TGPRegion.Create(Region); FGraphics.IntersectClip(r); finally DeleteObject(Region); r.Free; end; {$ENDIF} end;
-
reporter Hmmm, this function works in respect to the Legend drawing, but it doesn't do the clipping correctly in Linux&MacOS:
Linux:
MacOS:
Windows:
I've also tested with this function to do the same in all the platforms, with the same results above:
procedure TGDIPlusCanvas.ClipRectangle(Const Rect:TRect); var tmpR : TRect; tmpP : TFourPoints; Region : HRgn; r : TGPRegion; begin PushClipRect; tmpR:=TeeRect(Rect.Left,Rect.Top-1,Rect.Right,Rect.Bottom+1); try RectToFourPoints(tmpR, 0, tmpP); Region:=CreatePolygonRgn(tmpP,4,ALTERNATE); r:=TGPRegion.Create(Region); FGraphics.IntersectClip(r); finally DeleteObject(Region); r.Free; end; end;
-
reporter I've simplified the issue removing any reference to TeeChart. Here you have the code to reproduce the clipping problem in Linux&MacOS:
uses GDIPOBJ, GDIPAPI; procedure TForm1.FormPaint(Sender: TObject); var G: TGPGraphics; chartRect: TRect; oldClipRect, seriesRect, legendRect: TGPRect; tmpP : Array[0..3] of TPoint; Region : HRgn; r : TGPRegion; begin G:=TGPGraphics.Create(Canvas.Handle); legendRect.Width:=100; legendRect.Height:=200; legendRect.X:=ClientRect.Width-legendRect.Width-50; legendRect.Y:=50; chartRect:=Rect(50,50,legendRect.X-200+50,clientRect.Height-100); seriesRect.X:=chartRect.Left+chartRect.Width-50; seriesRect.Width:=100; seriesRect.Y:=chartRect.Top+50; seriesRect.Height:=chartRect.Height; //draw Chart rectangle G.FillRectangle(TGPSolidBrush.Create(MakeColor(255,255,255)), MakeRect(chartRect)); G.DrawRectangle(TGPPen.Create(MakeColor(0,0,0)), MakeRect(chartRect)); //save clipping rect G.GetVisibleClipBounds(oldClipRect); //clip rectangle try tmpP[0]:=Point(chartRect.Left,chartRect.Top); tmpP[1]:=Point(chartRect.Left,chartRect.Bottom); tmpP[2]:=Point(chartRect.Right,chartRect.Bottom); tmpP[3]:=Point(chartRect.Right,chartRect.Top); Region:=CreatePolygonRgn(tmpP,4,ALTERNATE); r:=TGPRegion.Create(Region); G.IntersectClip(r); finally DeleteObject(Region); r.Free; end; //drawSeries G.FillRectangle(TGPSolidBrush.Create(MakeColor(125,200,255)), seriesRect); G.DrawRectangle(TGPPen.Create(MakeColor(0,0,0)), seriesRect); //restore saved clipping G.SetClip(oldClipRect); //drawLegend G.FillRectangle(TGPSolidBrush.Create(MakeColor(255,125,125)), legendRect); G.DrawRectangle(TGPPen.Create(MakeColor(0,0,0)), legendRect); end;
-
repo owner Thank you for detailed report. We start working on it.
One question, why don't you just use TGPGraphics.IntersectClip(const rect: TGPRectF) in ClipRectangle, but use such complicated code with Region ?
-
repo owner - changed status to resolved
Fixed at 1.06
-
reporter One question, why don't you just use TGPGraphics.IntersectClip(const rect: TGPRectF) in ClipRectangle, but use such complicated code with Region ?
Precisely the
TGPRectF
version ofTGPGraphics.IntersectClip
wasn't working as expected in Linux&MacOS and I found theTGPRegion
version was working well everywhere.Now, with v1.06, it seems to work perfectly.
Thanks! - Log in to comment
Actually this function uses native API to get clipping box. Why you think it is wrong ?