OutOfMemoryException in GoShape

Hi Walter,



I have a problem in GoShape (I think). As you can see in the “subject”, I get an “System.OutOfMemoryException”. I’m using GoWin 2.4.1.1.



My component loads “objects” and creates a GoGroup (MyGraphicBlock) for each. The GoGroup contains (among others) a GoRoundedRectangle as Background and a GoGroup containing the childs of this element. The childs are of the same kind, means GoGroups.



This works fine until the “top-level” parent element gets really big. I think this can be the reason for the problem. But I can’t influent to size of an element (means the nuber of childs ans subchilds…).



Here’s a part of my stack trace:



Internal error of MyComponent (System.OutOfMemoryException: Exception of type ‘System.OutOfMemoryException’ was thrown.

at Northwoods.Go.GoShape.GetBrushInfo(Brush b)

at Northwoods.Go.GoShape.set_Brush(Brush value)

at MyComponent.Graphic.MyBackgroundRectangle.set_Bounds(RectangleF value) in MyBackgroundRectangle.cs:line 79

at Northwoods.Go.GoGroup.MoveChildren(RectangleF old)

at Northwoods.Go.GoGroup.OnBoundsChanged(RectangleF old)

at MyComponent.Graphic.MyGraphicBlock.OnBoundsChanged(RectangleF old) in MyGraphicBlock.cs:line 1045

at Northwoods.Go.GoObject.set_Bounds(RectangleF value)

at Northwoods.Go.GoGroup.MoveChildren(RectangleF old)

at Northwoods.Go.GoGroup.OnBoundsChanged(RectangleF old)

at Northwoods.Go.GoObject.set_Bounds(RectangleF value)

at Northwoods.Go.GoListGroup.set_Bounds(RectangleF value)

at Northwoods.Go.GoGroup.MoveChildren(RectangleF old)

at MyComponent.Graphic.MyGraphicBlock.MoveChildren(RectangleF old) in MyGraphicBlock.cs:line 1228

at Northwoods.Go.GoGroup.OnBoundsChanged(RectangleF old)

at MyComponent.Graphic.MyGraphicBlock.OnBoundsChanged(RectangleF old) in MyGraphicBlock.cs:line 1045

at Northwoods.Go.GoObject.set_Bounds(RectangleF value)

at Northwoods.Go.GoGroup.MoveChildren(RectangleF old)

at Northwoods.Go.GoGroup.OnBoundsChanged(RectangleF old)

at Northwoods.Go.GoObject.set_Bounds(RectangleF value)

at Northwoods.Go.GoListGroup.set_Bounds(RectangleF value)

at Northwoods.Go.GoGroup.MoveChildren(RectangleF old)





As I said before, the exception is only thrown in case of really big structures. Is there a possibility to circumvent the problem?





Regards

Matthias

That is almost certainly a GDI+ error.
Do you know about how large the biggest GoRoundedRectangle is?
When I run Demo1 (2.4.1) and change the Size of a GoRoundedRectangle to 5000000x5000000, everything seems to work fine. But I could imagine getting some GDI+ errors in these circumstances, and even more likely when objects/coordinates are even larger.
Do you get the same problem if you replace GoRoundedRectangle with a GoRectangle? Or just set GoRoundedRectangle.Corner to new SizeF(0, 0)?

Thanks for the quick reply.



Can you tell me the maximum size of a Rectangle or how to compute in relation to the memory?



Matthias

There isn’t any well-defined maximum size for anything.

As a practical matter, the design of GoDiagram is geared towards having everything be within coordinates of +/- 1 million.
But there are definitely GDI+ bugs that we discover and then need to work-around.
Still, I'd like to know the answers to my questions.

I tried using the GoRectangle instead of the GoRoundedRectangle but without any effect. Then I tried modifying the Brush of the Rectangle from “LinearGradientBrush” to “SolidBrush” and that seems to be reason of the problem. Using the “SolidBrush” works fine, switching to Gradient crashes…



As an additional info: my GoView uses DoubleBuffering to circumvent update problems (see my entry ‘Big Update Problem’). But turning off DoubleBuffering doesn’t solve this problem.



Any ideas?



Thanks

Matthias

Sounds like a limitation of GDI+. Apparently when the area to be painted is too large, you should substitute a SolidBrush. I suppose we could consider trying to work around this problem in version 3, but for now, you need to do this yourself in your custom shape’s code to construct a LinearGradientBrush.

Ok, I create the LinearGradientBrush in my “Paint - Overriding” of the Rectangle and use the “using” statement.



using (myBrush = new LinearGradientBrush(…))

{

g.FillPath…

}



That fixed the memory exception problem.





But I figured out another problem using the LinearGradientBrush:



I have a class MyRect, derived from GoRoundedRectagle. The only thing I do is overriding Paint and create a LinearGradientBrush like above. If the “Bounds” (Location) are “small”, everything works fine. But setting the Location to (X:70000; Y:70000) results in a damaged brush for this rectangle.



How can I insert a small screenshot of this?



Code:



//The Rectangle:

public class MyRect : GoRoundedRectangle

{

private Brush myBrush;

public bool main = false;



public override void Paint(Graphics g, GoView view)

{

//base.Paint(g, view);



using (myBrush = new LinearGradientBrush(this.Bounds, Color.Blue, Color.White, LinearGradientMode.ForwardDiagonal))

{

g.FillPath(myBrush, this.GetPath());

}



g.DrawPath(this.Pen, this.GetPath());

}

}



//adding to view (in main form):

MyRect r3 = new MyRect();

r3.Bounds = new RectangleF(70000, 70000, 120, 45);

this.goView1.Document.Add(r3);





I searched a long time to figure out what the problem is, but without any success. GDI+ again???



I hope you can help me,



thanks in advance

Matthias

Yes, I’m afraid so.

You could do:
[code] public override void Paint(Graphics g, GoView view) {
RectangleF r = this.Bounds;
using (GraphicsPath path = (GraphicsPath)GetPath().Clone()) {
using (Brush b = new LinearGradientBrush(new RectangleF(0, 0, r.Width, r.Height),
Color.Blue, Color.White, LinearGradientMode.ForwardDiagonal)) {
g.TranslateTransform(r.X, r.Y);
Matrix m = new Matrix(1, 0, 0, 1, -r.X, -r.Y);
path.Transform(m);
g.FillPath(b, path);
g.DrawPath(this.Pen, path);
g.TranslateTransform(-r.X, -r.Y);
}
}
}[/code]

Great, excelent, brilliant.



I can’t explain myself why I need these “complex” operations / transformations, but it works.



So thank you very much, great job.



Matthias