[Pharo-project] Rome/Athens notes
Hi, i found rome API very close to OpenVG. Still OpenVG is a bit superior :) So, i'm using it as a guide to model/implement Rome interfaces. So, here is my thoughts (i also having a draft class skeleton for them): Paints: Paint is an object, which when applied to path, renders(draws) the path using paint's unique properties. I defined two methods in paint's base class: fillPath: aPath on: aCanvas self subclassResponsibility strokePath: aPath on: aCanvas self subclassResponsibility So, to draw a path, one should use a concrete paint to either fill it or stroke it (or both, if you want, but its handled by canvas and still will end up with separate fill & stroke requests to paint). I started from a quite basic things: NullPaint Paint which does not performs any drawing. Applying this paint to any path won't lead to any changes/processing. A simple OO approach to define 'nothing' :) SolidColorPaint instanceVariableNames: 'color' Paint with solid color. Most trivial thing which can be done :) RomePen instanceVariableNames: 'paint capStyle joinStyle width dash' A 'pen' paint is just encapsulating a set of properties, which is used for stroke. It is using another paint, which should handle the fills (in 'paint' ivar), while various stroke properties should be handled by itself. Filling with pen, will be the same as filling with its paint. While doing a stoke is different (includes path processing, given the values of pen's properties etc etc). I'm not sure with this part. Maybe stroke properties would be better to leave in canvas? Both OpenVG and Rome seems like following this road, but i don't quite like that stroke properties is global for canvas and lacking a proper encapsulation. CompositePaint Quite dumb thing. Holds a list of paints. When asked to fill or stroke the path, applies paints from own list. GradientPaint (abstract) LinearGradient RadialGradient etc.. paints which will use gradients for fills. Nothing fancy :) Canvas protocol: selectFill: anObject fill := anObject asRomePaintOn: self - selects a paint which will be used for fills. selectPen: anObject pen := anObject asRomePaintOn: self - selects a paint which will be used for stokes. stroke: anObject | path | path := anObject asRomePathOn: self. fill strokePath: path on: self. - stroke a path using currently selected 'pen' paint fill: anObject | path | path := anObject asRomePathOn: self. fill fillPath: path on: self. - fill path using paint for fills fillAndStroke: anObject | path | path := anObject asRomePathOn: self. fill fillPath: path on: self. pen strokePath: path on: self - fill and stroke path. And from that point, i wonder, do we need to have a paint's selection mechanisms at all? Because, we could simply do: canvas fill: myPath with: myPaint instead of: canvas selectFill: myPaint. canvas fill: myPath. Because you anyways can't draw a paths without paints, i don't see why canvas should have a notion of 'current fill' or 'current paint'. I think that with paint's encapsulation, its not necessary. I'd like to hear your thoughts about it. -- Best regards, Igor Stasenko AKA sig.
Hi,
i found rome API very close to OpenVG. Still OpenVG is a bit superior :) So, i'm using it as a guide to model/implement Rome interfaces.
Excellent!
So, here is my thoughts (i also having a draft class skeleton for them):
frankly consider that we are working on Rome because we need something to get access to Cairo/ whatever but we are newbie at the level. Now the good point for us is that we are smart newbies :) and ready to learn fast. So our first idea is - make it work (romePluginCanvas) - make all romeReferenceCanvas Get feedback, improve it improve it improve it as well as make all the code use it make all the code use it . So thanks for your brainstorming/ideas/wishes
Because, we could simply do:
canvas fill: myPath with: myPaint
instead of:
canvas selectFill: myPaint. canvas fill: myPath.
Because you anyways can't draw a paths without paints, i don't see why canvas should have a notion of 'current fill' or 'current paint'. I think that with paint's encapsulation, its not necessary.
I'd like to hear your thoughts about it.
No idea. Now at the back end level or "reference level" is there a value to separate? because like that you can do
canvas selectFill: myPaint. canvas fill: myPath. canvas fill: myPath.canvas fill: myPath.canvas fill: myPath.canvas fill: myPath.canvas fill: myPath.canvas fill: myPath.canvas fill: myPath.
Stef
Paints:
Paint is an object, which when applied to path, renders(draws) the path using paint's unique properties.
I defined two methods in paint's base class:
fillPath: aPath on: aCanvas
self subclassResponsibility
strokePath: aPath on: aCanvas
self subclassResponsibility
So, to draw a path, one should use a concrete paint to either fill it or stroke it (or both, if you want, but its handled by canvas and still will end up with separate fill & stroke requests to paint).
I started from a quite basic things:
NullPaint Paint which does not performs any drawing. Applying this paint to any path won't lead to any changes/processing. A simple OO approach to define 'nothing' :)
SolidColorPaint instanceVariableNames: 'color'
Paint with solid color. Most trivial thing which can be done :)
RomePen instanceVariableNames: 'paint capStyle joinStyle width dash'
A 'pen' paint is just encapsulating a set of properties, which is used for stroke. It is using another paint, which should handle the fills (in 'paint' ivar), while various stroke properties should be handled by itself. Filling with pen, will be the same as filling with its paint. While doing a stoke is different (includes path processing, given the values of pen's properties etc etc). I'm not sure with this part. Maybe stroke properties would be better to leave in canvas? Both OpenVG and Rome seems like following this road, but i don't quite like that stroke properties is global for canvas and lacking a proper encapsulation.
CompositePaint Quite dumb thing. Holds a list of paints. When asked to fill or stroke the path, applies paints from own list.
GradientPaint (abstract) LinearGradient RadialGradient etc.. paints which will use gradients for fills. Nothing fancy :)
Canvas protocol:
selectFill: anObject
fill := anObject asRomePaintOn: self
- selects a paint which will be used for fills.
selectPen: anObject
pen := anObject asRomePaintOn: self
- selects a paint which will be used for stokes.
stroke: anObject | path | path := anObject asRomePathOn: self.
fill strokePath: path on: self.
- stroke a path using currently selected 'pen' paint
fill: anObject | path | path := anObject asRomePathOn: self.
fill fillPath: path on: self.
- fill path using paint for fills
fillAndStroke: anObject | path | path := anObject asRomePathOn: self.
fill fillPath: path on: self. pen strokePath: path on: self
- fill and stroke path.
And from that point, i wonder, do we need to have a paint's selection mechanisms at all?
Because, we could simply do:
canvas fill: myPath with: myPaint
instead of:
canvas selectFill: myPaint. canvas fill: myPath.
Because you anyways can't draw a paths without paints, i don't see why canvas should have a notion of 'current fill' or 'current paint'. I think that with paint's encapsulation, its not necessary.
I'd like to hear your thoughts about it.
-- Best regards, Igor Stasenko AKA sig.
_______________________________________________ Pharo-project mailing list Pharo-project@lists.gforge.inria.fr http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/pharo-project
On 30 May 2010 17:26, Stéphane Ducasse <stephane.ducasse@inria.fr> wrote:
Hi,
i found rome API very close to OpenVG. Still OpenVG is a bit superior :) So, i'm using it as a guide to model/implement Rome interfaces.
Excellent!
So, here is my thoughts (i also having a draft class skeleton for them):
frankly consider that we are working on Rome because we need something to get access to Cairo/ whatever but we are newbie at the level. Now the good point for us is that we are smart newbies :) and ready to learn fast.
So our first idea is     - make it work (romePluginCanvas)     - make all romeReferenceCanvas
Get feedback, improve it improve it improve it as well as make all the code use it make all the code use it .
So thanks for your brainstorming/ideas/wishes
Because, we could simply do:
canvas fill: myPath with: myPaint
instead of:
canvas selectFill: myPaint. canvas fill: myPath.
Because you anyways can't draw a paths without paints, i don't see why canvas should have a notion of 'current fill' or 'current paint'. I think that with paint's encapsulation, its not necessary.
I'd like to hear your thoughts about it.
No idea. Now at the back end level or "reference level" is there a value to separate? because like that you can do
canvas selectFill: myPaint. canvas fill: myPath. canvas fill: myPath.canvas fill: myPath.canvas fill: myPath.canvas fill: myPath.canvas fill: myPath.canvas fill: myPath.canvas fill: myPath.
Right. I considered that too, before proposing ;) Selecting a paint and then drawing multiple paths using it may look like having some value. But the point is, that in practice you barely will use such feature. For instance, lets take a morph: Morph>>romeDrawOn: aCanvas aCanvas selectFill: self fillStyle; selectPen: self borderStyle; drawRectangle: self bounds Do you seen how you can reuse a previously selected paints here? I don't. You can't reuse, because you don't know what was selected previously (and querying it will cost you more cycles than just selecting a right one). So, that's how you will use it in 99% of cases: select fill select fill.. But not select fill fill fill .. One more example. A Tiger demo, which i did in OpenVG binding. A Tiger takes it roots from an SVG file, so it is right to say, that it covers the use of SVG for drawings. In SVG, each particular path it having own stroke/fill parameters. There is no way how you can reuse a previously selected paints, because each unique fragment having own settings, and even if a whole scene (as big as Tiger) using similar paints multiple times, you still can't reuse them because you need to follow the order of drawing (iterating over a collection of paths, but not a collection of paints), otherwise you won't get what you expecting to see. You can reuse paints by creating them, and then caching , so it won't cost you a conversion, each time you using it. (For instance you can convert a GradientFillStyle to appropriate paint object, and cache it somewhere). But selecting the paint costs nothing, and buys nothing in terms of speed (at least in my implementation, and i suspect in every other ;) ). I think that 'selection' and 'binding' mechanism in those APIs serve only one purpose: to minimize the number of arguments for function calls and as a workaround of having no OO. But in smalltalk world, we having objects, which can represent any kind of our domain objects (paths, paints etc), and so, from OO perspective binding/selecting looks like a useless thing. A big downside of such selection mechanism can be illustrated by taking OpenGL. It is cool, when you having one window, one context, one texture and one pencil to rule them all. But in practice, you often need more than one canvas, window, texture etc. And this is where such 'selection' mechanism starts standing in your way. For instance, if you working with multiple GL contexts in squeak, the only way how to ensure that you _always_ working with right context is to prepend each api call with: makeCurrent(myContextHandle). by literally turning every gl function like: func(a, b, c) into func(context, a, b, c) otherwise, you can't ensure a correct behavior, when you working with multiple contexts in multiple processes, having high chances being interrupted by each other. This is where passing an extra argument(s) is preferable, because it tells directly, with what object you wanna work with and so it minimizes the chances to make a mess. :)
Stef
Paints:
Paint is an object, which when applied to path, renders(draws) the path using paint's unique properties.
I defined two methods in paint's base class:
fillPath: aPath on: aCanvas
   self subclassResponsibility
strokePath: aPath on: aCanvas
   self subclassResponsibility
So, to draw a path, one should use a concrete paint to either fill it or stroke it (or both, if you want, but its handled by canvas and still will end up with separate fill & stroke requests to paint).
I started from a quite basic things:
NullPaint  Paint which does not performs any drawing.  Applying this paint to any path won't lead to any changes/processing.  A simple OO approach to define 'nothing' :)
SolidColorPaint    instanceVariableNames: 'color'
 Paint with solid color. Most trivial thing which can be done :)
RomePen    instanceVariableNames: 'paint capStyle joinStyle width dash'
A 'pen' paint is just encapsulating a set of properties, which is used for stroke. It is using another paint, which should handle the fills (in 'paint' ivar), while various stroke properties should be handled by itself. Filling with pen, will be the same as filling with its paint. While doing a stoke is different (includes path processing, given the values of pen's properties etc etc). I'm not sure with this part. Maybe stroke properties would be better to leave in canvas? Both OpenVG and Rome seems like following this road, but i don't quite like that stroke properties is global for canvas and lacking a proper encapsulation.
CompositePaint  Quite dumb thing. Holds a list of paints. When asked to fill or stroke the path, applies paints from own list.
GradientPaint (abstract)  LinearGradient  RadialGradient etc.. paints which will use gradients for fills. Nothing fancy :)
Canvas protocol:
selectFill: anObject
   fill := anObject asRomePaintOn: self
- selects a paint which will be used for fills.
selectPen: anObject
   pen := anObject asRomePaintOn: self
- selects a paint which will be used for stokes.
stroke: anObject    | path |    path := anObject asRomePathOn: self.
   fill strokePath: path on: self.
- stroke a path using currently selected 'pen' paint
fill: anObject    | path |    path := anObject asRomePathOn: self.
   fill fillPath: path on: self.
- fill path using paint for fills
fillAndStroke: anObject    | path |    path := anObject asRomePathOn: self.
   fill fillPath: path on: self.    pen strokePath: path on: self
- fill and stroke path.
And from that point, i wonder, do we need to have a paint's selection mechanisms at all?
Because, we could simply do:
canvas fill: myPath with: myPaint
instead of:
canvas selectFill: myPaint. canvas fill: myPath.
Because you anyways can't draw a paths without paints, i don't see why canvas should have a notion of 'current fill' or 'current paint'. I think that with paint's encapsulation, its not necessary.
I'd like to hear your thoughts about it.
-- Best regards, Igor Stasenko AKA sig.
_______________________________________________ Pharo-project mailing list Pharo-project@lists.gforge.inria.fr http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/pharo-project
_______________________________________________ Pharo-project mailing list Pharo-project@lists.gforge.inria.fr http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/pharo-project
-- Best regards, Igor Stasenko AKA sig.
cool post Stef On May 30, 2010, at 8:53 PM, Igor Stasenko wrote:
On 30 May 2010 17:26, Stéphane Ducasse <stephane.ducasse@inria.fr> wrote:
Hi,
i found rome API very close to OpenVG. Still OpenVG is a bit superior :) So, i'm using it as a guide to model/implement Rome interfaces.
Excellent!
So, here is my thoughts (i also having a draft class skeleton for them):
frankly consider that we are working on Rome because we need something to get access to Cairo/ whatever but we are newbie at the level. Now the good point for us is that we are smart newbies :) and ready to learn fast.
So our first idea is - make it work (romePluginCanvas) - make all romeReferenceCanvas
Get feedback, improve it improve it improve it as well as make all the code use it make all the code use it .
So thanks for your brainstorming/ideas/wishes
Because, we could simply do:
canvas fill: myPath with: myPaint
instead of:
canvas selectFill: myPaint. canvas fill: myPath.
Because you anyways can't draw a paths without paints, i don't see why canvas should have a notion of 'current fill' or 'current paint'. I think that with paint's encapsulation, its not necessary.
I'd like to hear your thoughts about it.
No idea. Now at the back end level or "reference level" is there a value to separate? because like that you can do
canvas selectFill: myPaint. canvas fill: myPath. canvas fill: myPath.canvas fill: myPath.canvas fill: myPath.canvas fill: myPath.canvas fill: myPath.canvas fill: myPath.canvas fill: myPath.
Right. I considered that too, before proposing ;) Selecting a paint and then drawing multiple paths using it may look like having some value.
But the point is, that in practice you barely will use such feature.
For instance, lets take a morph:
Morph>>romeDrawOn: aCanvas aCanvas selectFill: self fillStyle; selectPen: self borderStyle; drawRectangle: self bounds
Do you seen how you can reuse a previously selected paints here? I don't. You can't reuse, because you don't know what was selected previously (and querying it will cost you more cycles than just selecting a right one).
So, that's how you will use it in 99% of cases:
select fill select fill..
But not
select fill fill fill ..
One more example. A Tiger demo, which i did in OpenVG binding. A Tiger takes it roots from an SVG file, so it is right to say, that it covers the use of SVG for drawings. In SVG, each particular path it having own stroke/fill parameters. There is no way how you can reuse a previously selected paints, because each unique fragment having own settings, and even if a whole scene (as big as Tiger) using similar paints multiple times, you still can't reuse them because you need to follow the order of drawing (iterating over a collection of paths, but not a collection of paints), otherwise you won't get what you expecting to see.
You can reuse paints by creating them, and then caching , so it won't cost you a conversion, each time you using it. (For instance you can convert a GradientFillStyle to appropriate paint object, and cache it somewhere). But selecting the paint costs nothing, and buys nothing in terms of speed (at least in my implementation, and i suspect in every other ;) ).
I think that 'selection' and 'binding' mechanism in those APIs serve only one purpose: to minimize the number of arguments for function calls and as a workaround of having no OO. But in smalltalk world, we having objects, which can represent any kind of our domain objects (paths, paints etc), and so, from OO perspective binding/selecting looks like a useless thing.
A big downside of such selection mechanism can be illustrated by taking OpenGL. It is cool, when you having one window, one context, one texture and one pencil to rule them all. But in practice, you often need more than one canvas, window, texture etc. And this is where such 'selection' mechanism starts standing in your way. For instance, if you working with multiple GL contexts in squeak, the only way how to ensure that you _always_ working with right context is to prepend each api call with: makeCurrent(myContextHandle). by literally turning every gl function like: func(a, b, c) into func(context, a, b, c) otherwise, you can't ensure a correct behavior, when you working with multiple contexts in multiple processes, having high chances being interrupted by each other.
This is where passing an extra argument(s) is preferable, because it tells directly, with what object you wanna work with and so it minimizes the chances to make a mess. :)
Stef
Paints:
Paint is an object, which when applied to path, renders(draws) the path using paint's unique properties.
I defined two methods in paint's base class:
fillPath: aPath on: aCanvas
self subclassResponsibility
strokePath: aPath on: aCanvas
self subclassResponsibility
So, to draw a path, one should use a concrete paint to either fill it or stroke it (or both, if you want, but its handled by canvas and still will end up with separate fill & stroke requests to paint).
I started from a quite basic things:
NullPaint Paint which does not performs any drawing. Applying this paint to any path won't lead to any changes/processing. A simple OO approach to define 'nothing' :)
SolidColorPaint instanceVariableNames: 'color'
Paint with solid color. Most trivial thing which can be done :)
RomePen instanceVariableNames: 'paint capStyle joinStyle width dash'
A 'pen' paint is just encapsulating a set of properties, which is used for stroke. It is using another paint, which should handle the fills (in 'paint' ivar), while various stroke properties should be handled by itself. Filling with pen, will be the same as filling with its paint. While doing a stoke is different (includes path processing, given the values of pen's properties etc etc). I'm not sure with this part. Maybe stroke properties would be better to leave in canvas? Both OpenVG and Rome seems like following this road, but i don't quite like that stroke properties is global for canvas and lacking a proper encapsulation.
CompositePaint Quite dumb thing. Holds a list of paints. When asked to fill or stroke the path, applies paints from own list.
GradientPaint (abstract) LinearGradient RadialGradient etc.. paints which will use gradients for fills. Nothing fancy :)
Canvas protocol:
selectFill: anObject
fill := anObject asRomePaintOn: self
- selects a paint which will be used for fills.
selectPen: anObject
pen := anObject asRomePaintOn: self
- selects a paint which will be used for stokes.
stroke: anObject | path | path := anObject asRomePathOn: self.
fill strokePath: path on: self.
- stroke a path using currently selected 'pen' paint
fill: anObject | path | path := anObject asRomePathOn: self.
fill fillPath: path on: self.
- fill path using paint for fills
fillAndStroke: anObject | path | path := anObject asRomePathOn: self.
fill fillPath: path on: self. pen strokePath: path on: self
- fill and stroke path.
And from that point, i wonder, do we need to have a paint's selection mechanisms at all?
Because, we could simply do:
canvas fill: myPath with: myPaint
instead of:
canvas selectFill: myPaint. canvas fill: myPath.
Because you anyways can't draw a paths without paints, i don't see why canvas should have a notion of 'current fill' or 'current paint'. I think that with paint's encapsulation, its not necessary.
I'd like to hear your thoughts about it.
-- Best regards, Igor Stasenko AKA sig.
_______________________________________________ Pharo-project mailing list Pharo-project@lists.gforge.inria.fr http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/pharo-project
_______________________________________________ Pharo-project mailing list Pharo-project@lists.gforge.inria.fr http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/pharo-project
-- Best regards, Igor Stasenko AKA sig.
_______________________________________________ Pharo-project mailing list Pharo-project@lists.gforge.inria.fr http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/pharo-project
On 30 May 2010 23:08, Stéphane Ducasse <stephane.ducasse@inria.fr> wrote:
cool post
Yeah, these things are quite interesting. Except that not much people actually interested in it :) Here's another thing, which can be done right (if we want). Rome/OpenVG Paths is actually nothing else than a special kind of more general thing - shape. So, at very basis, we should have only two components for painting: shape and paint. And in fact we need to support only a single operation: fill the shape with given paint. (The path stroke could be seen as a special kind of fill) So the question is: Really. Why we should constrain ourselves with specific things from a very starting, by cutting out a most basic (and abstact ideas) behind? There are infinite number of ways, how one could define a shape. While paths is only a small, yet effective representation of shapes. In same way there are infinite number of ways how one could define a paint. Then this looks like a strong basis for building-up a powerful & flexible graphics engine :)
Stef
On May 30, 2010, at 8:53 PM, Igor Stasenko wrote:
On 30 May 2010 17:26, Stéphane Ducasse <stephane.ducasse@inria.fr> wrote:
Hi,
i found rome API very close to OpenVG. Still OpenVG is a bit superior :) So, i'm using it as a guide to model/implement Rome interfaces.
Excellent!
So, here is my thoughts (i also having a draft class skeleton for them):
frankly consider that we are working on Rome because we need something to get access to Cairo/ whatever but we are newbie at the level. Now the good point for us is that we are smart newbies :) and ready to learn fast.
So our first idea is     - make it work (romePluginCanvas)     - make all romeReferenceCanvas
Get feedback, improve it improve it improve it as well as make all the code use it make all the code use it .
So thanks for your brainstorming/ideas/wishes
Because, we could simply do:
canvas fill: myPath with: myPaint
instead of:
canvas selectFill: myPaint. canvas fill: myPath.
Because you anyways can't draw a paths without paints, i don't see why canvas should have a notion of 'current fill' or 'current paint'. I think that with paint's encapsulation, its not necessary.
I'd like to hear your thoughts about it.
No idea. Now at the back end level or "reference level" is there a value to separate? because like that you can do
canvas selectFill: myPaint. canvas fill: myPath. canvas fill: myPath.canvas fill: myPath.canvas fill: myPath.canvas fill: myPath.canvas fill: myPath.canvas fill: myPath.canvas fill: myPath.
Right. I considered that too, before proposing ;) Selecting a paint and then drawing multiple paths using it may look like having some value.
But the point is, that in practice you barely will use such feature.
For instance, lets take a morph:
Morph>>romeDrawOn: aCanvas    aCanvas        selectFill: self fillStyle;        selectPen: self borderStyle;        drawRectangle: self bounds
Do you seen how you can reuse a previously selected paints here? I don't. You can't reuse, because you don't know what was selected previously (and querying it will cost you more cycles than just selecting a right one).
So, that's how you will use it in 99% of cases:
select fill select fill..
But not
select fill fill fill ..
One more example. A Tiger demo, which i did in OpenVG binding. A Tiger takes it roots from an SVG file, so it is right to say, that it covers the use of SVG for drawings. In SVG, each particular path it having own stroke/fill parameters. There is no way how you can reuse a previously selected paints, because each unique fragment having own settings, and even if a whole scene (as big as Tiger) using similar paints multiple times, you still can't reuse them because you need to follow the order of drawing (iterating over a collection of paths, but not a collection of paints), otherwise you won't get what you expecting to see.
You can reuse paints by creating them, and then caching , so it won't cost you a conversion, each time you using it. (For instance you can convert a GradientFillStyle to appropriate paint object, and cache it somewhere). But selecting the paint costs nothing, and buys nothing in terms of speed (at least in my implementation, and i suspect in every other ;) ).
I think that 'selection' and 'binding' mechanism in those APIs serve only one purpose: to minimize the number of arguments for function calls and as a workaround of having no OO. But in smalltalk world, we having objects, which can represent any kind of our domain objects (paths, paints etc), and so, from OO perspective binding/selecting looks like a useless thing.
A big downside of such selection mechanism can be illustrated by taking OpenGL. It is cool, when you having one window, one context, one texture and one pencil to rule them all. But in practice, you often need more than one canvas, window, texture etc. And this is where such 'selection' mechanism starts standing in your way. For instance, if you working with multiple GL contexts in squeak, the only way how to ensure that you _always_ working with right context is to prepend each api call with: Â makeCurrent(myContextHandle). by literally turning every gl function like: Â func(a, b, c) into func(context, a, b, c) otherwise, you can't ensure a correct behavior, when you working with multiple contexts in multiple processes, having high chances being interrupted by each other.
This is where passing an extra argument(s) is preferable, because it tells directly, with what object you wanna work with and so it minimizes the chances to make a mess. :)
Stef
Paints:
Paint is an object, which when applied to path, renders(draws) the path using paint's unique properties.
I defined two methods in paint's base class:
fillPath: aPath on: aCanvas
   self subclassResponsibility
strokePath: aPath on: aCanvas
   self subclassResponsibility
So, to draw a path, one should use a concrete paint to either fill it or stroke it (or both, if you want, but its handled by canvas and still will end up with separate fill & stroke requests to paint).
I started from a quite basic things:
NullPaint  Paint which does not performs any drawing.  Applying this paint to any path won't lead to any changes/processing.  A simple OO approach to define 'nothing' :)
SolidColorPaint    instanceVariableNames: 'color'
 Paint with solid color. Most trivial thing which can be done :)
RomePen    instanceVariableNames: 'paint capStyle joinStyle width dash'
A 'pen' paint is just encapsulating a set of properties, which is used for stroke. It is using another paint, which should handle the fills (in 'paint' ivar), while various stroke properties should be handled by itself. Filling with pen, will be the same as filling with its paint. While doing a stoke is different (includes path processing, given the values of pen's properties etc etc). I'm not sure with this part. Maybe stroke properties would be better to leave in canvas? Both OpenVG and Rome seems like following this road, but i don't quite like that stroke properties is global for canvas and lacking a proper encapsulation.
CompositePaint  Quite dumb thing. Holds a list of paints. When asked to fill or stroke the path, applies paints from own list.
GradientPaint (abstract)  LinearGradient  RadialGradient etc.. paints which will use gradients for fills. Nothing fancy :)
Canvas protocol:
selectFill: anObject
   fill := anObject asRomePaintOn: self
- selects a paint which will be used for fills.
selectPen: anObject
   pen := anObject asRomePaintOn: self
- selects a paint which will be used for stokes.
stroke: anObject    | path |    path := anObject asRomePathOn: self.
   fill strokePath: path on: self.
- stroke a path using currently selected 'pen' paint
fill: anObject    | path |    path := anObject asRomePathOn: self.
   fill fillPath: path on: self.
- fill path using paint for fills
fillAndStroke: anObject    | path |    path := anObject asRomePathOn: self.
   fill fillPath: path on: self.    pen strokePath: path on: self
- fill and stroke path.
And from that point, i wonder, do we need to have a paint's selection mechanisms at all?
Because, we could simply do:
canvas fill: myPath with: myPaint
instead of:
canvas selectFill: myPaint. canvas fill: myPath.
Because you anyways can't draw a paths without paints, i don't see why canvas should have a notion of 'current fill' or 'current paint'. I think that with paint's encapsulation, its not necessary.
I'd like to hear your thoughts about it.
-- Best regards, Igor Stasenko AKA sig.
_______________________________________________ Pharo-project mailing list Pharo-project@lists.gforge.inria.fr http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/pharo-project
_______________________________________________ Pharo-project mailing list Pharo-project@lists.gforge.inria.fr http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/pharo-project
-- Best regards, Igor Stasenko AKA sig.
_______________________________________________ Pharo-project mailing list Pharo-project@lists.gforge.inria.fr http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/pharo-project
_______________________________________________ Pharo-project mailing list Pharo-project@lists.gforge.inria.fr http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/pharo-project
-- Best regards, Igor Stasenko AKA sig.
On May 30, 2010, at 10:57 PM, Igor Stasenko wrote:
On 30 May 2010 23:08, Stéphane Ducasse <stephane.ducasse@inria.fr> wrote:
cool post
Yeah, these things are quite interesting. Except that not much people actually interested in it :)
I do not think so. Good posts are read more that you believe. Now in mailing-list the numbers of mails cut the knowledge after a point.
Here's another thing, which can be done right (if we want).
Rome/OpenVG Paths is actually nothing else than a special kind of more general thing - shape.
So, at very basis, we should have only two components for painting: shape and paint. And in fact we need to support only a single operation: fill the shape with given paint. (The path stroke could be seen as a special kind of fill)
So the question is: Really. Why we should constrain ourselves with specific things from a very starting, by cutting out a most basic (and abstact ideas) behind?
There are infinite number of ways, how one could define a shape. While paths is only a small, yet effective representation of shapes. In same way there are infinite number of ways how one could define a paint.
Then this looks like a strong basis for building-up a powerful & flexible graphics engine :)
I do not know. Do the other frameworks outside smalltalk use something else than paths? I think that we should start - making rome working. We are nearly there - test it - refactor it. - I would like to see the canvas for morphic30 too. - refactor the system to use that. stef
On 31 May 2010 00:20, Stéphane Ducasse <stephane.ducasse@inria.fr> wrote:
On May 30, 2010, at 10:57 PM, Igor Stasenko wrote:
On 30 May 2010 23:08, Stéphane Ducasse <stephane.ducasse@inria.fr> wrote:
cool post
Yeah, these things are quite interesting. Except that not much people actually interested in it :)
I do not think so. Good posts are read more that you believe. Now in mailing-list the numbers of mails cut the knowledge after a point.
But i posted here mainly to discuss these ideas. If we don't have a discussion, then we won't have a resolution, and its not matters how good post is or not, because a true value of any idea can be determined by considering all alternatives and discussing them. But maybe i'm a bit too hurry , because you mentioned that first things which needs to be done is to make current stuff working. The other thing is, that i am writing GL stuff from scratch (mostly), so i tend to pay more attention on design first, and then on implementation.
Here's another thing, which can be done right (if we want).
Rome/OpenVG Paths is actually nothing else than a special kind of more general thing - shape.
So, at very basis, we should have only two components for painting: shape and paint. And in fact we need to support only a single operation: fill the shape with given paint. (The path stroke could be seen as a special kind of fill)
So the question is: Really. Why we should constrain ourselves with specific things from a very starting, by cutting out a most basic (and abstact ideas) behind?
There are infinite number of ways, how one could define a shape. While paths is only a small, yet effective representation of shapes. In same way there are infinite number of ways how one could define a paint.
Then this looks like a strong basis for building-up a powerful & flexible graphics engine :)
I do not know. Do the other frameworks outside smalltalk use something else than paths?
Yes. In 3D you have meshes, NURB surfaces , constructive-solid geometry and tons of other stuff.
I think that we should start     - making rome working. We are nearly there     - test it     - refactor it.     - I would like to see the canvas for morphic30 too.     - refactor the system to use that. stef
Yes. Yes. Yes :)
_______________________________________________ Pharo-project mailing list Pharo-project@lists.gforge.inria.fr http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/pharo-project
-- Best regards, Igor Stasenko AKA sig.
Hi Igor, Thanks for investing time into this. I do not have much knowledge in this area, nor any free time at the moment, but I would gladly try to test. Cheers, Doru On 30 May 2010, at 23:34, Igor Stasenko wrote:
On 31 May 2010 00:20, Stéphane Ducasse <stephane.ducasse@inria.fr> wrote:
On May 30, 2010, at 10:57 PM, Igor Stasenko wrote:
On 30 May 2010 23:08, Stéphane Ducasse <stephane.ducasse@inria.fr> wrote:
cool post
Yeah, these things are quite interesting. Except that not much people actually interested in it :)
I do not think so. Good posts are read more that you believe. Now in mailing-list the numbers of mails cut the knowledge after a point.
But i posted here mainly to discuss these ideas. If we don't have a discussion, then we won't have a resolution, and its not matters how good post is or not, because a true value of any idea can be determined by considering all alternatives and discussing them. But maybe i'm a bit too hurry , because you mentioned that first things which needs to be done is to make current stuff working. The other thing is, that i am writing GL stuff from scratch (mostly), so i tend to pay more attention on design first, and then on implementation.
Here's another thing, which can be done right (if we want).
Rome/OpenVG Paths is actually nothing else than a special kind of more general thing - shape.
So, at very basis, we should have only two components for painting: shape and paint. And in fact we need to support only a single operation: fill the shape with given paint. (The path stroke could be seen as a special kind of fill)
So the question is: Really. Why we should constrain ourselves with specific things from a very starting, by cutting out a most basic (and abstact ideas) behind?
There are infinite number of ways, how one could define a shape. While paths is only a small, yet effective representation of shapes. In same way there are infinite number of ways how one could define a paint.
Then this looks like a strong basis for building-up a powerful & flexible graphics engine :)
I do not know. Do the other frameworks outside smalltalk use something else than paths?
Yes. In 3D you have meshes, NURB surfaces , constructive-solid geometry and tons of other stuff.
I think that we should start - making rome working. We are nearly there - test it - refactor it. - I would like to see the canvas for morphic30 too. - refactor the system to use that. stef
Yes. Yes. Yes :)
_______________________________________________ Pharo-project mailing list Pharo-project@lists.gforge.inria.fr http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/pharo-project
-- Best regards, Igor Stasenko AKA sig.
_______________________________________________ Pharo-project mailing list Pharo-project@lists.gforge.inria.fr http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/pharo-project
-- www.tudorgirba.com "Being happy is a matter of choice."
Hi Igor, Thanks for investing time into this. I do not have much knowledge in this area, nor any free time at the moment, but I would gladly try to test. Cheers, Doru On 30 May 2010, at 23:34, Igor Stasenko wrote:
On 31 May 2010 00:20, Stéphane Ducasse <stephane.ducasse@inria.fr> wrote:
On May 30, 2010, at 10:57 PM, Igor Stasenko wrote:
On 30 May 2010 23:08, Stéphane Ducasse <stephane.ducasse@inria.fr> wrote:
cool post
Yeah, these things are quite interesting. Except that not much people actually interested in it :)
I do not think so. Good posts are read more that you believe. Now in mailing-list the numbers of mails cut the knowledge after a point.
But i posted here mainly to discuss these ideas. If we don't have a discussion, then we won't have a resolution, and its not matters how good post is or not, because a true value of any idea can be determined by considering all alternatives and discussing them. But maybe i'm a bit too hurry , because you mentioned that first things which needs to be done is to make current stuff working. The other thing is, that i am writing GL stuff from scratch (mostly), so i tend to pay more attention on design first, and then on implementation.
Here's another thing, which can be done right (if we want).
Rome/OpenVG Paths is actually nothing else than a special kind of more general thing - shape.
So, at very basis, we should have only two components for painting: shape and paint. And in fact we need to support only a single operation: fill the shape with given paint. (The path stroke could be seen as a special kind of fill)
So the question is: Really. Why we should constrain ourselves with specific things from a very starting, by cutting out a most basic (and abstact ideas) behind?
There are infinite number of ways, how one could define a shape. While paths is only a small, yet effective representation of shapes. In same way there are infinite number of ways how one could define a paint.
Then this looks like a strong basis for building-up a powerful & flexible graphics engine :)
I do not know. Do the other frameworks outside smalltalk use something else than paths?
Yes. In 3D you have meshes, NURB surfaces , constructive-solid geometry and tons of other stuff.
I think that we should start - making rome working. We are nearly there - test it - refactor it. - I would like to see the canvas for morphic30 too. - refactor the system to use that. stef
Yes. Yes. Yes :)
_______________________________________________ Pharo-project mailing list Pharo-project@lists.gforge.inria.fr http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/pharo-project
-- Best regards, Igor Stasenko AKA sig.
_______________________________________________ Pharo-project mailing list Pharo-project@lists.gforge.inria.fr http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/pharo-project
-- www.tudorgirba.com "Being happy is a matter of choice."
participants (3)
-
Igor Stasenko -
Stéphane Ducasse -
Tudor Girba