On 30 May 2010 23:08, Stéphane Ducasse <[email protected]> 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 <[email protected]> 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
>>>> [email protected]
>>>> http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/pharo-project
>>>
>>>
>>> _______________________________________________
>>> Pharo-project mailing list
>>> [email protected]
>>> http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/pharo-project
>>>
>>
>>
>>
>> --
>> Best regards,
>> Igor Stasenko AKA sig.
>>
>> _______________________________________________
>> Pharo-project mailing list
>> [email protected]
>> http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/pharo-project
>
>
> _______________________________________________
> Pharo-project mailing list
> [email protected]
> http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/pharo-project
>



-- 
Best regards,
Igor Stasenko AKA sig.

_______________________________________________
Pharo-project mailing list
[email protected]
http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/pharo-project

Reply via email to