Sign in Join

Live chat for Free Pascal, Lazarus, Delphi and every Pascal programmer.

Mailing lists / fpc-devel / 2011-11

TFPCustomCanvas Expanded Clipping

32 messages · 7 people · –

Reply by email Subscribe to this list Your subscription

Read-only archive. Use j and k to move between messages.

Felipe Monteiro de Carvalho

Hello,

I am facing a problem with clipping in TFPCustomCanvas because it has these properties:

    property ClipRect : TRect read GetClipRect write SetClipRect;
    property Clipping : boolean read GetClipping write SetClipping;

Which obviously is not extensible for non-rectangular formats. I already have written my own extensible and object oriented clipper, but I'm unsure how to properly integrate it into TFPCustomCanvas. To diminish code duplication and to allow fpvectorial to use TFPCustomCanvas it would be good if TFPCustomCanvas and it's descendents are at least aware that someone might use a different kind of Clipping.

So I am thinking of adding these properties in TFPCustomCanvas:
  property ClipRegion: TObject read GetClipRegion write SetClipRegion;
  property RegionClipping: Boolean read GetRegionClipping write
SetRegionClipping;

So TFPCustomCanvas would be aware that we are can have an extended clipping, although it by itself does not know how to process it. Here I see 2 options of how to interprete the 2 clipping systems: 1> Make them independent, so if you set both Clipping and RegionClipping you might get 2 clippings done o.O
2> Make them dependent, so RegionClipping only sets if ClipRect or ClipRegion should be used. Instead of checking for Clipping it would check for (Clipping and not RegionClipping) to apply the ClipRect

The generic object TObject is utilized here for ClipRegion because TCanvas and TLazCanvas will use different regions, which match only in LCL-CustomDrawn.

what do you think?

Felipe Monteiro de Carvalho

Reply by email

Unknown author
to Felipe Monteiro de Carvalho
Felipe Monteiro de Carvalho wrote 35 lines
Hello, I am facing a problem with clipping in TFPCustomCanvas because it has these properties: property ClipRect : TRect read GetClipRect write SetClipRect; property Clipping : boolean read GetClipping write SetClipping; Which obviously is not extensible for non-rectangular formats. I already have written my own extensible and object oriented clipper, but I'm unsure how to properly integrate it into TFPCustomCanvas. To diminish code duplication and to allow fpvectorial to use TFPCustomCanvas it would be good if TFPCustomCanvas and it's descendents are at least aware that someone might use a different kind of Clipping. So I am thinking of adding these properties in TFPCustomCanvas: property ClipRegion: TObject read GetClipRegion write SetClipRegion; property RegionClipping: Boolean read GetRegionClipping write SetRegionClipping; So TFPCustomCanvas would be aware that we are can have an extended clipping, although it by itself does not know how to process it. Here I see 2 options of how to interprete the 2 clipping systems: 1> Make them independent, so if you set both Clipping and RegionClipping you might get 2 clippings done o.O 2> Make them dependent, so RegionClipping only sets if ClipRect or ClipRegion should be used. Instead of checking for Clipping it would check for (Clipping and not RegionClipping) to apply the ClipRect The generic object TObject is utilized here for ClipRegion because TCanvas and TLazCanvas will use different regions, which match only in LCL-CustomDrawn. what do you think?

Good basics.

What about the following:

Create TBaseClipRegion with abstract method PointIsInRegion(P : TPoint) (and maybe some others, like line intersections or so).

Create a descendent TRectClipRegion with property ClipRect: TRect. It can implement the abstract method(s).

Then implement the ClipRegion property, as you propose.

Setting the ClipRect property just sets ClipRegion to a TRectClipRegion instance with the Rect filled in. (TFPCustomCanvas should own this instance, i.e. destroy when canvas is destroyed)

Property clipping just determines whether the ClipRegion object is used, yes or no.

Seems pretty straightforward to me, backwards compatible, and only a single extra property is introduced (ClipRegion).

Michael.

Reply by email

zeljko
to Unknown author
Show quoted text 17 lines
Create TBaseClipRegion with abstract method PointIsInRegion(P : TPoint) (and maybe some others, like line intersections or so). Create a descendent TRectClipRegion with property ClipRect: TRect. It can implement the abstract method(s). Then implement the ClipRegion property, as you propose. Setting the ClipRect property just sets ClipRegion to a TRectClipRegion instance with the Rect filled in. (TFPCustomCanvas should own this instance, i.e. destroy when canvas is destroyed) Property clipping just determines whether the ClipRegion object is used, yes or no. Seems pretty straightforward to me, backwards compatible, and only a single extra property is introduced (ClipRegion).

+1. That's how qt organized it's painting (QPainter) ClipRect = bounding rect of clip region (region can have more than 1 rect eg. poly region).

zeljko

Reply by email

Unknown author
to zeljko
zeljko wrote 23 lines
On Wednesday 30 of November 2011 10:35:59 wrote: > Create TBaseClipRegion with abstract method PointIsInRegion(P : TPoint) > (and maybe some others, like line intersections or so). > > Create a descendent TRectClipRegion with property ClipRect: TRect. > It can implement the abstract method(s). > > Then implement the ClipRegion property, as you propose. > > Setting the ClipRect property just sets ClipRegion to a TRectClipRegion > instance with the Rect filled in. (TFPCustomCanvas should own this > instance, i.e. destroy when canvas is destroyed) > > Property clipping just determines whether the ClipRegion object > is used, yes or no. > > Seems pretty straightforward to me, backwards compatible, and only a single > extra property is introduced (ClipRegion). +1. That's how qt organized it's painting (QPainter) ClipRect = bounding rect of clip region (region can have more than 1 rect eg. poly region).

For the record: I am not affiliated with Qt in any way ;-)

Michael.

Reply by email

Hans-Peter Diettrich
to Felipe Monteiro de Carvalho: I am facing a problem with clipping in TFPCustomCanvas because it has these properties:…
Show quoted text 9 lines
I am facing a problem with clipping in TFPCustomCanvas because it has these properties: property ClipRect : TRect read GetClipRect write SetClipRect; property Clipping : boolean read GetClipping write SetClipping; Which obviously is not extensible for non-rectangular formats. I already have written my own extensible and object oriented clipper, but I'm unsure how to properly integrate it into TFPCustomCanvas.

What's the purpose of your clipper?

IMO the window manager uses an update region internally, from which one or more paint requests are generated, for rectangular ClipRects.

User code can reduce the ClipRect (or region) further, when a certain area (control) is painted, and output outside the control's bounds should be suppressed.

I'm not sure how far non-rectangular clipping regions are supported by all widgetsets, and wouldn't rely on such a capability.

DoDi

Reply by email

Sven Barth
to Hans-Peter Diettrich
Hans-Peter Diettrich wrote 23 lines
Felipe Monteiro de Carvalho schrieb: > I am facing a problem with clipping in TFPCustomCanvas because it has > these properties: > > property ClipRect : TRect read GetClipRect write SetClipRect; > property Clipping : boolean read GetClipping write SetClipping; > > Which obviously is not extensible for non-rectangular formats. I > already have written my own extensible and object oriented clipper, > but I'm unsure how to properly integrate it into TFPCustomCanvas. What's the purpose of your clipper? IMO the window manager uses an update region internally, from which one or more paint requests are generated, for rectangular ClipRects. User code can reduce the ClipRect (or region) further, when a certain area (control) is painted, and output outside the control's bounds should be suppressed. I'm not sure how far non-rectangular clipping regions are supported by all widgetsets, and wouldn't rely on such a capability.

You are aware that TFPCustomCanvas can be used for widgetset independant canvases as well? Also Felipe said that he'll need it for his fpvectorial project.

Regards,
Sven

Reply by email

Sven Barth
to Hans-Peter Diettrich: What's the purpose of your clipper? IMO the window manager uses an update region…
Hans-Peter Diettrich wrote 23 lines
Felipe Monteiro de Carvalho schrieb: > I am facing a problem with clipping in TFPCustomCanvas because it has > these properties: > > property ClipRect : TRect read GetClipRect write SetClipRect; > property Clipping : boolean read GetClipping write SetClipping; > > Which obviously is not extensible for non-rectangular formats. I > already have written my own extensible and object oriented clipper, > but I'm unsure how to properly integrate it into TFPCustomCanvas. What's the purpose of your clipper? IMO the window manager uses an update region internally, from which one or more paint requests are generated, for rectangular ClipRects. User code can reduce the ClipRect (or region) further, when a certain area (control) is painted, and output outside the control's bounds should be suppressed. I'm not sure how far non-rectangular clipping regions are supported by all widgetsets, and wouldn't rely on such a capability.

You are aware that TFPCustomCanvas can be used for widgetset independant canvases as well? Also Felipe said that he'll need it for his fpvectorial project (which is also widgetset independant).

Regards,
Sven

Reply by email

Felipe Monteiro de Carvalho
to Hans-Peter Diettrich: What's the purpose of your clipper? IMO the window manager uses an update region…
Hans-Peter Diettrich wrote
What's the purpose of your clipper?

I use/will use the same clipper (lcl/lazregions.pas) for a multitude of purposes:

1> To prevent subcontrols from painting outside their area in LCL-CustomDrawn 2> To implement Canvas Region Clipping in lazcanvas (which is the Canvas from LCL-CustomDrawn). This feature is utilized for example by fpvectorial to be able to render PostScript correctly 3> To implement TWinControl.SetShape in LCL-CustomDrawn 4> To verify to which control a mouse/touch event bellongs to in LCL-CustomDrawn.

IMO the window manager uses an update region internally, from which one or more paint requests are generated, for rectangular ClipRects.

It looks like that you are confusing Invalidate Rect with canvas clip regions. They are not the same thing.

I'm not sure how far non-rectangular clipping regions are supported by all widgetsets, and wouldn't rely on such a capability.

I use canvas clip regions in fpvectorial so I know that at least LCL-Win32, LCL-Qt and LCL-Gtk2 support rectangular, poligonal, rounded rect and elliptical regions. From poligonal regions you can also support arbitrary paths by using a transformation implemented in fpvectorial. So summing up you can have pretty much any kind of region that you imagine. I think that only rarely used corner cases like internal holes in regions and poligons with lines which cross one another are not currently implemented. LCL-Carbon is a bit behind from what I remember, but I don't quite remember what exactly is missing or if I already fixed it.

Felipe Monteiro de Carvalho

Reply by email

Hans-Peter Diettrich
to Sven Barth: You are aware that TFPCustomCanvas can be used for widgetset independant canvases as…
Show quoted text 6 lines
> I'm not sure how far non-rectangular clipping regions are supported by > all widgetsets, and wouldn't rely on such a capability. You are aware that TFPCustomCanvas can be used for widgetset independant canvases as well? Also Felipe said that he'll need it for his fpvectorial project.

What's the purpose of defining a clipping region, when the drawing pritives don't respect it?

DoDi

Reply by email

Mattias Gaertner
to Hans-Peter Diettrich

 

Hans-Peter Diettrich hat am 30. November 2011 um 15:24 geschrieben:

Show quoted text 11 lines
Sven Barth schrieb: >> I'm not sure how far non-rectangular clipping regions are supported by >> all widgetsets, and wouldn't rely on such a capability. > > You are aware that TFPCustomCanvas can be used for widgetset independant > canvases as well? Also Felipe said that he'll need it for his > fpvectorial project. What's the purpose of defining a clipping region, when the drawing pritives don't respect it? 

The LCL TCanvas must define a clipregion that is supported by the LCL widgetset drawing functions.
Other fpcanvas implementations can define other clipregions.  
Mattias
 

Reply by email

Felipe Monteiro de Carvalho
to Hans-Peter Diettrich: What's the purpose of defining a clipping region, when the drawing pritives don't respect…
Hans-Peter Diettrich wrote
What's the purpose of defining a clipping region, when the drawing pritives don't respect it?

The clipping region is enforced in:

procedure SetColor (x,y:integer; const AValue:TFPColor); override;

Probably not the fastest way to do it, but it works very well. And it is fast for rectangular regions, so only for less common use cases (like fpvectorial rendering postscript) it gets slower.

One can also optimize on a per-primitive basis later on. Line() already has such an optimization in fcl-line but this optimization conflicted with my non-rectangular region support =) So that's yet another reason why I want to make a change here.

Felipe Monteiro de Carvalho

Reply by email

Felipe Monteiro de Carvalho
to Unknown author: Good basics. What about the following: Create TBaseClipRegion with abstract method…
Show quoted text 6 lines
Good basics. What about the following: Create TBaseClipRegion with abstract method PointIsInRegion(P : TPoint) (and maybe some others, like line intersections or so).

Indeed good idea, I am implementing like that with slightly different names (TFPCustomRegion and IsPointInRegion).

And what about adding virtual to many drawing methods in TFPCustomCanvas? This way TCanvas could override them more cleanly without the need to hide them.

I know that the design is to make people implement DoRectangle, etc, instead, but I can clearly see a case for changing more directly the behavior. Also fcl-image comes without debug info, so removing the methods from TCanvas would bring a debugging annoyance.

Felipe Monteiro de Carvalho

Reply by email

Felipe Monteiro de Carvalho
to Felipe Monteiro de Carvalho
Felipe Monteiro de Carvalho wrote
Indeed good idea, I am implementing like that with slightly different names (TFPCustomRegion and IsPointInRegion).

commited, I did not mention anything from Clip in the name of the region because it is not necessary useful only for drawing clipping, it can also be the base of event clipping and window and control shaping.

I also joined zeljko's idea. If the region is not rectangular and you read the property ClipRect, it will return the bounding rectangle of the region. For rectagular regions it does the same, but the bounding box matches the region rectangle. It comes with a class for rectangular region clipping which is the trivial case for backwards compatibility.

Felipe Monteiro de Carvalho

Reply by email

zeljko
to Felipe Monteiro de Carvalho
Felipe Monteiro de Carvalho wrote
I also joined zeljko's idea. If the region is not rectangular and you

It's not my idea ,I've just explained how it works in qt :)

read the property ClipRect, it will return the bounding rectangle of the region. For rectagular regions it does the same, but the bounding

Yes, it must be so if you deal with > 1 rect or non-rectangular or eg. poly regions.
Note that xxx_boundingRect() functions of qt are marked as slow (I guess it's case when you deal with eg 1000 rects in region and you must calculate lower TopLeft and high BottomRight) in their docs, I hope that we'll have faster ones :)

zeljko

box matches the region rectangle. It comes with a class for rectangular region clipping which is the trivial case for backwards compatibility.

Reply by email

Unknown author
to Felipe Monteiro de Carvalho: On Wed, Dec 7, 2011 at 8:06 AM, Felipe Monteiro de Carvalho commited, I did not mention…
Felipe Monteiro de Carvalho wrote 16 lines
On Wed, Dec 7, 2011 at 8:06 AM, Felipe Monteiro de Carvalho wrote: > Indeed good idea, I am implementing like that with slightly different > names (TFPCustomRegion and IsPointInRegion). commited, I did not mention anything from Clip in the name of the region because it is not necessary useful only for drawing clipping, it can also be the base of event clipping and window and control shaping. I also joined zeljko's idea. If the region is not rectangular and you read the property ClipRect, it will return the bounding rectangle of the region. For rectagular regions it does the same, but the bounding box matches the region rectangle. It comes with a class for rectangular region clipping which is the trivial case for backwards compatibility.

Great job !

Michael.

Reply by email

Unknown author
to Felipe Monteiro de Carvalho: Indeed good idea, I am implementing like that with slightly different names…
Felipe Monteiro de Carvalho wrote 19 lines
On Wed, Nov 30, 2011 at 10:35 AM, wrote: > Good basics. > > What about the following: > > Create TBaseClipRegion with abstract method PointIsInRegion(P : TPoint) > (and maybe some others, like line intersections or so). Indeed good idea, I am implementing like that with slightly different names (TFPCustomRegion and IsPointInRegion). And what about adding virtual to many drawing methods in TFPCustomCanvas? This way TCanvas could override them more cleanly without the need to hide them. I know that the design is to make people implement DoRectangle, etc, instead, but I can clearly see a case for changing more directly the behavior. Also fcl-image comes without debug info, so removing the methods from TCanvas would bring a debugging annoyance.

At first sight I would think this is not a good proposal, because it was a conscious decision to do it the way it is done now.

But first please explain what you mean with "This way TCanvas could override them more cleanly without the need to hide them." ?

Michael.

Reply by email

Felipe Monteiro de Carvalho
to Unknown author
Show quoted text 7 lines
At first sight I would think this is not a good proposal, because it was a conscious decision to do it the way it is done now. But first please explain what you mean with "This way TCanvas could override them more cleanly without the need to hide them." ? From Graphics.pas:
  TCanvas = class(TFPCustomCanvas)
    procedure Ellipse(const ARect: TRect); // already in fpcanvas
    procedure Ellipse(x1, y1, x2, y2: Integer); virtual; // already in fpcanvas
......
    procedure Polygon(const Points: array of TPoint); // already in fpcanvas
    procedure Polyline(const Points: array of TPoint;
                       StartIndex: Integer;
                       NumPts: Integer = -1);
    procedure Polyline(Points: PPoint; NumPts: Integer); virtual;
    procedure Polyline(const Points: array of TPoint); // already in fpcanvas
    procedure Rectangle(X1,Y1,X2,Y2: Integer); virtual; // already in fpcanvas
    procedure Rectangle(const ARect: TRect); // already in fpcanvas
    procedure RoundRect(X1, Y1, X2, Y2: Integer; RX,RY: Integer); virtual;
    procedure RoundRect(const Rect: TRect; RX,RY: Integer);
    procedure TextOut(X,Y: Integer; const Text: String); virtual; //
already in fpcanvas

So TCanvas already "overrides" all of the drawing routines in TFPCustomCanvas, but because they are not virtual he is forced to hide them.

And like I said I don't think TCanvas will change because that would impact debugability, in my Mac when it enters unknown routines in the FCL it doesn't simply go to the next known place, it totally looses track of where the stepping is going. I already suffer from that in TLazCanvas because it implements things the "TFPCustomCanvas" way.

So I propose to change TFPCustomCanvas to have virtual, so that we can more cleanly connect the routines which do the same and have the same parameters.

Felipe Monteiro de Carvalho

Reply by email

Felipe Monteiro de Carvalho
to Felipe Monteiro de Carvalho

On top of that the drawing routines in TFPCustomCanvas are not single-liners calling DoSomething, for example:

procedure TFPCustomCanvas.Ellipse (const Bounds:TRect);
var p,b,dp,db,pb : boolean;
begin
  p := Pen.style  psClear;
  b := Brush.style  bsClear;
  pb := false;
  dp:=False;
  db:=False;
  if p and (Pen is TFPCustomDrawPen) then
........

So not having them as virtual ruins our hability to change their behavior.

Also TCanvas does not draw via Pen, Brush and Font like TFPCustomCanvas does.

Felipe Monteiro de Carvalho

Reply by email

Felipe Monteiro de Carvalho
to zeljko: It's not my idea ,I've just explained how it works in qt :) Yes, it must be so if you…
zeljko wrote
Note that xxx_boundingRect() functions of qt are marked as slow (I guess it's case when you deal with eg 1000 rects in region and you must calculate lower TopLeft and high BottomRight) in their docs, I hope that we'll have faster ones :)

Regions with thousands of rectangles look something extremely exotic to me, unless qt regions work internally by reducing all regions to a series of rectangles.

But we will have real poligonal regions implemented, which allow for arbitrary paths via a transformation. I already use this for drawing poligons in TLazCanvas, so we already have IsPointInRegion for poligons implemented according to:

http://www.visibone.com/inpoly/inpoly.c.txt
http://www.visibone.com/inpoly/

So we can reduce all regions to a small amount of poligons. I never measured to know if IsPointInRegion is faster via 100s of rectangles or via poligon, but unless via poligons is dramatically slower I would definitively not want to change into the 100s of rectangles way.

Felipe Monteiro de Carvalho

Reply by email

Hans-Peter Diettrich
to Felipe Monteiro de Carvalho
Show quoted text 9 lines
On Wed, Dec 7, 2011 at 9:28 AM, zeljko wrote: > Note that xxx_boundingRect() functions of qt are marked as slow (I guess > it's case when you deal with eg 1000 rects in region and you must calculate > lower TopLeft and high BottomRight) in their docs, I hope that we'll have > faster ones :) Regions with thousands of rectangles look something extremely exotic to me, unless qt regions work internally by reducing all regions to a series of rectangles.

IMO the fastest implementation paints everything to a bitmap, then masks the painting with the region. This should be faster than clipping every single drawing primitve.

DoDi

Reply by email

Felipe Monteiro de Carvalho
to Hans-Peter Diettrich
Hans-Peter Diettrich wrote
IMO the fastest implementation paints everything to a bitmap, then masks the painting with the region. This should be faster than clipping every single drawing primitve.

Please prove with test cases which take into account both speed and memory usage and are executed against my implementation and also against whatever else proposed =)

Things in practice are much more complex then one might initially imagine. My regions implementation is reused for several things: 1> Drawing clipping
2> Drawing complex objects like poligons, polybeziers, arbitrary regions 3> To clip mouse/touch events

Would your suggestion work in all of them? Will it be faster in all of them? Costing how much more memory?

Also you propose to first draw to a temporary bitmap then mask it ... ummm, not sure if this is really faster because you need to move memory 2 times. Currently I draw everything directly into the single double buffer of the surface which has the same format as the underlying backend requires... so there are many things to take into account and I think that only profiling could show the advantages of each implementation.

Not to mention that improving invalidate rect to detect which controls need to be repainted might be a lot more useful in reducing the paint time then changing the regions implementation.

Felipe Monteiro de Carvalho

Reply by email

Felipe Monteiro de Carvalho
to Felipe Monteiro de Carvalho
Felipe Monteiro de Carvalho wrote
ummm, not sure if this is really faster because you need to move memory 2 times.

Actually 3 times, because first you would need to copy the existing image to the temp bitmap (to support alpha blending), then draw to it and then draw again to the real surface.

Felipe Monteiro de Carvalho

Reply by email

Unknown author
to Hans-Peter Diettrich: IMO the fastest implementation paints everything to a bitmap, then masks the painting…
Hans-Peter Diettrich wrote 15 lines
Felipe Monteiro de Carvalho schrieb: > On Wed, Dec 7, 2011 at 9:28 AM, zeljko wrote: >> Note that xxx_boundingRect() functions of qt are marked as slow (I guess >> it's case when you deal with eg 1000 rects in region and you must >> calculate >> lower TopLeft and high BottomRight) in their docs, I hope that we'll have >> faster ones :) > > Regions with thousands of rectangles look something extremely exotic > to me, unless qt regions work internally by reducing all regions to a > series of rectangles. IMO the fastest implementation paints everything to a bitmap, then masks the painting with the region. This should be faster than clipping every single drawing primitve.

Vectorial drawing - e.g. Postscript or PDF - does not work like that.

Michael.

Reply by email

Hans-Peter Diettrich
to Felipe Monteiro de Carvalho: On Wed, Dec 7, 2011 at 11:27 AM, Hans-Peter Diettrich Please prove with test cases which…
Show quoted text 15 lines
On Wed, Dec 7, 2011 at 11:27 AM, Hans-Peter Diettrich wrote: > IMO the fastest implementation paints everything to a bitmap, then masks the > painting with the region. This should be faster than clipping every single > drawing primitve. Please prove with test cases which take into account both speed and memory usage and are executed against my implementation and also against whatever else proposed =) Things in practice are much more complex then one might initially imagine. My regions implementation is reused for several things: 1> Drawing clipping 2> Drawing complex objects like poligons, polybeziers, arbitrary regions 3> To clip mouse/touch events

Thanks, this finally answers my old question, what's the purpose of regions in your model. My suggestion was about clipping regions only, not about regions as paint objects.

DoDi

Reply by email

Felipe Monteiro de Carvalho
to Hans-Peter Diettrich

Some more changes I'd like to propose. It seams that Rectangle is not TCanvas compatible:

procedure TFPPixelCanvas.DoRectangle (const Bounds:TRect);

A rectangle over (0, 0, 10, 10) should not include the pixels line with x=10 and y=10 but instead go only to x=9 and y=9, it is considered that the position is in the top-left of the pixel

DoLine should not include the last point of the line (maybe unless you have a pen cap), although this one is a bit confusing. But it is how TCanvas works.

Hans-Peter Diettrich wrote 5 lines
> Things in practice are much more complex then one might initially > imagine. My regions implementation is reused for several things: > 1> Drawing clipping > 2> Drawing complex objects like poligons, polybeziers, arbitrary regions > 3> To clip mouse/touch events

There are more uses too:

4> Implement TRegion in LCL-CustomDrawn
5> Describe the shape of controls and forms

Felipe Monteiro de Carvalho

Reply by email

Unknown author
to Felipe Monteiro de Carvalho: Some more changes I'd like to propose. It seams that Rectangle is not TCanvas compatible:…
Felipe Monteiro de Carvalho wrote 12 lines
Some more changes I'd like to propose. It seams that Rectangle is not TCanvas compatible: procedure TFPPixelCanvas.DoRectangle (const Bounds:TRect); A rectangle over (0, 0, 10, 10) should not include the pixels line with x=10 and y=10 but instead go only to x=9 and y=9, it is considered that the position is in the top-left of the pixel DoLine should not include the last point of the line (maybe unless you have a pen cap), although this one is a bit confusing. But it is how TCanvas works.

Yes, but changing this will break existing code ?

Michael.

Reply by email

Hans-Peter Diettrich
to Unknown author
>> Yes, but changing this will break existing code ?

Such code can be considered broken, deserves an fix anyhow.

Show quoted text 5 lines
> Yes, it cannot do both at the same time, unless we add a property > PaintLikeTCanvas or something like that. Hm. I would reverse the property. "UseFPCPaint", which must be switched 'on'.

I'd suggest that you use the TCanvas conventions, before you run into well known pitfalls.

E.g. an empty rectangle should be (x,y, x,y), while a single pixel should be (x,y, x+1,y+1). The Width is Right-Left, not Right-Left+1. Otherwise combining regions, tiling (tables...), rotating etc. will be overly complicated and consequently almost buggy.

DoDi

Reply by email

Felipe Monteiro de Carvalho
to Hans-Peter Diettrich
Hans-Peter Diettrich wrote 7 lines
I'd suggest that you use the TCanvas conventions, before you run into well known pitfalls. E.g. an empty rectangle should be (x,y, x,y), while a single pixel should be (x,y, x+1,y+1). The Width is Right-Left, not Right-Left+1. Otherwise combining regions, tiling (tables...), rotating etc. will be overly complicated and consequently almost buggy.

Yes, in the case of the rectangle drawing I think it was a typo by who implemented the current rectangle in fcl-image, I have done various similar typos in my coding and they don't mean I really wanted to redefine rectangle.

But the TCanvas line is trully confusing by not adding the last pixel.

Felipe Monteiro de Carvalho

Reply by email

Hans-Peter Diettrich
to Felipe Monteiro de Carvalho
Show quoted text 6 lines
Yes, in the case of the rectangle drawing I think it was a typo by who implemented the current rectangle in fcl-image, I have done various similar typos in my coding and they don't mean I really wanted to redefine rectangle. But the TCanvas line is trully confusing by not adding the last pixel.

It works properly in drawing polygons, in detail with lines of different colors or styles. When the last (end) pixel would be painted for every line, the connection points would be drawn twice. This doesn't look dramatic for polygons, but may cause trouble in drawing other elements.

DoDi

Reply by email